mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-12-12 00:31:21 -05:00
Merge branch 'master' into production
This commit is contained in:
commit
b837de2394
14 changed files with 172 additions and 6 deletions
|
@ -55,7 +55,7 @@ module.exports = FacebookHandler = class FacebookHandler extends CocoClass
|
|||
js = d.createElement('script')
|
||||
js.id = id
|
||||
js.async = true
|
||||
js.src = '//connect.facebook.net/en_US/all.js'
|
||||
js.src = '//connect.facebook.net/en_US/sdk.js'
|
||||
|
||||
#js.src = '//connect.facebook.net/en_US/all/debug.js'
|
||||
ref.parentNode.insertBefore js, ref
|
||||
|
@ -63,12 +63,13 @@ module.exports = FacebookHandler = class FacebookHandler extends CocoClass
|
|||
)(document)
|
||||
|
||||
window.fbAsyncInit = =>
|
||||
FB.init
|
||||
FB.init({
|
||||
appId: (if document.location.origin is 'http://localhost:3000' then '607435142676437' else '148832601965463') # App ID
|
||||
channelUrl: document.location.origin + '/channel.html' # Channel File
|
||||
cookie: true # enable cookies to allow the server to access the session
|
||||
xfbml: true # parse XFBML
|
||||
|
||||
version: 'v2.7'
|
||||
})
|
||||
FB.getLoginStatus (response) =>
|
||||
if response.status is 'connected'
|
||||
@connected = true
|
||||
|
|
|
@ -287,6 +287,7 @@
|
|||
email_good: "Email looks good!"
|
||||
name_taken: "Username already taken! Try {{suggestedName}}?"
|
||||
name_available: "Username available!"
|
||||
name_is_email: "Username may not be an email"
|
||||
choose_type: "Choose your account type:"
|
||||
teacher_type_1: "Teach programming using CodeCombat!"
|
||||
teacher_type_2: "Set up your class"
|
||||
|
|
|
@ -354,6 +354,16 @@ module.exports = class User extends CocoModel
|
|||
options.type = 'PUT'
|
||||
@fetch(options)
|
||||
|
||||
destudent: (options={}) ->
|
||||
options.url = _.result(@, 'url') + '/destudent'
|
||||
options.type = 'POST'
|
||||
@fetch(options)
|
||||
|
||||
deteacher: (options={}) ->
|
||||
options.url = _.result(@, 'url') + '/deteacher'
|
||||
options.type = 'POST'
|
||||
@fetch(options)
|
||||
|
||||
tiersByLevel = [-1, 0, 0.05, 0.14, 0.18, 0.32, 0.41, 0.5, 0.64, 0.82, 0.91, 1.04, 1.22, 1.35, 1.48, 1.65, 1.78, 1.96, 2.1, 2.24, 2.38, 2.55, 2.69, 2.86, 3.03, 3.16, 3.29, 3.42, 3.58, 3.74, 3.89, 4.04, 4.19, 4.32, 4.47, 4.64, 4.79, 4.96,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 10, 10.5, 11, 11.5, 12, 12.5, 13, 13.5, 14, 14.5, 15
|
||||
]
|
||||
|
|
|
@ -3,6 +3,12 @@ extends /templates/core/modal-base-flat
|
|||
// DNT
|
||||
|
||||
block modal-header-content
|
||||
.pull-right
|
||||
if view.user.isStudent()
|
||||
button#destudent-btn.btn.btn-burgandy Destudent
|
||||
if view.user.isTeacher()
|
||||
button#deteacher-btn.btn.btn-burgandy Deteacher
|
||||
|
||||
h3 Administer User
|
||||
h4 #{view.user.get('name') || 'Unnamed'} / #{view.user.get('email')}
|
||||
span= view.user.id
|
||||
|
|
|
@ -231,7 +231,7 @@ module.exports = class AccountSettingsView extends CocoView
|
|||
$('.nano').nanoScroller({scrollTo: @$el.find('.has-error')})
|
||||
else
|
||||
noty
|
||||
text: res.responseText
|
||||
text: res.responseJSON?.message or res.responseText
|
||||
type: 'error'
|
||||
layout: 'topCenter'
|
||||
timeout: 5000
|
||||
|
|
|
@ -13,6 +13,8 @@ module.exports = class AdministerUserModal extends ModalView
|
|||
events:
|
||||
'click #save-changes': 'onClickSaveChanges'
|
||||
'click #add-seats-btn': 'onClickAddSeatsButton'
|
||||
'click #destudent-btn': 'onClickDestudentButton'
|
||||
'click #deteacher-btn': 'onClickDeteacherButton'
|
||||
|
||||
initialize: (options, @userHandle) ->
|
||||
@user = new User({_id:@userHandle})
|
||||
|
@ -71,3 +73,33 @@ module.exports = class AdministerUserModal extends ModalView
|
|||
@listenTo prepaid, 'sync', ->
|
||||
@state = 'made-prepaid'
|
||||
@renderSelectors('#prepaid-form')
|
||||
|
||||
onClickDestudentButton: (e) ->
|
||||
button = $(e.currentTarget)
|
||||
button.attr('disabled', true).text('...')
|
||||
Promise.resolve(@user.destudent())
|
||||
.then =>
|
||||
button.remove()
|
||||
.catch (e) =>
|
||||
button.attr('disabled', false).text('Destudent')
|
||||
noty {
|
||||
text: e.message or e.responseJSON?.message or e.responseText or 'Unknown Error'
|
||||
type: 'error'
|
||||
}
|
||||
if e.stack
|
||||
throw e
|
||||
|
||||
onClickDeteacherButton: (e) ->
|
||||
button = $(e.currentTarget)
|
||||
button.attr('disabled', true).text('...')
|
||||
Promise.resolve(@user.deteacher())
|
||||
.then =>
|
||||
button.remove()
|
||||
.catch (e) =>
|
||||
button.attr('disabled', false).text('Destudent')
|
||||
noty {
|
||||
text: e.message or e.responseJSON?.message or e.responseText or 'Unknown Error'
|
||||
type: 'error'
|
||||
}
|
||||
if e.stack
|
||||
throw e
|
||||
|
|
|
@ -146,6 +146,11 @@ module.exports = class BasicInfoView extends CocoView
|
|||
})
|
||||
|
||||
forms.clearFormAlerts(@$el)
|
||||
|
||||
if data.name and forms.validateEmail(data.name)
|
||||
forms.setErrorToProperty(@$el, 'name', $.i18n.t('signup.name_is_email'))
|
||||
return false
|
||||
|
||||
res = tv4.validateMultiple data, @formSchema()
|
||||
forms.applyErrorsToForm(@$('form'), res.errors) unless res.valid
|
||||
return res.valid
|
||||
|
|
|
@ -143,7 +143,7 @@ module.exports = class PlayLevelView extends RootView
|
|||
|
||||
onLevelLoaded: (e) ->
|
||||
@god = new God({@gameUIState}) unless e.level.isType('web-dev')
|
||||
@setUpGod() if @waitingToSetUpGod
|
||||
@setupGod() if @waitingToSetUpGod
|
||||
|
||||
trackLevelLoadEnd: ->
|
||||
return if @isEditorPreview
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
// Unset someone with a student role. Remove from classrooms, unset role.
|
||||
|
||||
// Usage
|
||||
|
|
|
@ -66,4 +66,5 @@ module.exports.modules = modules = # by collection name
|
|||
'users': 'User'
|
||||
|
||||
mongoose.modelNameByCollection = (collection) ->
|
||||
return require('../models/LevelSession') if collection is 'level.sessions'
|
||||
mongoose.model modules[collection] if collection of modules
|
||||
|
|
|
@ -8,9 +8,11 @@ Promise = require 'bluebird'
|
|||
parse = require '../commons/parse'
|
||||
request = require 'request'
|
||||
mongoose = require 'mongoose'
|
||||
database = require '../commons/database'
|
||||
sendwithus = require '../sendwithus'
|
||||
User = require '../models/User'
|
||||
Classroom = require '../models/Classroom'
|
||||
CourseInstance = require '../models/CourseInstance'
|
||||
facebook = require '../lib/facebook'
|
||||
gplus = require '../lib/gplus'
|
||||
TrialRequest = require '../models/TrialRequest'
|
||||
|
@ -211,3 +213,44 @@ module.exports =
|
|||
yield trialRequest.update({$unset: {applicant: ''}})
|
||||
|
||||
res.status(200).send(req.user.toObject({req: req}))
|
||||
|
||||
destudent: wrap (req, res) ->
|
||||
user = yield database.getDocFromHandle(req, User)
|
||||
if not user
|
||||
throw new errors.NotFound('User not found.')
|
||||
|
||||
if not user.isStudent()
|
||||
return res.status(200).send(user.toObject({req: req}))
|
||||
|
||||
yield Classroom.update(
|
||||
{ members: user._id },
|
||||
{ $pull: {members: user._id} },
|
||||
{ multi: true }
|
||||
)
|
||||
|
||||
yield CourseInstance.update(
|
||||
{ members: user._id },
|
||||
{ $pull: {members: user._id} },
|
||||
{ multi: true }
|
||||
)
|
||||
|
||||
yield user.update({ $unset: {role: ''}})
|
||||
user.set('role', undefined)
|
||||
return res.status(200).send(user.toObject({req: req}))
|
||||
|
||||
|
||||
deteacher: wrap (req, res) ->
|
||||
user = yield database.getDocFromHandle(req, User)
|
||||
if not user
|
||||
throw new errors.NotFound('User not found.')
|
||||
|
||||
if not user.isTeacher()
|
||||
return res.status(200).send(user.toObject({req: req}))
|
||||
|
||||
yield TrialRequest.remove(
|
||||
{ applicant: user._id },
|
||||
)
|
||||
|
||||
yield user.update({ $unset: {role: ''}})
|
||||
user.set('role', undefined)
|
||||
return res.status(200).send(user.toObject({req: req}))
|
||||
|
|
|
@ -361,6 +361,10 @@ UserSchema.pre('save', (next) ->
|
|||
@set('email', undefined)
|
||||
@set('emailLower', undefined)
|
||||
if name = @get('name')
|
||||
filter = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,63}$/i # https://news.ycombinator.com/item?id=5763990
|
||||
if filter.test(name)
|
||||
return next(new errors.UnprocessableEntity('Name may not be an email'))
|
||||
|
||||
@set('nameLower', name.toLowerCase())
|
||||
else
|
||||
@set('name', undefined)
|
||||
|
|
|
@ -104,6 +104,8 @@ module.exports.setup = (app) ->
|
|||
app.post('/db/user/:handle/signup-with-facebook', mw.users.signupWithFacebook)
|
||||
app.post('/db/user/:handle/signup-with-gplus', mw.users.signupWithGPlus)
|
||||
app.post('/db/user/:handle/signup-with-password', mw.users.signupWithPassword)
|
||||
app.post('/db/user/:handle/destudent', mw.auth.checkHasPermission(['admin']), mw.users.destudent)
|
||||
app.post('/db/user/:handle/deteacher', mw.auth.checkHasPermission(['admin']), mw.users.deteacher)
|
||||
|
||||
app.get('/db/prepaid', mw.auth.checkLoggedIn(), mw.prepaids.fetchByCreator)
|
||||
app.get('/db/prepaid/-/active-schools', mw.auth.checkHasPermission(['admin']), mw.prepaids.fetchActiveSchools)
|
||||
|
|
|
@ -3,6 +3,9 @@ utils = require '../utils'
|
|||
urlUser = '/db/user'
|
||||
User = require '../../../server/models/User'
|
||||
Classroom = require '../../../server/models/Classroom'
|
||||
CourseInstance = require '../../../server/models/CourseInstance'
|
||||
Course = require '../../../server/models/Course'
|
||||
Campaign = require '../../../server/models/Campaign'
|
||||
TrialRequest = require '../../../server/models/TrialRequest'
|
||||
Prepaid = require '../../../server/models/Prepaid'
|
||||
request = require '../request'
|
||||
|
@ -970,3 +973,62 @@ describe 'POST /db/user/:handle/signup-with-gplus', ->
|
|||
expect(res.statusCode).toBe(409)
|
||||
done()
|
||||
|
||||
describe 'POST /db/user/:handle/destudent', ->
|
||||
beforeEach utils.wrap (done) ->
|
||||
yield utils.clearModels([User, Classroom, CourseInstance, Course, Campaign])
|
||||
done()
|
||||
|
||||
it 'removes a student user from all classrooms and unsets their role property', utils.wrap (done) ->
|
||||
student1 = yield utils.initUser({role: 'student'})
|
||||
student2 = yield utils.initUser({role: 'student'})
|
||||
members = [student1._id, student2._id]
|
||||
|
||||
classroom = new Classroom({members})
|
||||
yield classroom.save()
|
||||
courseInstance = new CourseInstance({members})
|
||||
yield courseInstance.save()
|
||||
|
||||
admin = yield utils.initAdmin()
|
||||
yield utils.loginUser(admin)
|
||||
|
||||
url = getURL("/db/user/#{student1.id}/destudent")
|
||||
[res, body] = yield request.postAsync({url, json:true})
|
||||
|
||||
student1 = yield User.findById(student1.id)
|
||||
student2 = yield User.findById(student2.id)
|
||||
classroom = yield Classroom.findById(classroom.id)
|
||||
courseInstance = yield CourseInstance.findById(courseInstance.id)
|
||||
|
||||
expect(student1.get('role')).toBeUndefined()
|
||||
expect(student2.get('role')).toBe('student')
|
||||
expect(classroom.get('members').length).toBe(1)
|
||||
expect(classroom.get('members')[0].toString()).toBe(student2.id)
|
||||
expect(courseInstance.get('members').length).toBe(1)
|
||||
expect(courseInstance.get('members')[0].toString()).toBe(student2.id)
|
||||
done()
|
||||
|
||||
describe 'POST /db/user/:handle/deteacher', ->
|
||||
beforeEach utils.wrap (done) ->
|
||||
yield utils.clearModels([User, TrialRequest])
|
||||
done()
|
||||
|
||||
it 'removes a student user from all classrooms and unsets their role property', utils.wrap (done) ->
|
||||
teacher = yield utils.initUser({role: 'teacher'})
|
||||
yield utils.loginUser(teacher)
|
||||
trialRequest = yield utils.makeTrialRequest(teacher)
|
||||
|
||||
admin = yield utils.initAdmin()
|
||||
yield utils.loginUser(admin)
|
||||
|
||||
trialRequest = yield TrialRequest.findById(trialRequest.id)
|
||||
expect(trialRequest).toBeDefined()
|
||||
expect(teacher.get('role')).toBe('teacher')
|
||||
|
||||
url = getURL("/db/user/#{teacher.id}/deteacher")
|
||||
[res, body] = yield request.postAsync({url, json:true})
|
||||
|
||||
trialRequest = yield TrialRequest.findById(trialRequest.id)
|
||||
expect(trialRequest).toBeNull()
|
||||
teacher = yield User.findById(teacher.id)
|
||||
expect(teacher.get('role')).toBeUndefined()
|
||||
done()
|
||||
|
|
Loading…
Reference in a new issue