Migrate /db/trial.request for #3469

This commit is contained in:
Scott Erickson 2016-03-09 16:59:25 -08:00
parent 356523dd4b
commit f21baa7af5
11 changed files with 207 additions and 227 deletions

View file

@ -7,5 +7,5 @@ module.exports = class TrialRequestCollection extends CocoCollection
fetchOwn: (options) ->
options = _.extend({data: {}}, options)
options.url = _.result(@, 'url') + '/-/own'
options.data.applicant = me.id
@fetch(options)

View file

@ -36,8 +36,8 @@ ArticleSchema.plugin(plugins.SearchablePlugin, {searchable: ['body', 'name']})
ArticleSchema.plugin(plugins.TranslationCoveragePlugin)
ArticleSchema.plugin(plugins.PatchablePlugin)
ArticleSchema.postEditableProperties = []
ArticleSchema.editableProperties = ['body', 'name', 'i18n', 'i18nCoverage']
ArticleSchema.jsonSchema = require '../../app/schemas/models/article'
ArticleSchema.statics.postEditableProperties = []
ArticleSchema.statics.editableProperties = ['body', 'name', 'i18n', 'i18nCoverage']
ArticleSchema.statics.jsonSchema = require '../../app/schemas/models/article'
module.exports = mongoose.model('article', ArticleSchema)

View file

@ -56,6 +56,7 @@ module.exports =
doc.set('original', doc._id)
doc.set('creator', req.user._id)
return doc
applyCustomSearchToDBQ: (req, dbq) ->
specialParameters = ['term', 'project', 'conditions']
@ -125,11 +126,11 @@ module.exports =
assignBody: (req, doc, options={}) ->
if _.isEmpty(req.body)
throw new errors.UnprocessableEntity('No input')
props = doc.schema.editableProperties.slice()
props = doc.schema.statics.editableProperties.slice()
if doc.isNew
props = props.concat doc.schema.postEditableProperties
props = props.concat doc.schema.statics.postEditableProperties
if doc.schema.uses_coco_permissions and req.user
isOwner = doc.getAccessForUserObjectId(req.user._id) is 'owner'
@ -152,7 +153,7 @@ module.exports =
# so that validation doesn't get hung up on Date objects in the documents.
delete obj.dateCreated
tv4 = require('tv4').tv4
result = tv4.validateMultiple(obj, doc.schema.jsonSchema)
result = tv4.validateMultiple(obj, doc.schema.statics.jsonSchema)
if not result.valid
throw new errors.UnprocessableEntity('JSON-schema validation failed', { validationErrors: result.errors })

View file

@ -29,7 +29,6 @@ module.exports.handlers =
'poll': 'polls/poll_handler'
'prepaid': 'prepaids/prepaid_handler'
'subscription': 'payments/subscription_handler'
'trial_request': 'trial_requests/trial_request_handler'
'user_polls_record': 'polls/user_polls_record_handler'
module.exports.handlerUrlOverrides =
@ -44,7 +43,6 @@ module.exports.handlerUrlOverrides =
'user_remark': 'user.remark'
'mail_sent': 'mail.sent'
'user_polls_record': 'user.polls.record'
'trial_request': 'trial.request'
'user_code_problem': 'user.code.problem'
module.exports.routes =

View file

@ -4,5 +4,6 @@ module.exports =
named: require './named'
patchable: require './patchable'
rest: require './rest'
trialRequests: require './trial-requests'
users: require './users'
versions: require './versions'

View file

