mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-02-17 08:50:58 -05:00
Add Classroom server model and endpoints
This commit is contained in:
parent
d6b57f0e76
commit
27d423a410
6 changed files with 208 additions and 0 deletions
14
app/schemas/models/classroom.schema.coffee
Normal file
14
app/schemas/models/classroom.schema.coffee
Normal file
|
@ -0,0 +1,14 @@
|
|||
c = require './../schemas'
|
||||
|
||||
ClassroomSchema = c.object {title: 'Classroom', required: ['name']}
|
||||
c.extendNamedProperties ClassroomSchema # name first
|
||||
|
||||
_.extend ClassroomSchema.properties,
|
||||
members: c.array {title: 'Members'}, c.objectId()
|
||||
ownerID: c.objectId()
|
||||
description: {type: 'string'}
|
||||
code: c.shortString(title: "Unique code to redeem")
|
||||
|
||||
c.extendBasicProperties ClassroomSchema, 'Classroom'
|
||||
|
||||
module.exports = ClassroomSchema
|
36
server/classrooms/Classroom.coffee
Normal file
36
server/classrooms/Classroom.coffee
Normal file
|
@ -0,0 +1,36 @@
|
|||
mongoose = require 'mongoose'
|
||||
log = require 'winston'
|
||||
config = require '../../server_config'
|
||||
plugins = require '../plugins/plugins'
|
||||
User = require '../users/User'
|
||||
jsonSchema = require '../../app/schemas/models/classroom.schema'
|
||||
|
||||
ClassroomSchema = new mongoose.Schema {}, {strict: false, minimize: false, read:config.mongo.readpref}
|
||||
|
||||
ClassroomSchema.statics.privateProperties = []
|
||||
ClassroomSchema.statics.editableProperties = [
|
||||
'description'
|
||||
'name'
|
||||
]
|
||||
|
||||
ClassroomSchema.statics.generateNewCode = (done) ->
|
||||
tryCode = ->
|
||||
code = _.sample("abcdefghijklmnopqrstuvwxyz0123456789", 8).join('')
|
||||
Classroom.findOne code: code, (err, classroom) ->
|
||||
return done() if err
|
||||
return done(code) unless classroom
|
||||
tryCode()
|
||||
tryCode()
|
||||
|
||||
ClassroomSchema.plugin plugins.NamedPlugin
|
||||
|
||||
ClassroomSchema.pre('save', (next) ->
|
||||
return next() if @get('code')
|
||||
Classroom.generateNewCode (code) =>
|
||||
@set 'code', code
|
||||
next()
|
||||
)
|
||||
|
||||
ClassroomSchema.statics.jsonSchema = jsonSchema
|
||||
|
||||
module.exports = Classroom = mongoose.model 'classroom', ClassroomSchema, 'classrooms'
|
58
server/classrooms/classroom_handler.coffee
Normal file
58
server/classrooms/classroom_handler.coffee
Normal file
|
@ -0,0 +1,58 @@
|
|||
async = require 'async'
|
||||
mongoose = require 'mongoose'
|
||||
Handler = require '../commons/Handler'
|
||||
Classroom = require './Classroom'
|
||||
User = require '../users/User'
|
||||
|
||||
ClassroomHandler = class ClassroomHandler extends Handler
|
||||
modelClass: Classroom
|
||||
jsonSchema: require '../../app/schemas/models/classroom.schema'
|
||||
allowedMethods: ['GET', 'POST', 'PUT', 'DELETE']
|
||||
|
||||
hasAccess: (req) ->
|
||||
return false unless req.user
|
||||
return true if req.method is 'GET'
|
||||
req.method in @allowedMethods or req.user?.isAdmin()
|
||||
|
||||
hasAccessToDocument: (req, document, method=null) ->
|
||||
return false unless document?
|
||||
return true if req.user?.isAdmin()
|
||||
return true if document.get('ownerID')?.equals req.user?._id
|
||||
isGet = (method or req.method).toLowerCase() is 'get'
|
||||
isMember = _.any(document.get('members') or [], (memberID) -> memberID.equals(req.user.get('_id')))
|
||||
return true if isGet and isMember
|
||||
false
|
||||
|
||||
makeNewInstance: (req) ->
|
||||
instance = super(req)
|
||||
instance.set 'ownerID', req.user._id
|
||||
instance.set 'members', []
|
||||
instance
|
||||
|
||||
getByRelationship: (req, res, args...) ->
|
||||
method = req.method.toLowerCase()
|
||||
return @joinClassroomAPI(req, res, args[0]) if method is 'post' and args[1] is 'members'
|
||||
super(arguments...)
|
||||
|
||||
joinClassroomAPI: (req, res, classroomID) ->
|
||||
return @sendBadInputError(res, 'Need an object with a code') unless req.body?.code
|
||||
Classroom.findById classroomID, (err, classroom) =>
|
||||
return @sendDatabaseError(res, err) if err
|
||||
return @sendNotFoundError(res) if not classroom
|
||||
return @sendBadInputError(res, 'Bad code') unless req.body.code is classroom.get('code')
|
||||
members = _.clone(classroom.get('members'))
|
||||
if _.any(members, (memberID) -> memberID.equals(req.user.get('_id')))
|
||||
return @sendSuccess(res, @formatEntity(req, classroom))
|
||||
members.push req.user.get('_id')
|
||||
classroom.set('members', members)
|
||||
classroom.save (err, classroom) =>
|
||||
return @sendDatabaseError(res, err) if err
|
||||
return @sendSuccess(res, @formatEntity(req, classroom))
|
||||
|
||||
formatEntity: (req, doc) ->
|
||||
if req.user?.isAdmin() or req.user?.get('_id').equals(doc.get('ownerID'))
|
||||
return doc.toObject()
|
||||
return _.omit(doc.toObject(), 'code')
|
||||
|
||||
|
||||
module.exports = new ClassroomHandler()
|
|
@ -8,6 +8,7 @@ module.exports.handlers =
|
|||
'article': 'articles/article_handler'
|
||||
'campaign': 'campaigns/campaign_handler'
|
||||
'clan': 'clans/clan_handler'
|
||||
'classroom': 'classrooms/classroom_handler'
|
||||
'course': 'courses/course_handler'
|
||||
'course_instance': 'courses/course_instance_handler'
|
||||
'level': 'levels/level_handler'
|
||||
|
|
|
@ -32,6 +32,7 @@ models_path = [
|
|||
'../../server/articles/Article'
|
||||
'../../server/campaigns/Campaign'
|
||||
'../../server/clans/Clan'
|
||||
'../../server/classrooms/Classroom'
|
||||
'../../server/courses/Course'
|
||||
'../../server/courses/CourseInstance'
|
||||
'../../server/levels/Level'
|
||||
|
|
98
test/server/functional/classrooms.spec.coffee
Normal file
98
test/server/functional/classrooms.spec.coffee
Normal file
|
@ -0,0 +1,98 @@
|
|||
config = require '../../../server_config'
|
||||
require '../common'
|
||||
utils = require '../../../app/core/utils' # Must come after require /common
|
||||
mongoose = require 'mongoose'
|
||||
|
||||
classroomsURL = getURL('/db/classroom')
|
||||
|
||||
describe 'GET /db/classrooms/:id', ->
|
||||
it 'Clear database users and clans', (done) ->
|
||||
clearModels [User, Classroom], (err) ->
|
||||
throw err if err
|
||||
done()
|
||||
|
||||
it 'creates a new classroom for the given user', (done) ->
|
||||
loginNewUser (user1) ->
|
||||
data = { name: 'Classroom 1' }
|
||||
request.post {uri: classroomsURL, json: data }, (err, res, body) ->
|
||||
expect(res.statusCode).toBe(200)
|
||||
classroomID = body._id
|
||||
request.get {uri: classroomsURL + '/' + body._id }, (err, res, body) ->
|
||||
expect(res.statusCode).toBe(200)
|
||||
expect(body._id).toBe(classroomID = body._id)
|
||||
done()
|
||||
|
||||
describe 'POST /db/classrooms', ->
|
||||
|
||||
it 'Clear database users and clans', (done) ->
|
||||
clearModels [User, Classroom], (err) ->
|
||||
throw err if err
|
||||
done()
|
||||
|
||||
it 'creates a new classroom for the given user', (done) ->
|
||||
loginNewUser (user1) ->
|
||||
data = { name: 'Classroom 1' }
|
||||
request.post {uri: classroomsURL, json: data }, (err, res, body) ->
|
||||
expect(res.statusCode).toBe(200)
|
||||
expect(body.name).toBe('Classroom 1')
|
||||
expect(body.members.length).toBe(0)
|
||||
expect(body.ownerID).toBe(user1.id)
|
||||
done()
|
||||
|
||||
it 'does not work for anonymous users', (done) ->
|
||||
logoutUser ->
|
||||
data = { name: 'Classroom 2' }
|
||||
request.post {uri: classroomsURL, json: data }, (err, res, body) ->
|
||||
expect(res.statusCode).toBe(401)
|
||||
done()
|
||||
|
||||
|
||||
describe 'PUT /db/classrooms', ->
|
||||
|
||||
it 'Clear database users and clans', (done) ->
|
||||
clearModels [User, Classroom], (err) ->
|
||||
throw err if err
|
||||
done()
|
||||
|
||||
it 'edits name and description', (done) ->
|
||||
loginNewUser (user1) ->
|
||||
data = { name: 'Classroom 2' }
|
||||
request.post {uri: classroomsURL, json: data }, (err, res, body) ->
|
||||
expect(res.statusCode).toBe(200)
|
||||
data = { name: 'Classroom 3', description: 'New Description' }
|
||||
url = classroomsURL + '/' + body._id
|
||||
request.put { uri: url, json: data }, (err, res, body) ->
|
||||
expect(body.name).toBe('Classroom 3')
|
||||
expect(body.description).toBe('New Description')
|
||||
done()
|
||||
|
||||
it 'is not allowed if you are just a member', (done) ->
|
||||
loginNewUser (user1) ->
|
||||
data = { name: 'Classroom 4' }
|
||||
request.post {uri: classroomsURL, json: data }, (err, res, body) ->
|
||||
expect(res.statusCode).toBe(200)
|
||||
classroomCode = body.code
|
||||
loginNewUser (user2) ->
|
||||
url = classroomsURL + '/' + body._id + '/members'
|
||||
data = { code: classroomCode }
|
||||
request.post { uri: url, json: data }, (err, res, body) ->
|
||||
expect(res.statusCode).toBe(200)
|
||||
url = classroomsURL + '/' + body._id
|
||||
request.put { uri: url, json: data }, (err, res, body) ->
|
||||
expect(res.statusCode).toBe(403)
|
||||
done()
|
||||
|
||||
describe 'POST /db/classrooms/:id/members', ->
|
||||
|
||||
it 'adds the signed in user to the list of members in the classroom', (done) ->
|
||||
loginNewUser (user1) ->
|
||||
data = { name: 'Classroom 5' }
|
||||
request.post {uri: classroomsURL, json: data }, (err, res, body) ->
|
||||
classroomCode = body.code
|
||||
expect(res.statusCode).toBe(200)
|
||||
loginNewUser (user2) ->
|
||||
url = classroomsURL + '/' + body._id + '/members'
|
||||
data = { code: classroomCode }
|
||||
request.post { uri: url, json: data }, (err, res, body) ->
|
||||
expect(res.statusCode).toBe(200)
|
||||
done()
|
Loading…
Reference in a new issue