mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-27 17:45:40 -05:00
175 lines
7.4 KiB
CoffeeScript
175 lines
7.4 KiB
CoffeeScript
_ = require 'lodash'
|
|
utils = require '../lib/utils'
|
|
errors = require '../commons/errors'
|
|
wrap = require 'co-express'
|
|
Promise = require 'bluebird'
|
|
database = require '../commons/database'
|
|
mongoose = require 'mongoose'
|
|
Classroom = require '../models/Classroom'
|
|
Course = require '../models/Course'
|
|
Campaign = require '../models/Campaign'
|
|
Level = require '../models/Level'
|
|
parse = require '../commons/parse'
|
|
LevelSession = require '../models/LevelSession'
|
|
User = require '../models/User'
|
|
TrialRequest = require '../models/TrialRequest'
|
|
sendwithus = require '../sendwithus'
|
|
|
|
module.exports =
|
|
getByOwner: wrap (req, res, next) ->
|
|
options = req.query
|
|
ownerID = options.ownerID
|
|
return next() unless ownerID
|
|
throw new errors.UnprocessableEntity('Bad ownerID') unless utils.isID ownerID
|
|
throw new errors.Unauthorized() unless req.user
|
|
throw new errors.Forbidden('"ownerID" must be yourself') unless req.user.isAdmin() or ownerID is req.user.id
|
|
sanitizedOptions = {}
|
|
unless _.isUndefined(options.archived)
|
|
# Handles when .archived is true, vs false-or-null
|
|
sanitizedOptions.archived = { $ne: not (options.archived is 'true') }
|
|
dbq = Classroom.find _.merge sanitizedOptions, { ownerID: mongoose.Types.ObjectId(ownerID) }
|
|
dbq.select(parse.getProjectFromReq(req))
|
|
classrooms = yield dbq
|
|
classrooms = (classroom.toObject({req: req}) for classroom in classrooms)
|
|
res.status(200).send(classrooms)
|
|
|
|
fetchAllLevels: wrap (req, res, next) ->
|
|
classroom = yield database.getDocFromHandle(req, Classroom)
|
|
if not classroom
|
|
throw new errors.NotFound('Classroom not found.')
|
|
|
|
levelOriginals = []
|
|
for course in classroom.get('courses') or []
|
|
for level in course.levels
|
|
levelOriginals.push(level.original)
|
|
|
|
levels = yield Level.find({ original: { $in: levelOriginals }, slug: { $exists: true }}).select(parse.getProjectFromReq(req))
|
|
levels = (level.toObject({ req: req }) for level in levels)
|
|
|
|
# maintain course order
|
|
levelMap = {}
|
|
for level in levels
|
|
levelMap[level.original] = level
|
|
levels = (levelMap[levelOriginal.toString()] for levelOriginal in levelOriginals)
|
|
|
|
res.status(200).send(levels)
|
|
|
|
fetchLevelsForCourse: wrap (req, res) ->
|
|
classroom = yield database.getDocFromHandle(req, Classroom)
|
|
if not classroom
|
|
throw new errors.NotFound('Classroom not found.')
|
|
|
|
levelOriginals = []
|
|
for course in classroom.get('courses') or []
|
|
if course._id.toString() isnt req.params.courseID
|
|
continue
|
|
for level in course.levels
|
|
levelOriginals.push(level.original)
|
|
|
|
levels = yield Level.find({ original: { $in: levelOriginals }, slug: { $exists: true }}).select(parse.getProjectFromReq(req))
|
|
levels = (level.toObject({ req: req }) for level in levels)
|
|
|
|
# maintain course order
|
|
levelMap = {}
|
|
for level in levels
|
|
levelMap[level.original] = level
|
|
levels = (levelMap[levelOriginal.toString()] for levelOriginal in levelOriginals)
|
|
|
|
res.status(200).send(levels)
|
|
|
|
fetchMemberSessions: wrap (req, res, next) ->
|
|
throw new errors.Unauthorized() unless req.user
|
|
memberLimit = parse.getLimitFromReq(req, {default: 10, max: 100, param: 'memberLimit'})
|
|
memberSkip = parse.getSkipFromReq(req, {param: 'memberSkip'})
|
|
classroom = yield database.getDocFromHandle(req, Classroom)
|
|
throw new errors.NotFound('Classroom not found.') if not classroom
|
|
throw new errors.Forbidden('You do not own this classroom.') unless req.user.isAdmin() or classroom.get('ownerID').equals(req.user._id)
|
|
members = classroom.get('members') or []
|
|
members = members.slice(memberSkip, memberSkip + memberLimit)
|
|
dbqs = []
|
|
select = 'state.complete level creator playtime'
|
|
for member in members
|
|
dbqs.push(LevelSession.find({creator: member.toHexString()}).select(select).exec())
|
|
results = yield dbqs
|
|
sessions = _.flatten(results)
|
|
res.status(200).send(sessions)
|
|
|
|
fetchMembers: wrap (req, res, next) ->
|
|
throw new errors.Unauthorized() unless req.user
|
|
memberLimit = parse.getLimitFromReq(req, {default: 10, max: 100, param: 'memberLimit'})
|
|
memberSkip = parse.getSkipFromReq(req, {param: 'memberSkip'})
|
|
classroom = yield database.getDocFromHandle(req, Classroom)
|
|
throw new errors.NotFound('Classroom not found.') if not classroom
|
|
isOwner = classroom.get('ownerID').equals(req.user._id)
|
|
isMember = req.user.id in (m.toString() for m in classroom.get('members'))
|
|
unless req.user.isAdmin() or isOwner or isMember
|
|
throw new errors.Forbidden('You do not own this classroom.')
|
|
memberIDs = classroom.get('members') or []
|
|
memberIDs = memberIDs.slice(memberSkip, memberSkip + memberLimit)
|
|
|
|
members = yield User.find({ _id: { $in: memberIDs }}).select(parse.getProjectFromReq(req))
|
|
# members = yield User.find({ _id: { $in: memberIDs }, deleted: { $ne: true }}).select(parse.getProjectFromReq(req))
|
|
memberObjects = (member.toObject({ req: req, includedPrivates: ["name", "email"] }) for member in members)
|
|
|
|
res.status(200).send(memberObjects)
|
|
|
|
post: wrap (req, res) ->
|
|
throw new errors.Unauthorized() unless req.user and not req.user.isAnonymous()
|
|
throw new errors.Forbidden() unless req.user?.isTeacher()
|
|
classroom = database.initDoc(req, Classroom)
|
|
classroom.set 'ownerID', req.user._id
|
|
classroom.set 'members', []
|
|
database.assignBody(req, classroom)
|
|
|
|
# copy over data from how courses are right now
|
|
courses = yield Course.find()
|
|
campaigns = yield Campaign.find({_id: {$in: (course.get('campaignID') for course in courses)}})
|
|
campaignMap = {}
|
|
campaignMap[campaign.id] = campaign for campaign in campaigns
|
|
coursesData = []
|
|
for course in courses
|
|
courseData = { _id: course._id, levels: [] }
|
|
campaign = campaignMap[course.get('campaignID').toString()]
|
|
levels = _.values(campaign.get('levels'))
|
|
levels = _.sortBy(levels, 'campaignIndex')
|
|
for level in levels
|
|
levelData = { original: mongoose.Types.ObjectId(level.original) }
|
|
_.extend(levelData, _.pick(level, 'type', 'slug', 'name'))
|
|
courseData.levels.push(levelData)
|
|
coursesData.push(courseData)
|
|
classroom.set('courses', coursesData)
|
|
|
|
# finish
|
|
database.validateDoc(classroom)
|
|
classroom = yield classroom.save()
|
|
res.status(201).send(classroom.toObject({req: req}))
|
|
|
|
inviteMembers: wrap (req, res) ->
|
|
if not req.body.emails
|
|
throw new errors.UnprocessableEntity('Emails not included')
|
|
|
|
classroom = yield database.getDocFromHandle(req, Classroom)
|
|
if not classroom
|
|
throw new errors.NotFound('Classroom not found.')
|
|
|
|
unless classroom.get('ownerID').equals(req.user?._id)
|
|
throw new errors.Forbidden('Must be owner of classroom to send invites.')
|
|
|
|
user = req.user
|
|
teacherName = user.get('name')
|
|
teacherName ?= _.filter([user.get('firstName'), user.get('lastName')]).join(' ')
|
|
trialRequest = yield TrialRequest.findOne({applicant: user._id})
|
|
schoolName = trialRequest?.get('properties')?.organization
|
|
|
|
for email in req.body.emails
|
|
context =
|
|
email_id: sendwithus.templates.course_invite_email
|
|
recipient:
|
|
address: email
|
|
email_data:
|
|
class_name: classroom.get('name')
|
|
teacher_name: teacherName
|
|
school_name: schoolName
|
|
join_link: "https://codecombat.com/courses?_cc=" + (classroom.get('codeCamel') or classroom.get('code'))
|
|
sendwithus.api.send context, _.noop
|
|
res.status(200).send({})
|