codecombat/server/middleware/levels.coffee

86 lines
3.5 KiB
CoffeeScript
Raw Normal View History

wrap = require 'co-express'
errors = require '../commons/errors'
Level = require '../models/Level'
LevelSession = require '../models/LevelSession'
CourseInstance = require '../models/CourseInstance'
Classroom = require '../models/Classroom'
Course = require '../models/Course'
database = require '../commons/database'
module.exports =
upsertSession: wrap (req, res) ->
level = yield database.getDocFromHandle(req, Level)
if not level
throw new errors.NotFound('Level not found.')
sessionQuery =
level:
original: level.get('original').toString()
majorVersion: level.get('version').major
creator: req.user.id
if req.query.team?
sessionQuery.team = req.query.team
session = yield LevelSession.findOne(sessionQuery)
if session
return res.send(session.toObject({req: req}))
attrs = sessionQuery
_.extend(attrs, {
state:
complete: false
scripts:
currentScript: null # will not save empty objects
permissions: [
{target: req.user.id, access: 'owner'}
{target: 'public', access: 'write'}
]
codeLanguage: req.user.get('aceConfig')?.language ? 'python'
})
if level.get('type') in ['course', 'course-ladder'] or req.query.course?
# Find the course and classroom that has assigned this level, verify access
courseInstances = yield CourseInstance.find({members: req.user._id})
classroomIDs = (courseInstance.get('classroomID') for courseInstance in courseInstances)
classroomIDs = _.filter _.uniq classroomIDs, false, (objectID='') -> objectID.toString()
classrooms = yield Classroom.find({ _id: { $in: classroomIDs }})
classroomWithLevel = null
courseID = null
classroomMap = {}
classroomMap[classroom.id] = classroom for classroom in classrooms
levelOriginal = level.get('original')
for courseInstance in courseInstances
classroomID = courseInstance.get('classroomID')
continue unless classroomID
classroom = classroomMap[classroomID.toString()]
continue unless classroom
courseID = courseInstance.get('courseID')
classroomCourse = _.find(classroom.get('courses'), (c) -> c._id.equals(courseID))
for courseLevel in classroomCourse.levels
if courseLevel.original.equals(levelOriginal)
classroomWithLevel = classroom
break
break if classroomWithLevel
unless classroomWithLevel
throw new errors.PaymentRequired('You must be in a course which includes this level to play it')
course = yield Course.findById(courseID).select('free')
unless course.get('free') or req.user.isEnrolled()
throw new errors.PaymentRequired('You must be enrolled to access this content')
lang = classroomWithLevel.get('aceConfig')?.language
attrs.codeLanguage = lang if lang
else
requiresSubscription = level.get('requiresSubscription') or (req.user.isOnPremiumServer() and level.get('campaign') and not (level.slug in ['dungeons-of-kithgard', 'gems-in-the-deep', 'shadow-guard', 'forgetful-gemsmith', 'signs-and-portents', 'true-names']))
canPlayAnyway = req.user.isPremium() or level.get 'adventurer'
if requiresSubscription and not canPlayAnyway
throw new errors.PaymentRequired('This level requires a subscription to play')
session = new LevelSession(attrs)
yield session.save()
res.send(session.toObject({req: req}))