@ -0,0 +1,44 @@
utils = require '../lib/utils'
errors = require '../commons/errors'
wrap = require 'co-express'
Promise = require 'bluebird'
database = require '../commons/database'
mongoose = require 'mongoose'
TrialRequest = require '../models/TrialRequest'
module.exports =
post: wrap (req, res) ->
if req.user.isAnonymous()
email = req.body?.properties?.email
throw new errors.UnprocessableEntity('Email not provided.') unless email
email = email.toLowerCase()
user = yield User.findOne({emailLower: email})
throw new errors.Conflict('User with this email already exists.') if user
trialRequest = database.initDoc(req, TrialRequest)
trialRequest.set 'applicant', req.user._id
trialRequest.set 'created', new Date()
trialRequest.set 'status', 'submitted'
database.assignBody(req, trialRequest)
database.validateDoc(trialRequest)
trialRequest = yield trialRequest.save()
res.status(201).send(trialRequest.toObject({req: req}))
put: wrap (req, res) ->
trialRequest = yield database.getDocFromHandle(req, TrialRequest)
throw new errors.NotFound('Trial Request not found.') if not trialRequest
database.assignBody(req, trialRequest)
trialRequest.set('reviewDate', new Date())
trialRequest.set('reviewer', req.user.get('_id'))
database.validateDoc(trialRequest)
trialRequest = yield trialRequest.save()
res.status(200).send(trialRequest.toObject({req: req}))
fetchByApplicant: wrap (req, res, next) ->
applicantID = req.query.applicant
return next() unless applicantID
throw new errors.UnprocessableEntity('Bad applicant id') unless utils.isID(applicantID)
throw new errors.Forbidden('May not fetch for anyone but yourself') unless req.user.id is applicantID
trialRequests = yield TrialRequest.find({applicant: mongoose.Types.ObjectId(applicantID)})
trialRequests = (tr.toObject({req: req}) for tr in trialRequests)
res.status(200).send(trialRequests)

View file

@ -26,6 +26,12 @@ module.exports.setup = (app) ->
app.get('/db/user', mw.users.fetchByGPlusID, mw.users.fetchByFacebookID)
app.get '/db/products', require('./db/product').get
TrialRequest = require '../models/TrialRequest'
app.get('/db/trial.request', mw.trialRequests.fetchByApplicant, mw.auth.checkHasPermission(['admin']), mw.rest.get(TrialRequest))
app.post('/db/trial.request', mw.auth.checkLoggedIn(), mw.trialRequests.post)
app.get('/db/trial.request/:handle', mw.auth.checkHasPermission(['admin']), mw.rest.getByHandle(TrialRequest))
app.put('/db/trial.request/:handle', mw.auth.checkHasPermission(['admin']), mw.trialRequests.put)
app.get '/healthcheck', (req, res) ->
try

View file

@ -1,54 +0,0 @@
async = require 'async'
log = require 'winston'
mongoose = require 'mongoose'
Handler = require '../commons/Handler'
TrialRequest = require './TrialRequest'
User = require '../users/User'
TrialRequestHandler = class TrialRequestHandler extends Handler
modelClass: TrialRequest
jsonSchema: require '../../app/schemas/models/trial_request.schema'
hasAccess: (req) ->
req.method in ['POST'] or req.user?.isAdmin()
hasAccessToDocument: (req, document, method=null) ->
return false unless document?
return true if req.user?.isAdmin()
false
makeNewInstance: (req) ->
instance = super(req)
instance.set 'applicant', req.user._id
instance.set 'created', new Date()
instance.set 'status', 'submitted'
instance
post: (req, res) ->
return @sendForbiddenError(res) unless req.user?
if req.user.isAnonymous()
email = req.body?.properties?.email
return @sendBadInputError(res, 'email not provided') unless email
User.findOne({emailLower: req.body.properties.email}).exec (err, user) =>
return @sendDatabaseError(res, err) if err
return @sendError(res, 409, 'User with this email already exists.') if user
super(req, res)
else
super(req, res)
put: (req, res, id) ->
req.body.reviewDate = new Date()
req.body.reviewer = req.user.get('_id')
super(req, res, id)
getByRelationship: (req, res, args...) ->
return @getOwn(req, res) if args[1] is 'own'
super(arguments...)
getOwn: (req, res) ->
return @sendForbiddenError(res) unless req.user?
TrialRequest.find {applicant: req.user.get('_id')}, (err, documents) =>
return @sendDatabaseError(res, err) if err
@sendSuccess(res, documents)
module.exports = new TrialRequestHandler()

View file

@ -32,7 +32,7 @@ models_path = [
'../../server/achievements/EarnedAchievement'
'../../server/payments/Payment'
'../../server/prepaids/Prepaid'
'../../server/trial_requests/TrialRequest'
'../../server/models/TrialRequest'
]
for m in models_path

