Merge branch 'master' into production

This commit is contained in:
Matt Lott 2016-04-07 12:15:57 -07:00
commit 5d24bfce56
158 changed files with 1089 additions and 943 deletions

View file

@ -85,6 +85,7 @@ module.exports = class ConvertToTeacherAccountView extends RootView
if error if error
forms.scrollToFirstError() forms.scrollToFirstError()
return return
attrs['siteOrigin'] = 'convert teacher'
@trialRequest = new TrialRequest({ @trialRequest = new TrialRequest({
type: 'course' type: 'course'
properties: attrs properties: attrs

View file

@ -105,6 +105,7 @@ module.exports = class CreateTeacherAccountView extends RootView
if error if error
forms.scrollToFirstError() forms.scrollToFirstError()
return return
trialRequestAttrs['siteOrigin'] = 'create teacher'
@trialRequest = new TrialRequest({ @trialRequest = new TrialRequest({
type: 'course' type: 'course'
properties: trialRequestAttrs properties: trialRequestAttrs

View file

@ -90,6 +90,7 @@ module.exports = class RequestQuoteView extends RootView
if error if error
forms.scrollToFirstError() forms.scrollToFirstError()
return return
attrs['siteOrigin'] = 'demo request'
@trialRequest = new TrialRequest({ @trialRequest = new TrialRequest({
type: 'course' type: 'course'
properties: attrs properties: attrs

View file

@ -12,7 +12,7 @@ var mongoose = require('mongoose');
database.connect(); database.connect();
var Achievement = require('../server/achievements/Achievement'); var Achievement = require('../server/models/Achievement');
var tierNames = { var tierNames = {
"Wood": 1, "Wood": 1,

View file

@ -17,8 +17,8 @@ do (setupLodash = this) ->
database.connect() database.connect()
UserHandler = require '../server/users/user_handler' UserHandler = require '../server/handlers/user_handler'
User = require '../server/users/User' User = require '../server/models/User'
startDate = new Date 2015, 11, 1 startDate = new Date 2015, 11, 1

View file

@ -7,9 +7,9 @@ async = require 'async'
serverSetup = require '../server_setup' serverSetup = require '../server_setup'
sendwithus = require '../server/sendwithus' sendwithus = require '../server/sendwithus'
User = require '../server/users/User' User = require '../server/models/User'
Level = require '../server/levels/Level' Level = require '../server/models/Level'
LevelSession = require '../server/levels/sessions/LevelSession' LevelSession = require '../server/models/LevelSession'
tournamentResults = require '../app/views/play/ladder/tournament_results' tournamentResults = require '../app/views/play/ladder/tournament_results'
alreadyEmailed = [] alreadyEmailed = []

View file

@ -0,0 +1,54 @@
// Usage: mongo <server>/coco -u <read-only-username> -p <read-only-password> what-unlocks-level.js
// Prints the slugs for levels that unlock the level given in findUnlocksForSlug
// CHANGE THIS to whatever level you want to find the unlocks for.
var findUnlocksForSlug = 'kithgard-apprentice';
var campaignSlugs = ['dungeon', 'forest', 'desert', 'mountain', 'glacier'];
print("Levels that unlock " + findUnlocksForSlug + ":");
var unlockLevel = db.levels.findOne({ slug: findUnlocksForSlug });
if(!unlockLevel) {
print("Level " + findUnlocksForSlug + " not found.");
quit();
}
var levelID = unlockLevel.original;
// print(levelID);
campaignSlugs.forEach(function(slug) {
print("*** Searching " + slug + " ***");
var campaign = db.campaigns.findOne({slug: slug });
var levelOriginals = Object.keys(campaign.levels);
//*** Each level in the campaign
levelOriginals.some(function(original) {
var level = campaign.levels[original];
eachLevel(level);
// this stops the .some() after one, for testing
// return true;
});
});
// ***** //
function eachLevel(level) {
if(level.rewards) {
for(var i=0; i < level.rewards.length; i++) {
var reward = level.rewards[i];
if(reward.level && reward.level == levelID) {
var found = db.levels.findOne({original: ObjectId(level.original)});
if(found.slug) {
print(found.slug);
} else {
print("Found unlocking level, but it has no slug: " + JSON.stringify(reward.level));
}
}
}
}
}

View file

@ -12,7 +12,7 @@ do (setupLodash = this) ->
database.connect() database.connect()
EarnedAchievementHandler = require '../server/achievements/earned_achievement_handler' EarnedAchievementHandler = require '../server/handlers/earned_achievement_handler'
log.info 'Starting earned achievement recalculation...' log.info 'Starting earned achievement recalculation...'
EarnedAchievementHandler.constructor.recalculate (err) -> EarnedAchievementHandler.constructor.recalculate (err) ->
log.error err if err? log.error err if err?

View file

@ -12,9 +12,9 @@ do (setupLodash = this) ->
database.connect() database.connect()
User = require '../server/users/User' User = require '../server/models/User'
Payment = require '../server/payments/Payment' Payment = require '../server/models/Payment'
PaymentHandler = require '../server/payments/payment_handler' PaymentHandler = require '../server/handlers/payment_handler'
t0 = new Date().getTime() t0 = new Date().getTime()
total = 100000 total = 100000

View file

@ -12,7 +12,7 @@ do (setupLodash = this) ->
database.connect() database.connect()
### USER STATS ### ### USER STATS ###
UserHandler = require '../server/users/user_handler' UserHandler = require '../server/handlers/user_handler'
report = (func, name, done) -> report = (func, name, done) ->
log.info 'Started ' + name + '...' log.info 'Started ' + name + '...'

View file

@ -13,9 +13,9 @@ do (setupLodash = this) ->
database.connect() database.connect()
LocalMongo = require '../app/lib/LocalMongo' LocalMongo = require '../app/lib/LocalMongo'
User = require '../server/users/User' User = require '../server/models/User'
EarnedAchievement = require '../server/achievements/EarnedAchievement' EarnedAchievement = require '../server/models/EarnedAchievement'
Achievement = require '../server/achievements/Achievement' Achievement = require '../server/models/Achievement'
Achievement.loadAchievements (achievementCategories) -> Achievement.loadAchievements (achievementCategories) ->
# Really, it's just the 'users' category, since we don't keep all the LevelSession achievements in memory, rather letting the clients make those. # Really, it's just the 'users' category, since we don't keep all the LevelSession achievements in memory, rather letting the clients make those.
userAchievements = achievementCategories.users userAchievements = achievementCategories.users

View file

@ -14,8 +14,8 @@ do (setupLodash = this) ->
database.connect() database.connect()
UserHandler = require '../server/users/user_handler' UserHandler = require '../server/handlers/user_handler'
User = require '../server/users/User' User = require '../server/models/User'
userIDs = [ userIDs = [
# Fill in userID strings here # Fill in userID strings here

View file

@ -199,8 +199,8 @@ repeatableAchievements =
b: 1 b: 1
c: 0 c: 0
Achievement = require '../server/achievements/Achievement' Achievement = require '../server/models/Achievement'
EarnedAchievement = require '../server/achievements/EarnedAchievement' EarnedAchievement = require '../server/models/EarnedAchievement'
Achievement.find {}, (err, achievements) -> Achievement.find {}, (err, achievements) ->
achievementIDs = (achievement.get('_id') + '' for achievement in achievements) achievementIDs = (achievement.get('_id') + '' for achievement in achievements)

View file

@ -6,8 +6,8 @@ GLOBAL.Aether = Aether = require 'aether'
async = require 'async' async = require 'async'
serverSetup = require '../server_setup' serverSetup = require '../server_setup'
Level = require '../server/levels/Level' Level = require '../server/models/Level'
LevelSession = require '../server/levels/sessions/LevelSession' LevelSession = require '../server/models/LevelSession'
{createAetherOptions} = require '../app/lib/aether_utils' {createAetherOptions} = require '../app/lib/aether_utils'
i = 0 i = 0

View file

@ -1,43 +0,0 @@
mongoose = require 'mongoose'
plugins = require '../plugins/plugins'
config = require '../../server_config'
ArticleSchema = new mongoose.Schema(body: String, {strict: false,read:config.mongo.readpref})
ArticleSchema.index(
{
index: 1
_fts: 'text'
_ftsx: 1
},
{
name: 'search index'
sparse: true
weights: {body: 1, name: 1}
default_language: 'english'
'language_override': 'searchLanguage'
'textIndexVersion': 2
})
ArticleSchema.index(
{
original: 1
'version.major': -1
'version.minor': -1
},
{
name: 'version index'
unique: true
})
ArticleSchema.index({slug: 1}, {name: 'slug index', sparse: true, unique: true})
ArticleSchema.plugin(plugins.NamedPlugin)
ArticleSchema.plugin(plugins.VersionedPlugin)
ArticleSchema.plugin(plugins.SearchablePlugin, {searchable: ['body', 'name']})
ArticleSchema.plugin(plugins.TranslationCoveragePlugin)
ArticleSchema.plugin(plugins.PatchablePlugin)
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

@ -1,41 +0,0 @@
mongoose = require 'mongoose'
plugins = require '../plugins/plugins'
log = require 'winston'
config = require '../../server_config'
jsonSchema = require '../../app/schemas/models/campaign.schema'
CampaignSchema = new mongoose.Schema(body: String, {strict: false,read:config.mongo.readpref})
CampaignSchema.index({i18nCoverage: 1}, {name: 'translation coverage index', sparse: true})
CampaignSchema.index({slug: 1}, {name: 'slug index', sparse: true, unique: true})
CampaignSchema.index({type: 1}, {name: 'type index', sparse: true})
CampaignSchema.plugin(plugins.NamedPlugin)
CampaignSchema.plugin(plugins.TranslationCoveragePlugin)
CampaignSchema.plugin plugins.PatchablePlugin
CampaignSchema.statics.updateAdjacentCampaigns = (savedCampaign) ->
Campaign = require '../campaigns/Campaign'
query = {}
query["adjacentCampaigns.#{savedCampaign.get '_id'}"] = {$exists: true}
Campaign.find(query).exec (err, campaigns) ->
return log.error "Couldn't search for adjacent campaigns to update because of #{err}" if err
for campaign in campaigns
acs = campaign.get 'adjacentCampaigns'
ac = acs[savedCampaign.get '_id']
# Let's make sure that we're adding translations, otherwise let's not update yet.
# We could possibly remove this; not sure it's worth having.
[oldI18NCount, newI18NCount] = [0, 0]
oldI18NCount += _.size(translations) for lang, translations of ac.i18n ? {}
newI18NCount += _.size(translations) for lang, translations of savedCampaign.get('i18n') ? {}
continue unless newI18NCount > oldI18NCount
ac.i18n = savedCampaign.get('i18n')
# Save without using middleware so that we don't get into a post-save loop.
Campaign.findByIdAndUpdate campaign._id, {$set: {adjacentCampaigns: acs}}, (err, doc) ->
return log.error "Couldn't save updated adjacent campaign because of #{err}" if err
CampaignSchema.post 'save', -> @constructor.updateAdjacentCampaigns @
CampaignSchema.statics.jsonSchema = jsonSchema
module.exports = mongoose.model('campaign', CampaignSchema)

View file

@ -1,63 +0,0 @@
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'
utils = require '../lib/utils'
ClassroomSchema = new mongoose.Schema {}, {strict: false, minimize: false, read:config.mongo.readpref}
ClassroomSchema.index({ownerID: 1}, {name: 'ownerID index'})
ClassroomSchema.index({members: 1}, {name: 'members index'})
ClassroomSchema.index({code: 1}, {name: 'code index', unique: true})
ClassroomSchema.statics.privateProperties = []
ClassroomSchema.statics.editableProperties = [
'description'
'name'
'aceConfig'
'averageStudentExp'
'ageRangeMin'
'ageRangeMax'
'archived'
]
ClassroomSchema.statics.generateNewCode = (done) ->
tryCode = ->
# Use 4 code words once we get past 10M classrooms
codeCamel = utils.getCodeCamel(3)
code = codeCamel.toLowerCase()
Classroom.findOne code: code, (err, classroom) ->
return done() if err
return done(code, codeCamel) unless classroom
tryCode()
tryCode()
ClassroomSchema.pre('save', (next) ->
return next() if @get('code')
Classroom.generateNewCode (code, codeCamel) =>
@set 'code', code
@set 'codeCamel', codeCamel
next()
)
ClassroomSchema.methods.isOwner = (userID) ->
return userID.equals(@get('ownerID'))
ClassroomSchema.methods.isMember = (userID) ->
return _.any @get('members') or [], (memberID) -> userID.equals(memberID)
ClassroomSchema.statics.jsonSchema = jsonSchema
ClassroomSchema.set('toObject', {
transform: (doc, ret, options) ->
return ret unless options.req
user = options.req.user
unless user?.isAdmin() or user?.get('_id').equals(doc.get('ownerID'))
delete ret.code
delete ret.codeCamel
return ret
})
module.exports = Classroom = mongoose.model 'classroom', ClassroomSchema, 'classrooms'

View file

@ -3,8 +3,8 @@ mongoose = require 'mongoose'
Grid = require 'gridfs-stream' Grid = require 'gridfs-stream'
errors = require './errors' errors = require './errors'
log = require 'winston' log = require 'winston'
Patch = require '../patches/Patch' Patch = require '../models/Patch'
User = require '../users/User' User = require '../models/User'
sendwithus = require '../sendwithus' sendwithus = require '../sendwithus'
slack = require '../slack' slack = require '../slack'
deltasLib = require '../../app/core/deltas' deltasLib = require '../../app/core/deltas'

View file

@ -19,7 +19,7 @@ module.exports =
# Hack around Mongoose not exporting Aggregate so that we can patch its exec, too # Hack around Mongoose not exporting Aggregate so that we can patch its exec, too
# https://github.com/LearnBoost/mongoose/issues/1910 # https://github.com/LearnBoost/mongoose/issues/1910
Level = require '../levels/Level' Level = require '../models/Level'
Aggregate = Level.aggregate().constructor Aggregate = Level.aggregate().constructor
maxAge = (Math.random() * 10 + 10) * 60 * 1000 # Randomize so that each server doesn't refresh cache from db at same times maxAge = (Math.random() * 10 + 10) * 60 * 1000 # Randomize so that each server doesn't refresh cache from db at same times
mongooseCache.install(mongoose, {max: 1000, maxAge: maxAge, debug: false}, Aggregate) mongooseCache.install(mongoose, {max: 1000, maxAge: maxAge, debug: false}, Aggregate)

View file

@ -1,35 +1,35 @@
module.exports.handlers = module.exports.handlers =
'analytics_log_event': 'analytics/analytics_log_event_handler' 'analytics_log_event': 'handlers/analytics_log_event_handler'
'analytics_perday': 'analytics/analytics_perday_handler' 'analytics_perday': 'handlers/analytics_perday_handler'
'analytics_string': 'analytics/analytics_string_handler' 'analytics_string': 'handlers/analytics_string_handler'
'analytics_stripe_invoice': 'analytics/analytics_stripe_invoice_handler' 'analytics_stripe_invoice': 'handlers/analytics_stripe_invoice_handler'
# TODO: Disabling this until we know why our app servers CPU grows out of control. # TODO: Disabling this until we know why our app servers CPU grows out of control.
# 'analytics_users_active': 'analytics/analytics_users_active_handler' # 'analytics_users_active': 'handlers/analytics_users_active_handler'
'article': 'articles/article_handler' 'article': 'handlers/article_handler'
'campaign': 'campaigns/campaign_handler' 'campaign': 'handlers/campaign_handler'
'clan': 'clans/clan_handler' 'clan': 'handlers/clan_handler'
'classroom': 'classrooms/classroom_handler' 'classroom': 'handlers/classroom_handler'
'course': 'courses/course_handler' 'course': 'handlers/course_handler'
'course_instance': 'courses/course_instance_handler' 'course_instance': 'handlers/course_instance_handler'
'level': 'levels/level_handler' 'level': 'handlers/level_handler'
'level_component': 'levels/components/level_component_handler' 'level_component': 'handlers/level_component_handler'
'level_feedback': 'levels/feedbacks/level_feedback_handler' 'level_feedback': 'handlers/level_feedback_handler'
'level_session': 'levels/sessions/level_session_handler' 'level_session': 'handlers/level_session_handler'
'level_system': 'levels/systems/level_system_handler' 'level_system': 'handlers/level_system_handler'
'patch': 'patches/patch_handler' 'patch': 'handlers/patch_handler'
'payment': 'payments/payment_handler' 'payment': 'handlers/payment_handler'
'purchase': 'purchases/purchase_handler' 'purchase': 'handlers/purchase_handler'
'thang_type': 'levels/thangs/thang_type_handler' 'thang_type': 'handlers/thang_type_handler'
'user': 'users/user_handler' 'user': 'handlers/user_handler'
'user_code_problem': 'user_code_problems/user_code_problem_handler' 'user_code_problem': 'handlers/user_code_problem_handler'
'user_remark': 'users/remarks/user_remark_handler' 'user_remark': 'handlers/user_remark_handler'
'mail_sent': 'mail/sent/mail_sent_handler' 'mail_sent': 'handlers/mail_sent_handler'
'achievement': 'achievements/achievement_handler' 'achievement': 'handlers/achievement_handler'
'earned_achievement': 'achievements/earned_achievement_handler' 'earned_achievement': 'handlers/earned_achievement_handler'
'poll': 'polls/poll_handler' 'poll': 'handlers/poll_handler'
'prepaid': 'prepaids/prepaid_handler' 'prepaid': 'handlers/prepaid_handler'
'subscription': 'payments/subscription_handler' 'subscription': 'handlers/subscription_handler'
'user_polls_record': 'polls/user_polls_record_handler' 'user_polls_record': 'handlers/user_polls_record_handler'
module.exports.handlerUrlOverrides = module.exports.handlerUrlOverrides =
'analytics_log_event': 'analytics.log.event' 'analytics_log_event': 'analytics.log.event'

View file

@ -1,32 +0,0 @@
mongoose = require 'mongoose'
config = require '../../server_config'
plugins = require '../plugins/plugins'
jsonSchema = require '../../app/schemas/models/course_instance.schema'
CourseInstanceSchema = new mongoose.Schema {
ownerID: mongoose.Schema.Types.ObjectId
courseID: mongoose.Schema.Types.ObjectId
classroomID: mongoose.Schema.Types.ObjectId
prepaidID: mongoose.Schema.Types.ObjectId
members: [mongoose.Schema.Types.ObjectId]
}, {strict: false, minimize: false, read:config.mongo.readpref}
CourseInstanceSchema.index({ownerID: 1}, {name: 'ownerID index'})
CourseInstanceSchema.index({members: 1}, {name: 'members index'})
CourseInstanceSchema.index({classroomID: 1}, {name: 'classroomID index', sparse: true})
CourseInstanceSchema.index({prepaidID: 1}, {name: 'prepaidID index', sparse: true}) # Deprecated? Can we get rid of this?
CourseInstanceSchema.statics.privateProperties = []
CourseInstanceSchema.statics.editableProperties = [
'description'
'name'
'aceConfig'
]
CourseInstanceSchema.statics.postEditableProperties = [
'courseID'
'classroomID'
]
CourseInstanceSchema.statics.jsonSchema = jsonSchema
module.exports = CourseInstance = mongoose.model 'course.instance', CourseInstanceSchema, 'course.instances'

View file

@ -1,4 +1,4 @@
Achievement = require './Achievement' Achievement = require './../models/Achievement'
Handler = require '../commons/Handler' Handler = require '../commons/Handler'
class AchievementHandler extends Handler class AchievementHandler extends Handler

View file

@ -1,9 +1,9 @@
log = require 'winston' log = require 'winston'
mongoose = require 'mongoose' mongoose = require 'mongoose'
utils = require '../lib/utils' utils = require '../lib/utils'
AnalyticsLogEvent = require './AnalyticsLogEvent' AnalyticsLogEvent = require './../models/AnalyticsLogEvent'
Campaign = require '../campaigns/Campaign' Campaign = require '../models/Campaign'
Level = require '../levels/Level' Level = require '../models/Level'
Handler = require '../commons/Handler' Handler = require '../commons/Handler'
class AnalyticsLogEventHandler extends Handler class AnalyticsLogEventHandler extends Handler

View file

@ -1,7 +1,7 @@
AnalyticsPerDay = require './AnalyticsPerDay' AnalyticsPerDay = require './../models/AnalyticsPerDay'
AnalyticsString = require './AnalyticsString' AnalyticsString = require './../models/AnalyticsString'
Campaign = require '../campaigns/Campaign' Campaign = require '../models/Campaign'
Level = require '../levels/Level' Level = require '../models/Level'
Handler = require '../commons/Handler' Handler = require '../commons/Handler'
log = require 'winston' log = require 'winston'

View file

@ -1,4 +1,4 @@
AnalyticsString = require './AnalyticsString' AnalyticsString = require './../models/AnalyticsString'
Handler = require '../commons/Handler' Handler = require '../commons/Handler'
class AnalyticsStringHandler extends Handler class AnalyticsStringHandler extends Handler

View file

@ -1,5 +1,5 @@
Handler = require '../commons/Handler' Handler = require '../commons/Handler'
AnalyticsStripeInvoice = require './AnalyticsStripeInvoice' AnalyticsStripeInvoice = require './../models/AnalyticsStripeInvoice'
class AnalyticsStripeInvoiceHandler extends Handler class AnalyticsStripeInvoiceHandler extends Handler
modelClass: AnalyticsStripeInvoice modelClass: AnalyticsStripeInvoice

View file

@ -1,4 +1,4 @@
AnalyticsUsersActive = require './AnalyticsUsersActive' AnalyticsUsersActive = require './../models/AnalyticsUsersActive'
Handler = require '../commons/Handler' Handler = require '../commons/Handler'
class AnalyticsUsersActiveHandler extends Handler class AnalyticsUsersActiveHandler extends Handler

View file

@ -1,6 +1,6 @@
# TODO: Remove once mapping.coffee is refactored out # TODO: Remove once mapping.coffee is refactored out
Article = require './Article' Article = require './../models/Article'
Handler = require '../commons/Handler' Handler = require '../commons/Handler'
ArticleHandler = class ArticleHandler extends Handler ArticleHandler = class ArticleHandler extends Handler

View file

@ -1,6 +1,6 @@
Campaign = require './Campaign' Campaign = require './../models/Campaign'
Level = require '../levels/Level' Level = require '../models/Level'
Achievement = require '../achievements/Achievement' Achievement = require '../models/Achievement'
Handler = require '../commons/Handler' Handler = require '../commons/Handler'
async = require 'async' async = require 'async'
mongoose = require 'mongoose' mongoose = require 'mongoose'

View file

@ -1,14 +1,14 @@
async = require 'async' async = require 'async'
mongoose = require 'mongoose' mongoose = require 'mongoose'
Handler = require '../commons/Handler' Handler = require '../commons/Handler'
AnalyticsLogEvent = require '../analytics/AnalyticsLogEvent' AnalyticsLogEvent = require '../models/AnalyticsLogEvent'
Clan = require './Clan' Clan = require './../models/Clan'
EarnedAchievement = require '../achievements/EarnedAchievement' EarnedAchievement = require '../models/EarnedAchievement'
EarnedAchievementHandler = require '../achievements/earned_achievement_handler' EarnedAchievementHandler = require './earned_achievement_handler'
LevelSession = require '../levels/sessions/LevelSession' LevelSession = require '../models/LevelSession'
LevelSessionHandler = require '../levels/sessions/level_session_handler' LevelSessionHandler = require './level_session_handler'
User = require '../users/User' User = require '../models/User'
UserHandler = require '../users/user_handler' UserHandler = require './user_handler'
memberLimit = 200 memberLimit = 200

View file

@ -1,11 +1,11 @@
async = require 'async' async = require 'async'
mongoose = require 'mongoose' mongoose = require 'mongoose'
Handler = require '../commons/Handler' Handler = require '../commons/Handler'
Classroom = require './Classroom' Classroom = require './../models/Classroom'
User = require '../users/User' User = require '../models/User'
sendwithus = require '../sendwithus' sendwithus = require '../sendwithus'
utils = require '../lib/utils' utils = require '../lib/utils'
UserHandler = require '../users/user_handler' UserHandler = require './user_handler'
ClassroomHandler = class ClassroomHandler extends Handler ClassroomHandler = class ClassroomHandler extends Handler
modelClass: Classroom modelClass: Classroom

View file

@ -1,15 +1,15 @@
async = require 'async' async = require 'async'
Handler = require '../commons/Handler' Handler = require '../commons/Handler'
Campaign = require '../campaigns/Campaign' Campaign = require '../models/Campaign'
Classroom = require '../classrooms/Classroom' Classroom = require '../models/Classroom'
Course = require '../models/Course' Course = require '../models/Course'
CourseInstance = require './CourseInstance' CourseInstance = require './../models/CourseInstance'
LevelSession = require '../levels/sessions/LevelSession' LevelSession = require '../models/LevelSession'
LevelSessionHandler = require '../levels/sessions/level_session_handler' LevelSessionHandler = require './level_session_handler'
Prepaid = require '../prepaids/Prepaid' Prepaid = require '../models/Prepaid'
PrepaidHandler = require '../prepaids/prepaid_handler' PrepaidHandler = require './prepaid_handler'
User = require '../users/User' User = require '../models/User'
UserHandler = require '../users/user_handler' UserHandler = require './user_handler'
utils = require '../../app/core/utils' utils = require '../../app/core/utils'
{objectIdFromTimestamp} = require '../lib/utils' {objectIdFromTimestamp} = require '../lib/utils'
sendwithus = require '../sendwithus' sendwithus = require '../sendwithus'

View file

@ -1,14 +1,14 @@
log = require 'winston' log = require 'winston'
mongoose = require 'mongoose' mongoose = require 'mongoose'
async = require 'async' async = require 'async'
Achievement = require './Achievement' Achievement = require './../models/Achievement'
EarnedAchievement = require './EarnedAchievement' EarnedAchievement = require './../models/EarnedAchievement'
User = require '../users/User' User = require '../models/User'
Handler = require '../commons/Handler' Handler = require '../commons/Handler'
LocalMongo = require '../../app/lib/LocalMongo' LocalMongo = require '../../app/lib/LocalMongo'
util = require '../../app/core/utils' util = require '../../app/core/utils'
LevelSession = require '../levels/sessions/LevelSession' LevelSession = require '../models/LevelSession'
UserPollsRecord = require '../polls/UserPollsRecord' UserPollsRecord = require '../models/UserPollsRecord'
class EarnedAchievementHandler extends Handler class EarnedAchievementHandler extends Handler
modelClass: EarnedAchievement modelClass: EarnedAchievement

View file

@ -1,10 +1,10 @@
LevelComponent = require './LevelComponent' LevelComponent = require './../models/LevelComponent'
Handler = require '../../commons/Handler' Handler = require '../commons/Handler'
mongoose = require 'mongoose' mongoose = require 'mongoose'
LevelComponentHandler = class LevelComponentHandler extends Handler LevelComponentHandler = class LevelComponentHandler extends Handler
modelClass: LevelComponent modelClass: LevelComponent
jsonSchema: require '../../../app/schemas/models/level_component' jsonSchema: require '../../app/schemas/models/level_component'
editableProperties: [ editableProperties: [
'system' 'system'
'description' 'description'

View file

@ -1,10 +1,10 @@
LevelFeedback = require './LevelFeedback' LevelFeedback = require './../models/LevelFeedback'
Handler = require '../../commons/Handler' Handler = require '../commons/Handler'
class LevelFeedbackHandler extends Handler class LevelFeedbackHandler extends Handler
modelClass: LevelFeedback modelClass: LevelFeedback
editableProperties: ['rating', 'review', 'level', 'levelID', 'levelName'] editableProperties: ['rating', 'review', 'level', 'levelID', 'levelName']
jsonSchema: require '../../../app/schemas/models/level_feedback' jsonSchema: require '../../app/schemas/models/level_feedback'
makeNewInstance: (req) -> makeNewInstance: (req) ->
feedback = super(req) feedback = super(req)

View file

@ -1,17 +1,17 @@
Level = require './Level' Level = require './../models/Level'
Session = require './sessions/LevelSession' Session = require './../models/LevelSession'
User = require '../users/User' User = require '../models/User'
SessionHandler = require './sessions/level_session_handler' SessionHandler = require './level_session_handler'
Feedback = require './feedbacks/LevelFeedback' Feedback = require './../models/LevelFeedback'
Handler = require '../commons/Handler' Handler = require '../commons/Handler'
mongoose = require 'mongoose' mongoose = require 'mongoose'
async = require 'async' async = require 'async'
utils = require '../lib/utils' utils = require '../lib/utils'
log = require 'winston' log = require 'winston'
Campaign = require '../campaigns/Campaign' Campaign = require '../models/Campaign'
Course = require '../models/Course' Course = require '../models/Course'
CourseInstance = require '../courses/CourseInstance' CourseInstance = require '../models/CourseInstance'
Classroom = require '../classrooms/Classroom' Classroom = require '../models/Classroom'
LevelHandler = class LevelHandler extends Handler LevelHandler = class LevelHandler extends Handler
modelClass: Level modelClass: Level

View file

@ -1,5 +1,5 @@
LevelSession = require './LevelSession' LevelSession = require './../models/LevelSession'
Handler = require '../../commons/Handler' Handler = require '../commons/Handler'
log = require 'winston' log = require 'winston'
TIMEOUT = 1000 * 30 # no activity for 30 seconds means it's not active TIMEOUT = 1000 * 30 # no activity for 30 seconds means it's not active

View file

@ -1,5 +1,5 @@
LevelSystem = require './LevelSystem' LevelSystem = require './../models/LevelSystem'
Handler = require '../../commons/Handler' Handler = require '../commons/Handler'
LevelSystemHandler = class LevelSystemHandler extends Handler LevelSystemHandler = class LevelSystemHandler extends Handler
modelClass: LevelSystem modelClass: LevelSystem
@ -13,7 +13,7 @@ LevelSystemHandler = class LevelSystemHandler extends Handler
'configSchema' 'configSchema'
] ]
postEditableProperties: ['name'] postEditableProperties: ['name']
jsonSchema: require '../../../app/schemas/models/level_system' jsonSchema: require '../../app/schemas/models/level_system'
getEditableProperties: (req, document) -> getEditableProperties: (req, document) ->
props = super(req, document) props = super(req, document)

View file

@ -1,10 +1,10 @@
MailSent = require './MailSent' MailSent = require './../models/MailSent'
Handler = require '../../commons/Handler' Handler = require '../commons/Handler'
class MailSentHandler extends Handler class MailSentHandler extends Handler
modelClass: MailSent modelClass: MailSent
editableProperties: ['mailTask','user','sent'] editableProperties: ['mailTask','user','sent']
jsonSchema: require '../../../app/schemas/models/mail_sent' jsonSchema: require '../../app/schemas/models/mail_sent'
hasAccess: (req) -> hasAccess: (req) ->
req.user?.isAdmin() req.user?.isAdmin()

View file

@ -1,5 +1,5 @@
Patch = require './Patch' Patch = require './../models/Patch'
User = require '../users/User' User = require '../models/User'
Handler = require '../commons/Handler' Handler = require '../commons/Handler'
schema = require '../../app/schemas/models/patch' schema = require '../../app/schemas/models/patch'
{handlers} = require '../commons/mapping' {handlers} = require '../commons/mapping'

View file

@ -1,7 +1,7 @@
Payment = require './Payment' Payment = require './../models/Payment'
Prepaid = require '../prepaids/Prepaid' Prepaid = require '../models/Prepaid'
Product = require '../models/Product' Product = require '../models/Product'
User = require '../users/User' User = require '../models/User'
Handler = require '../commons/Handler' Handler = require '../commons/Handler'
{handlers} = require '../commons/mapping' {handlers} = require '../commons/mapping'
mongoose = require 'mongoose' mongoose = require 'mongoose'

View file

@ -1,5 +1,5 @@
Poll = require './Poll' Poll = require './../models/Poll'
UserPollsRecord = require './UserPollsRecord' UserPollsRecord = require './../models/UserPollsRecord'
Handler = require '../commons/Handler' Handler = require '../commons/Handler'
async = require 'async' async = require 'async'
mongoose = require 'mongoose' mongoose = require 'mongoose'

View file

@ -1,8 +1,8 @@
Course = require '../models/Course' Course = require '../models/Course'
Handler = require '../commons/Handler' Handler = require '../commons/Handler'
slack = require '../slack' slack = require '../slack'
Prepaid = require './Prepaid' Prepaid = require './../models/Prepaid'
User = require '../users/User' User = require '../models/User'
StripeUtils = require '../lib/stripe_utils' StripeUtils = require '../lib/stripe_utils'
utils = require '../../app/core/utils' utils = require '../../app/core/utils'
mongoose = require 'mongoose' mongoose = require 'mongoose'

View file

@ -1,5 +1,5 @@
Purchase = require './Purchase' Purchase = require './../models/Purchase'
User = require '../users/User' User = require '../models/User'
Handler = require '../commons/Handler' Handler = require '../commons/Handler'
{handlers} = require '../commons/mapping' {handlers} = require '../commons/mapping'
mongoose = require 'mongoose' mongoose = require 'mongoose'

View file

@ -9,8 +9,8 @@ config = require '../../server_config'
Handler = require '../commons/Handler' Handler = require '../commons/Handler'
slack = require '../slack' slack = require '../slack'
discountHandler = require './discount_handler' discountHandler = require './discount_handler'
Prepaid = require '../prepaids/Prepaid' Prepaid = require '../models/Prepaid'
User = require '../users/User' User = require '../models/User'
{findStripeSubscription} = require '../lib/utils' {findStripeSubscription} = require '../lib/utils'
{getSponsoredSubsAmount} = require '../../app/core/utils' {getSponsoredSubsAmount} = require '../../app/core/utils'
StripeUtils = require '../lib/stripe_utils' StripeUtils = require '../lib/stripe_utils'

View file

@ -1,9 +1,9 @@
ThangType = require './ThangType' ThangType = require './../models/ThangType'
Handler = require '../../commons/Handler' Handler = require '../commons/Handler'
ThangTypeHandler = class ThangTypeHandler extends Handler ThangTypeHandler = class ThangTypeHandler extends Handler
modelClass: ThangType modelClass: ThangType
jsonSchema: require '../../../app/schemas/models/thang_type' jsonSchema: require '../../app/schemas/models/thang_type'
editableProperties: [ editableProperties: [
'name' 'name'
'raw' 'raw'

View file

@ -1,4 +1,4 @@
UserCodeProblem = require './UserCodeProblem' UserCodeProblem = require './../models/UserCodeProblem'
Handler = require '../commons/Handler' Handler = require '../commons/Handler'
utils = require '../lib/utils' utils = require '../lib/utils'

View file

@ -1,7 +1,7 @@
schema = require '../../app/schemas/models/user' schema = require '../../app/schemas/models/user'
crypto = require 'crypto' crypto = require 'crypto'
request = require 'request' request = require 'request'
User = require './User' User = require './../models/User'
Handler = require '../commons/Handler' Handler = require '../commons/Handler'
mongoose = require 'mongoose' mongoose = require 'mongoose'
config = require '../../server_config' config = require '../../server_config'
@ -9,23 +9,23 @@ errors = require '../commons/errors'
async = require 'async' async = require 'async'
log = require 'winston' log = require 'winston'
moment = require 'moment' moment = require 'moment'
AnalyticsLogEvent = require '../analytics/AnalyticsLogEvent' AnalyticsLogEvent = require '../models/AnalyticsLogEvent'
Clan = require '../clans/Clan' Clan = require '../models/Clan'
CourseInstance = require '../courses/CourseInstance' CourseInstance = require '../models/CourseInstance'
LevelSession = require '../levels/sessions/LevelSession' LevelSession = require '../models/LevelSession'
LevelSessionHandler = require '../levels/sessions/level_session_handler' LevelSessionHandler = require './level_session_handler'
Payment = require '../payments/Payment' Payment = require '../models/Payment'
SubscriptionHandler = require '../payments/subscription_handler' SubscriptionHandler = require './subscription_handler'
DiscountHandler = require '../payments/discount_handler' DiscountHandler = require './discount_handler'
EarnedAchievement = require '../achievements/EarnedAchievement' EarnedAchievement = require '../models/EarnedAchievement'
UserRemark = require './remarks/UserRemark' UserRemark = require './../models/UserRemark'
{findStripeSubscription} = require '../lib/utils' {findStripeSubscription} = require '../lib/utils'
{isID} = require '../lib/utils' {isID} = require '../lib/utils'
slack = require '../slack' slack = require '../slack'
sendwithus = require '../sendwithus' sendwithus = require '../sendwithus'
Prepaid = require '../prepaids/Prepaid' Prepaid = require '../models/Prepaid'
UserPollsRecord = require '../polls/UserPollsRecord' UserPollsRecord = require '../models/UserPollsRecord'
EarnedAchievement = require '../achievements/EarnedAchievement' EarnedAchievement = require '../models/EarnedAchievement'
serverProperties = ['passwordHash', 'emailLower', 'nameLower', 'passwordReset', 'lastIP'] serverProperties = ['passwordHash', 'emailLower', 'nameLower', 'passwordReset', 'lastIP']
candidateProperties = [ candidateProperties = [
@ -792,7 +792,7 @@ UserHandler = class UserHandler extends Handler
expanded = deltas.flattenDelta obj.get 'delta' expanded = deltas.flattenDelta obj.get 'delta'
_.some expanded, (delta) -> 'i18n' in delta.dataPath _.some expanded, (delta) -> 'i18n' in delta.dataPath
Patch = require '../patches/Patch' Patch = require '../models/Patch'
# filter is passed a mongoose document and should return a boolean, # filter is passed a mongoose document and should return a boolean,
# determining whether the patch should be counted # determining whether the patch should be counted
countPatchesByUsersInMemory = (query, filter, statName, done) -> countPatchesByUsersInMemory = (query, filter, statName, done) ->
@ -836,7 +836,7 @@ UserHandler = class UserHandler extends Handler
updateUser user, count, doneWithUser updateUser user, count, doneWithUser
countPatchesByUsers = (query, statName, done) -> countPatchesByUsers = (query, statName, done) ->
Patch = require '../patches/Patch' Patch = require '../models/Patch'
userStream = User.find({anonymous: false}).sort('_id').stream() userStream = User.find({anonymous: false}).sort('_id').stream()
streamFinished = false streamFinished = false
@ -870,7 +870,7 @@ UserHandler = class UserHandler extends Handler
statRecalculators: statRecalculators:
gamesCompleted: (done) -> gamesCompleted: (done) ->
LevelSession = require '../levels/sessions/LevelSession' LevelSession = require '../models/LevelSession'
userStream = User.find({anonymous: false}).sort('_id').stream() userStream = User.find({anonymous: false}).sort('_id').stream()
streamFinished = false streamFinished = false
@ -899,23 +899,23 @@ UserHandler = class UserHandler extends Handler
User.findByIdAndUpdate user.get('_id'), update, doneWithUser User.findByIdAndUpdate user.get('_id'), update, doneWithUser
articleEdits: (done) -> articleEdits: (done) ->
Article = require '../articles/Article' Article = require '../models/Article'
countEdits Article, done countEdits Article, done
levelEdits: (done) -> levelEdits: (done) ->
Level = require '../levels/Level' Level = require '../models/Level'
countEdits Level, done countEdits Level, done
levelComponentEdits: (done) -> levelComponentEdits: (done) ->
LevelComponent = require '../levels/components/LevelComponent' LevelComponent = require '../models/LevelComponent'
countEdits LevelComponent, done countEdits LevelComponent, done
levelSystemEdits: (done) -> levelSystemEdits: (done) ->
LevelSystem = require '../levels/systems/LevelSystem' LevelSystem = require '../models/LevelSystem'
countEdits LevelSystem, done countEdits LevelSystem, done
thangTypeEdits: (done) -> thangTypeEdits: (done) ->
ThangType = require '../levels/thangs/ThangType' ThangType = require '../models/ThangType'
countEdits ThangType, done countEdits ThangType, done
patchesContributed: (done) -> patchesContributed: (done) ->

View file

@ -1,4 +1,4 @@
UserPollsRecord = require './UserPollsRecord' UserPollsRecord = require './../models/UserPollsRecord'
Handler = require '../commons/Handler' Handler = require '../commons/Handler'
async = require 'async' async = require 'async'
mongoose = require 'mongoose' mongoose = require 'mongoose'

View file

@ -1,10 +1,10 @@
UserRemark = require './UserRemark' UserRemark = require './../models/UserRemark'
Handler = require '../../commons/Handler' Handler = require '../commons/Handler'
class UserRemarkHandler extends Handler class UserRemarkHandler extends Handler
modelClass: UserRemark modelClass: UserRemark
editableProperties: ['user', 'contact', 'history', 'tasks', 'userName', 'contactName'] editableProperties: ['user', 'contact', 'history', 'tasks', 'userName', 'contactName']
jsonSchema: require '../../../app/schemas/models/user_remark' jsonSchema: require '../../app/schemas/models/user_remark'
hasAccess: (req) -> hasAccess: (req) ->
req.user?.isAdmin() req.user?.isAdmin()

View file

@ -1,6 +1,6 @@
config = require '../../server_config' config = require '../../server_config'
request = require 'request' request = require 'request'
User = require '../users/User' User = require '../models/User'
http = require 'http' http = require 'http'
authstr = new Buffer("#{config.picoCTF_auth.username}:#{config.picoCTF_auth.password}").toString 'base64' authstr = new Buffer("#{config.picoCTF_auth.username}:#{config.picoCTF_auth.password}").toString 'base64'

View file

@ -1,6 +1,6 @@
log = require 'winston' log = require 'winston'
Payment = require '../payments/Payment' Payment = require '../models/Payment'
PaymentHandler = require '../payments/payment_handler' PaymentHandler = require '../handlers/payment_handler'
module.exports = module.exports =
logError: (user, msg) -> logError: (user, msg) ->

View file

@ -1,4 +1,4 @@
AnalyticsString = require '../analytics/AnalyticsString' AnalyticsString = require '../models/AnalyticsString'
log = require 'winston' log = require 'winston'
mongoose = require 'mongoose' mongoose = require 'mongoose'
config = require '../../server_config' config = require '../../server_config'

View file

@ -5,7 +5,7 @@ wrap = require 'co-express'
Promise = require 'bluebird' Promise = require 'bluebird'
parse = require '../commons/parse' parse = require '../commons/parse'
request = require 'request' request = require 'request'
User = require '../users/User' User = require '../models/User'
utils = require '../lib/utils' utils = require '../lib/utils'
mongoose = require 'mongoose' mongoose = require 'mongoose'

View file

@ -4,9 +4,9 @@ wrap = require 'co-express'
Promise = require 'bluebird' Promise = require 'bluebird'
database = require '../commons/database' database = require '../commons/database'
mongoose = require 'mongoose' mongoose = require 'mongoose'
Campaign = require '../campaigns/Campaign' Campaign = require '../models/Campaign'
parse = require '../commons/parse' parse = require '../commons/parse'
LevelSession = require '../levels/sessions/LevelSession' LevelSession = require '../models/LevelSession'
module.exports = module.exports =
fetchByType: wrap (req, res, next) -> fetchByType: wrap (req, res, next) ->

View file

@ -5,10 +5,10 @@ wrap = require 'co-express'
Promise = require 'bluebird' Promise = require 'bluebird'
database = require '../commons/database' database = require '../commons/database'
mongoose = require 'mongoose' mongoose = require 'mongoose'
Classroom = require '../classrooms/Classroom' Classroom = require '../models/Classroom'
parse = require '../commons/parse' parse = require '../commons/parse'
LevelSession = require '../levels/sessions/LevelSession' LevelSession = require '../models/LevelSession'
User = require '../users/User' User = require '../models/User'
module.exports = module.exports =
getByOwner: wrap (req, res, next) -> getByOwner: wrap (req, res, next) ->

View file

@ -3,7 +3,7 @@ wrap = require 'co-express'
Promise = require 'bluebird' Promise = require 'bluebird'
parse = require '../commons/parse' parse = require '../commons/parse'
request = require 'request' request = require 'request'
User = require '../users/User' User = require '../models/User'
module.exports = module.exports =

View file

@ -1,6 +1,6 @@
utils = require '../lib/utils' utils = require '../lib/utils'
errors = require '../commons/errors' errors = require '../commons/errors'
User = require '../users/User' User = require '../models/User'
sendwithus = require '../sendwithus' sendwithus = require '../sendwithus'
slack = require '../slack' slack = require '../slack'
_ = require 'lodash' _ = require 'lodash'

View file

@ -55,7 +55,7 @@ AchievementSchema.statics.achievementCollections = {}
# TODO might want to tweak this to only load new achievements # TODO might want to tweak this to only load new achievements
AchievementSchema.statics.loadAchievements = (done) -> AchievementSchema.statics.loadAchievements = (done) ->
AchievementSchema.statics.resetAchievements() AchievementSchema.statics.resetAchievements()
Achievement = require('../achievements/Achievement') Achievement = require('./Achievement')
query = Achievement.find({collection: {$ne: 'level.sessions'}}) query = Achievement.find({collection: {$ne: 'level.sessions'}})
query.exec (err, docs) -> query.exec (err, docs) ->
_.each docs, (achievement) -> _.each docs, (achievement) ->

View file

@ -1,3 +1,43 @@
# TODO: Migrate Article to here mongoose = require 'mongoose'
plugins = require '../plugins/plugins'
config = require '../../server_config'
module.exports = require '../articles/Article' ArticleSchema = new mongoose.Schema(body: String, {strict: false,read:config.mongo.readpref})
ArticleSchema.index(
{
index: 1
_fts: 'text'
_ftsx: 1
},
{
name: 'search index'
sparse: true
weights: {body: 1, name: 1}
default_language: 'english'
'language_override': 'searchLanguage'
'textIndexVersion': 2
})
ArticleSchema.index(
{
original: 1
'version.major': -1
'version.minor': -1
},
{
name: 'version index'
unique: true
})
ArticleSchema.index({slug: 1}, {name: 'slug index', sparse: true, unique: true})
ArticleSchema.plugin(plugins.NamedPlugin)
ArticleSchema.plugin(plugins.VersionedPlugin)
ArticleSchema.plugin(plugins.SearchablePlugin, {searchable: ['body', 'name']})
ArticleSchema.plugin(plugins.TranslationCoveragePlugin)
ArticleSchema.plugin(plugins.PatchablePlugin)
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

@ -1,3 +1,41 @@
# TODO: Migrate Campaign to here mongoose = require 'mongoose'
plugins = require '../plugins/plugins'
log = require 'winston'
config = require '../../server_config'
jsonSchema = require '../../app/schemas/models/campaign.schema.coffee'
module.exports = require '../campaigns/Campaign' CampaignSchema = new mongoose.Schema(body: String, {strict: false,read:config.mongo.readpref})
CampaignSchema.index({i18nCoverage: 1}, {name: 'translation coverage index', sparse: true})
CampaignSchema.index({slug: 1}, {name: 'slug index', sparse: true, unique: true})
CampaignSchema.index({type: 1}, {name: 'type index', sparse: true})
CampaignSchema.plugin(plugins.NamedPlugin)
CampaignSchema.plugin(plugins.TranslationCoveragePlugin)
CampaignSchema.plugin plugins.PatchablePlugin
CampaignSchema.statics.updateAdjacentCampaigns = (savedCampaign) ->
Campaign = require './Campaign'
query = {}
query["adjacentCampaigns.#{savedCampaign.get '_id'}"] = {$exists: true}
Campaign.find(query).exec (err, campaigns) ->
return log.error "Couldn't search for adjacent campaigns to update because of #{err}" if err
for campaign in campaigns
acs = campaign.get 'adjacentCampaigns'
ac = acs[savedCampaign.get '_id']
# Let's make sure that we're adding translations, otherwise let's not update yet.
# We could possibly remove this; not sure it's worth having.
[oldI18NCount, newI18NCount] = [0, 0]
oldI18NCount += _.size(translations) for lang, translations of ac.i18n ? {}
newI18NCount += _.size(translations) for lang, translations of savedCampaign.get('i18n') ? {}
continue unless newI18NCount > oldI18NCount
ac.i18n = savedCampaign.get('i18n')
# Save without using middleware so that we don't get into a post-save loop.
Campaign.findByIdAndUpdate campaign._id, {$set: {adjacentCampaigns: acs}}, (err, doc) ->
return log.error "Couldn't save updated adjacent campaign because of #{err}" if err
CampaignSchema.post 'save', -> @constructor.updateAdjacentCampaigns @
CampaignSchema.statics.jsonSchema = jsonSchema
module.exports = mongoose.model('campaign', CampaignSchema)

View file

@ -2,8 +2,8 @@ mongoose = require 'mongoose'
log = require 'winston' log = require 'winston'
config = require '../../server_config' config = require '../../server_config'
plugins = require '../plugins/plugins' plugins = require '../plugins/plugins'
User = require '../users/User' User = require './User'
jsonSchema = require '../../app/schemas/models/clan.schema' jsonSchema = require '../../app/schemas/models/clan.schema.coffee'
ClanSchema = new mongoose.Schema {}, {strict: false, minimize: false, read:config.mongo.readpref} ClanSchema = new mongoose.Schema {}, {strict: false, minimize: false, read:config.mongo.readpref}

View file

@ -1,3 +1,63 @@
# TODO: Migrate Classroom to here mongoose = require 'mongoose'
log = require 'winston'
config = require '../../server_config'
plugins = require '../plugins/plugins'
User = require './User'
jsonSchema = require '../../app/schemas/models/classroom.schema.coffee'
utils = require '../lib/utils'
module.exports = require '../classrooms/Classroom' ClassroomSchema = new mongoose.Schema {}, {strict: false, minimize: false, read:config.mongo.readpref}
ClassroomSchema.index({ownerID: 1}, {name: 'ownerID index'})
ClassroomSchema.index({members: 1}, {name: 'members index'})
ClassroomSchema.index({code: 1}, {name: 'code index', unique: true})
ClassroomSchema.statics.privateProperties = []
ClassroomSchema.statics.editableProperties = [
'description'
'name'
'aceConfig'
'averageStudentExp'
'ageRangeMin'
'ageRangeMax'
'archived'
]
ClassroomSchema.statics.generateNewCode = (done) ->
tryCode = ->
# Use 4 code words once we get past 10M classrooms
codeCamel = utils.getCodeCamel(3)
code = codeCamel.toLowerCase()
Classroom.findOne code: code, (err, classroom) ->
return done() if err
return done(code, codeCamel) unless classroom
tryCode()
tryCode()
ClassroomSchema.pre('save', (next) ->
return next() if @get('code')
Classroom.generateNewCode (code, codeCamel) =>
@set 'code', code
@set 'codeCamel', codeCamel
next()
)
ClassroomSchema.methods.isOwner = (userID) ->
return userID.equals(@get('ownerID'))
ClassroomSchema.methods.isMember = (userID) ->
return _.any @get('members') or [], (memberID) -> userID.equals(memberID)
ClassroomSchema.statics.jsonSchema = jsonSchema
ClassroomSchema.set('toObject', {
transform: (doc, ret, options) ->
return ret unless options.req
user = options.req.user
unless user?.isAdmin() or user?.get('_id').equals(doc.get('ownerID'))
delete ret.code
delete ret.codeCamel
return ret
})
module.exports = Classroom = mongoose.model 'classroom', ClassroomSchema, 'classrooms'

View file

@ -1,3 +1,32 @@
# TODO: Migrate CourseInstance to here mongoose = require 'mongoose'
config = require '../../server_config'
plugins = require '../plugins/plugins'
jsonSchema = require '../../app/schemas/models/course_instance.schema.coffee'
module.exports = require '../courses/CourseInstance' CourseInstanceSchema = new mongoose.Schema {
ownerID: mongoose.Schema.Types.ObjectId
courseID: mongoose.Schema.Types.ObjectId
classroomID: mongoose.Schema.Types.ObjectId
prepaidID: mongoose.Schema.Types.ObjectId
members: [mongoose.Schema.Types.ObjectId]
}, {strict: false, minimize: false, read:config.mongo.readpref}
CourseInstanceSchema.index({ownerID: 1}, {name: 'ownerID index'})
CourseInstanceSchema.index({members: 1}, {name: 'members index'})
CourseInstanceSchema.index({classroomID: 1}, {name: 'classroomID index', sparse: true})
CourseInstanceSchema.index({prepaidID: 1}, {name: 'prepaidID index', sparse: true}) # Deprecated? Can we get rid of this?
CourseInstanceSchema.statics.privateProperties = []
CourseInstanceSchema.statics.editableProperties = [
'description'
'name'
'aceConfig'
]
CourseInstanceSchema.statics.postEditableProperties = [
'courseID'
'classroomID'
]
CourseInstanceSchema.statics.jsonSchema = jsonSchema
module.exports = CourseInstance = mongoose.model 'course.instance', CourseInstanceSchema, 'course.instances'

View file

@ -17,7 +17,7 @@ EarnedAchievementSchema.index({user: 1, achievement: 1}, {unique: true, name: 'e
EarnedAchievementSchema.index({user: 1, changed: -1}, {name: 'latest '}) EarnedAchievementSchema.index({user: 1, changed: -1}, {name: 'latest '})
EarnedAchievementSchema.statics.createForAchievement = (achievement, doc, originalDocObj=null, previouslyEarnedAchievement=null, done) -> EarnedAchievementSchema.statics.createForAchievement = (achievement, doc, originalDocObj=null, previouslyEarnedAchievement=null, done) ->
User = require '../users/User' User = require './User'
userObjectID = doc.get(achievement.get('userField')) userObjectID = doc.get(achievement.get('userField'))
userID = if _.isObject userObjectID then userObjectID.toHexString() else userObjectID # Standardize! Use strings, not ObjectId's userID = if _.isObject userObjectID then userObjectID.toHexString() else userObjectID # Standardize! Use strings, not ObjectId's

View file

@ -1,7 +1,7 @@
mongoose = require 'mongoose' mongoose = require 'mongoose'
plugins = require '../../plugins/plugins' plugins = require '../plugins/plugins'
jsonschema = require '../../../app/schemas/models/level_component' jsonschema = require '../../app/schemas/models/level_component'
config = require '../../../server_config' config = require '../../server_config'
LevelComponentSchema = new mongoose.Schema { LevelComponentSchema = new mongoose.Schema {
description: String description: String

View file

@ -1,9 +1,9 @@
# TODO: not updated since rename from level_instance, or since we redid how all models are done; probably busted # TODO: not updated since rename from level_instance, or since we redid how all models are done; probably busted
mongoose = require 'mongoose' mongoose = require 'mongoose'
plugins = require '../../plugins/plugins' plugins = require '../plugins/plugins'
jsonschema = require '../../../app/schemas/models/level_feedback' jsonschema = require '../../app/schemas/models/level_feedback'
config = require '../../../server_config' config = require '../../server_config'
LevelFeedbackSchema = new mongoose.Schema({ LevelFeedbackSchema = new mongoose.Schema({
created: created:

View file

@ -1,9 +1,9 @@
mongoose = require 'mongoose' mongoose = require 'mongoose'
plugins = require '../../plugins/plugins' plugins = require '../plugins/plugins'
AchievablePlugin = require '../../plugins/achievements' AchievablePlugin = require '../plugins/achievements'
jsonschema = require '../../../app/schemas/models/level_session' jsonschema = require '../../app/schemas/models/level_session'
log = require 'winston' log = require 'winston'
config = require '../../../server_config' config = require '../../server_config'
LevelSessionSchema = new mongoose.Schema({ LevelSessionSchema = new mongoose.Schema({
created: created:
@ -43,8 +43,8 @@ LevelSessionSchema.post 'init', (doc) ->
playtime: doc.get 'playtime' playtime: doc.get 'playtime'
LevelSessionSchema.pre 'save', (next) -> LevelSessionSchema.pre 'save', (next) ->
User = require '../../users/User' # Avoid mutual inclusion cycles User = require './User' # Avoid mutual inclusion cycles
Level = require '../Level' Level = require './Level'
@set('changed', new Date()) @set('changed', new Date())
id = @get('id') id = @get('id')

View file

@ -1,7 +1,7 @@
mongoose = require 'mongoose' mongoose = require 'mongoose'
plugins = require '../../plugins/plugins' plugins = require '../plugins/plugins'
jsonschema = require '../../../app/schemas/models/level_system' jsonschema = require '../../app/schemas/models/level_system'
config = require '../../../server_config' config = require '../../server_config'
LevelSystemSchema = new mongoose.Schema { LevelSystemSchema = new mongoose.Schema {
description: String description: String

View file

@ -1,5 +1,5 @@
mongoose = require 'mongoose' mongoose = require 'mongoose'
plugins = require '../../plugins/plugins' plugins = require '../plugins/plugins'
LevelComponentSchema = new mongoose.Schema( LevelComponentSchema = new mongoose.Schema(
original: {type: mongoose.Schema.ObjectId, ref: 'level.session'} original: {type: mongoose.Schema.ObjectId, ref: 'level.session'}

View file

@ -1,6 +1,6 @@
mongoose = require 'mongoose' mongoose = require 'mongoose'
plugins = require '../../plugins/plugins' plugins = require '../plugins/plugins'
jsonschema = require '../../../app/schemas/models/mail_sent' jsonschema = require '../../app/schemas/models/mail_sent'
MailSent = new mongoose.Schema({ MailSent = new mongoose.Schema({
sent: sent:

View file

@ -1,3 +1,79 @@
# TODO: Migrate Patch to here mongoose = require('mongoose')
deltas = require '../../app/core/deltas'
log = require 'winston'
{handlers} = require '../commons/mapping'
config = require '../../server_config'
module.exports = require '../patches/Patch' PatchSchema = new mongoose.Schema({status: String}, {strict: false,read:config.mongo.readpref})
PatchSchema.pre 'save', (next) ->
return next() unless @isNew # patch can't be altered after creation, so only need to check data once
target = @get('target')
targetID = target.id
Handler = require '../commons/Handler'
if not Handler.isID(targetID)
err = new Error('Invalid input.')
err.response = {message: 'isn\'t a MongoDB id.', property: 'target.id'}
err.code = 422
return next(err)
collection = target.collection
handler = require('../' + handlers[collection])
handler.getDocumentForIdOrSlug targetID, (err, document) =>
if err
err = new Error('Server error.')
err.response = {message: '', property: 'target.id'}
err.code = 500
return next(err)
if not document
err = new Error('Target of patch not found.')
err.response = {message: 'was not found.', property: 'target.id'}
err.code = 404
return next(err)
target.id = document.get('_id')
if handler.modelClass.schema.uses_coco_versions
target.original = document.get('original')
version = document.get('version')
target.version = _.pick document.get('version'), 'major', 'minor'
@set('target', target)
else
target.original = targetID
patches = document.get('patches') or []
patches = _.clone patches
patches.push @_id
document.set 'patches', patches, {strict: false}
@targetLoaded = document
document.save (err) -> next(err)
PatchSchema.methods.isTranslationPatch = -> # Don't ever fat arrow bind this one
expanded = deltas.flattenDelta @get('delta')
_.some expanded, (delta) -> 'i18n' in delta.dataPath
PatchSchema.methods.isMiscPatch = ->
expanded = deltas.flattenDelta @get('delta')
_.some expanded, (delta) -> 'i18n' not in delta.dataPath
# Keep track of when a patch is pending and newly approved.
PatchSchema.path('status').set (newVal) ->
@set 'wasPending', @status is 'pending' and newVal isnt 'pending'
@set 'newlyAccepted', newVal is 'accepted' and not @get('newlyAccepted') # Only true on the first accept
newVal
PatchSchema.methods.isNewlyAccepted = -> @get('newlyAccepted')
PatchSchema.methods.wasPending = -> @get 'wasPending'
PatchSchema.pre 'save', (next) ->
User = require './User'
userID = @get('creator').toHexString()
if @get('status') is 'accepted'
User.incrementStat userID, 'stats.patchesContributed' # accepted patches
else if @get('status') is 'pending'
User.incrementStat userID, 'stats.patchesSubmitted' # submitted patches
next()
module.exports = mongoose.model('patch', PatchSchema)

View file

@ -1,6 +1,6 @@
mongoose = require 'mongoose' mongoose = require 'mongoose'
plugins = require '../plugins/plugins' plugins = require '../plugins/plugins'
jsonSchema = require '../../app/schemas/models/poll.schema' jsonSchema = require '../../app/schemas/models/poll.schema.coffee'
log = require 'winston' log = require 'winston'
config = require '../../server_config' config = require '../../server_config'
PollSchema = new mongoose.Schema { PollSchema = new mongoose.Schema {

View file

@ -1,6 +1,6 @@
mongoose = require 'mongoose' mongoose = require 'mongoose'
plugins = require '../../plugins/plugins' plugins = require '../plugins/plugins'
config = require '../../../server_config' config = require '../../server_config'
ThangTypeSchema = new mongoose.Schema({ ThangTypeSchema = new mongoose.Schema({
body: String, body: String,

View file

@ -3,10 +3,10 @@ log = require 'winston'
mongoose = require 'mongoose' mongoose = require 'mongoose'
config = require '../../server_config' config = require '../../server_config'
sendwithus = require '../sendwithus' sendwithus = require '../sendwithus'
Prepaid = require '../prepaids/Prepaid' Prepaid = require './Prepaid'
jsonSchema = require '../../app/schemas/models/trial_request.schema' jsonSchema = require '../../app/schemas/models/trial_request.schema'
Classroom = require '../classrooms/Classroom' Classroom = require './Classroom'
User = require '../users/User' User = require './User'
TrialRequestSchema = new mongoose.Schema {}, {strict: false, minimize: false, read:config.mongo.readpref} TrialRequestSchema = new mongoose.Schema {}, {strict: false, minimize: false, read:config.mongo.readpref}

View file

@ -1,3 +1,382 @@
# TODO: Migrate User to here mongoose = require 'mongoose'
jsonschema = require '../../app/schemas/models/user'
crypto = require 'crypto'
{salt, isProduction} = require '../../server_config'
mail = require '../commons/mail'
log = require 'winston'
plugins = require '../plugins/plugins'
AnalyticsUsersActive = require './AnalyticsUsersActive'
module.exports = require '../users/User' config = require '../../server_config'
stripe = require('stripe')(config.stripe.secretKey)
sendwithus = require '../sendwithus'
delighted = require '../delighted'
UserSchema = new mongoose.Schema({
dateCreated:
type: Date
'default': Date.now
}, {strict: false})
UserSchema.index({'dateCreated': 1})
UserSchema.index({'emailLower': 1}, {unique: true, sparse: true, name: 'emailLower_1'})
UserSchema.index({'facebookID': 1}, {sparse: true})
UserSchema.index({'gplusID': 1}, {sparse: true})
UserSchema.index({'iosIdentifierForVendor': 1}, {name: 'iOS identifier for vendor', sparse: true, unique: true})
UserSchema.index({'mailChimp.leid': 1}, {sparse: true})
UserSchema.index({'nameLower': 1}, {sparse: true, name: 'nameLower_1'})
UserSchema.index({'simulatedBy': 1})
UserSchema.index({'slug': 1}, {name: 'slug index', sparse: true, unique: true})
UserSchema.index({'stripe.subscriptionID': 1}, {unique: true, sparse: true})
UserSchema.index({'siteref': 1}, {name: 'siteref index', sparse: true})
UserSchema.index({'schoolName': 1}, {name: 'schoolName index', sparse: true})
UserSchema.index({'country': 1}, {name: 'country index', sparse: true})
UserSchema.index({'role': 1}, {name: 'role index', sparse: true})
UserSchema.post('init', ->
@set('anonymous', false) if @get('email')
)
UserSchema.methods.isInGodMode = ->
p = @get('permissions')
return p and 'godmode' in p
UserSchema.methods.isAdmin = ->
p = @get('permissions')
return p and 'admin' in p
UserSchema.methods.hasPermission = (neededPermissions) ->
permissions = @get('permissions') or []
if _.contains(permissions, 'admin')
return true
if _.isString(neededPermissions)
neededPermissions = [neededPermissions]
return _.size(_.intersection(permissions, neededPermissions))
UserSchema.methods.isArtisan = ->
p = @get('permissions')
return p and 'artisan' in p
UserSchema.methods.isAnonymous = ->
@get 'anonymous'
UserSchema.statics.teacherRoles = ['teacher', 'technology coordinator', 'advisor', 'principal', 'superintendent', 'parent']
UserSchema.methods.isTeacher = ->
return @get('role') in User.teacherRoles
UserSchema.methods.getUserInfo = ->
id: @get('_id')
email: if @get('anonymous') then 'Unregistered User' else @get('email')
UserSchema.methods.trackActivity = (activityName, increment) ->
now = new Date()
increment ?= parseInt increment or 1
increment = Math.max increment, 0
activity = @get('activity') ? {}
activity[activityName] ?= {first: now, count: 0}
activity[activityName].count += increment
activity[activityName].last = now
@set 'activity', activity
activity
emailNameMap =
generalNews: 'announcement'
adventurerNews: 'tester'
artisanNews: 'level_creator'
archmageNews: 'developer'
scribeNews: 'article_editor'
diplomatNews: 'translator'
ambassadorNews: 'support'
anyNotes: 'notification'
teacherNews: 'teacher'
UserSchema.methods.setEmailSubscription = (newName, enabled) ->
oldSubs = _.clone @get('emailSubscriptions')
if oldSubs and oldName = emailNameMap[newName]
oldSubs = (s for s in oldSubs when s isnt oldName)
oldSubs.push(oldName) if enabled
@set('emailSubscriptions', oldSubs)
newSubs = _.clone(@get('emails') or _.cloneDeep(jsonschema.properties.emails.default))
newSubs[newName] ?= {}
newSubs[newName].enabled = enabled
@set('emails', newSubs)
@newsSubsChanged = true if newName in mail.NEWS_GROUPS
UserSchema.methods.gems = ->
gemsEarned = @get('earned')?.gems ? 0
gemsEarned = gemsEarned + 100000 if @isInGodMode()
gemsPurchased = @get('purchased')?.gems ? 0
gemsSpent = @get('spent') ? 0
gemsEarned + gemsPurchased - gemsSpent
UserSchema.methods.isEmailSubscriptionEnabled = (newName) ->
emails = @get 'emails'
if not emails
oldSubs = @get('emailSubscriptions')
oldName = emailNameMap[newName]
return oldName and oldName in oldSubs if oldSubs
emails ?= {}
_.defaults emails, _.cloneDeep(jsonschema.properties.emails.default)
return emails[newName]?.enabled
UserSchema.statics.updateServiceSettings = (doc, callback) ->
return callback?() unless isProduction or GLOBAL.testing
return callback?() if doc.updatedMailChimp
return callback?() unless doc.get('email')
existingProps = doc.get('mailChimp')
emailChanged = (not existingProps) or existingProps?.email isnt doc.get('email')
if emailChanged and customerID = doc.get('stripe')?.customerID
unless stripe?.customers
console.error('Oh my god, Stripe is not imported correctly-how could we have done this (again)?')
stripe?.customers?.update customerID, {email:doc.get('email')}, (err, customer) ->
console.error('Error updating stripe customer...', err) if err
return callback?() unless emailChanged or doc.newsSubsChanged
newGroups = []
for [mailchimpEmailGroup, emailGroup] in _.zip(mail.MAILCHIMP_GROUPS, mail.NEWS_GROUPS)
newGroups.push(mailchimpEmailGroup) if doc.isEmailSubscriptionEnabled(emailGroup)
if (not existingProps) and newGroups.length is 0
return callback?() # don't add totally unsubscribed people to the list
params = {}
params.id = mail.MAILCHIMP_LIST_ID
params.email = if existingProps then {leid: existingProps.leid} else {email: doc.get('email')}
params.merge_vars = {
groupings: [{id: mail.MAILCHIMP_GROUP_ID, groups: newGroups}]
'new-email': doc.get('email')
}
params.update_existing = true
onSuccess = (data) ->
data.email = doc.get('email') # Make sure that we don't spam opt-in emails even if MailChimp doesn't update the email it gets in this object until they have confirmed.
doc.set('mailChimp', data)
doc.updatedMailChimp = true
doc.save()
callback?()
onFailure = (error) ->
log.error 'failed to subscribe', error, callback?
doc.updatedMailChimp = true
callback?()
mc?.lists.subscribe params, onSuccess, onFailure
UserSchema.statics.statsMapping =
edits:
article: 'stats.articleEdits'
level: 'stats.levelEdits'
'level.component': 'stats.levelComponentEdits'
'level.system': 'stats.levelSystemEdits'
'thang.type': 'stats.thangTypeEdits'
'Achievement': 'stats.achievementEdits'
'campaign': 'stats.campaignEdits'
'poll': 'stats.pollEdits'
translations:
article: 'stats.articleTranslationPatches'
level: 'stats.levelTranslationPatches'
'level.component': 'stats.levelComponentTranslationPatches'
'level.system': 'stats.levelSystemTranslationPatches'
'thang.type': 'stats.thangTypeTranslationPatches'
'Achievement': 'stats.achievementTranslationPatches'
'campaign': 'stats.campaignTranslationPatches'
'poll': 'stats.pollTranslationPatches'
misc:
article: 'stats.articleMiscPatches'
level: 'stats.levelMiscPatches'
'level.component': 'stats.levelComponentMiscPatches'
'level.system': 'stats.levelSystemMiscPatches'
'thang.type': 'stats.thangTypeMiscPatches'
'Achievement': 'stats.achievementMiscPatches'
'campaign': 'stats.campaignMiscPatches'
'poll': 'stats.pollMiscPatches'
UserSchema.statics.incrementStat = (id, statName, done, inc=1) ->
id = mongoose.Types.ObjectId id if _.isString id
@findById id, (err, user) ->
log.error err if err?
err = new Error "Could't find user with id '#{id}'" unless user or err
return done() if err?
user.incrementStat statName, done, inc
UserSchema.methods.incrementStat = (statName, done, inc=1) ->
if /^concepts\./.test statName
# Concept stats are nested a level deeper.
concepts = @get('concepts') or {}
concept = statName.split('.')[1]
concepts[concept] = (concepts[concept] or 0) + inc
@set 'concepts', concepts
else
@set statName, (@get(statName) or 0) + inc
@save (err) -> done?(err)
UserSchema.statics.unconflictName = unconflictName = (name, done) ->
User.findOne {slug: _.str.slugify(name)}, (err, otherUser) ->
return done err if err?
return done null, name unless otherUser
suffix = _.random(0, 9) + ''
unconflictName name + suffix, done
UserSchema.methods.register = (done) ->
@set('anonymous', false)
if (name = @get 'name')? and name isnt ''
unconflictName name, (err, uniqueName) =>
return done err if err
@set 'name', uniqueName
done()
else done()
if @isEmailSubscriptionEnabled 'generalNews'
data =
email_id: sendwithus.templates.welcome_email
recipient:
address: @get 'email'
sendwithus.api.send data, (err, result) ->
log.error "sendwithus post-save error: #{err}, result: #{result}" if err
delighted.addDelightedUser @
@saveActiveUser 'register'
UserSchema.methods.hasSubscription = ->
return false unless stripeObject = @get('stripe')
return true if stripeObject.sponsorID
return true if stripeObject.subscriptionID
return true if stripeObject.free is true
return true if _.isString(stripeObject.free) and new Date() < new Date(stripeObject.free)
UserSchema.methods.isPremium = ->
return true if @isInGodMode()
return true if @isAdmin()
return true if @hasSubscription()
return false
UserSchema.methods.formatEntity = (req, publicOnly=false) ->
obj = @toObject()
serverProperties = ['passwordHash', 'emailLower', 'nameLower', 'passwordReset', 'lastIP']
delete obj[prop] for prop in serverProperties
candidateProperties = ['jobProfile', 'jobProfileApproved', 'jobProfileNotes']
delete obj[prop] for prop in candidateProperties
includePrivates = not publicOnly and (req.user and (req.user.isAdmin() or req.user._id.equals(@_id)))
delete obj[prop] for prop in User.privateProperties unless includePrivates
return obj
UserSchema.methods.isOnPremiumServer = ->
@get('country') in ['china', 'brazil']
UserSchema.methods.level = ->
xp = @get('points') or 0
a = 5
b = c = 100
if xp > 0 then Math.floor(a * Math.log((1 / b) * (xp + c))) + 1 else 1
UserSchema.statics.saveActiveUser = (id, event, done=null) ->
# TODO: Disabling this until we know why our app servers CPU grows out of control.
return done?()
id = mongoose.Types.ObjectId id if _.isString id
@findById id, (err, user) ->
if err?
log.error err
else
user?.saveActiveUser event
done?()
UserSchema.methods.saveActiveUser = (event, done=null) ->
# TODO: Disabling this until we know why our app servers CPU grows out of control.
return done?()
try
return done?() if @isAdmin()
userID = @get('_id')
# Create if no active user entry for today
today = new Date()
minDate = new Date(Date.UTC(today.getUTCFullYear(), today.getUTCMonth(), today.getUTCDate()))
AnalyticsUsersActive.findOne({created: {$gte: minDate}, creator: mongoose.Types.ObjectId(userID)}).exec (err, activeUser) ->
if err?
log.error "saveActiveUser error retrieving active users: #{err}"
else if not activeUser
newActiveUser = new AnalyticsUsersActive()
newActiveUser.set 'creator', userID
newActiveUser.set 'event', event
newActiveUser.save (err) ->
log.error "Level session saveActiveUser error saving active user: #{err}" if err?
done?()
catch err
log.error err
done?()
UserSchema.pre('save', (next) ->
Classroom = require './Classroom'
if @isTeacher() and not @wasTeacher
Classroom.update({members: @_id}, {$pull: {members: @_id}}, {multi: true}).exec (err, res) ->
console.log 'removed self from all classrooms as a member', err, res
if email = @get('email')
@set('emailLower', email.toLowerCase())
if name = @get('name')
@set('nameLower', name.toLowerCase())
pwd = @get('password')
if @get('password')
@set('passwordHash', User.hashPassword(pwd))
@set('password', undefined)
if @get('email') and @get('anonymous') # a user registers
@register next
else
next()
)
UserSchema.post 'save', (doc) ->
doc.newsSubsChanged = not _.isEqual(_.pick(doc.get('emails'), mail.NEWS_GROUPS), _.pick(doc.startingEmails, mail.NEWS_GROUPS))
UserSchema.statics.updateServiceSettings(doc)
UserSchema.post 'init', (doc) ->
doc.wasTeacher = doc.isTeacher()
doc.startingEmails = _.cloneDeep(doc.get('emails'))
UserSchema.statics.hashPassword = (password) ->
password = password.toLowerCase()
shasum = crypto.createHash('sha512')
shasum.update(salt + password)
shasum.digest('hex')
UserSchema.statics.privateProperties = [
'permissions', 'email', 'mailChimp', 'firstName', 'lastName', 'gender', 'facebookID',
'gplusID', 'music', 'volume', 'aceConfig', 'employerAt', 'signedEmployerAgreement',
'emailSubscriptions', 'emails', 'activity', 'stripe', 'stripeCustomerID', 'chinaVersion', 'country',
'schoolName', 'ageRange', 'role'
]
UserSchema.statics.jsonSchema = jsonschema
UserSchema.statics.editableProperties = [
'name', 'photoURL', 'password', 'anonymous', 'wizardColor1', 'volume',
'firstName', 'lastName', 'gender', 'ageRange', 'facebookID', 'gplusID', 'emails',
'testGroupNumber', 'music', 'hourOfCode', 'hourOfCodeComplete', 'preferredLanguage',
'wizard', 'aceConfig', 'autocastDelay', 'lastLevel', 'jobProfile', 'savedEmployerFilterAlerts',
'heroConfig', 'iosIdentifierForVendor', 'siteref', 'referrer', 'schoolName', 'role'
]
UserSchema.statics.serverProperties = ['passwordHash', 'emailLower', 'nameLower', 'passwordReset', 'lastIP']
UserSchema.statics.candidateProperties = [ 'jobProfile', 'jobProfileApproved', 'jobProfileNotes']
UserSchema.set('toObject', {
transform: (doc, ret, options) ->
req = options.req
return ret unless req # TODO: Make deleting properties the default, but the consequences are far reaching
publicOnly = options.publicOnly
delete ret[prop] for prop in User.serverProperties
includePrivates = not publicOnly and (req.user and (req.user.isAdmin() or req.user._id.equals(doc._id) or req.session.amActually is doc.id))
if options.includedPrivates
excludedPrivates = _.reject User.privateProperties, (prop) ->
prop in options.includedPrivates
else
excludedPrivates = User.privateProperties
delete ret[prop] for prop in excludedPrivates unless includePrivates
delete ret[prop] for prop in User.candidateProperties
return ret
})
UserSchema.plugin plugins.NamedPlugin
module.exports = User = mongoose.model('User', UserSchema)
AchievablePlugin = require '../plugins/achievements'
UserSchema.plugin(AchievablePlugin)

View file

@ -1,9 +1,9 @@
mongoose = require 'mongoose' mongoose = require 'mongoose'
plugins = require '../plugins/plugins' plugins = require '../plugins/plugins'
jsonSchema = require '../../app/schemas/models/user-polls-record.schema' jsonSchema = require '../../app/schemas/models/user-polls-record.schema.coffee'
log = require 'winston' log = require 'winston'
Poll = require './Poll' Poll = require './Poll'
User = require '../users/User' User = require './User'
UserPollsRecordSchema = new mongoose.Schema {}, {strict: false, minimize: false} UserPollsRecordSchema = new mongoose.Schema {}, {strict: false, minimize: false}

View file

@ -1,6 +1,6 @@
mongoose = require 'mongoose' mongoose = require 'mongoose'
plugins = require '../../plugins/plugins' plugins = require '../plugins/plugins'
jsonschema = require '../../../app/schemas/models/user_remark' jsonschema = require '../../app/schemas/models/user_remark'
UserRemarkSchema = new mongoose.Schema({ UserRemarkSchema = new mongoose.Schema({
created: created:

View file

@ -1,79 +0,0 @@
mongoose = require('mongoose')
deltas = require '../../app/core/deltas'
log = require 'winston'
{handlers} = require '../commons/mapping'
config = require '../../server_config'
PatchSchema = new mongoose.Schema({status: String}, {strict: false,read:config.mongo.readpref})
PatchSchema.pre 'save', (next) ->
return next() unless @isNew # patch can't be altered after creation, so only need to check data once
target = @get('target')
targetID = target.id
Handler = require '../commons/Handler'
if not Handler.isID(targetID)
err = new Error('Invalid input.')
err.response = {message: 'isn\'t a MongoDB id.', property: 'target.id'}
err.code = 422
return next(err)
collection = target.collection
handler = require('../' + handlers[collection])
handler.getDocumentForIdOrSlug targetID, (err, document) =>
if err
err = new Error('Server error.')
err.response = {message: '', property: 'target.id'}
err.code = 500
return next(err)
if not document
err = new Error('Target of patch not found.')
err.response = {message: 'was not found.', property: 'target.id'}
err.code = 404
return next(err)
target.id = document.get('_id')
if handler.modelClass.schema.uses_coco_versions
target.original = document.get('original')
version = document.get('version')
target.version = _.pick document.get('version'), 'major', 'minor'
@set('target', target)
else
target.original = targetID
patches = document.get('patches') or []
patches = _.clone patches
patches.push @_id
document.set 'patches', patches, {strict: false}
@targetLoaded = document
document.save (err) -> next(err)
PatchSchema.methods.isTranslationPatch = -> # Don't ever fat arrow bind this one
expanded = deltas.flattenDelta @get('delta')
_.some expanded, (delta) -> 'i18n' in delta.dataPath
PatchSchema.methods.isMiscPatch = ->
expanded = deltas.flattenDelta @get('delta')
_.some expanded, (delta) -> 'i18n' not in delta.dataPath
# Keep track of when a patch is pending and newly approved.
PatchSchema.path('status').set (newVal) ->
@set 'wasPending', @status is 'pending' and newVal isnt 'pending'
@set 'newlyAccepted', newVal is 'accepted' and not @get('newlyAccepted') # Only true on the first accept
newVal
PatchSchema.methods.isNewlyAccepted = -> @get('newlyAccepted')
PatchSchema.methods.wasPending = -> @get 'wasPending'
PatchSchema.pre 'save', (next) ->
User = require '../users/User'
userID = @get('creator').toHexString()
if @get('status') is 'accepted'
User.incrementStat userID, 'stats.patchesContributed' # accepted patches
else if @get('status') is 'pending'
User.incrementStat userID, 'stats.patchesSubmitted' # submitted patches
next()
module.exports = mongoose.model('patch', PatchSchema)

View file

@ -1,5 +1,5 @@
mongoose = require 'mongoose' mongoose = require 'mongoose'
EarnedAchievement = require '../achievements/EarnedAchievement' EarnedAchievement = require '../models/EarnedAchievement'
LocalMongo = require '../../app/lib/LocalMongo' LocalMongo = require '../../app/lib/LocalMongo'
util = require '../../app/core/utils' util = require '../../app/core/utils'
log = require 'winston' log = require 'winston'
@ -9,8 +9,8 @@ log = require 'winston'
# TODO if this is still a common scenario I could implement a database hit after all, but only # TODO if this is still a common scenario I could implement a database hit after all, but only
# on the condition that it's necessary and still not too frequent in occurrence # on the condition that it's necessary and still not too frequent in occurrence
AchievablePlugin = (schema, options) -> AchievablePlugin = (schema, options) ->
User = require '../users/User' # Avoid mutual inclusion cycles User = require '../models/User' # Avoid mutual inclusion cycles
Achievement = require '../achievements/Achievement' Achievement = require '../models/Achievement'
# Keep track the document before it's saved # Keep track the document before it's saved
schema.post 'init', (doc) -> schema.post 'init', (doc) ->

View file

@ -267,7 +267,7 @@ module.exports.VersionedPlugin = (schema) ->
# Assume every save is a new version, hence an edit # Assume every save is a new version, hence an edit
schema.pre 'save', (next) -> schema.pre 'save', (next) ->
User = require '../users/User' # Avoid mutual inclusion cycles User = require '../models/User' # Avoid mutual inclusion cycles
userID = @get('creator')?.toHexString() userID = @get('creator')?.toHexString()
return next() unless userID? return next() unless userID?

View file

@ -6,10 +6,10 @@ errors = require '../commons/errors'
aws = require 'aws-sdk' aws = require 'aws-sdk'
db = require './../routes/db' db = require './../routes/db'
queues = require '../commons/queue' queues = require '../commons/queue'
LevelSession = require '../levels/sessions/LevelSession' LevelSession = require '../models/LevelSession'
Level = require '../levels/Level' Level = require '../models/Level'
User = require '../users/User' User = require '../models/User'
TaskLog = require './scoring/ScoringTask' TaskLog = require './../models/ScoringTask'
scoringUtils = require './scoring/scoringUtils' scoringUtils = require './scoring/scoringUtils'
getTwoGames = require './scoring/getTwoGames' getTwoGames = require './scoring/getTwoGames'
recordTwoGames = require './scoring/recordTwoGames' recordTwoGames = require './scoring/recordTwoGames'

View file

@ -2,8 +2,8 @@ log = require 'winston'
async = require 'async' async = require 'async'
errors = require '../../commons/errors' errors = require '../../commons/errors'
scoringUtils = require './scoringUtils' scoringUtils = require './scoringUtils'
LevelSession = require '../../levels/sessions/LevelSession' LevelSession = require '../../models/LevelSession'
Level = require '../../levels/Level' Level = require '../../models/Level'
module.exports = createNewTask = (req, res) -> module.exports = createNewTask = (req, res) ->
requestSessionID = req.body.session requestSessionID = req.body.session

View file

@ -2,8 +2,8 @@ log = require 'winston'
async = require 'async' async = require 'async'
errors = require '../../commons/errors' errors = require '../../commons/errors'
scoringUtils = require './scoringUtils' scoringUtils = require './scoringUtils'
LevelSession = require '../../levels/sessions/LevelSession' LevelSession = require '../../models/LevelSession'
TaskLog = require './ScoringTask' TaskLog = require './../../models/ScoringTask'
module.exports = dispatchTaskToConsumer = (req, res) -> module.exports = dispatchTaskToConsumer = (req, res) ->
yetiGuru = {} yetiGuru = {}

View file

@ -2,7 +2,7 @@ log = require 'winston'
async = require 'async' async = require 'async'
errors = require '../../commons/errors' errors = require '../../commons/errors'
scoringUtils = require './scoringUtils' scoringUtils = require './scoringUtils'
LevelSession = require '../../levels/sessions/LevelSession' LevelSession = require '../../models/LevelSession'
Mandate = require '../../models/Mandate' Mandate = require '../../models/Mandate'
module.exports = getTwoGames = (req, res) -> module.exports = getTwoGames = (req, res) ->

View file

@ -2,8 +2,8 @@ log = require 'winston'
async = require 'async' async = require 'async'
errors = require '../../commons/errors' errors = require '../../commons/errors'
scoringUtils = require './scoringUtils' scoringUtils = require './scoringUtils'
LevelSession = require '../../levels/sessions/LevelSession' LevelSession = require '../../models/LevelSession'
TaskLog = require './ScoringTask' TaskLog = require './../../models/ScoringTask'
module.exports = processTaskResult = (req, res) -> module.exports = processTaskResult = (req, res) ->
return if scoringUtils.simulatorIsTooOld req, res return if scoringUtils.simulatorIsTooOld req, res

View file

@ -2,7 +2,7 @@ log = require 'winston'
async = require 'async' async = require 'async'
errors = require '../../commons/errors' errors = require '../../commons/errors'
scoringUtils = require './scoringUtils' scoringUtils = require './scoringUtils'
LevelSession = require '../../levels/sessions/LevelSession' LevelSession = require '../../models/LevelSession'
module.exports = recordTwoGames = (req, res) -> module.exports = recordTwoGames = (req, res) ->
sessions = req.body.sessions sessions = req.body.sessions

View file

@ -1,8 +1,8 @@
log = require 'winston' log = require 'winston'
async = require 'async' async = require 'async'
bayes = new (require 'bayesian-battle')() bayes = new (require 'bayesian-battle')()
LevelSession = require '../../levels/sessions/LevelSession' LevelSession = require '../../models/LevelSession'
User = require '../../users/User' User = require '../../models/User'
perfmon = require '../../commons/perfmon' perfmon = require '../../commons/perfmon'
SIMULATOR_VERSION = 3 SIMULATOR_VERSION = 3

Some files were not shown because too many files have changed in this diff Show more