mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-12-13 09:11:22 -05:00
Merge branch 'master' into production
This commit is contained in:
commit
5d24bfce56
158 changed files with 1089 additions and 943 deletions
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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 = []
|
||||||
|
|
54
scripts/mongodb/queries/what-unlocks-level.js
Normal file
54
scripts/mongodb/queries/what-unlocks-level.js
Normal 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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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?
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 + '...'
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
|
|
@ -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)
|
|
|
@ -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'
|
|
|
@ -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'
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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'
|
||||||
|
|
|
@ -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'
|
|
|
@ -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
|
|
@ -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
|
|
@ -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'
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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'
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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'
|
|
@ -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
|
|
@ -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'
|
|
@ -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)
|
|
@ -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
|
|
@ -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
|
|
@ -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)
|
|
@ -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()
|
|
@ -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'
|
|
@ -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'
|
|
@ -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'
|
|
@ -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'
|
|
@ -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'
|
|
@ -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'
|
|
@ -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'
|
|
@ -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'
|
||||||
|
|
|
@ -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) ->
|
|
@ -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'
|
|
@ -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()
|
|
@ -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'
|
||||||
|
|
|
@ -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) ->
|
||||||
|
|
|
@ -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'
|
||||||
|
|
|
@ -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'
|
||||||
|
|
||||||
|
|
|
@ -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) ->
|
||||||
|
|
|
@ -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) ->
|
||||||
|
|
|
@ -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 =
|
||||||
|
|
|
@ -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'
|
||||||
|
|
|
@ -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) ->
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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}
|
||||||
|
|
|
@ -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'
|
||||||
|
|
|
@ -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'
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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:
|
|
@ -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')
|
|
@ -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
|
|
@ -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'}
|
|
@ -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:
|
|
@ -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)
|
||||||
|
|
|
@ -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 {
|
|
@ -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,
|
|
@ -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}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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}
|
||||||
|
|
|
@ -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:
|
|
@ -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)
|
|
|
@ -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) ->
|
||||||
|
|
|
@ -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?
|
||||||
|
|
||||||
|
|
|
@ -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'
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 = {}
|
||||||
|
|
|
@ -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) ->
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
Loading…
Reference in a new issue