2015-10-02 18:47:36 +00:00
|
|
|
import _ from 'lodash';
|
2016-05-03 07:45:34 +00:00
|
|
|
import moment from 'moment';
|
|
|
|
import loopback from 'loopback';
|
|
|
|
import path from 'path';
|
2015-10-02 18:47:36 +00:00
|
|
|
import dedent from 'dedent';
|
|
|
|
import { Observable } from 'rx';
|
2016-02-10 04:54:49 +00:00
|
|
|
import debug from 'debug';
|
2015-10-02 18:47:36 +00:00
|
|
|
|
|
|
|
import {
|
|
|
|
ifNoUser401,
|
|
|
|
ifNoUserSend
|
|
|
|
} from '../utils/middleware';
|
|
|
|
|
2016-02-10 04:54:49 +00:00
|
|
|
import { observeQuery } from '../utils/rx';
|
2015-10-02 18:47:36 +00:00
|
|
|
|
2015-10-06 02:58:44 +00:00
|
|
|
import {
|
2015-12-09 22:34:33 +00:00
|
|
|
frontEndChallengeId,
|
2016-01-11 23:58:37 +00:00
|
|
|
dataVisChallengeId,
|
2015-12-09 22:34:33 +00:00
|
|
|
backEndChallengeId
|
2015-10-06 02:58:44 +00:00
|
|
|
} from '../utils/constantStrings.json';
|
|
|
|
|
2015-10-07 04:08:24 +00:00
|
|
|
import {
|
|
|
|
completeCommitment$
|
|
|
|
} from '../utils/commit';
|
|
|
|
|
2016-01-11 23:58:37 +00:00
|
|
|
import certTypes from '../utils/certTypes.json';
|
|
|
|
|
2016-01-27 19:34:44 +00:00
|
|
|
const log = debug('fcc:certification');
|
2016-05-03 07:45:34 +00:00
|
|
|
const renderCertifedEmail = loopback.template(path.join(
|
|
|
|
__dirname,
|
|
|
|
'..',
|
|
|
|
'views',
|
|
|
|
'emails',
|
|
|
|
'certified.ejs'
|
|
|
|
));
|
|
|
|
const renderNotifyEmail = loopback.template(path.join(
|
|
|
|
__dirname,
|
|
|
|
'..',
|
|
|
|
'views',
|
|
|
|
'emails',
|
|
|
|
'a-new-user.ejs'
|
|
|
|
));
|
2015-10-02 18:47:36 +00:00
|
|
|
const sendMessageToNonUser = ifNoUserSend(
|
|
|
|
'must be logged in to complete.'
|
|
|
|
);
|
|
|
|
|
2016-02-10 04:54:49 +00:00
|
|
|
function isCertified(ids, challengeMap = {}) {
|
|
|
|
return _.every(ids, ({ id }) => challengeMap[id]);
|
2015-10-02 18:47:36 +00:00
|
|
|
}
|
|
|
|
|
2016-01-11 23:58:37 +00:00
|
|
|
function getIdsForCert$(id, Challenge) {
|
|
|
|
return observeQuery(
|
2015-10-02 18:47:36 +00:00
|
|
|
Challenge,
|
|
|
|
'findById',
|
2016-01-11 23:58:37 +00:00
|
|
|
id,
|
2015-10-02 18:47:36 +00:00
|
|
|
{
|
2015-10-06 02:58:44 +00:00
|
|
|
id: true,
|
|
|
|
tests: true,
|
|
|
|
name: true,
|
|
|
|
challengeType: true
|
2015-10-02 18:47:36 +00:00
|
|
|
}
|
|
|
|
)
|
|
|
|
.shareReplay();
|
2016-01-11 23:58:37 +00:00
|
|
|
}
|
2015-10-02 18:47:36 +00:00
|
|
|
|
2016-05-03 07:45:34 +00:00
|
|
|
// getFormatedDate(challengeMap: Object, challengeId: String) => String, throws
|
|
|
|
function getFormatedDate(challengeMap, challengeId) {
|
|
|
|
return moment(challengeMap[challengeId].completedDate)
|
2016-05-31 02:20:49 +00:00
|
|
|
.format('MMMM D, YYYY');
|
2016-05-03 07:45:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// sendCertifiedEmail(
|
|
|
|
// {
|
|
|
|
// email: String,
|
|
|
|
// username: String,
|
|
|
|
// isFrontEndCert: Boolean,
|
|
|
|
// isBackEndCert: Boolean,
|
|
|
|
// isDataVisCert: Boolean
|
|
|
|
// },
|
|
|
|
// send$: Observable
|
|
|
|
// ) => Observable
|
|
|
|
function sendCertifiedEmail(
|
|
|
|
{
|
|
|
|
email,
|
|
|
|
name,
|
|
|
|
username,
|
|
|
|
isFrontEndCert,
|
|
|
|
isBackEndCert,
|
|
|
|
isDataVisCert,
|
|
|
|
challengeMap
|
|
|
|
},
|
|
|
|
send$
|
|
|
|
) {
|
|
|
|
if (
|
|
|
|
!isFrontEndCert ||
|
|
|
|
!isBackEndCert ||
|
|
|
|
!isDataVisCert
|
|
|
|
) {
|
|
|
|
return Observable.just(false);
|
|
|
|
}
|
|
|
|
let frontEndDate;
|
|
|
|
let backEndDate;
|
|
|
|
let dataVisDate;
|
|
|
|
try {
|
|
|
|
frontEndDate = getFormatedDate(challengeMap, frontEndChallengeId);
|
|
|
|
backEndDate = getFormatedDate(challengeMap, backEndChallengeId);
|
|
|
|
dataVisDate = getFormatedDate(challengeMap, dataVisChallengeId);
|
|
|
|
} catch (err) {
|
|
|
|
return Observable.throw(err);
|
|
|
|
}
|
|
|
|
|
|
|
|
const notifyTeam = {
|
|
|
|
type: 'email',
|
|
|
|
to: 'Michael@FreeCodeCamp.com',
|
|
|
|
from: 'Team@FreeCodeCamp.com',
|
|
|
|
subject: 'A new user has arrived!',
|
|
|
|
text: renderNotifyEmail({
|
|
|
|
username,
|
|
|
|
name,
|
|
|
|
frontEndDate,
|
|
|
|
dataVisDate,
|
|
|
|
backEndDate
|
|
|
|
})
|
|
|
|
};
|
|
|
|
const notifyUser = {
|
|
|
|
type: 'email',
|
|
|
|
to: email,
|
|
|
|
from: 'Michael@FreeCodeCamp.com',
|
|
|
|
subject: 'Congratulation on gaining your third certification!',
|
|
|
|
text: renderCertifedEmail({
|
|
|
|
username,
|
|
|
|
name
|
|
|
|
})
|
|
|
|
};
|
|
|
|
return Observable.combineLatest(
|
|
|
|
send$(notifyTeam),
|
|
|
|
send$(notifyUser),
|
|
|
|
() => true
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2016-01-11 23:58:37 +00:00
|
|
|
export default function certificate(app) {
|
|
|
|
const router = app.loopback.Router();
|
2016-05-03 07:45:34 +00:00
|
|
|
const { Email, Challenge } = app.models;
|
2016-01-11 23:58:37 +00:00
|
|
|
|
|
|
|
const certTypeIds = {
|
|
|
|
[certTypes.frontEnd]: getIdsForCert$(frontEndChallengeId, Challenge),
|
2016-01-12 00:23:24 +00:00
|
|
|
[certTypes.dataVis]: getIdsForCert$(dataVisChallengeId, Challenge),
|
|
|
|
[certTypes.backEnd]: getIdsForCert$(backEndChallengeId, Challenge)
|
2016-01-11 23:58:37 +00:00
|
|
|
};
|
2015-10-02 18:47:36 +00:00
|
|
|
|
|
|
|
router.post(
|
|
|
|
'/certificate/verify/front-end',
|
|
|
|
ifNoUser401,
|
2016-01-11 23:58:37 +00:00
|
|
|
verifyCert.bind(null, certTypes.frontEnd)
|
2015-10-02 18:47:36 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
router.post(
|
2015-12-09 22:34:33 +00:00
|
|
|
'/certificate/verify/back-end',
|
2015-10-02 18:47:36 +00:00
|
|
|
ifNoUser401,
|
2016-01-11 23:58:37 +00:00
|
|
|
verifyCert.bind(null, certTypes.backEnd)
|
|
|
|
);
|
|
|
|
|
|
|
|
router.post(
|
|
|
|
'/certificate/verify/data-visualization',
|
|
|
|
ifNoUser401,
|
|
|
|
verifyCert.bind(null, certTypes.dataVis)
|
2015-10-02 18:47:36 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
router.post(
|
|
|
|
'/certificate/honest',
|
|
|
|
sendMessageToNonUser,
|
|
|
|
postHonest
|
|
|
|
);
|
|
|
|
|
|
|
|
app.use(router);
|
|
|
|
|
2016-01-11 23:58:37 +00:00
|
|
|
function verifyCert(certType, req, res, next) {
|
2016-02-10 04:54:49 +00:00
|
|
|
const { user } = req;
|
2016-04-08 21:24:21 +00:00
|
|
|
return user.getChallengeMap$()
|
2016-04-07 04:08:19 +00:00
|
|
|
.flatMap(() => certTypeIds[certType])
|
2015-10-06 02:58:44 +00:00
|
|
|
.flatMap(challenge => {
|
|
|
|
const {
|
|
|
|
id,
|
|
|
|
tests,
|
|
|
|
name,
|
|
|
|
challengeType
|
|
|
|
} = challenge;
|
2015-10-02 18:47:36 +00:00
|
|
|
if (
|
2016-05-03 07:45:34 +00:00
|
|
|
user[certType] ||
|
|
|
|
!isCertified(tests, user.challengeMap)
|
2015-10-02 18:47:36 +00:00
|
|
|
) {
|
2016-05-03 07:45:34 +00:00
|
|
|
return Observable.just(false);
|
2015-10-02 18:47:36 +00:00
|
|
|
}
|
2016-05-03 07:45:34 +00:00
|
|
|
const updateData = {
|
|
|
|
$set: {
|
|
|
|
[`challengeMap.${id}`]: {
|
|
|
|
id,
|
|
|
|
name,
|
|
|
|
completedDate: new Date(),
|
|
|
|
challengeType
|
|
|
|
},
|
|
|
|
[certType]: true
|
|
|
|
}
|
|
|
|
};
|
|
|
|
// set here so sendCertifiedEmail works properly
|
|
|
|
// not used otherwise
|
|
|
|
user[certType] = true;
|
|
|
|
user.challengeMap[id] = { completedDate: new Date() };
|
|
|
|
return Observable.combineLatest(
|
|
|
|
// update user data
|
|
|
|
user.update$(updateData),
|
|
|
|
// If user has committed to nonprofit,
|
|
|
|
// this will complete their pledge
|
|
|
|
completeCommitment$(user),
|
|
|
|
// sends notification email is user has all three certs
|
|
|
|
// if not it noop
|
|
|
|
sendCertifiedEmail(user, Email.send$),
|
|
|
|
({ count }, pledgeOrMessage) => ({ count, pledgeOrMessage })
|
|
|
|
)
|
|
|
|
.map(
|
|
|
|
({ count, pledgeOrMessage }) => {
|
|
|
|
if (typeof pledgeOrMessage === 'string') {
|
|
|
|
log(pledgeOrMessage);
|
|
|
|
}
|
|
|
|
log(`${count} documents updated`);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
);
|
2015-10-02 18:47:36 +00:00
|
|
|
})
|
|
|
|
.subscribe(
|
2016-02-10 04:54:49 +00:00
|
|
|
(didCertify) => {
|
|
|
|
if (didCertify) {
|
2015-10-02 18:47:36 +00:00
|
|
|
return res.status(200).send(true);
|
|
|
|
}
|
|
|
|
return res.status(200).send(
|
|
|
|
dedent`
|
2015-10-07 09:22:04 +00:00
|
|
|
Looks like you have not completed the neccessary steps.
|
|
|
|
Please return to the challenge map.
|
2015-10-02 18:47:36 +00:00
|
|
|
`
|
|
|
|
);
|
|
|
|
},
|
|
|
|
next
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function postHonest(req, res, next) {
|
2016-02-10 04:54:49 +00:00
|
|
|
return req.user.update$({ $set: { isHonest: true } }).subscribe(
|
|
|
|
() => res.status(200).send(true),
|
|
|
|
next
|
|
|
|
);
|
2015-10-02 18:47:36 +00:00
|
|
|
}
|
|
|
|
}
|