Merge branch 'staging' into fix/normalize-flash-type
This commit is contained in:
@@ -6,8 +6,13 @@ import emoji from 'node-emoji';
|
||||
|
||||
import {
|
||||
frontEndChallengeId,
|
||||
dataVisChallengeId,
|
||||
backEndChallengeId
|
||||
backEndChallengeId,
|
||||
respWebDesignId,
|
||||
frontEndLibsId,
|
||||
jsAlgoDataStructId,
|
||||
dataVisId,
|
||||
apisMicroservicesId,
|
||||
infosecQaId
|
||||
} from '../utils/constantStrings.json';
|
||||
import certTypes from '../utils/certTypes.json';
|
||||
import {
|
||||
@@ -24,27 +29,44 @@ import {
|
||||
import supportedLanguages from '../../common/utils/supported-languages';
|
||||
import { getChallengeInfo, cachedMap } from '../utils/map';
|
||||
|
||||
const isSignUpDisabled = !!process.env.DISABLE_SIGNUP;
|
||||
const debug = debugFactory('fcc:boot:user');
|
||||
const sendNonUserToMap = ifNoUserRedirectTo('/map');
|
||||
const certIds = {
|
||||
[certTypes.frontEnd]: frontEndChallengeId,
|
||||
[certTypes.dataVis]: dataVisChallengeId,
|
||||
[certTypes.backEnd]: backEndChallengeId
|
||||
[certTypes.backEnd]: backEndChallengeId,
|
||||
[certTypes.respWebDesign]: respWebDesignId,
|
||||
[certTypes.frontEndLibs]: frontEndLibsId,
|
||||
[certTypes.jsAlgoDataStruct]: jsAlgoDataStructId,
|
||||
[certTypes.dataVis]: dataVisId,
|
||||
[certTypes.apisMicroservices]: apisMicroservicesId,
|
||||
[certTypes.infosecQa]: infosecQaId
|
||||
};
|
||||
|
||||
const certViews = {
|
||||
[certTypes.frontEnd]: 'certificate/front-end.jade',
|
||||
[certTypes.dataVis]: 'certificate/data-vis.jade',
|
||||
[certTypes.backEnd]: 'certificate/back-end.jade',
|
||||
[certTypes.fullStack]: 'certificate/full-stack.jade'
|
||||
[certTypes.fullStack]: 'certificate/full-stack.jade',
|
||||
[certTypes.respWebDesign]: 'certificate/responsive-web-design.jade',
|
||||
[certTypes.frontEndLibs]: 'certificate/front-end-libraries.jade',
|
||||
[certTypes.jsAlgoDataStruct]:
|
||||
'certificate/javascript-algorithms-and-data-structures.jade',
|
||||
[certTypes.dataVis]: 'certificate/data-visualization.jade',
|
||||
[certTypes.apisMicroservices]: 'certificate/apis-and-microservices.jade',
|
||||
[certTypes.infosecQa]:
|
||||
'certificate/information-security-and-quality-assurance.jade'
|
||||
};
|
||||
|
||||
const certText = {
|
||||
[certTypes.frontEnd]: 'Front End certified',
|
||||
[certTypes.dataVis]: 'Data Vis Certified',
|
||||
[certTypes.backEnd]: 'Back End Certified',
|
||||
[certTypes.fullStack]: 'Full Stack Certified'
|
||||
[certTypes.fullStack]: 'Full Stack Certified',
|
||||
[certTypes.respWebDesign]: 'Responsive Web Design Certified',
|
||||
[certTypes.frontEndLibs]: 'Front End Libraries Certified',
|
||||
[certTypes.jsAlgoDataStruct]:
|
||||
'JavaScript Algorithms and Data Structures Certified',
|
||||
[certTypes.dataVis]: 'Data Visualization Certified',
|
||||
[certTypes.apisMicroservices]: 'APIs and Microservices Certified',
|
||||
[certTypes.infosecQa]: 'Information Security and Quality Assurance Certified'
|
||||
};
|
||||
|
||||
const dateFormat = 'MMM DD, YYYY';
|
||||
@@ -139,7 +161,7 @@ function buildDisplayChallenges(
|
||||
module.exports = function(app) {
|
||||
const router = app.loopback.Router();
|
||||
const api = app.loopback.Router();
|
||||
const { AccessToken, Email, User } = app.models;
|
||||
const { Email, User } = app.models;
|
||||
const map$ = cachedMap(app.models);
|
||||
|
||||
function findUserByUsername$(username, fields) {
|
||||
@@ -153,23 +175,6 @@ module.exports = function(app) {
|
||||
);
|
||||
}
|
||||
|
||||
AccessToken.findOne$ = Observable.fromNodeCallback(
|
||||
AccessToken.findOne, AccessToken
|
||||
);
|
||||
|
||||
router.get('/login', function(req, res) {
|
||||
res.redirect(301, '/signin');
|
||||
});
|
||||
router.get('/logout', function(req, res) {
|
||||
res.redirect(301, '/signout');
|
||||
});
|
||||
router.get('/signup', getEmailSignin);
|
||||
router.get('/signin', getEmailSignin);
|
||||
router.get('/signout', signout);
|
||||
router.get('/email-signin', getEmailSignin);
|
||||
router.get('/deprecated-signin', getDepSignin);
|
||||
router.get('/passwordless-auth', invalidateAuthToken, getPasswordlessAuth);
|
||||
api.post('/passwordless-auth', postPasswordlessAuth);
|
||||
router.get(
|
||||
'/delete-my-account',
|
||||
sendNonUserToMap,
|
||||
@@ -208,11 +213,6 @@ module.exports = function(app) {
|
||||
showCert.bind(null, certTypes.frontEnd)
|
||||
);
|
||||
|
||||
api.get(
|
||||
'/:username/data-visualization-certification',
|
||||
showCert.bind(null, certTypes.dataVis)
|
||||
);
|
||||
|
||||
api.get(
|
||||
'/:username/back-end-certification',
|
||||
showCert.bind(null, certTypes.backEnd)
|
||||
@@ -223,6 +223,36 @@ module.exports = function(app) {
|
||||
(req, res) => res.redirect(req.url.replace('full-stack', 'back-end'))
|
||||
);
|
||||
|
||||
api.get(
|
||||
'/:username/responsive-web-design-certification',
|
||||
showCert.bind(null, certTypes.respWebDesign)
|
||||
);
|
||||
|
||||
api.get(
|
||||
'/:username/front-end-libraries-certification',
|
||||
showCert.bind(null, certTypes.frontEndLibs)
|
||||
);
|
||||
|
||||
api.get(
|
||||
'/:username/javascript-algorithms-data-structures-certification',
|
||||
showCert.bind(null, certTypes.jsAlgoDataStruct)
|
||||
);
|
||||
|
||||
api.get(
|
||||
'/:username/data-visualization-certification',
|
||||
showCert.bind(null, certTypes.dataVis)
|
||||
);
|
||||
|
||||
api.get(
|
||||
'/:username/apis-microservices-certification',
|
||||
showCert.bind(null, certTypes.apisMicroservices)
|
||||
);
|
||||
|
||||
api.get(
|
||||
'/:username/information-security-quality-assurance-certification',
|
||||
showCert.bind(null, certTypes.infosecQa)
|
||||
);
|
||||
|
||||
router.get('/:username', showUserProfile);
|
||||
router.get(
|
||||
'/:username/report-user/',
|
||||
@@ -240,179 +270,6 @@ module.exports = function(app) {
|
||||
app.use('/:lang', router);
|
||||
app.use(api);
|
||||
|
||||
const defaultErrorMsg = [ 'Oops, something is not right, please request a ',
|
||||
'fresh link to sign in / sign up.' ].join('');
|
||||
|
||||
function postPasswordlessAuth(req, res) {
|
||||
if (req.user || !(req.body && req.body.email)) {
|
||||
return res.redirect('/');
|
||||
}
|
||||
|
||||
return User.requestAuthEmail(req.body.email)
|
||||
.then(msg => {
|
||||
return res.status(200).send({ message: msg });
|
||||
})
|
||||
.catch(err => {
|
||||
debug(err);
|
||||
return res.status(200).send({ message: defaultErrorMsg });
|
||||
});
|
||||
}
|
||||
|
||||
function invalidateAuthToken(req, res, next) {
|
||||
if (req.user) {
|
||||
res.redirect('/');
|
||||
}
|
||||
|
||||
if (!req.query || !req.query.email || !req.query.token) {
|
||||
req.flash('info', { msg: defaultErrorMsg });
|
||||
return res.redirect('/email-signin');
|
||||
}
|
||||
|
||||
const authTokenId = req.query.token;
|
||||
const authEmailId = new Buffer(req.query.email, 'base64').toString();
|
||||
|
||||
return AccessToken.findOne$({ where: {id: authTokenId} })
|
||||
.map(authToken => {
|
||||
if (!authToken) {
|
||||
req.flash('info', { msg: defaultErrorMsg });
|
||||
return res.redirect('/email-signin');
|
||||
}
|
||||
|
||||
const userId = authToken.userId;
|
||||
return User.findById(userId, (err, user) => {
|
||||
if (err || !user || user.email !== authEmailId) {
|
||||
debug(err);
|
||||
req.flash('info', { msg: defaultErrorMsg });
|
||||
return res.redirect('/email-signin');
|
||||
}
|
||||
return authToken.validate((err, isValid) => {
|
||||
if (err) { throw err; }
|
||||
if (!isValid) {
|
||||
req.flash('info', { msg: [ 'Looks like the link you clicked has',
|
||||
'expired, please request a fresh link, to sign in.'].join('')
|
||||
});
|
||||
return res.redirect('/email-signin');
|
||||
}
|
||||
return authToken.destroy((err) => {
|
||||
if (err) { debug(err); }
|
||||
next();
|
||||
});
|
||||
});
|
||||
});
|
||||
})
|
||||
.subscribe(
|
||||
() => {},
|
||||
next
|
||||
);
|
||||
}
|
||||
|
||||
function getPasswordlessAuth(req, res, next) {
|
||||
if (req.user) {
|
||||
req.flash('info', {
|
||||
msg: 'Hey, looks like you’re already signed in.'
|
||||
});
|
||||
return res.redirect('/');
|
||||
}
|
||||
|
||||
if (!req.query || !req.query.email || !req.query.token) {
|
||||
req.flash('info', { msg: defaultErrorMsg });
|
||||
return res.redirect('/email-signin');
|
||||
}
|
||||
|
||||
const email = new Buffer(req.query.email, 'base64').toString();
|
||||
|
||||
return User.findOne$({ where: { email }})
|
||||
.map(user => {
|
||||
|
||||
if (!user) {
|
||||
debug(`did not find a valid user with email: ${email}`);
|
||||
req.flash('info', { msg: defaultErrorMsg });
|
||||
return res.redirect('/email-signin');
|
||||
}
|
||||
|
||||
const emailVerified = true;
|
||||
const emailAuthLinkTTL = null;
|
||||
const emailVerifyTTL = null;
|
||||
user.update$({
|
||||
emailVerified, emailAuthLinkTTL, emailVerifyTTL
|
||||
})
|
||||
.do((user) => {
|
||||
user.emailVerified = emailVerified;
|
||||
user.emailAuthLinkTTL = emailAuthLinkTTL;
|
||||
user.emailVerifyTTL = emailVerifyTTL;
|
||||
});
|
||||
|
||||
return user.createAccessToken(
|
||||
{ ttl: User.settings.ttl }, (err, accessToken) => {
|
||||
if (err) { throw err; }
|
||||
|
||||
var config = {
|
||||
signed: !!req.signedCookies,
|
||||
maxAge: accessToken.ttl
|
||||
};
|
||||
|
||||
if (accessToken && accessToken.id) {
|
||||
debug('setting cookies');
|
||||
res.cookie('access_token', accessToken.id, config);
|
||||
res.cookie('userId', accessToken.userId, config);
|
||||
}
|
||||
|
||||
return req.logIn({
|
||||
id: accessToken.userId.toString() }, err => {
|
||||
if (err) { return next(err); }
|
||||
|
||||
debug('user logged in');
|
||||
|
||||
if (req.session && req.session.returnTo) {
|
||||
var redirectTo = req.session.returnTo;
|
||||
if (redirectTo === '/map-aside') {
|
||||
redirectTo = '/map';
|
||||
}
|
||||
return res.redirect(redirectTo);
|
||||
}
|
||||
|
||||
req.flash('success', { msg:
|
||||
'Success! You have signed in to your account. Happy Coding!'
|
||||
});
|
||||
return res.redirect('/');
|
||||
});
|
||||
});
|
||||
})
|
||||
.subscribe(
|
||||
() => {},
|
||||
next
|
||||
);
|
||||
}
|
||||
|
||||
function signout(req, res) {
|
||||
req.logout();
|
||||
res.redirect('/');
|
||||
}
|
||||
|
||||
|
||||
function getDepSignin(req, res) {
|
||||
if (req.user) {
|
||||
return res.redirect('/');
|
||||
}
|
||||
return res.render('account/deprecated-signin', {
|
||||
title: 'Sign in to freeCodeCamp using a Deprecated Login'
|
||||
});
|
||||
}
|
||||
|
||||
function getEmailSignin(req, res) {
|
||||
if (req.user) {
|
||||
return res.redirect('/');
|
||||
}
|
||||
if (isSignUpDisabled) {
|
||||
return res.render('account/beta', {
|
||||
title: 'New sign ups are disabled'
|
||||
});
|
||||
}
|
||||
return res.render('account/email-signin', {
|
||||
title: 'Sign in to freeCodeCamp using your Email Address'
|
||||
});
|
||||
}
|
||||
|
||||
function getAccount(req, res) {
|
||||
const { username } = req.user;
|
||||
return res.redirect('/' + username);
|
||||
@@ -586,9 +443,14 @@ module.exports = function(app) {
|
||||
isLocked: true,
|
||||
isAvailableForHire: true,
|
||||
isFrontEndCert: true,
|
||||
isDataVisCert: true,
|
||||
isBackEndCert: true,
|
||||
isFullStackCert: true,
|
||||
isRespWebDesignCert: true,
|
||||
isFrontEndLibsCert: true,
|
||||
isJsAlgoDataStructCert: true,
|
||||
isDataVisCert: true,
|
||||
isApisMicroservicesCert: true,
|
||||
isInfosecQaCert: true,
|
||||
isHonest: true,
|
||||
username: true,
|
||||
name: true,
|
||||
|
||||
Reference in New Issue
Block a user