mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-02-17 00:40:56 -05:00
Add POST /db/course_instance/:id/members
This commit is contained in:
parent
429f50e1c6
commit
0e2305bc3d
4 changed files with 203 additions and 15 deletions
|
@ -8,7 +8,8 @@ _.extend CourseSchema.properties,
|
|||
concepts: c.array {title: 'Programming Concepts', uniqueItems: true}, c.concept
|
||||
description: {type: 'string'}
|
||||
duration: {type: 'number', description: 'Approximate hours of content'}
|
||||
pricePerSeat: {type: 'number', description: 'Price per seat in USD cents.'}
|
||||
pricePerSeat: {type: 'number', description: 'Price per seat in USD cents.'} # deprecated
|
||||
free: { type: 'boolean' }
|
||||
screenshot: c.url {title: 'URL', description: 'Link to course screenshot.'}
|
||||
|
||||
c.extendBasicProperties CourseSchema, 'Course'
|
||||
|
|
|
@ -12,6 +12,7 @@ User = require '../users/User'
|
|||
UserHandler = require '../users/user_handler'
|
||||
utils = require '../../app/core/utils'
|
||||
sendwithus = require '../sendwithus'
|
||||
mongoose = require 'mongoose'
|
||||
|
||||
CourseInstanceHandler = class CourseInstanceHandler extends Handler
|
||||
modelClass: CourseInstance
|
||||
|
@ -31,19 +32,45 @@ CourseInstanceHandler = class CourseInstanceHandler extends Handler
|
|||
|
||||
getByRelationship: (req, res, args...) ->
|
||||
relationship = args[1]
|
||||
return @createAPI(req, res) if relationship is 'create'
|
||||
return @getLevelSessionsAPI(req, res, args[0]) if args[1] is 'level_sessions'
|
||||
return @addMember(req, res, args[0]) if req.method is 'POST' and args[1] is 'members'
|
||||
return @getMembersAPI(req, res, args[0]) if args[1] is 'members'
|
||||
return @inviteStudents(req, res, args[0]) if relationship is 'invite_students'
|
||||
return @redeemPrepaidCodeAPI(req, res) if args[1] is 'redeem_prepaid'
|
||||
super arguments...
|
||||
|
||||
addMember: (req, res, courseInstanceID) ->
|
||||
userID = req.body.userID
|
||||
return @sendBadInputError(res, 'Input must be a MongoDB ID') unless utils.isID(userID)
|
||||
CourseInstance.findById courseInstanceID, (err, courseInstance) =>
|
||||
return @sendDatabaseError(res, err) if err
|
||||
return @sendNotFoundError(res, 'Course instance not found') unless courseInstance
|
||||
return @sendForbiddenError(res) unless courseInstance.get('ownerID').equals(req.user.get('_id'))
|
||||
Classroom.findById courseInstance.get('classroomID'), (err, classroom) =>
|
||||
return @sendDatabaseError(res, err) if err
|
||||
return @sendNotFoundError(res, 'Classroom referenced by course instance not found') unless classroom
|
||||
return @sendForbiddenError(res) unless _.any(classroom.get('members'), (memberID) -> memberID.toString() is userID)
|
||||
Prepaid.find({ 'redeemers.userID': mongoose.Types.ObjectId(userID) }).count (err, userIsPrepaid) =>
|
||||
return @sendDatabaseError(res, err) if err
|
||||
Course.findById courseInstance.get('courseID'), (err, course) =>
|
||||
return @sendDatabaseError(res, err) if err
|
||||
return @sendNotFoundError(res, 'Course referenced by course instance not found') unless course
|
||||
if not (course.get('free') or userIsPrepaid)
|
||||
return @sendPaymentRequiredError(res, 'Cannot add this user to a course instance until they are added to a prepaid')
|
||||
members = courseInstance.get('members')
|
||||
members.push(userID)
|
||||
courseInstance.set('members', members)
|
||||
courseInstance.save (err, courseInstance) =>
|
||||
return @sendDatabaseError(res, err) if err
|
||||
@sendSuccess(res, @formatEntity(req, courseInstance))
|
||||
|
||||
post: (req, res) ->
|
||||
return @sendBadInputError(res, 'No classroomID') unless req.body.classroomID
|
||||
return @sendBadInputError(res, 'No courseID') unless req.body.courseID
|
||||
Classroom.findById req.body.classroomID, (err, classroom) =>
|
||||
return @sendDatabaseError(res, err) if err
|
||||
return @sendNotFoundError(res, 'Classroom not found') unless classroom
|
||||
return @sendForbiddenError(res) unless classroom.get('ownerID').equals(req.user.get('_id'))
|
||||
Course.findById req.body.courseID, (err, course) =>
|
||||
return @sendDatabaseError(res, err) if err
|
||||
return @sendNotFoundError(res, 'Course not found') unless course
|
||||
|
|
|
@ -24,7 +24,7 @@ describe 'POST /db/course_instance', ->
|
|||
expect(body.classroomID).toBeDefined()
|
||||
done()
|
||||
|
||||
it 'fails if the Course does not exist', (done) ->
|
||||
it 'returns 404 if the Course does not exist', (done) ->
|
||||
test = @
|
||||
url = getURL('/db/course_instance')
|
||||
data = {
|
||||
|
@ -36,7 +36,7 @@ describe 'POST /db/course_instance', ->
|
|||
expect(res.statusCode).toBe(404)
|
||||
done()
|
||||
|
||||
it 'fails if the Classroom does not exist', (done) ->
|
||||
it 'returns 404 if the Classroom does not exist', (done) ->
|
||||
test = @
|
||||
url = getURL('/db/course_instance')
|
||||
data = {
|
||||
|
@ -46,4 +46,112 @@ describe 'POST /db/course_instance', ->
|
|||
}
|
||||
request.post {uri: url, json: data}, (err, res, body) ->
|
||||
expect(res.statusCode).toBe(404)
|
||||
done()
|
||||
done()
|
||||
|
||||
it 'return 403 if the logged in user does not own the Classroom', (done) ->
|
||||
test = @
|
||||
loginSam ->
|
||||
url = getURL('/db/course_instance')
|
||||
data = {
|
||||
name: 'Some Name'
|
||||
courseID: test.course.id
|
||||
classroomID: test.classroom.id
|
||||
}
|
||||
request.post {uri: url, json: data}, (err, res, body) ->
|
||||
expect(res.statusCode).toBe(403)
|
||||
done()
|
||||
|
||||
|
||||
describe 'POST /db/course_instance/:id/members', ->
|
||||
|
||||
beforeEach (done) -> clearModels([CourseInstance, Course, User, Classroom, Prepaid], done)
|
||||
beforeEach (done) -> loginJoe (@joe) => done()
|
||||
beforeEach init.course({free: true})
|
||||
beforeEach init.classroom()
|
||||
beforeEach init.courseInstance()
|
||||
beforeEach init.user()
|
||||
beforeEach init.prepaid()
|
||||
|
||||
it 'adds a member to the given CourseInstance', (done) ->
|
||||
async.eachSeries([
|
||||
|
||||
addTestUserToClassroom,
|
||||
(test, cb) ->
|
||||
url = getURL("/db/course_instance/#{test.courseInstance.id}/members")
|
||||
request.post {uri: url, json: {userID: test.user.id}}, (err, res, body) ->
|
||||
expect(res.statusCode).toBe(200)
|
||||
expect(body.members.length).toBe(1)
|
||||
expect(body.members[0]).toBe(test.user.id)
|
||||
cb()
|
||||
|
||||
], makeTestIterator(@), done)
|
||||
|
||||
|
||||
it 'return 403 if the member is not in the classroom', (done) ->
|
||||
async.eachSeries([
|
||||
|
||||
(test, cb) ->
|
||||
url = getURL("/db/course_instance/#{test.courseInstance.id}/members")
|
||||
request.post {uri: url, json: {userID: test.user.id}}, (err, res) ->
|
||||
expect(res.statusCode).toBe(403)
|
||||
cb()
|
||||
|
||||
], makeTestIterator(@), done)
|
||||
|
||||
|
||||
it 'returns 403 if the user does not own the course instance', (done) ->
|
||||
async.eachSeries([
|
||||
|
||||
addTestUserToClassroom,
|
||||
(test, cb) ->
|
||||
loginSam ->
|
||||
url = getURL("/db/course_instance/#{test.courseInstance.id}/members")
|
||||
request.post {uri: url, json: {userID: test.user.id}}, (err, res, body) ->
|
||||
expect(res.statusCode).toBe(403)
|
||||
cb()
|
||||
|
||||
], makeTestIterator(@), done)
|
||||
|
||||
it 'return 402 if the course is not free and the user is not in a prepaid', (done) ->
|
||||
async.eachSeries([
|
||||
|
||||
addTestUserToClassroom,
|
||||
makeTestCourseNotFree,
|
||||
(test, cb) ->
|
||||
url = getURL("/db/course_instance/#{test.courseInstance.id}/members")
|
||||
request.post {uri: url, json: {userID: test.user.id}}, (err, res) ->
|
||||
expect(res.statusCode).toBe(402)
|
||||
cb()
|
||||
|
||||
], makeTestIterator(@), done)
|
||||
|
||||
|
||||
it 'works if the course is not free and the user is in a prepaid', (done) ->
|
||||
async.eachSeries([
|
||||
|
||||
addTestUserToClassroom,
|
||||
makeTestCourseNotFree,
|
||||
addTestUserToPrepaid,
|
||||
(test, cb) ->
|
||||
url = getURL("/db/course_instance/#{test.courseInstance.id}/members")
|
||||
request.post {uri: url, json: {userID: test.user.id}}, (err, res) ->
|
||||
expect(res.statusCode).toBe(200)
|
||||
cb()
|
||||
|
||||
], makeTestIterator(@), done)
|
||||
|
||||
|
||||
makeTestCourseNotFree = (test, cb) ->
|
||||
test.course.set('free', false)
|
||||
test.course.save cb
|
||||
|
||||
addTestUserToClassroom = (test, cb) ->
|
||||
test.classroom.set('members', [test.user.get('_id')])
|
||||
test.classroom.save cb
|
||||
|
||||
addTestUserToPrepaid = (test, cb) ->
|
||||
test.prepaid.set('redeemers', [{userID: test.user.get('_id')}])
|
||||
test.prepaid.save cb
|
||||
|
||||
makeTestIterator = (testObject) -> (func, callback) -> func(testObject, callback)
|
||||
|
|
@ -18,17 +18,69 @@ module.exports.course = (properties) ->
|
|||
done()
|
||||
|
||||
|
||||
module.exports.classroom = (properties) ->
|
||||
properties = {}
|
||||
_.defaults(properties, {
|
||||
name: 'Unnamed classroom'
|
||||
})
|
||||
|
||||
module.exports.classroom = (givenProperties) ->
|
||||
return (done) ->
|
||||
properties = _.defaults({}, givenProperties, {
|
||||
name: 'Unnamed classroom'
|
||||
})
|
||||
test = @
|
||||
classroom = new Classroom(properties)
|
||||
classroom.save (err, classroom) ->
|
||||
url = getURL('/db/classroom')
|
||||
request.post {uri: url, json: properties}, (err, res, body) ->
|
||||
expect(res.statusCode).toBe(200)
|
||||
Classroom.findById body._id, (err, classroom) ->
|
||||
expect(err).toBeNull()
|
||||
expect(classroom).toBeTruthy()
|
||||
test.classroom = classroom
|
||||
done()
|
||||
|
||||
|
||||
module.exports.courseInstance = (givenProperties) ->
|
||||
return (done) ->
|
||||
properties = _.defaults({}, givenProperties, {
|
||||
name: 'Unnamed course instance'
|
||||
})
|
||||
test = @
|
||||
url = getURL('/db/course_instance')
|
||||
properties.courseID ?= test.course.id
|
||||
properties.classroomID ?= test.classroom.id
|
||||
request.post {uri: url, json: properties}, (err, res, body) ->
|
||||
expect(res.statusCode).toBe(200)
|
||||
CourseInstance.findById body._id, (err, courseInstance) ->
|
||||
expect(err).toBeNull()
|
||||
expect(courseInstance).toBeTruthy()
|
||||
test.courseInstance = courseInstance
|
||||
done()
|
||||
|
||||
|
||||
module.exports.user = (givenOptions) ->
|
||||
return (done) ->
|
||||
options = _.defaults({}, givenOptions, {
|
||||
setTo: 'user',
|
||||
properties: {
|
||||
name: 'User'+_.uniqueId()
|
||||
}
|
||||
})
|
||||
test = @
|
||||
user = new User(options.properties)
|
||||
user.save (err, user) ->
|
||||
expect(err).toBeNull()
|
||||
test.classroom = classroom
|
||||
test[options.setTo] = user
|
||||
done()
|
||||
|
||||
|
||||
|
||||
module.exports.prepaid = (givenOptions) ->
|
||||
return (done) ->
|
||||
options = _.defaults({}, givenOptions, {
|
||||
setTo: 'prepaid',
|
||||
properties: {
|
||||
type: 'course'
|
||||
maxRedeemers: 10
|
||||
redeemers: []
|
||||
}
|
||||
})
|
||||
test = @
|
||||
prepaid = new Prepaid(options.properties)
|
||||
prepaid.save (err, prepaid) ->
|
||||
expect(err).toBeNull()
|
||||
test[options.setTo] = prepaid
|
||||
done()
|
Loading…
Reference in a new issue