Add POST /db/course_instance/:id/members

This commit is contained in:
Scott Erickson 2015-11-03 14:00:51 -08:00
parent 429f50e1c6
commit 0e2305bc3d
4 changed files with 203 additions and 15 deletions

View file

@ -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'

View file

@ -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

View file

@ -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)

View file

@ -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()