feat: Guest email authentication (#1088)
* feat: API endpoints for email signin * fix: After testing * Initial signin flow working * move shared middleware * feat: Add guest signin toggle, obey on endpoints * feat: Basic email signin when enabled * Improve guest signin email Disable double signin with JWT * fix: Simple rate limiting * create placeholder users in db * fix: Give invited users default avatar add invited users to people settings * test * add transaction * tmp: test CI * derp * md5 * urgh * again * test: pass * test * fix: Remove usage of data values * guest signin page * Visually separator 'Invited' from other people tabs * fix: Edge case attempting SSO signin for guest email account * fix: Correctly set email auth method to cookie * Improve rate limit error display * lint: cleanup / comments * Improve invalid token error display * style tweaks * pass guest value to subdomain * Restore copy link option * feat: Allow invite revoke from people management * fix: Incorrect users email schema does not allow for user deletion * lint * fix: avatarUrl for deleted user failure * change default to off for guest invites * fix: Changing security settings wipes subdomain * fix: user delete permissioning * test: Add user.invite specs
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
// @flow
|
||||
import Sequelize from 'sequelize';
|
||||
import Router from 'koa-router';
|
||||
import auth from '../middlewares/authentication';
|
||||
import addHours from 'date-fns/add_hours';
|
||||
@@ -14,6 +15,7 @@ import {
|
||||
} from '../models';
|
||||
import * as Slack from '../slack';
|
||||
|
||||
const Op = Sequelize.Op;
|
||||
const router = new Router();
|
||||
|
||||
// start the oauth process and redirect user to Slack
|
||||
@@ -37,7 +39,7 @@ router.get('slack.callback', auth({ required: false }), async ctx => {
|
||||
ctx.assertPresent(state, 'state is required');
|
||||
|
||||
if (state !== ctx.cookies.get('state')) {
|
||||
ctx.redirect('/?notice=auth-error');
|
||||
ctx.redirect('/?notice=auth-error&error=state_mismatch');
|
||||
return;
|
||||
}
|
||||
if (error) {
|
||||
@@ -57,46 +59,75 @@ router.get('slack.callback', auth({ required: false }), async ctx => {
|
||||
},
|
||||
});
|
||||
|
||||
const [user, isFirstSignin] = await User.findOrCreate({
|
||||
where: {
|
||||
service: 'slack',
|
||||
serviceId: data.user.id,
|
||||
teamId: team.id,
|
||||
},
|
||||
defaults: {
|
||||
name: data.user.name,
|
||||
email: data.user.email,
|
||||
isAdmin: isFirstUser,
|
||||
avatarUrl: data.user.image_192,
|
||||
},
|
||||
});
|
||||
|
||||
if (isFirstUser) {
|
||||
await team.provisionFirstCollection(user.id);
|
||||
await team.provisionSubdomain(data.team.domain);
|
||||
}
|
||||
|
||||
if (isFirstSignin) {
|
||||
await Event.create({
|
||||
name: 'users.create',
|
||||
actorId: user.id,
|
||||
userId: user.id,
|
||||
teamId: team.id,
|
||||
data: {
|
||||
name: user.name,
|
||||
service: 'slack',
|
||||
try {
|
||||
const [user, isFirstSignin] = await User.findOrCreate({
|
||||
where: {
|
||||
[Op.or]: [
|
||||
{
|
||||
service: 'slack',
|
||||
serviceId: data.user.id,
|
||||
},
|
||||
{
|
||||
service: '',
|
||||
},
|
||||
],
|
||||
teamId: team.id,
|
||||
},
|
||||
defaults: {
|
||||
name: data.user.name,
|
||||
email: data.user.email,
|
||||
isAdmin: isFirstUser,
|
||||
avatarUrl: data.user.image_192,
|
||||
},
|
||||
ip: ctx.request.ip,
|
||||
});
|
||||
}
|
||||
|
||||
// update email address if it's changed in Slack
|
||||
if (!isFirstSignin && data.user.email !== user.email) {
|
||||
await user.update({ email: data.user.email });
|
||||
}
|
||||
if (isFirstUser) {
|
||||
await team.provisionFirstCollection(user.id);
|
||||
await team.provisionSubdomain(data.team.domain);
|
||||
}
|
||||
|
||||
// set cookies on response and redirect to team subdomain
|
||||
ctx.signIn(user, team, 'slack', isFirstSignin);
|
||||
if (isFirstSignin) {
|
||||
await Event.create({
|
||||
name: 'users.create',
|
||||
actorId: user.id,
|
||||
userId: user.id,
|
||||
teamId: team.id,
|
||||
data: {
|
||||
name: user.name,
|
||||
service: 'slack',
|
||||
},
|
||||
ip: ctx.request.ip,
|
||||
});
|
||||
}
|
||||
|
||||
// update email address if it's changed in Slack
|
||||
if (!isFirstSignin && data.user.email !== user.email) {
|
||||
await user.update({ email: data.user.email });
|
||||
}
|
||||
|
||||
// set cookies on response and redirect to team subdomain
|
||||
ctx.signIn(user, team, 'slack', isFirstSignin);
|
||||
} catch (err) {
|
||||
if (err instanceof Sequelize.UniqueConstraintError) {
|
||||
const exists = await User.findOne({
|
||||
where: {
|
||||
service: 'email',
|
||||
email: data.user.email,
|
||||
teamId: team.id,
|
||||
},
|
||||
});
|
||||
|
||||
if (exists) {
|
||||
ctx.redirect(`${team.url}?notice=email-auth-required`);
|
||||
} else {
|
||||
ctx.redirect(`${team.url}?notice=auth-error`);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
throw err;
|
||||
}
|
||||
});
|
||||
|
||||
router.get('slack.commands', auth({ required: false }), async ctx => {
|
||||
|
||||
Reference in New Issue
Block a user