View file

@ -1,172 +1,156 @@
require '../common'
utils = require '../utils'
_ = require 'lodash'
Promise = require 'bluebird'
describe 'Trial Requests', ->
fixture = {
type: 'subscription'
properties:
location: 'SF, CA'
age: '14-17'
numStudents: 14
heardAbout: 'magical interwebs'
}
describe 'POST /db/trial.request', ->
URL = getURL('/db/trial.request')
ownURL = getURL('/db/trial.request/-/own')
createTrialRequest = (user, type, properties, done) ->
requestBody =
type: type
properties: properties
request.post {uri: URL, json: requestBody }, (err, res, body) ->
expect(err).toBeNull()
beforeEach utils.wrap (done) ->
yield utils.clearModels([User, TrialRequest])
@user = yield utils.initUser()
yield utils.loginUser(@user)
fixture.properties.email = @user.get('email')
[res, body] = yield request.postAsync(getURL('/db/trial.request'), { json: fixture })
expect(res.statusCode).toBe(201)
expect(body._id).toBeDefined()
@trialRequest = yield TrialRequest.findById(body._id)
done()
it 'sets type and properties given', ->
expect(@trialRequest.get('type')).toBe('subscription')
expect(@trialRequest.get('properties').location).toBe('SF, CA')
it 'sets applicant to the user\'s id', ->
expect(@trialRequest.get('applicant').equals(@user._id)).toBe(true)
describe 'GET /db/trial.request', ->
beforeEach utils.wrap (done) ->
yield utils.clearModels([User, TrialRequest])
@user = yield utils.initUser()
yield utils.loginUser(@user)
fixture.properties.email = @user.get('email')
[res, body] = yield request.postAsync(getURL('/db/trial.request'), { json: fixture })
@trialRequest = yield TrialRequest.findById(body._id)
done()
it 'returns 403 to non-admins', utils.wrap (done) ->
[res, body] = yield request.getAsync(getURL('/db/trial.request'))
expect(res.statusCode).toEqual(403)
done()
it 'returns trial requests to admins', utils.wrap (done) ->
@admin = yield utils.initAdmin()
yield utils.loginUser(@admin)
[res, body] = yield request.getAsync(getURL('/db/trial.request'), { json: true })
expect(res.statusCode).toEqual(200)
expect(body.length).toBe(1)
done()
describe 'GET /db/trial.request?applicant=:userID', ->
beforeEach utils.wrap (done) ->
yield utils.clearModels([User, TrialRequest])
@user1 = yield utils.initUser()
@user2 = yield utils.initUser()
yield utils.loginUser(@user1)
@trialRequest1 = new TrialRequest({applicant: @user1._id})
yield @trialRequest1.save()
@trialRequest2 = yield new TrialRequest({applicant: @user2._id}).save()
done()
it 'returns trial requests for the given applicant', utils.wrap (done) ->
[res, body] = yield request.getAsync(getURL('/db/trial.request?applicant='+@user1.id), { json: true })
expect(res.statusCode).toEqual(200)
expect(body.length).toBe(1)
expect(body[0]._id).toBe(@trialRequest1.id)
done()
it 'returns 403 when non-admins request other people\'s trial requests', utils.wrap (done) ->
[res, body] = yield request.getAsync(getURL('/db/trial.request?applicant='+@user2.id), { json: true })
expect(res.statusCode).toEqual(403)
done()
describe 'PUT /db/trial.request/:handle', ->
putURL = null
beforeEach utils.wrap (done) ->
yield utils.clearModels([User, TrialRequest])
@user = yield utils.initUser()
yield utils.loginUser(@user)
fixture.properties.email = @user.get('email')
[res, body] = yield request.postAsync(getURL('/db/trial.request'), { json: fixture })
@trialRequest = yield TrialRequest.findById(body._id)
putURL = getURL('/db/trial.request/'+@trialRequest.id)
done()
it 'returns 403 to non-admins', ->
[res, body] = yield request.putAsync(getURL("/db/trial.request/#{@trialRequest.id}"))
expect(res.statusCode).toEqual(403)
done()
describe 'set status to "approved"', ->
beforeEach utils.wrap (done) ->
@admin = yield utils.initAdmin()
yield utils.loginUser(@admin)
[res, body] = yield request.putAsync(putURL, { json: { status: 'approved' } })
expect(res.statusCode).toBe(200)
expect(body.type).toEqual(type)
expect(body.properties).toEqual(properties)
expect(body.applicant).toEqual(user.id)
expect(body.status).toEqual('submitted')
TrialRequest.findById body._id, (err, doc) ->
expect(err).toBeNull()
expect(doc.get('type')).toEqual(type)
expect(doc.get('properties')).toEqual(properties)
expect(doc.get('applicant')).toEqual(user._id)
expect(doc.get('status')).toEqual('submitted')
done(doc)
it 'Clear database', (done) ->
clearModels [User, TrialRequest], (err) ->
throw err if err
expect(body.status).toBe('approved')
setTimeout done, 10 # let changes propagate
it 'sets reviewDate and reviewer', utils.wrap (done) ->
trialRequest = yield TrialRequest.findById(@trialRequest.id)
expect(trialRequest.get('reviewDate')).toBeDefined()
expect(trialRequest.get('reviewer').equals(@admin._id))
expect(new Date(trialRequest.get('reviewDate'))).toBeLessThan(new Date())
done()
it 'gives the user two enrollments', utils.wrap (done) ->
prepaids = yield Prepaid.find({'properties.trialRequestID': @trialRequest._id})
expect(prepaids.length).toEqual(1)
prepaid = prepaids[0]
expect(prepaid.get('type')).toEqual('course')
expect(prepaid.get('creator')).toEqual(@user.get('_id'))
expect(prepaid.get('maxRedeemers')).toEqual(2)
done()
it 'enables teacherNews for the user', utils.wrap (done) ->
user = yield User.findById(@user._id)
expect(user.get('emails')?.teacherNews?.enabled).toEqual(true)
done()
it 'Create trial request', (done) ->
loginNewUser (user) ->
properties =
email: user.get('email')
location: 'SF, CA'
age: '14-17'
numStudents: 14
heardAbout: 'magical interwebs'
createTrialRequest user, 'subscription', properties, (trialRequest) ->
done()
describe 'set status to "denied"', ->
it 'Get trial requests, non-admin', (done) ->
loginNewUser (user) ->
properties =
email: user.get('email')
location: 'SF, CA'
age: '14-17'
numStudents: 14
heardAbout: 'magical interwebs'
createTrialRequest user, 'subscription', properties, (trialRequest) ->
request.get URL, (err, res, body) ->
expect(res.statusCode).toEqual(403)
done()
beforeEach utils.wrap (done) ->
@admin = yield utils.initAdmin()
yield utils.loginUser(@admin)
[res, body] = yield request.putAsync(putURL, { json: { status: 'denied' } })
expect(res.statusCode).toBe(200)
expect(body.status).toBe('denied')
setTimeout done, 10 # let changes propagate
it 'Get trial requests, admin', (done) ->
loginNewUser (user) ->
properties =
email: user.get('email')
location: 'SF, CA'
age: '14-17'
numStudents: 14
heardAbout: 'magical interwebs'
createTrialRequest user, 'subscription', properties, (trialRequest) ->
loginNewUser (admin) ->
admin.set('permissions', ['admin'])
admin.save (err, user) ->
request.get URL, (err, res, body) ->
expect(res.statusCode).toEqual(200)
expect(body.length).toBeGreaterThan(0)
done()
it 'Get own trial requests', (done) ->
loginNewUser (user) ->
properties =
email: user.get('email')
location: 'SF, CA'
age: '14-17'
numStudents: 14
heardAbout: 'magical interwebs'
createTrialRequest user, 'subscription', properties, (trialRequest) ->
request.get ownURL, (err, res, body) ->
expect(res.statusCode).toEqual(200)
ownRequests = JSON.parse(body)
expect(ownRequests.length).toEqual(1)
expect(ownRequests[0]._id).toEqual(trialRequest.id)
done()
it 'Get non-owned trial request, non-admin', (done) ->
loginNewUser (user) ->
properties =
email: user.get('email')
location: 'SF, CA'
age: '14-17'
numStudents: 14
heardAbout: 'magical interwebs'
createTrialRequest user, 'subscription', properties, (trialRequest) ->
loginNewUser (user2) ->
request.get URL + "/#{trialRequest.id}", (err, res, body) ->
expect(res.statusCode).toEqual(403)
done()
it 'Approve trial request', (done) ->
loginNewUser (user) ->
properties =
email: user.get('email')
location: 'SF, CA'
age: '14-17'
numStudents: 14
heardAbout: 'magical interwebs'
createTrialRequest user, 'subscription', properties, (trialRequest) ->
loginNewUser (admin) ->
admin.set('permissions', ['admin'])
admin.save (err, admin) ->
requestBody = trialRequest.toObject()
requestBody.status = 'approved'
request.put {uri: URL, json: requestBody }, (err, res, body) ->
expect(err).toBeNull()
expect(res.statusCode).toBe(200)
expect(body.status).toEqual('approved')
expect(body.reviewDate).toBeDefined()
expect(new Date(body.reviewDate)).toBeLessThan(new Date())
expect(body.reviewer).toEqual(admin.id)
TrialRequest.findById body._id, (err, doc) ->
expect(err).toBeNull()
expect(doc.get('status')).toEqual('approved')
expect(doc.get('reviewDate')).toBeDefined()
expect(new Date(doc.get('reviewDate'))).toBeLessThan(new Date())
expect(doc.get('reviewer')).toEqual(admin._id)
Prepaid.find {'properties.trialRequestID': doc.get('_id')}, (err, prepaids) ->
expect(err).toBeNull()
return done(err) if err
expect(prepaids.length).toEqual(1)
prepaid = prepaids[0]
expect(prepaid.get('type')).toEqual('course')
expect(prepaid.get('creator')).toEqual(user.get('_id'))
expect(prepaid.get('maxRedeemers')).toEqual(2)
User.findById user._id, (err, user) =>
expect(err).toBeNull()
return done(err) if err
expect(user.get('emails')?.teacherNews?.enabled).toEqual(true)
done()
it 'Deny trial request', (done) ->
loginNewUser (user) ->
properties =
email: user.get('email')
location: 'SF, CA'
age: '14-17'
numStudents: 14
heardAbout: 'magical interwebs'
createTrialRequest user, 'subscription', properties, (trialRequest) ->
loginNewUser (admin) ->
admin.set('permissions', ['admin'])
admin.save (err, user) ->
requestBody = trialRequest.toObject()
requestBody.status = 'denied'
request.put {uri: URL, json: requestBody }, (err, res, body) ->
expect(err).toBeNull()
expect(res.statusCode).toBe(200)
expect(body.status).toEqual('denied')
expect(body.reviewDate).toBeDefined()
expect(new Date(body.reviewDate)).toBeLessThan(new Date())
expect(body.reviewer).toEqual(admin.id)
expect(body.prepaidCode).not.toBeDefined()
TrialRequest.findById body._id, (err, doc) ->
expect(err).toBeNull()
expect(doc.get('status')).toEqual('denied')
expect(doc.get('reviewDate')).toBeDefined()
expect(new Date(doc.get('reviewDate'))).toBeLessThan(new Date())
expect(doc.get('reviewer')).toEqual(admin._id)
expect(doc.get('prepaidCode')).not.toBeDefined()
done()
it 'sets reviewDate and reviewer', utils.wrap (done) ->
trialRequest = yield TrialRequest.findById(@trialRequest.id)
expect(trialRequest.get('reviewDate')).toBeDefined()
expect(trialRequest.get('reviewer').equals(@admin._id))
expect(new Date(trialRequest.get('reviewDate'))).toBeLessThan(new Date())
done()
it 'does not give the user two enrollments', utils.wrap (done) ->
prepaids = yield Prepaid.find({'properties.trialRequestID': @trialRequest._id})
expect(prepaids.length).toEqual(0)
done()