codecombat/app/models/Classroom.coffee

191 lines
6.2 KiB
CoffeeScript
Raw Normal View History

2015-11-03 19:41:06 -05:00
CocoModel = require './CocoModel'
schema = require 'schemas/models/classroom.schema'
utils = require '../core/utils'
Improve student account recovery This adds the ability to verify email addresses of a user, so we know they have access to the email address on their account. Until a user has verified their email address, any teacher of a class they're in can reset their password for them via the Teacher Dashboard. When a user's email address is verified, a teacher may trigger a password recovery email to be sent to the student. Verification links are valid forever, until the user changes the email address they have on file. They are created using a timestamp, with a sha256 of timestamp+salt+userID+email. Currently the hash value is rather long, could be shorter. Squashed commit messages: Add server endpoints for verifying email address Add server endpoints for verifying email address (pt 2) Add Server+Client endpoint for sending verification email Add client view for verification links Add Edit Student Modal for resetting passwords Add specs for EditStudentModal Tweak method name in EditStudentModal Add edit student button to TeacherClassView Fix up frontend for teacher password resetting Add middleware for teacher password resetting Improve button UX in EditStudentModal Add JoinClassModal Add welcome emails, use broad name Use email without domain as fallback instead of full email Fetch user on edit student modal open Don't allow password reset if student email is verified Set role to student on user signup with classCode Tweak interface for joinClassModal Add button to request verification email for yourself Fix verify email template ID Move text to en.coffee Minor tweaks Fix code review comments Fix some tests, disable a broken one Fix misc tests Fix more tests Refactor recovery email sending to auth Fix overbroad sass Add options to refactored recovery email function Rename getByCode to fetchByCode Fix error message Fix up error handling in users middleware Use .get instead of .toObject Use findById Fix more code review comments Disable still-broken test
2016-05-11 17:39:26 -04:00
User = require 'models/User'
2015-11-03 19:41:06 -05:00
module.exports = class Classroom extends CocoModel
@className: 'Classroom'
@schema: schema
urlRoot: '/db/classroom'
2016-03-30 16:57:19 -04:00
initialize: () ->
@listenTo @, 'change:aceConfig', @capitalizeLanguageName
super(arguments...)
Improve student account recovery This adds the ability to verify email addresses of a user, so we know they have access to the email address on their account. Until a user has verified their email address, any teacher of a class they're in can reset their password for them via the Teacher Dashboard. When a user's email address is verified, a teacher may trigger a password recovery email to be sent to the student. Verification links are valid forever, until the user changes the email address they have on file. They are created using a timestamp, with a sha256 of timestamp+salt+userID+email. Currently the hash value is rather long, could be shorter. Squashed commit messages: Add server endpoints for verifying email address Add server endpoints for verifying email address (pt 2) Add Server+Client endpoint for sending verification email Add client view for verification links Add Edit Student Modal for resetting passwords Add specs for EditStudentModal Tweak method name in EditStudentModal Add edit student button to TeacherClassView Fix up frontend for teacher password resetting Add middleware for teacher password resetting Improve button UX in EditStudentModal Add JoinClassModal Add welcome emails, use broad name Use email without domain as fallback instead of full email Fetch user on edit student modal open Don't allow password reset if student email is verified Set role to student on user signup with classCode Tweak interface for joinClassModal Add button to request verification email for yourself Fix verify email template ID Move text to en.coffee Minor tweaks Fix code review comments Fix some tests, disable a broken one Fix misc tests Fix more tests Refactor recovery email sending to auth Fix overbroad sass Add options to refactored recovery email function Rename getByCode to fetchByCode Fix error message Fix up error handling in users middleware Use .get instead of .toObject Use findById Fix more code review comments Disable still-broken test
2016-05-11 17:39:26 -04:00
parse: (obj) ->
if obj._id
# It's just the classroom object
return obj
else
# It's a compound response with other stuff too
@owner = new User(obj.owner)
return obj.data
2016-03-30 16:57:19 -04:00
capitalizeLanguageName: ->
language = @get('aceConfig')?.language
@capitalLanguage = utils.capitalLanguages[language]
joinWithCode: (code, opts) ->
options = {
Improve student account recovery This adds the ability to verify email addresses of a user, so we know they have access to the email address on their account. Until a user has verified their email address, any teacher of a class they're in can reset their password for them via the Teacher Dashboard. When a user's email address is verified, a teacher may trigger a password recovery email to be sent to the student. Verification links are valid forever, until the user changes the email address they have on file. They are created using a timestamp, with a sha256 of timestamp+salt+userID+email. Currently the hash value is rather long, could be shorter. Squashed commit messages: Add server endpoints for verifying email address Add server endpoints for verifying email address (pt 2) Add Server+Client endpoint for sending verification email Add client view for verification links Add Edit Student Modal for resetting passwords Add specs for EditStudentModal Tweak method name in EditStudentModal Add edit student button to TeacherClassView Fix up frontend for teacher password resetting Add middleware for teacher password resetting Improve button UX in EditStudentModal Add JoinClassModal Add welcome emails, use broad name Use email without domain as fallback instead of full email Fetch user on edit student modal open Don't allow password reset if student email is verified Set role to student on user signup with classCode Tweak interface for joinClassModal Add button to request verification email for yourself Fix verify email template ID Move text to en.coffee Minor tweaks Fix code review comments Fix some tests, disable a broken one Fix misc tests Fix more tests Refactor recovery email sending to auth Fix overbroad sass Add options to refactored recovery email function Rename getByCode to fetchByCode Fix error message Fix up error handling in users middleware Use .get instead of .toObject Use findById Fix more code review comments Disable still-broken test
2016-05-11 17:39:26 -04:00
url: @urlRoot + '/~/members'
type: 'POST'
data: { code: code }
Improve student account recovery This adds the ability to verify email addresses of a user, so we know they have access to the email address on their account. Until a user has verified their email address, any teacher of a class they're in can reset their password for them via the Teacher Dashboard. When a user's email address is verified, a teacher may trigger a password recovery email to be sent to the student. Verification links are valid forever, until the user changes the email address they have on file. They are created using a timestamp, with a sha256 of timestamp+salt+userID+email. Currently the hash value is rather long, could be shorter. Squashed commit messages: Add server endpoints for verifying email address Add server endpoints for verifying email address (pt 2) Add Server+Client endpoint for sending verification email Add client view for verification links Add Edit Student Modal for resetting passwords Add specs for EditStudentModal Tweak method name in EditStudentModal Add edit student button to TeacherClassView Fix up frontend for teacher password resetting Add middleware for teacher password resetting Improve button UX in EditStudentModal Add JoinClassModal Add welcome emails, use broad name Use email without domain as fallback instead of full email Fetch user on edit student modal open Don't allow password reset if student email is verified Set role to student on user signup with classCode Tweak interface for joinClassModal Add button to request verification email for yourself Fix verify email template ID Move text to en.coffee Minor tweaks Fix code review comments Fix some tests, disable a broken one Fix misc tests Fix more tests Refactor recovery email sending to auth Fix overbroad sass Add options to refactored recovery email function Rename getByCode to fetchByCode Fix error message Fix up error handling in users middleware Use .get instead of .toObject Use findById Fix more code review comments Disable still-broken test
2016-05-11 17:39:26 -04:00
success: => @trigger 'join:success'
error: => @trigger 'join:error'
}
_.extend options, opts
@fetch(options)
Improve student account recovery This adds the ability to verify email addresses of a user, so we know they have access to the email address on their account. Until a user has verified their email address, any teacher of a class they're in can reset their password for them via the Teacher Dashboard. When a user's email address is verified, a teacher may trigger a password recovery email to be sent to the student. Verification links are valid forever, until the user changes the email address they have on file. They are created using a timestamp, with a sha256 of timestamp+salt+userID+email. Currently the hash value is rather long, could be shorter. Squashed commit messages: Add server endpoints for verifying email address Add server endpoints for verifying email address (pt 2) Add Server+Client endpoint for sending verification email Add client view for verification links Add Edit Student Modal for resetting passwords Add specs for EditStudentModal Tweak method name in EditStudentModal Add edit student button to TeacherClassView Fix up frontend for teacher password resetting Add middleware for teacher password resetting Improve button UX in EditStudentModal Add JoinClassModal Add welcome emails, use broad name Use email without domain as fallback instead of full email Fetch user on edit student modal open Don't allow password reset if student email is verified Set role to student on user signup with classCode Tweak interface for joinClassModal Add button to request verification email for yourself Fix verify email template ID Move text to en.coffee Minor tweaks Fix code review comments Fix some tests, disable a broken one Fix misc tests Fix more tests Refactor recovery email sending to auth Fix overbroad sass Add options to refactored recovery email function Rename getByCode to fetchByCode Fix error message Fix up error handling in users middleware Use .get instead of .toObject Use findById Fix more code review comments Disable still-broken test
2016-05-11 17:39:26 -04:00
fetchByCode: (code, opts) ->
options = {
url: _.result(@, 'url')
data: { code: code, "with-owner": true }
}
_.extend options, opts
@fetch(options)
getLevelNumber: (levelID, defaultNumber) ->
unless @levelNumberMap
@levelNumberMap = {}
language = @get('aceConfig')?.language
for course in @get('courses') ? []
levels = []
for level in course.levels when level.original
continue if language? and level.primerLanguage is language
levels.push({key: level.original, practice: level.practice ? false})
_.assign(@levelNumberMap, utils.createLevelNumberMap(levels))
@levelNumberMap[levelID] ? defaultNumber
removeMember: (userID, opts) ->
options = {
url: _.result(@, 'url') + '/members'
type: 'DELETE'
data: { userID: userID }
}
_.extend options, opts
2016-03-30 16:57:19 -04:00
@fetch(options)
setStudentPassword: (student, password, options) ->
classroomID = @.id
$.ajax {
url: "/db/classroom/#{classroomID}/members/#{student.id}/reset-password"
method: 'POST'
data: { password }
success: => @trigger 'save-password:success'
error: (response) => @trigger 'save-password:error', response.responseJSON
}
2016-04-13 12:54:24 -04:00
getLevels: (options={}) ->
# options: courseID, withoutLadderLevels, projectLevels
2016-04-13 12:54:24 -04:00
Levels = require 'collections/Levels'
courses = @get('courses')
return new Levels() unless courses
levelObjects = []
for course in courses
if options.courseID and options.courseID isnt course._id
continue
levelObjects.push(course.levels)
levels = new Levels(_.flatten(levelObjects))
language = @get('aceConfig')?.language
levels.remove(levels.filter((level) => level.get('primerLanguage') is language)) if language
2016-04-13 12:54:24 -04:00
if options.withoutLadderLevels
levels.remove(levels.filter((level) -> level.isLadder()))
if options.projectLevels
levels.remove(levels.filter((level) -> level.get('shareable') isnt 'project'))
2016-04-13 12:54:24 -04:00
return levels
2016-04-13 12:54:24 -04:00
getLadderLevel: (courseID) ->
Levels = require 'collections/Levels'
courses = @get('courses')
course = _.findWhere(courses, {_id: courseID})
return unless course
levels = new Levels(course.levels)
return levels.find (l) -> l.isLadder()
2016-08-11 19:38:14 -04:00
getProjectLevel: (courseID) ->
Levels = require 'collections/Levels'
courses = @get('courses')
course = _.findWhere(courses, {_id: courseID})
return unless course
levels = new Levels(course.levels)
return levels.find (l) -> l.isProject()
2016-04-13 12:54:24 -04:00
statsForSessions: (sessions, courseID) ->
return null unless sessions
sessions = sessions.models or sessions
arena = @getLadderLevel(courseID)
2016-08-11 19:38:14 -04:00
project = @getProjectLevel(courseID)
courseLevels = @getLevels({courseID: courseID, withoutLadderLevels: true})
levelSessionMap = {}
levelSessionMap[session.get('level').original] = session for session in sessions
currentIndex = -1
lastStarted = null
levelsTotal = 0
levelsLeft = 0
lastPlayed = null
playtime = 0
levels = []
for level, index in courseLevels.models
levelsTotal++ unless level.get('practice')
complete = false
if session = levelSessionMap[level.get('original')]
complete = session.get('state').complete ? false
playtime += session.get('playtime') ? 0
lastPlayed = level
if complete
currentIndex = index
else
lastStarted = level
levelsLeft++ unless level.get('practice')
else if not level.get('practice')
levelsLeft++
levels.push
practice: level.get('practice') ? false
complete: complete
lastPlayed = lastStarted ? lastPlayed
needsPractice = false
nextIndex = 0
if currentIndex >= 0
currentLevel = courseLevels.models[currentIndex]
currentPlaytime = levelSessionMap[currentLevel.get('original')]?.get('playtime') ? 0
needsPractice = utils.needsPractice(currentPlaytime, currentLevel.get('practiceThresholdMinutes'))
nextIndex = utils.findNextLevel(levels, currentIndex, needsPractice)
nextLevel = courseLevels.models[nextIndex]
nextLevel ?= _.find courseLevels.models, (level) -> not levelSessionMap[level.get('original')]?.get('state')?.complete
stats =
levels:
size: levelsTotal
left: levelsLeft
done: levelsLeft is 0
numDone: levelsTotal - levelsLeft
pctDone: (100 * (levelsTotal - levelsLeft) / levelsTotal).toFixed(1) + '%'
lastPlayed: lastPlayed
next: nextLevel
first: courseLevels.first()
arena: arena
2016-08-11 19:38:14 -04:00
project: project
playtime: playtime
stats
2016-04-13 12:54:24 -04:00
fetchForCourseInstance: (courseInstanceID, options={}) ->
return unless courseInstanceID
2016-04-13 12:54:24 -04:00
CourseInstance = require 'models/CourseInstance'
courseInstance = if _.isString(courseInstanceID) then new CourseInstance({_id:courseInstanceID}) else courseInstanceID
options = _.extend(options, {
url: _.result(courseInstance, 'url') + '/classroom'
})
@fetch(options)
inviteMembers: (emails, options={}) ->
options.data ?= {}
2016-06-06 16:43:41 -04:00
options.data.emails = emails
options.url = @url() + '/invite-members'
options.type = 'POST'
@fetch(options)
updateCourses: (options={}) ->
options.url = @url() + '/update-courses'
options.type = 'POST'
@fetch(options)