2017-07-13 18:39:07 +00:00
|
|
|
import { Observable } from 'rx';
|
|
|
|
// import debug from 'debug';
|
|
|
|
import dedent from 'dedent';
|
2018-06-28 14:57:15 +00:00
|
|
|
import { isEmail } from 'validator';
|
2015-06-11 18:38:08 +00:00
|
|
|
|
2017-07-13 18:39:07 +00:00
|
|
|
import { observeMethod, observeQuery } from '../../server/utils/rx';
|
|
|
|
import { wrapHandledError } from '../../server/utils/create-handled-error.js';
|
2015-08-12 19:15:19 +00:00
|
|
|
|
2017-07-13 18:39:07 +00:00
|
|
|
// const log = debug('fcc:models:userIdent');
|
2015-06-11 18:38:08 +00:00
|
|
|
|
2015-08-04 21:52:06 +00:00
|
|
|
export default function(UserIdent) {
|
2017-07-13 18:39:07 +00:00
|
|
|
UserIdent.on('dataSourceAttached', () => {
|
|
|
|
UserIdent.findOne$ = observeMethod(UserIdent, 'findOne');
|
|
|
|
});
|
2018-06-28 14:57:15 +00:00
|
|
|
|
2015-08-13 02:08:05 +00:00
|
|
|
UserIdent.login = function(
|
2017-07-13 18:39:07 +00:00
|
|
|
_provider,
|
2015-08-13 02:08:05 +00:00
|
|
|
authScheme,
|
|
|
|
profile,
|
|
|
|
credentials,
|
|
|
|
options,
|
|
|
|
cb
|
|
|
|
) {
|
2017-07-13 18:39:07 +00:00
|
|
|
const User = UserIdent.app.models.User;
|
|
|
|
const AccessToken = UserIdent.app.models.AccessToken;
|
2015-08-13 02:08:05 +00:00
|
|
|
options = options || {};
|
|
|
|
if (typeof options === 'function' && !cb) {
|
|
|
|
cb = options;
|
|
|
|
options = {};
|
|
|
|
}
|
2018-06-28 14:57:15 +00:00
|
|
|
|
|
|
|
// get the social provider data and the external id from auth0
|
2015-08-13 02:08:05 +00:00
|
|
|
profile.id = profile.id || profile.openid;
|
2018-06-28 14:57:15 +00:00
|
|
|
const auth0IdString = '' + profile.id;
|
2018-09-20 09:22:45 +00:00
|
|
|
const [provider, socialExtId] = auth0IdString.split('|');
|
2017-07-13 18:39:07 +00:00
|
|
|
const query = {
|
2015-08-13 02:08:05 +00:00
|
|
|
where: {
|
2017-07-13 18:39:07 +00:00
|
|
|
provider: provider,
|
2018-06-28 14:57:15 +00:00
|
|
|
externalId: socialExtId
|
2017-07-13 18:39:07 +00:00
|
|
|
},
|
|
|
|
include: 'user'
|
2016-04-22 03:35:19 +00:00
|
|
|
};
|
2018-06-28 14:57:15 +00:00
|
|
|
// get the email from the auth0 (its expected from social providers)
|
2018-09-20 09:22:45 +00:00
|
|
|
const email =
|
|
|
|
profile && profile.emails && profile.emails[0]
|
|
|
|
? profile.emails[0].value
|
|
|
|
: '';
|
2018-06-28 14:57:15 +00:00
|
|
|
if (!isEmail('' + email)) {
|
|
|
|
throw wrapHandledError(
|
|
|
|
new Error('invalid or empty email recieved from auth0'),
|
|
|
|
{
|
|
|
|
message: dedent`
|
|
|
|
Oops... something is not right. We did not find a valid email from your
|
|
|
|
${provider} account. Please try again with a different provider that has an
|
|
|
|
email available with it.
|
|
|
|
`,
|
|
|
|
type: 'info',
|
|
|
|
redirectTo: '/'
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
2018-05-19 15:51:49 +00:00
|
|
|
|
2018-06-28 14:57:15 +00:00
|
|
|
if (provider === 'email') {
|
2018-05-19 15:51:49 +00:00
|
|
|
return User.findOne$({ where: { email } })
|
|
|
|
.flatMap(user => {
|
2018-09-20 09:22:45 +00:00
|
|
|
return user
|
|
|
|
? Observable.of(user)
|
|
|
|
: User.create$({ email }).toPromise();
|
2018-05-22 12:40:00 +00:00
|
|
|
})
|
|
|
|
.flatMap(user => {
|
|
|
|
if (!user) {
|
|
|
|
throw wrapHandledError(
|
2018-05-22 16:26:12 +00:00
|
|
|
new Error('could not find or create a user'),
|
2018-05-22 12:40:00 +00:00
|
|
|
{
|
|
|
|
message: dedent`
|
2018-06-28 14:57:15 +00:00
|
|
|
Oops... something is not right. We could not find or create a
|
|
|
|
user with that email.
|
2018-05-22 12:40:00 +00:00
|
|
|
`,
|
|
|
|
type: 'info',
|
|
|
|
redirectTo: '/'
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
2018-09-20 09:22:45 +00:00
|
|
|
const createToken = observeQuery(AccessToken, 'create', {
|
|
|
|
userId: user.id,
|
|
|
|
created: new Date(),
|
|
|
|
ttl: user.constructor.settings.ttl
|
2018-05-22 12:40:00 +00:00
|
|
|
});
|
2018-09-20 09:22:45 +00:00
|
|
|
const updateUserPromise = new Promise((resolve, reject) =>
|
|
|
|
user.updateAttributes(
|
|
|
|
{
|
|
|
|
emailVerified: true,
|
|
|
|
emailAuthLinkTTL: null,
|
|
|
|
emailVerifyTTL: null
|
|
|
|
},
|
|
|
|
err => {
|
|
|
|
if (err) {
|
|
|
|
return reject(err);
|
|
|
|
}
|
|
|
|
return resolve();
|
|
|
|
}
|
|
|
|
)
|
|
|
|
);
|
2018-05-21 19:07:01 +00:00
|
|
|
return Observable.combineLatest(
|
|
|
|
Observable.of(user),
|
|
|
|
createToken,
|
2018-09-20 09:22:45 +00:00
|
|
|
Observable.fromPromise(updateUserPromise),
|
|
|
|
(user, token) => ({ user, token })
|
2018-05-21 19:07:01 +00:00
|
|
|
);
|
2018-05-19 15:51:49 +00:00
|
|
|
})
|
2018-09-20 09:22:45 +00:00
|
|
|
.subscribe(({ user, token }) => cb(null, user, null, token), cb);
|
2018-05-19 15:51:49 +00:00
|
|
|
} else {
|
|
|
|
return UserIdent.findOne$(query)
|
|
|
|
.flatMap(identity => {
|
2018-09-20 09:22:45 +00:00
|
|
|
return identity
|
|
|
|
? Observable.of(identity.user())
|
|
|
|
: User.findOne$({ where: { email } }).flatMap(user => {
|
|
|
|
return user
|
|
|
|
? Observable.of(user)
|
|
|
|
: User.create$({ email }).toPromise();
|
2018-05-19 15:51:49 +00:00
|
|
|
});
|
2018-06-28 14:57:15 +00:00
|
|
|
})
|
|
|
|
.flatMap(user => {
|
2018-09-20 09:22:45 +00:00
|
|
|
const createToken = observeQuery(AccessToken, 'create', {
|
|
|
|
userId: user.id,
|
|
|
|
created: new Date(),
|
|
|
|
ttl: user.constructor.settings.ttl
|
|
|
|
});
|
2018-11-12 16:58:34 +00:00
|
|
|
const updateUser = new Promise((resolve, reject) =>
|
|
|
|
user.updateAttributes(
|
|
|
|
{
|
|
|
|
email: email,
|
|
|
|
emailVerified: true,
|
|
|
|
emailAuthLinkTTL: null,
|
|
|
|
emailVerifyTTL: null
|
|
|
|
},
|
|
|
|
err => {
|
|
|
|
if (err) {
|
|
|
|
return reject(err);
|
|
|
|
}
|
|
|
|
return resolve();
|
|
|
|
}
|
|
|
|
)
|
|
|
|
);
|
2018-05-19 15:51:49 +00:00
|
|
|
return Observable.combineLatest(
|
2018-05-20 08:10:15 +00:00
|
|
|
Observable.of(user),
|
2018-05-19 15:51:49 +00:00
|
|
|
createToken,
|
2018-11-12 16:58:34 +00:00
|
|
|
Observable.fromPromise(updateUser),
|
2018-06-28 14:57:15 +00:00
|
|
|
(user, token) => ({ user, token })
|
2018-05-19 15:51:49 +00:00
|
|
|
);
|
|
|
|
})
|
2018-09-20 09:22:45 +00:00
|
|
|
.subscribe(({ user, token }) => cb(null, user, null, token), cb);
|
2018-05-19 15:51:49 +00:00
|
|
|
}
|
2015-08-13 02:08:05 +00:00
|
|
|
};
|
2015-08-04 21:52:06 +00:00
|
|
|
}
|