From 279f953628e8d598362b19b61a367fe2d0b505fb Mon Sep 17 00:00:00 2001 From: Berkeley Martinez Date: Tue, 2 Jun 2015 15:05:26 -0700 Subject: [PATCH] Move models to common/models closes #795 --- app.js | 706 ------------------------- {models => common/models}/Bonfire.js | 3 - {models => common/models}/Challenge.js | 4 +- {models => common/models}/Comment.js | 8 - common/models/Courseware.js | 21 + common/models/FieldGuide.js | 18 + {models => common/models}/Job.js | 2 - common/models/Nonprofit.js | 27 + common/models/Story.js | 52 ++ common/models/User.js | 204 +++++++ config/passport.js | 6 +- controllers/challengeMap.js | 59 --- controllers/resources.js | 636 ---------------------- models/Courseware.js | 21 - models/FieldGuide.js | 19 - models/Nonprofit.js | 28 - models/Story.js | 53 -- models/User.js | 205 ------- server/boot/challenge.js | 8 +- server/boot/challengeMap.js | 4 +- server/boot/fieldGuide.js | 4 +- server/boot/home.js | 4 +- server/boot/jobs.js | 2 +- server/boot/nonprofits.js | 2 +- server/boot/story.js | 10 +- server/boot/user.js | 2 +- server/boot/utility.js | 12 +- server/resources/resources.js | 6 +- 28 files changed, 354 insertions(+), 1772 deletions(-) delete mode 100755 app.js rename {models => common/models}/Bonfire.js (88%) rename {models => common/models}/Challenge.js (79%) rename {models => common/models}/Comment.js (85%) create mode 100644 common/models/Courseware.js create mode 100644 common/models/FieldGuide.js rename {models => common/models}/Job.js (77%) create mode 100644 common/models/Nonprofit.js create mode 100644 common/models/Story.js create mode 100644 common/models/User.js delete mode 100644 controllers/challengeMap.js delete mode 100644 controllers/resources.js delete mode 100644 models/Courseware.js delete mode 100644 models/FieldGuide.js delete mode 100644 models/Nonprofit.js delete mode 100644 models/Story.js delete mode 100644 models/User.js diff --git a/app.js b/app.js deleted file mode 100755 index 97ee11c775..0000000000 --- a/app.js +++ /dev/null @@ -1,706 +0,0 @@ -require('dotenv').load(); -// handle uncaught exceptions. Forever will restart process on shutdown -process.on('uncaughtException', function (err) { - console.error( - (new Date()).toUTCString() + ' uncaughtException:', - err.message - ); - console.error(err.stack); - /* eslint-disable no-process-exit */ - process.exit(1); - /* eslint-enable no-process-exit */ -}); - -var express = require('express'), - accepts = require('accepts'), - cookieParser = require('cookie-parser'), - compress = require('compression'), - session = require('express-session'), - logger = require('morgan'), - errorHandler = require('errorhandler'), - methodOverride = require('method-override'), - bodyParser = require('body-parser'), - helmet = require('helmet'), - frameguard = require('frameguard'), - csp = require('helmet-csp'), - MongoStore = require('connect-mongo')(session), - flash = require('express-flash'), - path = require('path'), - mongoose = require('mongoose'), - passport = require('passport'), - expressValidator = require('express-validator'), - request = require('request'), - forceDomain = require('forcedomain'), - lessMiddleware = require('less-middleware'), - - /** - * Controllers (route handlers). - */ - homeController = require('./controllers/home'), - resourcesController = require('./controllers/resources'), - userController = require('./controllers/user'), - nonprofitController = require('./controllers/nonprofits'), - fieldGuideController = require('./controllers/fieldGuide'), - challengeMapController = require('./controllers/challengeMap'), - challengeController = require('./controllers/challenge'), - jobsController = require('./controllers/jobs'), - - /** - * Stories - */ - storyController = require('./controllers/story'), - - /** - * API keys and Passport configuration. - */ - secrets = require('./config/secrets'), - passportConf = require('./config/passport'); - -/** - * Create Express server. - */ -var app = express(); - -/** - * Connect to MongoDB. - */ -mongoose.connect(secrets.db); -mongoose.connection.on('error', function () { - console.error( - 'MongoDB Connection Error. Please make sure that MongoDB is running.' - ); -}); - -/** - * Express configuration. - */ - - -app.set('port', process.env.PORT || 3000); -app.set('views', path.join(__dirname, 'views')); -app.set('view engine', 'jade'); - -if (process.env.NODE_ENV === 'production') { - app.use(forceDomain({ - hostname: 'www.freecodecamp.com' - })); -} - -app.use(compress()); -app.use(lessMiddleware(__dirname + '/public')); -app.use(logger('dev')); -app.use(bodyParser.json()); -app.use(bodyParser.urlencoded({extended: true})); -app.use(expressValidator({ - customValidators: { - matchRegex: function (param, regex) { - return regex.test(param); - } - } -})); -app.use(methodOverride()); -app.use(cookieParser()); -app.use(session({ - resave: true, - saveUninitialized: true, - secret: secrets.sessionSecret, - store: new MongoStore({ - url: secrets.db, - 'autoReconnect': true - }) -})); -app.use(passport.initialize()); -app.use(passport.session()); -app.use(flash()); -app.disable('x-powered-by'); - -app.use(helmet.xssFilter()); -app.use(helmet.noSniff()); -app.use(helmet.frameguard()); -app.use(function(req, res, next) { - res.header('Access-Control-Allow-Origin', '*'); - res.header('Access-Control-Allow-Headers', - 'Origin, X-Requested-With, Content-Type, Accept' - ); - next(); -}); - -var trusted = [ - "'self'", - 'blob:', - '*.freecodecamp.com', - 'http://www.freecodecamp.com', - 'ws://freecodecamp.com/', - 'ws://www.freecodecamp.com/', - '*.gstatic.com', - '*.google-analytics.com', - '*.googleapis.com', - '*.google.com', - '*.gstatic.com', - '*.doubleclick.net', - '*.twitter.com', - '*.twitch.tv', - '*.twimg.com', - "'unsafe-eval'", - "'unsafe-inline'", - '*.bootstrapcdn.com', - '*.cloudflare.com', - 'https://*.cloudflare.com', - 'localhost:3001', - 'ws://localhost:3001/', - 'http://localhost:3001', - 'localhost:3000', - 'ws://localhost:3000/', - 'http://localhost:3000', - '*.ionicframework.com', - 'https://syndication.twitter.com', - '*.youtube.com', - '*.jsdelivr.net', - 'https://*.jsdelivr.net', - '*.ytimg.com', - '*.bitly.com', - 'http://cdn.inspectlet.com/', - 'wss://inspectletws.herokuapp.com/', - 'http://hn.inspectlet.com/' -]; - -app.use(helmet.csp({ - defaultSrc: trusted, - scriptSrc: [ - '*.optimizely.com', - '*.aspnetcdn.com', - '*.d3js.org' - ].concat(trusted), - 'connect-src': [ - ].concat(trusted), - styleSrc: trusted, - imgSrc: [ - /* allow all input since we have user submitted images for public profile*/ - '*' - ].concat(trusted), - fontSrc: ['*.googleapis.com'].concat(trusted), - mediaSrc: [ - '*.amazonaws.com', - '*.twitter.com' - ].concat(trusted), - frameSrc: [ - - '*.gitter.im', - '*.gitter.im https:', - '*.vimeo.com', - '*.twitter.com', - '*.ghbtns.com' - ].concat(trusted), - reportOnly: false, // set to true if you only want to report errors - setAllHeaders: false, // set to true if you want to set all headers - safari5: false // set to true if you want to force buggy CSP in Safari 5 -})); - -app.use(function (req, res, next) { - // Make user object available in templates. - res.locals.user = req.user; - next(); -}); - -app.use(express.static(__dirname + '/public', {maxAge: 86400000 })); - -app.use(function (req, res, next) { - // Remember original destination before login. - var path = req.path.split('/')[1]; - if (/auth|login|logout|signin|signup|fonts|favicon/i.test(path)) { - return next(); - } else if (/\/stories\/comments\/\w+/i.test(req.path)) { - return next(); - } - req.session.returnTo = req.path; - next(); -}); - -/** - * Main routes. - */ - -app.get('/', homeController.index); - -app.get('/nonprofit-project-instructions', function(req, res) { - res.redirect(301, '/field-guide/how-do-free-code-camp\'s-nonprofit-projects-work'); -}); - -app.post('/get-help', resourcesController.getHelp); - -app.post('/get-pair', resourcesController.getPair); - -app.get('/chat', resourcesController.chat); - -app.get('/twitch', resourcesController.twitch); - -app.get('/cats.json', function(req, res) { - res.send( - [ - { - "name": "cute", - "imageLink": "https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcRaP1ecF2jerISkdhjr4R9yM9-8ClUy-TA36MnDiFBukd5IvEME0g" - }, - { - "name": "grumpy", - "imageLink": "http://cdn.grumpycats.com/wp-content/uploads/2012/09/GC-Gravatar-copy.png" - }, - { - "name": "mischievous", - "imageLink": "http://www.kittenspet.com/wp-content/uploads/2012/08/cat_with_funny_face_3-200x200.jpg" - } - ] - ) -}); - -// Agile Project Manager Onboarding - -app.get('/pmi-acp-agile-project-managers', - resourcesController.agileProjectManagers); - -app.get('/agile', function(req, res) { - res.redirect(301, '/pmi-acp-agile-project-managers'); -}); - -app.get('/pmi-acp-agile-project-managers-form', - resourcesController.agileProjectManagersForm); - -// Nonprofit Onboarding - -app.get('/nonprofits', resourcesController.nonprofits); - -app.get('/nonprofits-form', resourcesController.nonprofitsForm); - -app.get('/map', - userController.userMigration, - challengeMapController.challengeMap -); - -app.get('/live-pair-programming', function(req, res) { - res.redirect(301, '/field-guide/live-stream-pair-programming-on-twitch.tv'); -}); - -app.get('/install-screenhero', function(req, res) { - res.redirect(301, '/field-guide/install-screenhero'); -}); - -app.get('/guide-to-our-nonprofit-projects', function(req, res) { - res.redirect(301, '/field-guide/a-guide-to-our-nonprofit-projects'); -}); - -app.get('/chromebook', function(req, res) { - res.redirect(301, '/field-guide/chromebook'); -}); - -app.get('/deploy-a-website', function(req, res) { - res.redirect(301, '/field-guide/deploy-a-website'); -}); - -app.get('/gmail-shortcuts', function(req, res) { - res.redirect(301, '/field-guide/gmail-shortcuts'); -}); - -app.get('/nodeschool-challenges', function(req, res) { - res.redirect(301, '/field-guide/nodeschool-challenges'); -}); - - -app.get('/learn-to-code', challengeMapController.challengeMap); -app.get('/about', function(req, res) { - res.redirect(301, '/map'); -}); -app.get('/signin', userController.getSignin); - -app.get('/login', function(req, res) { - res.redirect(301, '/signin'); -}); - -app.post('/signin', userController.postSignin); - -app.get('/signout', userController.signout); - -app.get('/logout', function(req, res) { - res.redirect(301, '/signout'); -}); - -app.get('/forgot', userController.getForgot); - -app.post('/forgot', userController.postForgot); - -app.get('/reset/:token', userController.getReset); - -app.post('/reset/:token', userController.postReset); - -app.get('/email-signup', userController.getEmailSignup); - -app.get('/email-signin', userController.getEmailSignin); - -app.post('/email-signup', userController.postEmailSignup); - -app.post('/email-signin', userController.postSignin); - -/** - * Nonprofit Project routes. - */ - -app.get('/nonprofits/directory', nonprofitController.nonprofitsDirectory); - -app.get( - '/nonprofits/:nonprofitName', - nonprofitController.returnIndividualNonprofit -); - -app.get( - '/jobs', - jobsController.jobsDirectory -); - -app.get( - '/jobs-form', - resourcesController.jobsForm -); - -app.get('/privacy', function(req, res) { - res.redirect(301, '/field-guide/what-is-the-free-code-camp-privacy-policy?'); -}); - -app.get('/submit-cat-photo', resourcesController.catPhotoSubmit); - -app.get('/api/slack', function(req, res) { - if (req.user) { - if (req.user.email) { - var invite = { - 'email': req.user.email, - 'token': process.env.SLACK_KEY, - 'set_active': true - }; - - var headers = { - 'User-Agent': 'Node Browser/0.0.1', - 'Content-Type': 'application/x-www-form-urlencoded' - }; - - var options = { - url: 'https://freecodecamp.slack.com/api/users.admin.invite', - method: 'POST', - headers: headers, - form: invite - }; - - request(options, function (error, response, body) { - if (!error && response.statusCode === 200) { - req.flash('success', { - msg: "We've successfully requested an invite for you. Please check your email and follow the instructions from Slack." - }); - req.user.sentSlackInvite = true; - req.user.save(function(err, user) { - if (err) { - next(err); - } - return res.redirect('back'); - }); - } else { - req.flash('errors', { - msg: "The invitation email did not go through for some reason. Please try again or -1; - }); - }); - - function numberWithCommas(x) { - return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ','); - } - - var date1 = new Date('10/15/2014'); - var date2 = new Date(); - var timeDiff = Math.abs(date2.getTime() - date1.getTime()); - var daysRunning = Math.ceil(timeDiff / (1000 * 3600 * 24)); - challengeList[0].completed[0] += - - User.count({}, function (err, camperCount) { - if (err) { - return next(err); - } - res.render('challengeMap/show', { - daysRunning: daysRunning, - camperCount: numberWithCommas(camperCount), - title: "A map of all Free Code Camp's Challenges", - challengeList: challengeList, - completedChallengeList: completedChallengeList - }); - }); - } -}; diff --git a/controllers/resources.js b/controllers/resources.js deleted file mode 100644 index 64f0289bd7..0000000000 --- a/controllers/resources.js +++ /dev/null @@ -1,636 +0,0 @@ -var async = require('async'), - path = require('path'), - moment = require('moment'), - Twit = require('twit'), - debug = require('debug')('freecc:cntr:resources'), - cheerio = require('cheerio'), - request = require('request'), - R = require('ramda'), - _ = require('lodash'), - fs = require('fs'), - - - constantStrings = require('./constantStrings.json'), - User = require('../models/User'), - Challenge = require('./../models/Challenge'), - Story = require('./../models/Story'), - FieldGuide = require('./../models/FieldGuide'), - Nonprofit = require('./../models/Nonprofit'), - Comment = require('./../models/Comment'), - resources = require('./resources.json'), - secrets = require('./../config/secrets'), - nonprofits = require('../seed_data/nonprofits.json'), - fieldGuides = require('../seed_data/field-guides.json'), - Slack = require('node-slack'), - slack = new Slack(secrets.slackHook); - -/** - * Cached values - */ -var allFieldGuideIds, allFieldGuideNames, allNonprofitNames, - challengeMap, challengeMapForDisplay, challengeMapWithIds, - challengeMapWithNames, allChallengeIds, allChallenges; - -/** - * GET / - * Resources. - */ - -Array.zip = function(left, right, combinerFunction) { - var counter, - results = []; - - for (counter = 0; counter < Math.min(left.length, right.length); counter++) { - results.push(combinerFunction(left[counter], right[counter])); - } - - return results; -}; - -(function() { - if (!challengeMap) { - var localChallengeMap = {}; - var files = fs.readdirSync( - path.join(__dirname, '/../seed_data/challenges') - ); - var keyCounter = 0; - files = files.map(function (file) { - return require( - path.join(__dirname, '/../seed_data/challenges/' + file) - ); - }); - files = files.sort(function (a, b) { - return a.order - b.order; - }); - files.forEach(function (file) { - localChallengeMap[keyCounter++] = file; - }); - challengeMap = _.cloneDeep(localChallengeMap); - } -})(); - - -module.exports = { - - getChallengeMapForDisplay: function() { - if (!challengeMapForDisplay) { - challengeMapForDisplay = {}; - Object.keys(challengeMap).forEach(function(key) { - challengeMapForDisplay[key] = { - name: challengeMap[key].name, - dashedName: challengeMap[key].name.replace(/\s/g, '-'), - challenges: challengeMap[key].challenges - } - }); - } - return challengeMapForDisplay; - }, - - getChallengeMapWithIds: function() { - if (!challengeMapWithIds) { - challengeMapWithIds = {}; - Object.keys(challengeMap).forEach(function (key) { - var onlyIds = challengeMap[key].challenges.map(function (elem) { - return elem._id; - }); - challengeMapWithIds[key] = onlyIds; - }); - } - return challengeMapWithIds; - }, - - allChallengeIds: function() { - - if (!allChallengeIds) { - allChallengeIds = []; - Object.keys(this.getChallengeMapWithIds()).forEach(function(key) { - allChallengeIds.push(challengeMapWithIds[key]); - }); - allChallengeIds = R.flatten(allChallengeIds); - } - return allChallengeIds; - }, - - allChallenges: function() { - if (!allChallenges) { - allChallenges = []; - Object.keys(this.getChallengeMapWithNames()).forEach(function(key) { - allChallenges.push(challengeMap[key].challenges); - }); - allChallenges = R.flatten(allChallenges); - } - return allChallenges; - }, - - getChallengeMapWithNames: function() { - if (!challengeMapWithNames) { - challengeMapWithNames = {}; - Object.keys(challengeMap). - forEach(function (key) { - var onlyNames = challengeMap[key].challenges.map(function (elem) { - return elem.name; - }); - challengeMapWithNames[key] = onlyNames; - }); - } - return challengeMapWithNames; - }, - - sitemap: function sitemap(req, res, next) { - var appUrl = 'http://www.freecodecamp.com'; - var now = moment(new Date()).format('YYYY-MM-DD'); - - - async.parallel({ - users: function(callback) { - User.aggregate() - .group({_id: 1, usernames: { $addToSet: '$profile.username'}}) - .match({'profile.username': { $ne: ''}}) - .exec(function(err, users) { - if (err) { - debug('User err: ', err); - callback(err); - } else { - callback(null, users[0].usernames); - } - }); - }, - - challenges: function (callback) { - Challenge.aggregate() - .group({_id: 1, names: { $addToSet: '$name'}}) - .exec(function (err, challenges) { - if (err) { - debug('Challenge err: ', err); - callback(err); - } else { - callback(null, challenges[0].names); - } - }); - }, - stories: function (callback) { - Story.aggregate() - .group({_id: 1, links: {$addToSet: '$link'}}) - .exec(function (err, stories) { - if (err) { - debug('Story err: ', err); - callback(err); - } else { - callback(null, stories[0].links); - } - }); - }, - nonprofits: function (callback) { - Nonprofit.aggregate() - .group({_id: 1, names: { $addToSet: '$name'}}) - .exec(function (err, nonprofits) { - if (err) { - debug('User err: ', err); - callback(err); - } else { - callback(null, nonprofits[0].names); - } - }); - }, - fieldGuides: function (callback) { - FieldGuide.aggregate() - .group({_id: 1, names: { $addToSet: '$name'}}) - .exec(function (err, fieldGuides) { - if (err) { - debug('User err: ', err); - callback(err); - } else { - callback(null, fieldGuides[0].names); - } - }); - } - }, function (err, results) { - if (err) { - return next(err); - } else { - setTimeout(function() { - res.header('Content-Type', 'application/xml'); - res.render('resources/sitemap', { - appUrl: appUrl, - now: now, - users: results.users, - challenges: results.challenges, - stories: results.stories, - nonprofits: results.nonprofits, - fieldGuides: results.fieldGuides - }); - }, 0); - } - } - ); - }, - - chat: function chat(req, res) { - if (req.user && req.user.progressTimestamps.length > 5) { - res.redirect('http://freecodecamp.slack.com'); - } else { - res.render('resources/chat', { - title: 'Watch us code live on Twitch.tv' - }); - } - }, - - jobsForm: function jobsForm(req, res) { - res.render('resources/jobs-form', { - title: 'Employer Partnership Form for Job Postings, Recruitment and Corporate Sponsorships' - }); - }, - - catPhotoSubmit: function catPhotoSubmit(req, res) { - res.send( - 'Success! You have submitted your cat photo. Return to your website ' + - 'by typing any letter into your code editor.' - ); - }, - - nonprofits: function nonprofits(req, res) { - res.render('resources/nonprofits', { - title: 'A guide to our Nonprofit Projects' - }); - }, - - nonprofitsForm: function nonprofitsForm(req, res) { - res.render('resources/nonprofits-form', { - title: 'Nonprofit Projects Proposal Form' - }); - }, - - agileProjectManagers: function agileProjectManagers(req, res) { - res.render('resources/pmi-acp-agile-project-managers', { - title: 'Get Agile Project Management Experience for the PMI-ACP' - }); - }, - - agileProjectManagersForm: function agileProjectManagersForm(req, res) { - res.render('resources/pmi-acp-agile-project-managers-form', { - title: 'Agile Project Management Program Application Form' - }); - }, - - twitch: function twitch(req, res) { - res.render('resources/twitch', { - title: "Enter Free Code Camp's Chat Rooms" - }); - }, - - unsubscribe: function unsubscribe(req, res, next) { - User.findOne({ email: req.params.email }, function(err, user) { - if (user) { - if (err) { - return next(err); - } - user.sendMonthlyEmail = false; - user.save(function () { - if (err) { - return next(err); - } - res.redirect('/unsubscribed'); - }); - } else { - res.redirect('/unsubscribed'); - } - }); - }, - - unsubscribed: function unsubscribed(req, res) { - res.render('resources/unsubscribed', { - title: 'You have been unsubscribed' - }); - }, - - githubCalls: function(req, res, next) { - var githubHeaders = { - headers: { - 'User-Agent': constantStrings.gitHubUserAgent - }, - port: 80 - }; - request( - [ - 'https://api.github.com/repos/freecodecamp/', - 'freecodecamp/pulls?client_id=', - secrets.github.clientID, - '&client_secret=', - secrets.github.clientSecret - ].join(''), - githubHeaders, - function(err, status1, pulls) { - if (err) { return next(err); } - pulls = pulls ? - Object.keys(JSON.parse(pulls)).length : - "Can't connect to github"; - - request( - [ - 'https://api.github.com/repos/freecodecamp/', - 'freecodecamp/issues?client_id=', - secrets.github.clientID, - '&client_secret=', - secrets.github.clientSecret - ].join(''), - githubHeaders, - function (err, status2, issues) { - if (err) { return next(err); } - issues = ((pulls === parseInt(pulls, 10)) && issues) ? - Object.keys(JSON.parse(issues)).length - pulls : - "Can't connect to GitHub"; - res.send({ - issues: issues, - pulls: pulls - }); - } - ); - } - ); - }, - - trelloCalls: function(req, res, next) { - request( - 'https://trello.com/1/boards/BA3xVpz9/cards?key=' + - secrets.trello.key, - function(err, status, trello) { - if (err) { return next(err); } - trello = (status && status.statusCode === 200) ? - (JSON.parse(trello)) : - "Can't connect to to Trello"; - - res.end(JSON.stringify(trello)); - }); - }, - - bloggerCalls: function(req, res, next) { - request( - 'https://www.googleapis.com/blogger/v3/blogs/2421288658305323950/' + - 'posts?key=' + - secrets.blogger.key, - function (err, status, blog) { - if (err) { return next(err); } - - blog = (status && status.statusCode === 200) ? - JSON.parse(blog) : - "Can't connect to Blogger"; - res.end(JSON.stringify(blog)); - } - ); - }, - - about: function(req, res, next) { - if (req.user) { - if ( - !req.user.profile.picture || - req.user.profile.picture.indexOf('apple-touch-icon-180x180.png') !== -1 - ) { - req.user.profile.picture = - 'https://s3.amazonaws.com/freecodecamp/camper-image-placeholder.png'; - // TODO(berks): unhandled callback - req.user.save(); - } - } - var date1 = new Date('10/15/2014'); - var date2 = new Date(); - - var timeDiff = Math.abs(date2.getTime() - date1.getTime()); - var daysRunning = Math.ceil(timeDiff / (1000 * 3600 * 24)); - var announcements = resources.announcements; - function numberWithCommas(x) { - return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ','); - } - User.count({}, function (err, c3) { - if (err) { - debug('User err: ', err); - return next(err); - } - - res.render('resources/learn-to-code', { - title: 'About Free Code Camp', - daysRunning: daysRunning, - c3: numberWithCommas(c3), - announcements: announcements - }); - }); - }, - - randomPhrase: function() { - return resources.phrases[ - Math.floor(Math.random() * resources.phrases.length) - ]; - }, - - randomVerb: function() { - return resources.verbs[ - Math.floor(Math.random() * resources.verbs.length) - ]; - }, - - randomCompliment: function() { - return resources.compliments[ - Math.floor(Math.random() * resources.compliments.length) - ]; - }, - - allFieldGuideIds: function() { - if (allFieldGuideIds) { - return allFieldGuideIds; - } else { - allFieldGuideIds = fieldGuides.map(function (elem) { - return elem._id; - }); - return allFieldGuideIds; - } - }, - - allFieldGuideNamesAndIds: function() { - if (allFieldGuideNames) { - return allFieldGuideNames; - } else { - allFieldGuideNames = fieldGuides.map(function (elem) { - return { - name: elem.name, - dashedName: elem.dashedName, - id: elem._id }; - }); - return allFieldGuideNames; - } - }, - - allNonprofitNames: function() { - if (allNonprofitNames) { - return allNonprofitNames; - } else { - allNonprofitNames = nonprofits.map(function (elem) { - return { name: elem.name }; - }); - return allNonprofitNames; - } - }, - - whichEnvironment: function() { - return process.env.NODE_ENV; - }, - - getURLTitle: function(url, callback) { - (function () { - var result = {title: '', image: '', url: '', description: ''}; - request(url, function (error, response, body) { - if (!error && response.statusCode === 200) { - var $ = cheerio.load(body); - var metaDescription = $("meta[name='description']"); - var metaImage = $("meta[property='og:image']"); - var urlImage = metaImage.attr('content') ? - metaImage.attr('content') : - ''; - - var metaTitle = $('title'); - var description = metaDescription.attr('content') ? - metaDescription.attr('content') : - ''; - - result.title = metaTitle.text().length < 90 ? - metaTitle.text() : - metaTitle.text().slice(0, 87) + '...'; - - result.image = urlImage; - result.description = description; - callback(null, result); - } else { - callback(new Error('failed')); - } - }); - })(); - }, - - updateUserStoryPictures: function(userId, picture, username, cb) { - - var counter = 0, - foundStories, - foundComments; - - Story.find({'author.userId': userId}, function(err, stories) { - if (err) { - return cb(err); - } - foundStories = stories; - counter++; - saveStoriesAndComments(); - }); - Comment.find({'author.userId': userId}, function(err, comments) { - if (err) { - return cb(err); - } - foundComments = comments; - counter++; - saveStoriesAndComments(); - }); - - function saveStoriesAndComments() { - if (counter !== 2) { - return; - } - var tasks = []; - R.forEach(function(comment) { - comment.author.picture = picture; - comment.author.username = username; - comment.markModified('author'); - tasks.push(function(cb) { - comment.save(cb); - }); - }, foundComments); - - R.forEach(function(story) { - story.author.picture = picture; - story.author.username = username; - story.markModified('author'); - tasks.push(function(cb) { - story.save(cb); - }); - }, foundStories); - async.parallel(tasks, function(err) { - if (err) { - return cb(err); - } - cb(); - }); - } - }, - codepenResources: { - twitter: function(req, res, next) { - // sends out random tweets about javascript - var T = new Twit({ - 'consumer_key': secrets.twitter.consumerKey, - 'consumer_secret': secrets.twitter.consumerSecret, - 'access_token': secrets.twitter.token, - 'access_token_secret': secrets.twitter.tokenSecret - }); - - var screenName; - if (req.params.screenName) { - screenName = req.params.screenName; - } else { - screenName = 'freecodecamp'; - } - - T.get( - 'statuses/user_timeline', - { - 'screen_name': screenName, - count: 10 - }, - function(err, data) { - if (err) { return next(err); } - return res.json(data); - } - ); - }, - twitterFCCStream: function() { - // sends out a tweet stream from FCC's account - }, - twitch: function() { - // exports information from the twitch account - }, - slack: function() { - - } - }, - - getHelp: function(req, res, next) { - var userName = req.user.profile.username; - var code = req.body.payload.code ? '\n```\n' + - req.body.payload.code + '\n```\n' - : ''; - var challenge = req.body.payload.challenge; - - slack.send({ - text: "*@" + userName + "* wants help with " + challenge + ". " + - code + "Hey, *@" + userName + "*, if no one helps you right " + - "away, try typing out your problem in detail to me. Like this: " + - "http://en.wikipedia.org/wiki/Rubber_duck_debugging", - channel: '#help', - username: "Debuggy the Rubber Duck", - icon_url: "https://pbs.twimg.com/profile_images/3609875545/569237541c920fa78d78902069615caf.jpeg" - }); - return res.sendStatus(200); - }, - - getPair: function(req, res, next) { - var userName = req.user.profile.username; - var challenge = req.body.payload.challenge; - slack.send({ - text: "Anyone want to pair with *@" + userName + "* on " + challenge + - "?\nMake sure you install Screen Hero here: " + - "http://freecodecamp.com/field-guide/how-do-i-install-screenhero\n" + - "Then start your pair program session with *@" + userName + - "* by typing \"/hero @" + userName + "\" into Slack.\n And *@"+ userName + - "*, be sure to launch Screen Hero, then keep coding. " + - "Another camper may pair with you soon.", - channel: '#letspair', - username: "Companion Cube", - icon_url: "https://lh3.googleusercontent.com/-f6xDPDV2rPE/AAAAAAAAAAI/AAAAAAAAAAA/mdlESXQu11Q/photo.jpg" - }); - return res.sendStatus(200); - } -}; diff --git a/models/Courseware.js b/models/Courseware.js deleted file mode 100644 index d760acdfd3..0000000000 --- a/models/Courseware.js +++ /dev/null @@ -1,21 +0,0 @@ -var mongoose = require('mongoose'); -var secrets = require('../config/secrets'); - -/** - * - * @type {exports.Schema} - */ - -var coursewareSchema = new mongoose.Schema({ - name: { - type: String, - unique: true - }, - difficulty: String, - description: Array, - tests: Array, - challengeSeed: Array, - challengeType: Number // 0 = html, 1 = javascript only, 2 = video, 3 = zipline, 4 = basejump -}); - -module.exports = mongoose.model('Courseware', coursewareSchema); diff --git a/models/FieldGuide.js b/models/FieldGuide.js deleted file mode 100644 index b9c2613eed..0000000000 --- a/models/FieldGuide.js +++ /dev/null @@ -1,19 +0,0 @@ -var mongoose = require('mongoose'); -var secrets = require('../config/secrets'); - -var fieldGuideSchema = new mongoose.Schema({ - name: { - type: String, - unique: false - }, - dashedName: { - type: String, - unique: false - }, - description: { - type: Array, - unique: false - } -}); - -module.exports = mongoose.model('FieldGuide', fieldGuideSchema); diff --git a/models/Nonprofit.js b/models/Nonprofit.js deleted file mode 100644 index 34443461da..0000000000 --- a/models/Nonprofit.js +++ /dev/null @@ -1,28 +0,0 @@ -var mongoose = require('mongoose'); -var secrets = require('../config/secrets'); - -/** - * - * @type {exports.Schema} - */ - -var Long = mongoose.Types.Long; -var nonprofitSchema = new mongoose.Schema({ - name: String, - requestedDeliverables: Array, - whatDoesNonprofitDo: String, - websiteLink: String, - stakeholderName: String, - stakeholderEmail: String, - endUser: String, - approvedDeliverables: Array, - projectDescription: String, - logoUrl: String, - imageUrl: String, - estimatedHours: 0, - interestedCampers: [], - confirmedCampers: [], - currentStatus: String // "confirmed", "started", "completed", "aborted" -}); - -module.exports = mongoose.model('Nonprofit', nonprofitSchema); diff --git a/models/Story.js b/models/Story.js deleted file mode 100644 index 7b60674845..0000000000 --- a/models/Story.js +++ /dev/null @@ -1,53 +0,0 @@ -var mongoose = require('mongoose'); -var secrets = require('../config/secrets'); - -var storySchema = new mongoose.Schema({ - headline: { - type: String, - unique: false - }, - timePosted: { - type: Number, - default: 0 - }, - link: { - type: String, - unique: false - }, - metaDescription: { - type: String, - default: '', - unique: false - }, - description: { - type: String, - unique: false - }, - originalStoryAuthorEmail: { - type: String, - default: '' - }, - rank: { - type: Number, - default: -Infinity - }, - upVotes: { - type: Array, - default: [] - }, - author: {}, - comments: { - type: Array, - default: [] - }, - image: { - type: String, - default: '' - }, - storyLink: { - type: String, - default: '' - } -}); - -module.exports = mongoose.model('Story', storySchema); diff --git a/models/User.js b/models/User.js deleted file mode 100644 index a9ffe11ffb..0000000000 --- a/models/User.js +++ /dev/null @@ -1,205 +0,0 @@ -var bcrypt = require('bcrypt-nodejs'); -var crypto = require('crypto'); -var mongoose = require('mongoose'); -require('mongoose-long')(mongoose); - -var Long = mongoose.Types.Long; -var userSchema = new mongoose.Schema({ - email: { - type: String, - lowercase: true, - trim: true, - sparse: true - }, - password: String, - facebook: String, - twitter: String, - google: String, - github: String, - linkedin: String, - tokens: Array, - progressTimestamps: { - type: Array, - default: [] - }, - profile: { - username: { - type: String, - sparse: true, - lowercase: true, - trim: true - }, - bio: { - type: String, - default: '' - }, - name: { - type: String, - default: '' - }, - gender: { - type: String, - default: '' - }, - location: { - type: String, - default: '' - }, - picture: { - type: String, - default: '' - }, - linkedinProfile: { - type: String, - default: '' - }, - githubProfile: { - type: String, - default: '' - }, - codepenProfile: { - type: String, - default: '' - }, - twitterHandle: { - type: String, - default: '' - }, - facebookProfile: { - type: String, - default: '' - } - }, - portfolio: { - website1Link: { - type: String, - default: '' - }, - website1Title: { - type: String, - default: '' - }, - website1Image: { - type: String, - default: '' - }, - website2Link: { - type: String, - default: '' - }, - website2Title: { - type: String, - default: '' - }, - website2Image: { - type: String, - default: '' - }, - website3Link: { - type: String, - default: '' - }, - website3Title: { - type: String, - default: '' - }, - website3Image: { - type: String, - default: '' - } - }, - resetPasswordToken: String, - sentSlackInvite: false, - resetPasswordExpires: Date, - uncompletedBonfires: Array, - completedBonfires: [ - { - _id: String, - name: String, - completedWith: String, - completedDate: Long, - solution: String - } - ], - uncompletedCoursewares: Array, - completedCoursewares: [ - { - completedDate: { - type: Long, - default: Date.now() - }, - _id: String, - name: String, - completedWith: String, - solution: String, - githubLink: String, - verified: Boolean - } - ], - completedFieldGuides: [], - uncompletedFieldGuides: [], - currentStreak: { - type: Number, - default: 0 - }, - longestStreak: { - type: Number, - default: 0 - }, - needsSomeDataModeled: { type: Boolean, default: false}, - - // needsMigration has been deprecated, use needsSomeDataModeled - needsMigration: { type: Boolean, default: true }, - sendMonthlyEmail: { type: Boolean, default: true }, - challengesHash: {}, - currentChallenge: {}, - completedChallenges: [ - { - completedDate: Long, - _id: String, - name: String, - completedWith: String, - solution: String, - githubLink: String, - verified: Boolean, - challengeType: { - type: Number, - default: 0 - } - } - ], - uncompletedChallenges: Array, -}); - -/** - * Password hashing Mongoose middleware. - */ - -userSchema.pre('save', function(next) { - var user = this; - - if (!user.isModified('password')) { return next(); } - - bcrypt.genSalt(5, function(err, salt) { - if (err) { return next(err); } - - bcrypt.hash(user.password, salt, null, function(err, hash) { - if (err) { return next(err); } - user.password = hash; - next(); - }); - }); -}); - -/** - * Helper method for validationg user's password. - */ - -userSchema.methods.comparePassword = function(candidatePassword, cb) { - bcrypt.compare(candidatePassword, this.password, function(err, isMatch) { - if (err) { return cb(err); } - cb(null, isMatch); - }); -}; - -module.exports = mongoose.model('User', userSchema); diff --git a/server/boot/challenge.js b/server/boot/challenge.js index 97cf181d98..b2bb53142c 100644 --- a/server/boot/challenge.js +++ b/server/boot/challenge.js @@ -32,11 +32,11 @@ var R = require('ramda'), express = require('express'), - Challenge = require('./../../models/Challenge'), - User = require('./../../models/User'), - resources = require('./../resources/resources'), + Challenge = require('../../common/models/Challenge'), + User = require('../../common/models/User'), + resources = require('../resources/resources'), userMigration = require('../resources/middleware').userMigration, - MDNlinks = require('./../../seed_data/bonfireMDNlinks'); + MDNlinks = require('../../seed_data/bonfireMDNlinks'); var router = express.Router(); var challengeMapWithNames = resources.getChallengeMapWithNames(); diff --git a/server/boot/challengeMap.js b/server/boot/challengeMap.js index b7ab297736..8d8bb727c9 100644 --- a/server/boot/challengeMap.js +++ b/server/boot/challengeMap.js @@ -1,9 +1,9 @@ var R = require('ramda'), + express = require('express'), // debug = require('debug')('freecc:cntr:challengeMap'), - User = require('../../models/User'), + User = require('../../common/models/User'), resources = require('./../resources/resources'), middleware = require('../resources/middleware'), - express = require('express'), router = express.Router(); router.get('/map', middleware.userMigration, challengeMap); diff --git a/server/boot/fieldGuide.js b/server/boot/fieldGuide.js index f70ca3ef32..7497a4440e 100644 --- a/server/boot/fieldGuide.js +++ b/server/boot/fieldGuide.js @@ -1,8 +1,8 @@ var R = require('ramda'), express = require('express'), // debug = require('debug')('freecc:fieldguides'), - FieldGuide = require('./../../models/FieldGuide'), - resources = require('./../resources/resources'); + FieldGuide = require('../../common/models/FieldGuide'), + resources = require('../resources/resources'); var router = express.Router(); diff --git a/server/boot/home.js b/server/boot/home.js index 9360c0823b..16cb3434a0 100644 --- a/server/boot/home.js +++ b/server/boot/home.js @@ -1,7 +1,7 @@ -var message = - 'Learn to Code JavaScript and get a Coding Job by Helping Nonprofits'; var express = require('express'); var router = express.Router(); +var message = + 'Learn to Code JavaScript and get a Coding Job by Helping Nonprofits'; router.get('/', index); diff --git a/server/boot/jobs.js b/server/boot/jobs.js index 52d0a5cab7..5cba0c2f64 100644 --- a/server/boot/jobs.js +++ b/server/boot/jobs.js @@ -1,5 +1,5 @@ var express = require('express'); -var Job = require('./../../models/Job'); +var Job = require('../../common/models/Job'); var router = express.Router(); router.get('/jobs', jobsDirectory); diff --git a/server/boot/nonprofits.js b/server/boot/nonprofits.js index 12e0dff04f..2fe25a6194 100644 --- a/server/boot/nonprofits.js +++ b/server/boot/nonprofits.js @@ -1,5 +1,5 @@ var express = require('express'), - Nonprofit = require('./../../models/Nonprofit'); + Nonprofit = require('../../common/models/Nonprofit'); var router = express.Router(); diff --git a/server/boot/story.js b/server/boot/story.js index f69a2a7f32..ef5fc134ac 100755 --- a/server/boot/story.js +++ b/server/boot/story.js @@ -2,12 +2,12 @@ var nodemailer = require('nodemailer'), sanitizeHtml = require('sanitize-html'), express = require('express'), moment = require('moment'), - // debug = require('debug')('freecc:cntr:story'), - Story = require('./../../models/Story'), - Comment = require('./../../models/Comment'), - User = require('./../../models/User'), - resources = require('./../resources/resources'), mongodb = require('mongodb'), + // debug = require('debug')('freecc:cntr:story'), + Story = require('../../common/models/Story'), + Comment = require('../../common/models/Comment'), + User = require('../../common/models/User'), + resources = require('../resources/resources'), MongoClient = mongodb.MongoClient, secrets = require('../../config/secrets'), router = express.Router(); diff --git a/server/boot/user.js b/server/boot/user.js index 074a403a0f..8d3f7f1cfb 100644 --- a/server/boot/user.js +++ b/server/boot/user.js @@ -8,7 +8,7 @@ var _ = require('lodash'), express = require('express'), debug = require('debug')('freecc:cntr:userController'), - User = require('../../models/User'), + User = require('../../common/models/User'), secrets = require('../../config/secrets'), resources = require('./../resources/resources'); diff --git a/server/boot/utility.js b/server/boot/utility.js index 0a561c73b1..84cb611630 100644 --- a/server/boot/utility.js +++ b/server/boot/utility.js @@ -7,12 +7,12 @@ var express = require('express'), debug = require('debug')('freecc:cntr:resources'), constantStrings = require('../resources/constantStrings.json'), - User = require('../../models/User'), - Challenge = require('./../../models/Challenge'), - Story = require('./../../models/Story'), - FieldGuide = require('./../../models/FieldGuide'), - Nonprofit = require('./../../models/Nonprofit'), - secrets = require('./../../config/secrets'); + User = require('../../common/models/User'), + Challenge = require('../../common/models/Challenge'), + Story = require('../../common/models/Story'), + FieldGuide = require('../../common/models/FieldGuide'), + Nonprofit = require('../../common/models/Nonprofit'), + secrets = require('../../config/secrets'); var slack = new Slack(secrets.slackHook); var router = express.Router(); diff --git a/server/resources/resources.js b/server/resources/resources.js index 35daef88c2..4cece5435e 100644 --- a/server/resources/resources.js +++ b/server/resources/resources.js @@ -1,6 +1,6 @@ var async = require('async'), path = require('path'), - debug = require('debug')('freecc:cntr:resources'), // eslint-disable-line + // debug = require('debug')('freecc:cntr:resources'), cheerio = require('cheerio'), request = require('request'), R = require('ramda'), @@ -8,8 +8,8 @@ var async = require('async'), fs = require('fs'), - Story = require('./../../models/Story'), - Comment = require('./../../models/Comment'), + Story = require('../../common/models/Story'), + Comment = require('../../common/models/Comment'), resources = require('./resources.json'), nonprofits = require('../../seed_data/nonprofits.json'), fieldGuides = require('../../seed_data/field-guides.json');