2018-06-12 15:50:35 +00:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* Any ref to fixCompletedChallengesItem should be removed post
|
|
|
|
* a db migration to fix all completedChallenges
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2015-08-10 05:14:31 +00:00
|
|
|
import _ from 'lodash';
|
2016-02-09 22:33:25 +00:00
|
|
|
import debug from 'debug';
|
2016-01-10 04:08:01 +00:00
|
|
|
import accepts from 'accepts';
|
2016-08-05 21:49:23 +00:00
|
|
|
import dedent from 'dedent';
|
2015-11-10 01:27:56 +00:00
|
|
|
|
2018-10-28 06:18:13 +00:00
|
|
|
import { homeLocation } from '../../../config/env.json';
|
|
|
|
|
2016-06-01 22:52:08 +00:00
|
|
|
import { ifNoUserSend } from '../utils/middleware';
|
2018-05-14 07:34:51 +00:00
|
|
|
import { dasherize } from '../utils';
|
|
|
|
import pathMigrations from '../resources/pathMigration.json';
|
2018-06-12 15:50:35 +00:00
|
|
|
import { fixCompletedChallengeItem } from '../../common/utils';
|
2015-08-10 05:14:31 +00:00
|
|
|
|
2016-08-04 17:49:37 +00:00
|
|
|
const log = debug('fcc:boot:challenges');
|
2015-08-10 05:14:31 +00:00
|
|
|
|
2018-10-28 06:18:13 +00:00
|
|
|
const learnURL = `${homeLocation}/learn`;
|
2018-05-14 07:34:51 +00:00
|
|
|
|
2018-06-12 15:50:35 +00:00
|
|
|
const jsProjects = [
|
2018-10-28 06:18:13 +00:00
|
|
|
'aaa48de84e1ecc7c742e1124',
|
|
|
|
'a7f4d8f2483413a6ce226cac',
|
|
|
|
'56533eb9ac21ba0edf2244e2',
|
|
|
|
'aff0395860f5d3034dc0bfc9',
|
|
|
|
'aa2e6f85cab2ab736c9a9b24'
|
2018-06-12 15:50:35 +00:00
|
|
|
];
|
|
|
|
|
2018-10-28 06:18:13 +00:00
|
|
|
function buildUserUpdate(user, challengeId, _completedChallenge, timezone) {
|
2018-06-12 15:50:35 +00:00
|
|
|
const { files } = _completedChallenge;
|
|
|
|
let completedChallenge = {};
|
|
|
|
|
|
|
|
if (jsProjects.includes(challengeId)) {
|
|
|
|
completedChallenge = {
|
|
|
|
..._completedChallenge,
|
|
|
|
files: Object.keys(files)
|
|
|
|
.map(key => files[key])
|
2018-10-28 06:18:13 +00:00
|
|
|
.map(file =>
|
|
|
|
_.pick(file, ['contents', 'key', 'index', 'name', 'path', 'ext'])
|
|
|
|
)
|
2018-06-12 15:50:35 +00:00
|
|
|
};
|
|
|
|
} else {
|
|
|
|
completedChallenge = _.omit(_completedChallenge, ['files']);
|
|
|
|
}
|
2016-02-09 22:33:25 +00:00
|
|
|
let finalChallenge;
|
2018-05-24 13:59:46 +00:00
|
|
|
const updateData = {};
|
2018-05-15 13:56:26 +00:00
|
|
|
const { timezone: userTimezone, completedChallenges = [] } = user;
|
2016-02-09 22:33:25 +00:00
|
|
|
|
2018-05-15 13:56:26 +00:00
|
|
|
const oldChallenge = _.find(
|
|
|
|
completedChallenges,
|
|
|
|
({ id }) => challengeId === id
|
|
|
|
);
|
2016-02-09 22:33:25 +00:00
|
|
|
const alreadyCompleted = !!oldChallenge;
|
|
|
|
|
|
|
|
if (alreadyCompleted) {
|
2017-09-08 07:16:02 +00:00
|
|
|
finalChallenge = {
|
2016-02-09 22:33:25 +00:00
|
|
|
...completedChallenge,
|
2018-05-15 13:56:26 +00:00
|
|
|
completedDate: oldChallenge.completedDate
|
2016-02-09 22:33:25 +00:00
|
|
|
};
|
2016-02-10 20:01:00 +00:00
|
|
|
} else {
|
2016-02-09 22:33:25 +00:00
|
|
|
updateData.$push = {
|
2018-05-15 13:56:26 +00:00
|
|
|
...updateData.$push,
|
|
|
|
progressTimestamps: Date.now()
|
2016-02-09 22:33:25 +00:00
|
|
|
};
|
2017-09-04 10:41:55 +00:00
|
|
|
finalChallenge = {
|
2018-05-15 13:56:26 +00:00
|
|
|
...completedChallenge
|
2017-09-04 10:41:55 +00:00
|
|
|
};
|
2015-06-21 02:52:37 +00:00
|
|
|
}
|
2015-10-02 04:44:24 +00:00
|
|
|
|
2018-05-24 13:59:46 +00:00
|
|
|
updateData.$set = {
|
|
|
|
completedChallenges: _.uniqBy(
|
2018-06-12 15:50:35 +00:00
|
|
|
[finalChallenge, ...completedChallenges.map(fixCompletedChallengeItem)],
|
2018-05-24 13:59:46 +00:00
|
|
|
'id'
|
|
|
|
)
|
2016-02-09 22:33:25 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
if (
|
2016-02-10 18:05:51 +00:00
|
|
|
timezone &&
|
2016-02-09 22:33:25 +00:00
|
|
|
timezone !== 'UTC' &&
|
|
|
|
(!userTimezone || userTimezone === 'UTC')
|
|
|
|
) {
|
|
|
|
updateData.$set = {
|
|
|
|
...updateData.$set,
|
|
|
|
timezone: userTimezone
|
|
|
|
};
|
|
|
|
}
|
2016-01-10 04:08:01 +00:00
|
|
|
|
2016-02-09 22:33:25 +00:00
|
|
|
log('user update data', updateData);
|
|
|
|
|
2016-08-11 23:41:03 +00:00
|
|
|
return {
|
|
|
|
alreadyCompleted,
|
|
|
|
updateData,
|
2018-05-15 13:56:26 +00:00
|
|
|
completedDate: finalChallenge.completedDate
|
2016-08-11 23:41:03 +00:00
|
|
|
};
|
2015-06-21 02:52:37 +00:00
|
|
|
}
|
|
|
|
|
2018-10-28 06:18:13 +00:00
|
|
|
function buildChallengeUrl(challenge) {
|
|
|
|
const { superBlock, block, dashedName } = challenge;
|
|
|
|
return `/learn/${dasherize(superBlock)}/${dasherize(block)}/${dashedName}`;
|
|
|
|
}
|
|
|
|
|
|
|
|
function getFirstChallenge(Challenge) {
|
|
|
|
return new Promise(resolve => {
|
|
|
|
Challenge.find(
|
|
|
|
{ where: { challengeOrder: 0, superOrder: 1, order: 0 } },
|
|
|
|
(err, challenge) => {
|
|
|
|
if (err) {
|
|
|
|
console.log(err);
|
|
|
|
return resolve('/learn');
|
|
|
|
}
|
|
|
|
return resolve(buildChallengeUrl(challenge));
|
|
|
|
}
|
|
|
|
);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
async function createChallengeUrlResolver(app) {
|
|
|
|
const { Challenge } = app.models;
|
|
|
|
const cache = new Map();
|
|
|
|
const firstChallenge = await getFirstChallenge(Challenge);
|
|
|
|
|
|
|
|
return function resolveChallengeUrl(id) {
|
|
|
|
return new Promise(resolve => {
|
|
|
|
if (cache.has(id)) {
|
|
|
|
return resolve(cache.get(id));
|
|
|
|
}
|
|
|
|
return Challenge.findById(id, (err, challenge) => {
|
|
|
|
if (err) {
|
|
|
|
console.log(err);
|
|
|
|
return firstChallenge;
|
|
|
|
}
|
|
|
|
const challengeUrl = buildChallengeUrl(challenge);
|
|
|
|
cache.set(id, challengeUrl);
|
|
|
|
return resolve(challengeUrl);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
export default async function bootChallenge(app, done) {
|
2015-08-10 05:14:31 +00:00
|
|
|
const send200toNonUser = ifNoUserSend(true);
|
2016-08-04 17:49:37 +00:00
|
|
|
const api = app.loopback.Router();
|
|
|
|
const router = app.loopback.Router();
|
2018-10-28 06:18:13 +00:00
|
|
|
const challengeUrlResolver = await createChallengeUrlResolver(app);
|
2015-06-22 23:43:31 +00:00
|
|
|
|
2016-08-04 17:49:37 +00:00
|
|
|
api.post(
|
2016-06-01 22:52:08 +00:00
|
|
|
'/modern-challenge-completed',
|
|
|
|
send200toNonUser,
|
|
|
|
modernChallengeCompleted
|
|
|
|
);
|
|
|
|
|
2016-06-08 18:26:33 +00:00
|
|
|
// deprecate endpoint
|
|
|
|
// remove once new endpoint is live
|
2018-10-28 06:18:13 +00:00
|
|
|
api.post('/completed-challenge', send200toNonUser, completedChallenge);
|
2016-06-01 22:52:08 +00:00
|
|
|
|
2018-10-28 06:18:13 +00:00
|
|
|
api.post('/challenge-completed', send200toNonUser, completedChallenge);
|
2016-06-08 18:26:33 +00:00
|
|
|
|
2016-06-08 18:11:13 +00:00
|
|
|
// deprecate endpoint
|
|
|
|
// remove once new endpoint is live
|
2016-08-04 17:49:37 +00:00
|
|
|
api.post(
|
2015-06-22 23:43:31 +00:00
|
|
|
'/completed-zipline-or-basejump',
|
|
|
|
send200toNonUser,
|
2016-06-08 18:11:13 +00:00
|
|
|
projectCompleted
|
|
|
|
);
|
|
|
|
|
2018-10-28 06:18:13 +00:00
|
|
|
api.post('/project-completed', send200toNonUser, projectCompleted);
|
2015-06-03 02:02:54 +00:00
|
|
|
|
2017-01-27 05:07:22 +00:00
|
|
|
api.post(
|
|
|
|
'/backend-challenge-completed',
|
|
|
|
send200toNonUser,
|
|
|
|
backendChallengeCompleted
|
|
|
|
);
|
|
|
|
|
2018-10-28 06:18:13 +00:00
|
|
|
router.get('/challenges/current-challenge', redirectToCurrentChallenge);
|
2016-08-04 17:49:37 +00:00
|
|
|
|
2018-05-14 07:34:51 +00:00
|
|
|
router.get('/challenges', redirectToLearn);
|
|
|
|
|
|
|
|
router.get('/challenges/*', redirectToLearn);
|
|
|
|
|
|
|
|
router.get('/map', redirectToLearn);
|
|
|
|
|
2016-08-04 17:49:37 +00:00
|
|
|
app.use(api);
|
2018-05-23 20:10:56 +00:00
|
|
|
app.use('/external', api);
|
2018-08-29 19:52:41 +00:00
|
|
|
app.use('/internal', api);
|
2018-05-15 05:12:05 +00:00
|
|
|
app.use(router);
|
2015-06-03 23:31:42 +00:00
|
|
|
|
2016-06-01 22:52:08 +00:00
|
|
|
function modernChallengeCompleted(req, res, next) {
|
|
|
|
const type = accepts(req).type('html', 'json', 'text');
|
|
|
|
req.checkBody('id', 'id must be an ObjectId').isMongoId();
|
2016-02-15 01:10:26 +00:00
|
|
|
|
2016-06-01 22:52:08 +00:00
|
|
|
const errors = req.validationErrors(true);
|
|
|
|
if (errors) {
|
|
|
|
if (type === 'json') {
|
|
|
|
return res.status(403).send({ errors });
|
|
|
|
}
|
2016-02-15 01:10:26 +00:00
|
|
|
|
2016-06-01 22:52:08 +00:00
|
|
|
log('errors', errors);
|
|
|
|
return res.sendStatus(403);
|
2016-01-15 09:44:18 +00:00
|
|
|
}
|
2016-02-15 01:10:26 +00:00
|
|
|
|
2016-06-01 22:52:08 +00:00
|
|
|
const user = req.user;
|
2018-10-28 06:18:13 +00:00
|
|
|
return user
|
|
|
|
.getCompletedChallenges$()
|
2016-06-01 22:52:08 +00:00
|
|
|
.flatMap(() => {
|
|
|
|
const completedDate = Date.now();
|
2018-10-28 06:18:13 +00:00
|
|
|
const { id, files } = req.body;
|
2016-02-15 01:10:26 +00:00
|
|
|
|
2018-10-28 06:18:13 +00:00
|
|
|
const { alreadyCompleted, updateData } = buildUserUpdate(user, id, {
|
2016-06-01 22:52:08 +00:00
|
|
|
id,
|
2018-10-28 06:18:13 +00:00
|
|
|
files,
|
|
|
|
completedDate
|
|
|
|
});
|
2016-02-15 01:10:26 +00:00
|
|
|
|
2016-06-01 22:52:08 +00:00
|
|
|
const points = alreadyCompleted ? user.points : user.points + 1;
|
2016-01-14 23:15:44 +00:00
|
|
|
|
2018-10-28 06:18:13 +00:00
|
|
|
return user
|
|
|
|
.update$(updateData)
|
2018-06-12 15:50:35 +00:00
|
|
|
.doOnNext(() => user.manualReload())
|
2016-06-01 22:52:08 +00:00
|
|
|
.doOnNext(({ count }) => log('%s documents updated', count))
|
|
|
|
.map(() => {
|
|
|
|
if (type === 'json') {
|
|
|
|
return res.json({
|
|
|
|
points,
|
2016-08-11 23:41:03 +00:00
|
|
|
alreadyCompleted,
|
2018-05-15 13:56:26 +00:00
|
|
|
completedDate
|
2016-01-14 23:15:44 +00:00
|
|
|
});
|
2016-06-01 22:52:08 +00:00
|
|
|
}
|
|
|
|
return res.sendStatus(200);
|
|
|
|
});
|
2016-01-14 23:15:44 +00:00
|
|
|
})
|
|
|
|
.subscribe(() => {}, next);
|
2015-05-16 04:39:43 +00:00
|
|
|
}
|
|
|
|
|
2015-06-03 02:02:54 +00:00
|
|
|
function completedChallenge(req, res, next) {
|
2016-03-31 03:58:38 +00:00
|
|
|
req.checkBody('id', 'id must be an ObjectId').isMongoId();
|
2016-01-10 04:08:01 +00:00
|
|
|
const type = accepts(req).type('html', 'json', 'text');
|
2016-02-11 06:10:06 +00:00
|
|
|
const errors = req.validationErrors(true);
|
|
|
|
|
|
|
|
if (errors) {
|
|
|
|
if (type === 'json') {
|
|
|
|
return res.status(403).send({ errors });
|
|
|
|
}
|
|
|
|
|
|
|
|
log('errors', errors);
|
|
|
|
return res.sendStatus(403);
|
|
|
|
}
|
|
|
|
|
2018-10-28 06:18:13 +00:00
|
|
|
return req.user
|
|
|
|
.getCompletedChallenges$()
|
2016-04-07 04:08:19 +00:00
|
|
|
.flatMap(() => {
|
|
|
|
const completedDate = Date.now();
|
2018-06-12 15:50:35 +00:00
|
|
|
const { id, solution, timezone, files } = req.body;
|
2016-04-07 04:08:19 +00:00
|
|
|
|
2018-10-28 06:18:13 +00:00
|
|
|
const { alreadyCompleted, updateData } = buildUserUpdate(
|
2016-04-07 04:08:19 +00:00
|
|
|
req.user,
|
|
|
|
id,
|
2018-06-12 15:50:35 +00:00
|
|
|
{ id, solution, completedDate, files },
|
2016-04-07 04:08:19 +00:00
|
|
|
timezone
|
|
|
|
);
|
|
|
|
|
|
|
|
const user = req.user;
|
|
|
|
const points = alreadyCompleted ? user.points : user.points + 1;
|
|
|
|
|
2018-10-28 06:18:13 +00:00
|
|
|
return user
|
|
|
|
.update$(updateData)
|
2016-04-07 04:08:19 +00:00
|
|
|
.doOnNext(({ count }) => log('%s documents updated', count))
|
|
|
|
.map(() => {
|
|
|
|
if (type === 'json') {
|
|
|
|
return res.json({
|
|
|
|
points,
|
2016-08-11 23:41:03 +00:00
|
|
|
alreadyCompleted,
|
2018-05-15 13:56:26 +00:00
|
|
|
completedDate
|
2016-04-07 04:08:19 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
return res.sendStatus(200);
|
|
|
|
});
|
|
|
|
})
|
|
|
|
.subscribe(() => {}, next);
|
2015-05-21 01:50:31 +00:00
|
|
|
}
|
2015-05-20 02:31:01 +00:00
|
|
|
|
2016-06-08 18:11:13 +00:00
|
|
|
function projectCompleted(req, res, next) {
|
2016-02-11 06:10:06 +00:00
|
|
|
const type = accepts(req).type('html', 'json', 'text');
|
|
|
|
req.checkBody('id', 'id must be an ObjectId').isMongoId();
|
2016-06-08 18:11:13 +00:00
|
|
|
req.checkBody('challengeType', 'must be a number').isNumber();
|
|
|
|
req.checkBody('solution', 'solution must be a URL').isURL();
|
2016-02-11 06:10:06 +00:00
|
|
|
|
|
|
|
const errors = req.validationErrors(true);
|
|
|
|
|
|
|
|
if (errors) {
|
|
|
|
if (type === 'json') {
|
|
|
|
return res.status(403).send({ errors });
|
2016-01-20 06:30:01 +00:00
|
|
|
}
|
2016-02-11 06:10:06 +00:00
|
|
|
log('errors', errors);
|
|
|
|
return res.sendStatus(403);
|
|
|
|
}
|
2015-06-03 02:02:54 +00:00
|
|
|
|
2016-02-11 06:10:06 +00:00
|
|
|
const { user, body = {} } = req;
|
2015-06-21 02:52:37 +00:00
|
|
|
|
2018-10-28 06:18:13 +00:00
|
|
|
const completedChallenge = _.pick(body, [
|
|
|
|
'id',
|
|
|
|
'solution',
|
|
|
|
'githubLink',
|
|
|
|
'challengeType',
|
|
|
|
'files'
|
|
|
|
]);
|
2016-02-11 06:10:06 +00:00
|
|
|
completedChallenge.completedDate = Date.now();
|
2015-06-21 02:52:37 +00:00
|
|
|
|
2016-01-20 06:30:01 +00:00
|
|
|
if (
|
|
|
|
!completedChallenge.solution ||
|
|
|
|
// only basejumps require github links
|
2018-10-28 06:18:13 +00:00
|
|
|
(completedChallenge.challengeType === 4 && !completedChallenge.githubLink)
|
2016-01-20 06:30:01 +00:00
|
|
|
) {
|
2018-01-12 22:16:33 +00:00
|
|
|
req.flash(
|
|
|
|
'danger',
|
2018-10-28 06:18:13 +00:00
|
|
|
"You haven't supplied the necessary URLs for us to inspect your work."
|
2018-01-12 22:16:33 +00:00
|
|
|
);
|
2015-06-03 02:02:54 +00:00
|
|
|
return res.sendStatus(403);
|
2015-05-20 02:31:01 +00:00
|
|
|
}
|
2015-05-21 07:17:44 +00:00
|
|
|
|
2018-10-28 06:18:13 +00:00
|
|
|
return user
|
|
|
|
.getCompletedChallenges$()
|
2017-01-27 05:07:22 +00:00
|
|
|
.flatMap(() => {
|
2018-10-28 06:18:13 +00:00
|
|
|
const { alreadyCompleted, updateData } = buildUserUpdate(
|
|
|
|
user,
|
|
|
|
completedChallenge.id,
|
|
|
|
completedChallenge
|
|
|
|
);
|
2017-01-27 05:07:22 +00:00
|
|
|
|
2018-10-28 06:18:13 +00:00
|
|
|
return user
|
|
|
|
.update$(updateData)
|
2018-06-12 15:50:35 +00:00
|
|
|
.doOnNext(() => user.manualReload())
|
2017-01-27 05:07:22 +00:00
|
|
|
.doOnNext(({ count }) => log('%s documents updated', count))
|
|
|
|
.doOnNext(() => {
|
|
|
|
if (type === 'json') {
|
|
|
|
return res.send({
|
|
|
|
alreadyCompleted,
|
|
|
|
points: alreadyCompleted ? user.points : user.points + 1,
|
2018-05-15 13:56:26 +00:00
|
|
|
completedDate: completedChallenge.completedDate
|
2017-01-27 05:07:22 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
return res.status(200).send(true);
|
|
|
|
});
|
|
|
|
})
|
|
|
|
.subscribe(() => {}, next);
|
|
|
|
}
|
|
|
|
|
|
|
|
function backendChallengeCompleted(req, res, next) {
|
|
|
|
const type = accepts(req).type('html', 'json', 'text');
|
|
|
|
req.checkBody('id', 'id must be an ObjectId').isMongoId();
|
|
|
|
req.checkBody('solution', 'solution must be a URL').isURL();
|
|
|
|
|
|
|
|
const errors = req.validationErrors(true);
|
|
|
|
|
|
|
|
if (errors) {
|
|
|
|
if (type === 'json') {
|
|
|
|
return res.status(403).send({ errors });
|
|
|
|
}
|
|
|
|
log('errors', errors);
|
|
|
|
return res.sendStatus(403);
|
|
|
|
}
|
|
|
|
|
|
|
|
const { user, body = {} } = req;
|
|
|
|
|
2018-10-28 06:18:13 +00:00
|
|
|
const completedChallenge = _.pick(body, ['id', 'solution']);
|
2017-01-27 05:07:22 +00:00
|
|
|
completedChallenge.completedDate = Date.now();
|
|
|
|
|
2018-10-28 06:18:13 +00:00
|
|
|
return user
|
|
|
|
.getCompletedChallenges$()
|
2016-04-07 04:08:19 +00:00
|
|
|
.flatMap(() => {
|
2018-10-28 06:18:13 +00:00
|
|
|
const { alreadyCompleted, updateData } = buildUserUpdate(
|
|
|
|
user,
|
|
|
|
completedChallenge.id,
|
|
|
|
completedChallenge
|
|
|
|
);
|
2016-04-07 04:08:19 +00:00
|
|
|
|
2018-10-28 06:18:13 +00:00
|
|
|
return user
|
|
|
|
.update$(updateData)
|
2016-04-07 04:08:19 +00:00
|
|
|
.doOnNext(({ count }) => log('%s documents updated', count))
|
|
|
|
.doOnNext(() => {
|
|
|
|
if (type === 'json') {
|
|
|
|
return res.send({
|
|
|
|
alreadyCompleted,
|
2016-08-11 23:41:03 +00:00
|
|
|
points: alreadyCompleted ? user.points : user.points + 1,
|
2018-05-15 13:56:26 +00:00
|
|
|
completedDate: completedChallenge.completedDate
|
2016-04-07 04:08:19 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
return res.status(200).send(true);
|
2016-02-11 06:10:06 +00:00
|
|
|
});
|
|
|
|
})
|
2016-01-20 06:30:01 +00:00
|
|
|
.subscribe(() => {}, next);
|
2015-05-20 02:31:01 +00:00
|
|
|
}
|
2016-08-04 17:49:37 +00:00
|
|
|
|
2018-10-28 06:18:13 +00:00
|
|
|
async function redirectToCurrentChallenge(req, res, next) {
|
2016-08-04 17:49:37 +00:00
|
|
|
const { user } = req;
|
2017-08-04 03:45:36 +00:00
|
|
|
const challengeId = user && user.currentChallengeId;
|
2018-10-28 06:18:13 +00:00
|
|
|
log(req.user.username);
|
|
|
|
log(challengeId);
|
|
|
|
const challengeUrl = await challengeUrlResolver(challengeId).catch(next);
|
|
|
|
log(challengeUrl);
|
|
|
|
if (challengeUrl === '/learn') {
|
|
|
|
// this should normally not be hit if database is properly seeded
|
|
|
|
throw new Error(dedent`
|
|
|
|
Attempted to find the url for ${challengeId}'
|
|
|
|
but came up empty.
|
|
|
|
db may not be properly seeded.
|
|
|
|
`);
|
|
|
|
}
|
|
|
|
return res.redirect(`${homeLocation}${challengeUrl}`);
|
2016-08-04 17:49:37 +00:00
|
|
|
}
|
2018-05-14 07:34:51 +00:00
|
|
|
|
|
|
|
function redirectToLearn(req, res) {
|
|
|
|
const maybeChallenge = _.last(req.path.split('/'));
|
|
|
|
if (maybeChallenge in pathMigrations) {
|
|
|
|
const redirectPath = pathMigrations[maybeChallenge];
|
2018-05-15 05:12:05 +00:00
|
|
|
return res.status(302).redirect(`${learnURL}${redirectPath}`);
|
2018-05-14 07:34:51 +00:00
|
|
|
}
|
2018-05-15 05:12:05 +00:00
|
|
|
return res.status(302).redirect(learnURL);
|
2018-05-14 07:34:51 +00:00
|
|
|
}
|
2018-10-28 06:18:13 +00:00
|
|
|
done();
|
2016-08-04 17:49:37 +00:00
|
|
|
}
|