freeCodeCamp/api-server/common/models/User-Identity.js

155 lines
4.2 KiB
JavaScript
Raw Normal View History

import { Observable } from 'rx';
// import debug from 'debug';
import dedent from 'dedent';
import { isEmail } from 'validator';
import { observeMethod, observeQuery } from '../../server/utils/rx';
import { wrapHandledError } from '../../server/utils/create-handled-error.js';
// const log = debug('fcc:models:userIdent');
2015-08-04 21:52:06 +00:00
export default function(UserIdent) {
UserIdent.on('dataSourceAttached', () => {
UserIdent.findOne$ = observeMethod(UserIdent, 'findOne');
});
UserIdent.login = function(
_provider,
authScheme,
profile,
credentials,
options,
cb
) {
const User = UserIdent.app.models.User;
const AccessToken = UserIdent.app.models.AccessToken;
options = options || {};
if (typeof options === 'function' && !cb) {
cb = options;
options = {};
}
// get the social provider data and the external id from auth0
profile.id = profile.id || profile.openid;
const auth0IdString = '' + profile.id;
2018-06-29 20:01:56 +00:00
const [ provider, socialExtId ] = auth0IdString.split('|');
const query = {
where: {
provider: provider,
externalId: socialExtId
},
include: 'user'
};
// get the email from the auth0 (its expected from social providers)
const email = (profile && profile.emails && profile.emails[0]) ?
profile.emails[0].value : '';
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
if (provider === 'email') {
2018-05-19 15:51:49 +00:00
return User.findOne$({ where: { email } })
.flatMap(user => {
return user ?
Observable.of(user) :
User.create$({ email }).toPromise();
})
.flatMap(user => {
if (!user) {
throw wrapHandledError(
2018-05-22 16:26:12 +00:00
new Error('could not find or create a user'),
{
message: dedent`
Oops... something is not right. We could not find or create a
user with that email.
`,
type: 'info',
redirectTo: '/'
}
);
}
const createToken = observeQuery(
AccessToken,
'create',
{
userId: user.id,
created: new Date(),
ttl: user.constructor.settings.ttl
}
);
const updateUser = user.update$({
emailVerified: true,
emailAuthLinkTTL: null,
emailVerifyTTL: null
});
return Observable.combineLatest(
Observable.of(user),
createToken,
updateUser,
(user, token) => ({user, token})
);
2018-05-19 15:51:49 +00:00
})
.subscribe(
({ user, token }) => cb(null, user, null, token),
2018-05-19 15:51:49 +00:00
cb
);
} else {
2018-05-20 08:10:15 +00:00
2018-05-19 15:51:49 +00:00
return UserIdent.findOne$(query)
.flatMap(identity => {
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
});
})
.flatMap(user => {
2018-05-19 15:51:49 +00:00
const createToken = observeQuery(
AccessToken,
'create',
{
2018-05-19 15:51:49 +00:00
userId: user.id,
created: new Date(),
ttl: user.constructor.settings.ttl
}
2018-05-19 15:51:49 +00:00
);
const updateUser = user.update$({
email: email,
emailVerified: true,
emailAuthLinkTTL: null,
emailVerifyTTL: null
});
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,
updateUser,
(user, token) => ({ user, token })
2018-05-19 15:51:49 +00:00
);
})
.subscribe(
({ user, token }) => cb(null, user, null, token),
2018-05-19 15:51:49 +00:00
cb
);
2018-05-19 15:51:49 +00:00
}
};
2015-08-04 21:52:06 +00:00
}