codecombat/server/middleware/users.coffee
Matt Lott 63e38c82b2 Update school counts page with geoip and 10+ buckets
Placing teachers and students in unknown districts and schools if we
have geoip countries and states/regions.
Placing teachers/students in unknown schools if there are 10+ students.
2016-06-29 15:01:04 -07:00

119 lines
4.8 KiB
CoffeeScript

_ = require 'lodash'
co = require 'co'
countryList = require('country-list')()
errors = require '../commons/errors'
geoip = require 'geoip-lite'
wrap = require 'co-express'
Promise = require 'bluebird'
parse = require '../commons/parse'
request = require 'request'
mongoose = require 'mongoose'
sendwithus = require '../sendwithus'
User = require '../models/User'
Classroom = require '../models/Classroom'
module.exports =
fetchByGPlusID: wrap (req, res, next) ->
gpID = req.query.gplusID
gpAT = req.query.gplusAccessToken
return next() unless gpID and gpAT
dbq = User.find()
dbq.select(parse.getProjectFromReq(req))
url = "https://www.googleapis.com/oauth2/v2/userinfo?access_token=#{gpAT}"
[googleRes, body] = yield request.getAsync(url, {json: true})
idsMatch = gpID is body.id
throw new errors.UnprocessableEntity('Invalid G+ Access Token.') unless idsMatch
user = yield User.findOne({gplusID: gpID})
throw new errors.NotFound('No user with that G+ ID') unless user
res.status(200).send(user.toObject({req: req}))
fetchByFacebookID: wrap (req, res, next) ->
fbID = req.query.facebookID
fbAT = req.query.facebookAccessToken
return next() unless fbID and fbAT
dbq = User.find()
dbq.select(parse.getProjectFromReq(req))
url = "https://graph.facebook.com/me?access_token=#{fbAT}"
[facebookRes, body] = yield request.getAsync(url, {json: true})
idsMatch = fbID is body.id
throw new errors.UnprocessableEntity('Invalid Facebook Access Token.') unless idsMatch
user = yield User.findOne({facebookID: fbID})
throw new errors.NotFound('No user with that Facebook ID') unless user
res.status(200).send(user.toObject({req: req}))
removeFromClassrooms: wrap (req, res, next) ->
yield req.user.removeFromClassrooms()
next()
remainTeacher: wrap (req, res, next) ->
yield req.user.removeFromClassrooms()
user = yield User.findById req.user.id
res.status(200).send(user.toObject({req: req}))
becomeStudent: wrap (req, res, next) ->
userID = mongoose.Types.ObjectId(req.user.id)
yield Classroom.remove({ ownerID: userID }, false)
userID = mongoose.Types.ObjectId(req.user.id)
yield User.update({ _id: userID }, { $set: { "role": "student" } })
user = yield User.findById req.user.id
res.status(200).send(user.toObject({req: req}))
verifyEmailAddress: wrap (req, res, next) ->
user = yield User.findOne({ _id: mongoose.Types.ObjectId(req.params.userID) })
[timestamp, hash] = req.params.verificationCode.split(':')
unless user
throw new errors.UnprocessableEntity('User not found')
unless req.params.verificationCode is user.verificationCode(timestamp)
throw new errors.UnprocessableEntity('Verification code does not match')
yield User.update({ _id: user.id }, { emailVerified: true })
res.status(200).send({ role: user.get('role') })
resetEmailVerifiedFlag: wrap (req, res, next) ->
newEmail = req.body.email
_id = mongoose.Types.ObjectId(req.body._id)
if newEmail
user = yield User.findOne({ _id })
oldEmail = user.get('email')
if newEmail isnt oldEmail
yield User.update({ _id }, { $set: { emailVerified: false } })
next()
sendVerificationEmail: wrap (req, res, next) ->
user = yield User.findById(req.params.userID)
timestamp = (new Date).getTime()
if not user
throw new errors.NotFound('User not found')
context =
email_id: sendwithus.templates.verify_email
recipient:
address: user.get('email')
name: user.broadName()
email_data:
name: user.broadName()
verify_link: "http://codecombat.com/user/#{user._id}/verify/#{user.verificationCode(timestamp)}"
sendwithus.api.send context, (err, result) ->
res.status(200).send({})
getStudents: wrap (req, res, next) ->
throw new errors.Unauthorized('You must be an administrator.') unless req.user?.isAdmin()
query = $or: [{role: 'student'}, {$and: [{schoolName: {$exists: true}}, {schoolName: {$ne: ''}}, {anonymous: false}]}]
users = yield User.find(query).select('lastIP schoolName').lean()
for user in users
if ip = user.lastIP
user.geo = geoip.lookup(ip)
if country = user.geo?.country
user.geo.countryName = countryList.getName(country)
res.status(200).send(users)
getTeachers: wrap (req, res, next) ->
throw new errors.Unauthorized('You must be an administrator.') unless req.user?.isAdmin()
teacherRoles = ['teacher', 'technology coordinator', 'advisor', 'principal', 'superintendent', 'parent']
users = yield User.find(anonymous: false, role: {$in: teacherRoles}).select('lastIP').lean()
for user in users
if ip = user.lastIP
user.geo = geoip.lookup(ip)
if country = user.geo?.country
user.geo.countryName = countryList.getName(country)
res.status(200).send(users)