Refactored Users and Level Sessions to have private properties:

This commit is contained in:
Ruben Vereecken 2014-07-22 20:07:00 +02:00
parent 735a7082ee
commit 19d59ac8ff
5 changed files with 37 additions and 19 deletions

View file

@ -13,12 +13,20 @@ FETCH_LIMIT = 200
module.exports = class Handler
# subclasses should override these properties
modelClass: null
privateProperties: []
editableProperties: []
postEditableProperties: []
jsonSchema: {}
waterfallFunctions: []
allowedMethods: ['GET', 'POST', 'PUT', 'PATCH']
constructor: ->
# TODO The second 'or' is for backward compatibility only is for backward compatibility only
@privateProperties = @modelClass.privateProperties or @privateProperties or []
@editableProperties = @modelClass.editableProperties or @editableProperties or []
@postEditableProperties = @modelClass.postEditableProperties or @postEditableProperties or []
@jsonSchema = @modelClass.jsonSchema or @jsonSchema or {}
# subclasses should override these methods
hasAccess: (req) -> true
hasAccessToDocument: (req, document, method=null) ->
@ -435,3 +443,11 @@ module.exports = class Handler
delete: (req, res) -> @sendMethodNotAllowed res, @allowedMethods, 'DELETE not allowed.'
head: (req, res) -> @sendMethodNotAllowed res, @allowedMethods, 'HEAD not allowed.'
# This is not a Mongoose user
projectionForUser: (req, model, ownerID) ->
return {} if 'privateProperties' not of model or req.user._id + '' is ownerID + '' or req.user.isAdmin()
projection = {}
projection[field] = 0 for field in model.privateProperties
projection

View file

@ -24,4 +24,10 @@ LevelSessionSchema.pre 'save', (next) ->
@set('changed', new Date())
next()
LevelSessionSchema.statics.privateProperties = ['code', 'submittedCode', 'unsubscribed']
LevelSessionSchema.statics.editableProperties = ['multiplayer', 'players', 'code', 'codeLanguage', 'completed', 'state',
'levelName', 'creatorName', 'levelID', 'screenshot',
'chat', 'teamSpells', 'submitted', 'submittedCodeLanguage', 'unsubscribed', 'playtime']
LevelSessionSchema.statics.jsonSchema = jsonschema
module.exports = LevelSession = mongoose.model('level.session', LevelSessionSchema)

View file

@ -6,11 +6,6 @@ TIMEOUT = 1000 * 30 # no activity for 30 seconds means it's not active
class LevelSessionHandler extends Handler
modelClass: LevelSession
editableProperties: ['multiplayer', 'players', 'code', 'codeLanguage', 'completed', 'state',
'levelName', 'creatorName', 'levelID', 'screenshot',
'chat', 'teamSpells', 'submitted', 'submittedCodeLanguage', 'unsubscribed', 'playtime']
privateProperties: ['code', 'submittedCode', 'unsubscribed']
jsonSchema: require '../../../app/schemas/models/level_session'
getByRelationship: (req, res, args...) ->
return @getActiveSessions req, res if args.length is 2 and args[1] is 'active'

View file

@ -158,6 +158,18 @@ UserSchema.statics.hashPassword = (password) ->
shasum.update(salt + password)
shasum.digest('hex')
UserSchema.statics.privateProperties = [
'permissions', 'email', 'firstName', 'lastName', 'gender', 'facebookID',
'gplusID', 'music', 'volume', 'aceConfig', 'employerAt', 'signedEmployerAgreement'
]
UserSchema.statics.jsonSchema = jsonschema
UserSchema.statics.editableProperties = [
'name', 'photoURL', 'password', 'anonymous', 'wizardColor1', 'volume',
'firstName', 'lastName', 'gender', 'facebookID', 'gplusID', 'emails',
'testGroupNumber', 'music', 'hourOfCode', 'hourOfCodeComplete', 'preferredLanguage',
'wizard', 'aceConfig', 'autocastDelay', 'lastLevel', 'jobProfile'
]
UserSchema.plugin plugins.NamedPlugin
module.exports = User = mongoose.model('User', UserSchema)

View file

@ -14,37 +14,26 @@ EarnedAchievement = require '../achievements/EarnedAchievement'
UserRemark = require './remarks/UserRemark'
serverProperties = ['passwordHash', 'emailLower', 'nameLower', 'passwordReset']
privateProperties = [
'permissions', 'email', 'firstName', 'lastName', 'gender', 'facebookID',
'gplusID', 'music', 'volume', 'aceConfig', 'employerAt', 'signedEmployerAgreement'
]
candidateProperties = [
'jobProfile', 'jobProfileApproved', 'jobProfileNotes'
]
UserHandler = class UserHandler extends Handler
modelClass: User
jsonSchema: schema
editableProperties: [
'name', 'photoURL', 'password', 'anonymous', 'wizardColor1', 'volume',
'firstName', 'lastName', 'gender', 'facebookID', 'gplusID', 'emails',
'testGroupNumber', 'music', 'hourOfCode', 'hourOfCodeComplete', 'preferredLanguage',
'wizard', 'aceConfig', 'autocastDelay', 'lastLevel', 'jobProfile'
]
getEditableProperties: (req, document) ->
props = super req, document
props.push 'permissions' unless config.isProduction
props.push 'jobProfileApproved', 'jobProfileNotes','jobProfileApprovedDate' if req.user.isAdmin() # Admins naturally edit these
props.push privateProperties... if req.user.isAdmin() # Admins are mad with power
props.push @privateProperties... if req.user.isAdmin() # Admins are mad with power
props
formatEntity: (req, document) ->
formatEntity: (req, document) =>
return null unless document?
obj = document.toObject()
delete obj[prop] for prop in serverProperties
includePrivates = req.user and (req.user.isAdmin() or req.user._id.equals(document._id))
delete obj[prop] for prop in privateProperties unless includePrivates
delete obj[prop] for prop in @privateProperties unless includePrivates
includeCandidate = includePrivates or (obj.jobProfile?.active and req.user and ('employer' in (req.user.get('permissions') ? [])) and @employerCanViewCandidate req.user, obj)
delete obj[prop] for prop in candidateProperties unless includeCandidate
return obj