mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-04-27 22:43:54 -04:00
Merge branch 'master' into production
This commit is contained in:
commit
fb59521748
68 changed files with 327 additions and 185 deletions
app
lib
views/play/level/tome
server
articles
campaigns
commons
Handler.coffeeerrors.coffeei18n_schema.coffeelogging.coffeemail.coffeemetaschema.coffeeschemas.coffee
files
levels
plugins
routes
users
test/server
|
@ -95,7 +95,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
|||
sprite = new createjs.Shape()
|
||||
sprite.scaleX = sprite.scaleY = 1 / @options.resolutionFactor
|
||||
# temp, until these are re-exported with perspective
|
||||
if @options.camera and @thangType.get('name') in ['Dungeon Floor', 'Grass', 'Goal Trigger', 'Obstacle']
|
||||
if @options.camera and @thangType.get('name') in ['Dungeon Floor', 'Grass', 'Goal Trigger', 'Obstacle']
|
||||
sprite.scaleY *= @options.camera.y2x
|
||||
@imageObject = sprite
|
||||
@displayObject.addChild(sprite)
|
||||
|
@ -207,19 +207,10 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
|||
rotation
|
||||
|
||||
updateIsometricRotation: (rotation, imageObject) ->
|
||||
action = @currentRootAction
|
||||
return unless action
|
||||
# @flipOccasionally() if action.name is 'idle'
|
||||
imageObject ?= @imageObject
|
||||
imageObject.scaleX *= -1 if imageObject.scaleX < 0 # normalize to point right
|
||||
imageObject.scaleX *= -1 if Math.abs(rotation) >= 135
|
||||
# imageObject.scaleX *= -1 if @flipped and action.name is 'idle'
|
||||
|
||||
flipOccasionally: ->
|
||||
@flippedCount += 1
|
||||
return unless _.random(0,1000) <= 15 and @flippedCount > 30
|
||||
@flipped = not @flipped
|
||||
@flippedCount = 0
|
||||
return unless @currentAction
|
||||
return if _.string.endsWith(@currentAction.name, 'back')
|
||||
return if _.string.endsWith(@currentAction.name, 'fore')
|
||||
@imageObject.scaleX *= -1 if Math.abs(rotation) >= 90
|
||||
|
||||
##################################################
|
||||
updateAction: ->
|
||||
|
|
|
@ -227,10 +227,5 @@ module.exports = class WizardSprite extends IndieSprite
|
|||
if @targetSprite
|
||||
@pointToward(@targetSprite.thang.pos)
|
||||
|
||||
updateIsometricRotation: (rotation, imageObject) ->
|
||||
super rotation, imageObject
|
||||
imageObject ?= @imageObject
|
||||
imageObject.scaleX *= -1 if Math.abs(rotation) <= 45 or Math.abs(rotation) >= 135 # reverse it
|
||||
|
||||
updateMarks: ->
|
||||
super() if @displayObject.visible # not if we hid the wiz
|
||||
|
|
|
@ -221,7 +221,7 @@ module.exports = class World
|
|||
channel = 'world:' + channel
|
||||
for script in @scripts
|
||||
continue if script.channel isnt channel
|
||||
scriptNote = new WorldScriptNote script, event, world
|
||||
scriptNote = new WorldScriptNote script, event
|
||||
continue if scriptNote.invalid
|
||||
@scriptNotes.push scriptNote
|
||||
return unless @goalManager
|
||||
|
|
|
@ -56,7 +56,7 @@ module.exports = class Spell
|
|||
|
||||
createAether: (thang) ->
|
||||
aetherOptions =
|
||||
thisValue: thang.createUserContext()
|
||||
#thisValue: thang.createUserContext() # slooow, and not useful I guess?
|
||||
problems:
|
||||
jshint_W040: {level: "ignore"}
|
||||
aether_MissingThis: {level: (if thang.requiresThis then 'error' else 'warning')}
|
||||
|
|
|
@ -63,6 +63,7 @@ module.exports = class SpellToolbarView extends View
|
|||
@setStatementRatio e.offsetX / @$el.find('.progress').width()
|
||||
@updateTime()
|
||||
@maintainIndexHover = true
|
||||
@updateScroll()
|
||||
|
||||
onProgressMouseOut: (e) ->
|
||||
@maintainIndexHover = false
|
||||
|
@ -73,6 +74,7 @@ module.exports = class SpellToolbarView extends View
|
|||
lastTime = @statementTime
|
||||
@setStatementIndex @statementIndex + delta
|
||||
@updateTime() if @statementIndex isnt lastTime
|
||||
@updateScroll()
|
||||
|
||||
updateTime: ->
|
||||
@maintainIndexScrub = true
|
||||
|
@ -80,6 +82,12 @@ module.exports = class SpellToolbarView extends View
|
|||
@maintainIndexScrubTimeout = _.delay (=> @maintainIndexScrub = false), 500
|
||||
Backbone.Mediator.publish 'level-set-time', time: @statementTime, scrubDuration: 500
|
||||
|
||||
updateScroll: ->
|
||||
return unless statementStart = @callState?.statements?[@statementIndex]?.range[0]
|
||||
text = @ace.getValue()
|
||||
currentLine = text.substr(0, statementStart).split('\n').length - 1
|
||||
@ace.scrollToLine currentLine, true, true
|
||||
|
||||
setCallState: (callState, statementIndex, @callIndex, @metrics) ->
|
||||
return if callState is @callState and statementIndex is @statementIndex
|
||||
return unless @callState = callState
|
||||
|
|
|
@ -69,6 +69,7 @@ module.exports = class SpellView extends View
|
|||
@ace.setShowPrintMargin false
|
||||
@ace.setShowInvisibles false
|
||||
@ace.setBehavioursEnabled false
|
||||
@ace.setAnimatedScroll true
|
||||
@toggleControls null, @writable
|
||||
@aceSession.selection.on 'changeCursor', @onCursorActivity
|
||||
$(@ace.container).find('.ace_gutter').on 'click', '.ace_error, .ace_warning, .ace_info', @onAnnotationClick
|
||||
|
@ -461,6 +462,7 @@ module.exports = class SpellView extends View
|
|||
markerRange.id = @aceSession.addMarker markerRange, clazz, "text"
|
||||
@markerRanges.push markerRange
|
||||
@aceSession.addGutterDecoration start.row, clazz if clazz is 'executing'
|
||||
null
|
||||
|
||||
onAnnotationClick: ->
|
||||
alertBox = $("<div class='alert alert-info fade in'>#{msg}</div>")
|
||||
|
|
|
@ -9,15 +9,16 @@ winston = require 'winston'
|
|||
passport = require 'passport'
|
||||
useragent = require 'express-useragent'
|
||||
|
||||
auth = require './server/auth'
|
||||
db = require './server/db'
|
||||
file = require './server/file'
|
||||
folder = require './server/folder'
|
||||
user = require './server/handlers/user'
|
||||
logging = require './server/logging'
|
||||
sprites = require './server/sprites'
|
||||
contact = require './server/contact'
|
||||
languages = require './server/languages'
|
||||
auth = require './server/routes/auth'
|
||||
db = require './server/routes/db'
|
||||
file = require './server/routes/file'
|
||||
folder = require './server/routes/folder'
|
||||
user = require './server/users/user_handler'
|
||||
logging = require './server/commons/logging'
|
||||
sprites = require './server/routes/sprites'
|
||||
contact = require './server/routes/contact'
|
||||
languages = require './server/routes/languages'
|
||||
mail = require './server/routes/mail'
|
||||
|
||||
https = require 'https'
|
||||
http = require 'http'
|
||||
|
@ -82,6 +83,7 @@ contact.setupRoutes(app)
|
|||
file.setupRoutes(app)
|
||||
folder.setupRoutes(app)
|
||||
languages.setupRoutes(app)
|
||||
mail.setupRoutes(app)
|
||||
|
||||
# Some sort of cross-domain communication hack facebook requires
|
||||
app.get('/channel.html', (req, res) ->
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
mongoose = require('mongoose')
|
||||
plugins = require('./plugins')
|
||||
plugins = require('../plugins/plugins')
|
||||
|
||||
ArticleSchema = new mongoose.Schema(
|
||||
body: String,
|
|
@ -1,7 +1,5 @@
|
|||
winston = require('winston')
|
||||
request = require('request')
|
||||
Article = require('../models/Article')
|
||||
Handler = require('./Handler')
|
||||
Article = require('./Article')
|
||||
Handler = require('../commons/Handler')
|
||||
|
||||
ArticleHandler = class ArticleHandler extends Handler
|
||||
modelClass: Article
|
|
@ -1,4 +1,4 @@
|
|||
c = require './common'
|
||||
c = require '../commons/schemas'
|
||||
|
||||
ArticleSchema = c.object()
|
||||
c.extendNamedProperties ArticleSchema # name first
|
|
@ -1,5 +1,5 @@
|
|||
mongoose = require('mongoose')
|
||||
plugins = require('./plugins')
|
||||
plugins = require('../plugins/plugins')
|
||||
|
||||
NestedLevelSchema = new mongoose.Schema(
|
||||
name: String
|
|
@ -1,7 +1,5 @@
|
|||
winston = require('winston')
|
||||
request = require('request')
|
||||
Campaign = require('../models/Campaign')
|
||||
Handler = require('./Handler')
|
||||
Campaign = require('./Campaign')
|
||||
Handler = require('../commons/Handler')
|
||||
|
||||
CampaignHandler = class CampaignHandler extends Handler
|
||||
modelClass: Campaign
|
|
@ -1,7 +1,5 @@
|
|||
winston = require('winston')
|
||||
request = require('request')
|
||||
CampaignStatus = require('../models/CampaignStatus')
|
||||
Handler = require('./Handler')
|
||||
CampaignStatus = require('./CampaignStatus')
|
||||
Handler = require('../commons/Handler')
|
||||
|
||||
CampaignStatusHandler = class CampaignStatusHandler extends Handler
|
||||
modelClass: CampaignStatus
|
|
@ -1,7 +1,7 @@
|
|||
async = require 'async'
|
||||
mongoose = require('mongoose')
|
||||
Grid = require 'gridfs-stream'
|
||||
errors = require '../errors'
|
||||
errors = require './errors'
|
||||
|
||||
module.exports = class Handler
|
||||
# subclasses should override these properties
|
|
@ -1,5 +1,5 @@
|
|||
#this file will hold the experimental JSON schema for i18n
|
||||
c = require './common'
|
||||
c = require './schemas'
|
||||
|
||||
languageCodeArrayRegex = c.generateLanguageCodeArrayRegex()
|
||||
|
19
server/commons/mail.coffee
Normal file
19
server/commons/mail.coffee
Normal file
|
@ -0,0 +1,19 @@
|
|||
config = require '../../server_config'
|
||||
|
||||
module.exports.MAILCHIMP_LIST_ID = 'e9851239eb'
|
||||
module.exports.MAILCHIMP_GROUP_ID = '4529'
|
||||
module.exports.MAILCHIMP_GROUP_MAP =
|
||||
announcement: 'Announcements'
|
||||
tester: 'Adventurers'
|
||||
level_creator: 'Artisans'
|
||||
developer: 'Archmages'
|
||||
article_editor: 'Scribes'
|
||||
translator: 'Diplomats'
|
||||
support: 'Ambassadors'
|
||||
|
||||
nodemailer = require 'nodemailer'
|
||||
module.exports.transport = nodemailer.createTransport "SMTP",
|
||||
service: config.mail.service
|
||||
user: config.mail.username
|
||||
pass: config.mail.password
|
||||
authMethod: "LOGIN"
|
|
@ -1,5 +1,5 @@
|
|||
#language imports
|
||||
Language = require '../languages'
|
||||
Language = require '../routes/languages'
|
||||
# schema helper methods
|
||||
|
||||
me = module.exports
|
|
@ -1,5 +1,5 @@
|
|||
mongoose = require('mongoose')
|
||||
plugins = require('./plugins')
|
||||
plugins = require('../plugins/plugins')
|
||||
|
||||
FileSchema = new mongoose.Schema()
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
File = require('../models/File')
|
||||
Handler = require('./Handler')
|
||||
File = require('./File')
|
||||
Handler = require('../commons/Handler')
|
||||
|
||||
FileHandler = class FileHandler extends Handler
|
||||
modelClass: File
|
|
@ -1,4 +1,4 @@
|
|||
c = require './common'
|
||||
c = require '../commons/schemas'
|
||||
|
||||
FileSchema = c.baseSchema()
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
mongoose = require('mongoose')
|
||||
plugins = require('./plugins')
|
||||
jsonschema = require('../schemas/level')
|
||||
plugins = require('../plugins/plugins')
|
||||
jsonschema = require('./level_schema')
|
||||
|
||||
LevelSchema = new mongoose.Schema({
|
||||
description: String
|
|
@ -1,6 +1,6 @@
|
|||
mongoose = require('mongoose')
|
||||
plugins = require('./plugins')
|
||||
jsonschema = require('../schemas/level_component')
|
||||
plugins = require('../../plugins/plugins')
|
||||
jsonschema = require('./level_component_schema')
|
||||
|
||||
LevelComponentSchema = new mongoose.Schema {
|
||||
description: String
|
|
@ -1,7 +1,5 @@
|
|||
winston = require('winston')
|
||||
request = require('request')
|
||||
LevelComponent = require('../models/LevelComponent')
|
||||
Handler = require('./Handler')
|
||||
LevelComponent = require('./LevelComponent')
|
||||
Handler = require('../../commons/Handler')
|
||||
|
||||
LevelComponentHandler = class LevelComponentHandler extends Handler
|
||||
modelClass: LevelComponent
|
|
@ -1,5 +1,5 @@
|
|||
c = require './common'
|
||||
metaschema = require './metaschema'
|
||||
c = require '../../commons/schemas'
|
||||
metaschema = require '../../commons/metaschema'
|
||||
|
||||
attackSelfCode = """
|
||||
class AttacksSelf extends Component
|
|
@ -1,5 +1,5 @@
|
|||
mongoose = require('mongoose')
|
||||
Level = require('./Level')
|
||||
Level = require('../Level')
|
||||
|
||||
LevelDraftSchema = new mongoose.Schema(
|
||||
user: {type: mongoose.Schema.ObjectId, ref: 'User'}
|
|
@ -1,7 +1,5 @@
|
|||
winston = require('winston')
|
||||
request = require('request')
|
||||
LevelDraft = require('../models/LevelDraft')
|
||||
Handler = require('./Handler')
|
||||
LevelDraft = require('./LevelDraft')
|
||||
Handler = require('../../commons/Handler')
|
||||
|
||||
LevelDraftHandler = class LevelDraftHandler extends Handler
|
||||
modelClass: LevelDraft
|
|
@ -1,8 +1,8 @@
|
|||
# TODO: not updated since rename from level_instance, or since we redid how all models are done; probably busted
|
||||
|
||||
mongoose = require('mongoose')
|
||||
plugins = require('./plugins')
|
||||
jsonschema = require('../schemas/level_feedback')
|
||||
plugins = require('../../plugins/plugins')
|
||||
jsonschema = require('./level_feedback_schema')
|
||||
|
||||
LevelFeedbackSchema = new mongoose.Schema({
|
||||
created:
|
|
@ -1,5 +1,5 @@
|
|||
LevelFeedback = require('../models/LevelFeedback')
|
||||
Handler = require('./Handler')
|
||||
LevelFeedback = require('./LevelFeedback')
|
||||
Handler = require('../../commons/Handler')
|
||||
|
||||
class LevelFeedbackHandler extends Handler
|
||||
modelClass: LevelFeedback
|
|
@ -1,4 +1,4 @@
|
|||
c = require './common'
|
||||
c = require '../../commons/schemas'
|
||||
|
||||
LevelFeedbackLevelSchema = c.object {required: ['original', 'majorVersion']}, {
|
||||
original: c.objectId({})
|
|
@ -1,10 +1,8 @@
|
|||
winston = require('winston')
|
||||
request = require('request')
|
||||
Level = require('../models/Level')
|
||||
Session = require('../models/LevelSession')
|
||||
SessionHandler = require('./level_session')
|
||||
Feedback = require('../models/LevelFeedback')
|
||||
Handler = require('./Handler')
|
||||
Level = require('./Level')
|
||||
Session = require('./sessions/LevelSession')
|
||||
SessionHandler = require('./sessions/level_session_handler')
|
||||
Feedback = require('./feedbacks/LevelFeedback')
|
||||
Handler = require('../commons/Handler')
|
||||
mongoose = require('mongoose')
|
||||
|
||||
LevelHandler = class LevelHandler extends Handler
|
|
@ -1,5 +1,5 @@
|
|||
c = require './common'
|
||||
ThangComponentSchema = require './thang_component'
|
||||
c = require '../commons/schemas'
|
||||
ThangComponentSchema = require './thangs/thang_component_schema'
|
||||
|
||||
SpecificArticleSchema = c.object()
|
||||
c.extendNamedProperties SpecificArticleSchema # name first
|
|
@ -1,8 +1,8 @@
|
|||
# TODO: not updated since rename from level_instance, or since we redid how all models are done; probably busted
|
||||
|
||||
mongoose = require('mongoose')
|
||||
plugins = require('./plugins')
|
||||
jsonschema = require('../schemas/level_session')
|
||||
plugins = require('../../plugins/plugins')
|
||||
jsonschema = require('./level_session_schema')
|
||||
|
||||
LevelSessionSchema = new mongoose.Schema({
|
||||
created:
|
|
@ -1,5 +1,5 @@
|
|||
LevelSession = require('../models/LevelSession')
|
||||
Handler = require('./Handler')
|
||||
LevelSession = require('./LevelSession')
|
||||
Handler = require('../../commons/Handler')
|
||||
|
||||
TIMEOUT = 1000 * 30 # no activity for 30 seconds means it's not active
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
c = require './common'
|
||||
c = require '../../commons/schemas'
|
||||
|
||||
LevelSessionPlayerSchema = c.object {
|
||||
id: c.objectId(links: [{rel: 'extra', href: "/db/user/{($)}"}])
|
|
@ -1,6 +1,6 @@
|
|||
mongoose = require('mongoose')
|
||||
plugins = require('./plugins')
|
||||
jsonschema = require('../schemas/level_system')
|
||||
plugins = require('../../plugins/plugins')
|
||||
jsonschema = require('./level_system_schema')
|
||||
|
||||
LevelSystemSchema = new mongoose.Schema {
|
||||
description: String
|
|
@ -1,7 +1,5 @@
|
|||
winston = require('winston')
|
||||
request = require('request')
|
||||
LevelSystem = require('../models/LevelSystem')
|
||||
Handler = require('./Handler')
|
||||
LevelSystem = require('./LevelSystem')
|
||||
Handler = require('../../commons/Handler')
|
||||
|
||||
LevelSystemHandler = class LevelSystemHandler extends Handler
|
||||
modelClass: LevelSystem
|
|
@ -1,5 +1,5 @@
|
|||
c = require './common'
|
||||
metaschema = require './metaschema'
|
||||
c = require '../../commons/schemas'
|
||||
metaschema = require '../../commons/metaschema'
|
||||
|
||||
jitterSystemCode = """
|
||||
class Jitter extends System
|
|
@ -1,5 +1,5 @@
|
|||
mongoose = require('mongoose')
|
||||
plugins = require('./plugins')
|
||||
plugins = require('../../plugins/plugins')
|
||||
|
||||
LevelComponentSchema = new mongoose.Schema(
|
||||
original: {type: mongoose.Schema.ObjectId, ref: 'level.session'}
|
|
@ -1,5 +1,5 @@
|
|||
mongoose = require('mongoose')
|
||||
plugins = require('./plugins')
|
||||
plugins = require('../../plugins/plugins')
|
||||
|
||||
ThangTypeSchema = new mongoose.Schema({
|
||||
body: String,
|
|
@ -1,4 +1,4 @@
|
|||
c = require './common'
|
||||
c = require '../../commons/schemas'
|
||||
|
||||
module.exports = ThangComponentSchema = c.object {
|
||||
title: "Component"
|
|
@ -1,7 +1,7 @@
|
|||
winston = require('winston')
|
||||
request = require('request')
|
||||
ThangType = require('../models/ThangType')
|
||||
Handler = require('./Handler')
|
||||
ThangType = require('./ThangType')
|
||||
Handler = require('../../commons/Handler')
|
||||
|
||||
ThangTypeHandler = class ThangTypeHandler extends Handler
|
||||
modelClass: ThangType
|
|
@ -1,5 +1,5 @@
|
|||
c = require './common'
|
||||
ThangComponentSchema = require './thang_component'
|
||||
c = require '../../commons/schemas'
|
||||
ThangComponentSchema = require './thang_component_schema'
|
||||
|
||||
ThangTypeSchema = c.object()
|
||||
c.extendNamedProperties ThangTypeSchema # name first
|
|
@ -1,5 +1,5 @@
|
|||
mongoose = require('mongoose')
|
||||
User = require('./User')
|
||||
User = require('../users/User')
|
||||
textSearch = require('mongoose-text-search')
|
||||
|
||||
module.exports.NamedPlugin = (schema) ->
|
|
@ -1,11 +1,11 @@
|
|||
passport = require('passport')
|
||||
winston = require('winston')
|
||||
LocalStrategy = require('passport-local').Strategy
|
||||
User = require('./models/User')
|
||||
UserHandler = require('./handlers/user')
|
||||
config = require '../server_config'
|
||||
nodemailer = require 'nodemailer'
|
||||
errors = require './errors'
|
||||
User = require('../users/User')
|
||||
UserHandler = require('../users/user_handler')
|
||||
config = require '../../server_config'
|
||||
errors = require '../commons/errors'
|
||||
mail = require '../commons/mail'
|
||||
|
||||
module.exports.setupRoutes = (app) ->
|
||||
passport.serializeUser((user, done) -> done(null, user._id))
|
||||
|
@ -66,9 +66,8 @@ module.exports.setupRoutes = (app) ->
|
|||
user.save (err) =>
|
||||
return errors.serverError(res) if err
|
||||
if config.isProduction
|
||||
transport = createSMTPTransport()
|
||||
options = createMailOptions req.body.email, user.get('passwordReset')
|
||||
transport.sendMail options, (error, response) ->
|
||||
mail.transport.sendMail options, (error, response) ->
|
||||
if error
|
||||
console.error "Error sending mail: #{error.message or error}"
|
||||
return errors.serverError(res) if err
|
||||
|
@ -104,13 +103,4 @@ createMailOptions = (receiver, password) ->
|
|||
replyTo: config.mail.username
|
||||
subject: "[CodeCombat] Password Reset"
|
||||
text: "You can log into your account with: #{password}"
|
||||
#html: message.replace '\n', '<br>\n'
|
||||
|
||||
createSMTPTransport = ->
|
||||
return smtpTransport if smtpTransport
|
||||
smtpTransport = nodemailer.createTransport "SMTP",
|
||||
service: config.mail.service
|
||||
user: config.mail.username
|
||||
pass: config.mail.password
|
||||
authMethod: "LOGIN"
|
||||
smtpTransport
|
||||
#
|
|
@ -1,14 +1,13 @@
|
|||
config = require '../server_config'
|
||||
config = require '../../server_config'
|
||||
winston = require 'winston'
|
||||
nodemailer = require 'nodemailer'
|
||||
mail = require '../commons/mail'
|
||||
|
||||
module.exports.setupRoutes = (app) ->
|
||||
app.post '/contact', (req, res) ->
|
||||
winston.info "Sending mail from #{req.body.email} saying #{req.body.message}"
|
||||
if config.isProduction
|
||||
transport = createSMTPTransport()
|
||||
options = createMailOptions req.body.email, req.body.message, req.user
|
||||
transport.sendMail options, (error, response) ->
|
||||
mail.transport.sendMail options, (error, response) ->
|
||||
if error
|
||||
winston.error "Error sending mail: #{error.message or error}"
|
||||
else
|
||||
|
@ -17,21 +16,10 @@ module.exports.setupRoutes = (app) ->
|
|||
|
||||
createMailOptions = (sender, message, user) ->
|
||||
# TODO: use email templates here
|
||||
console.log 'text is now', "#{message}\n\n#{user.get('name')}\nID: #{user._id}"
|
||||
options =
|
||||
from: config.mail.username
|
||||
to: config.mail.username
|
||||
replyTo: sender
|
||||
subject: "[CodeCombat] Feedback - #{sender}"
|
||||
text: "#{message}\n\nUsername: #{user.get('name') or 'Anonymous'}\nID: #{user._id}"
|
||||
#html: message.replace '\n', '<br>\n'
|
||||
|
||||
smtpTransport = null
|
||||
createSMTPTransport = ->
|
||||
return smtpTransport if smtpTransport
|
||||
smtpTransport = nodemailer.createTransport "SMTP",
|
||||
service: config.mail.service
|
||||
user: config.mail.username
|
||||
pass: config.mail.password
|
||||
authMethod: "LOGIN"
|
||||
smtpTransport
|
||||
#html: message.replace '\n', '<br>\n'
|
|
@ -1,12 +1,43 @@
|
|||
config = require '../server_config'
|
||||
config = require '../../server_config'
|
||||
winston = require 'winston'
|
||||
mongoose = require 'mongoose'
|
||||
Grid = require 'gridfs-stream'
|
||||
async = require 'async'
|
||||
errors = require './errors'
|
||||
errors = require '../commons/errors'
|
||||
|
||||
testing = '--unittest' in process.argv
|
||||
|
||||
|
||||
handlers =
|
||||
'article': '../../server/articles/article_handler'
|
||||
'campaign': '../../server/campaigns/campaign_handler'
|
||||
'campaign_status': '../../server/campaigns/campaign_status_handler'
|
||||
'file': '../../server/files/file_handler'
|
||||
'level': '../../server/levels/level_handler'
|
||||
'level_component': '../../server/levels/components/level_component_handler'
|
||||
'level_draft': '../../server/levels/drafts/level_draft_handler'
|
||||
'level_feedback': '../../server/levels/feedbacks/level_feedback_handler'
|
||||
'level_session': '../../server/levels/sessions/level_session_handler'
|
||||
'level_system': '../../server/levels/systems/level_system_handler'
|
||||
'thang_type': '../../server/levels/thangs/thang_type_handler'
|
||||
'user': '../../server/users/user_handler'
|
||||
|
||||
schemas =
|
||||
'article': '../../server/articles/article_schema'
|
||||
'common': '../../server/commons/schemas'
|
||||
#'file': '../../server/files/file_schema'
|
||||
'i18n': '../../server/commons/i18n_schema'
|
||||
'level': '../../server/levels/level_schema'
|
||||
'level_component': '../../server/levels/components/level_component_schema'
|
||||
'level_feedback': '../../server/levels/feedbacks/level_feedback_schema'
|
||||
'level_session': '../../server/levels/sessions/level_session_schema'
|
||||
'level_system': '../../server/levels/systems/level_system_schema'
|
||||
'metaschema': '../../server/commons/metaschema'
|
||||
'thang_component': '../../server/levels/thangs/thang_component_schema'
|
||||
'thang_type': '../../server/levels/thangs/thang_type_schema'
|
||||
'user': '../../server/users/user_schema'
|
||||
|
||||
|
||||
module.exports.connectDatabase = () ->
|
||||
dbName = config.mongo.db
|
||||
dbName += '_unittest' if testing
|
||||
|
@ -30,7 +61,8 @@ module.exports.setupRoutes = (app) ->
|
|||
return getSchema(req, res, module) if parts[1] is 'schema'
|
||||
|
||||
try
|
||||
name = "./handlers/#{module.replace '.', '_'}"
|
||||
moduleName = module.replace '.', '_'
|
||||
name = handlers[moduleName]
|
||||
module = require(name)
|
||||
return module.getLatestVersion(req, res, parts[1], parts[3]) if parts[2] is 'version'
|
||||
return module.versions(req, res, parts[1]) if parts[2] is 'versions'
|
||||
|
@ -47,8 +79,9 @@ module.exports.setupRoutes = (app) ->
|
|||
|
||||
getSchema = (req, res, moduleName) ->
|
||||
try
|
||||
name = "./schemas/#{moduleName.replace '.', '_'}"
|
||||
name = schemas[moduleName.replace '.', '_']
|
||||
schema = require(name)
|
||||
|
||||
res.send(schema)
|
||||
res.end()
|
||||
|
|
@ -3,7 +3,7 @@ Grid = require 'gridfs-stream'
|
|||
fs = require 'fs'
|
||||
request = require 'request'
|
||||
mongoose = require('mongoose')
|
||||
errors = require './errors'
|
||||
errors = require '../commons/errors'
|
||||
|
||||
module.exports.setupRoutes = (app) ->
|
||||
app.all '/file*', (req, res) ->
|
|
@ -1,7 +1,5 @@
|
|||
fs = require 'fs'
|
||||
request = require 'request'
|
||||
mongoose = require('mongoose')
|
||||
errors = require './errors'
|
||||
errors = require '../commons/errors'
|
||||
|
||||
module.exports.setupRoutes = (app) ->
|
||||
app.all '/folder*', (req, res) ->
|
|
@ -1,6 +1,6 @@
|
|||
errors = require './errors'
|
||||
errors = require '../commons/errors'
|
||||
winston = require 'winston'
|
||||
locale = require '../app/locale/locale' # requiring from app; will break if we stop serving from where app lives
|
||||
locale = require '../../app/locale/locale' # requiring from app; will break if we stop serving from where app lives
|
||||
|
||||
module.exports.setupRoutes = (app) ->
|
||||
app.all '/languages/add/:lang/:namespace', (req, res) ->
|
57
server/routes/mail.coffee
Normal file
57
server/routes/mail.coffee
Normal file
|
@ -0,0 +1,57 @@
|
|||
mail = require '../commons/mail'
|
||||
map = _.invert mail.MAILCHIMP_GROUP_MAP
|
||||
User = require '../users/User.coffee'
|
||||
errors = require '../commons/errors'
|
||||
request = require 'request'
|
||||
|
||||
badLog = (text) ->
|
||||
console.log text
|
||||
request.post 'http://requestb.in/1brdpaz1', { form: {log: text} }
|
||||
|
||||
module.exports.setupRoutes = (app) ->
|
||||
app.all '/mail/webhook', (req, res) ->
|
||||
post = req.body
|
||||
|
||||
unless post.type in ['unsubscribe', 'profile']
|
||||
badLog("Bad post type: #{post.type}")
|
||||
return res.end()
|
||||
|
||||
unless post['data[email]']
|
||||
badLog("Ignoring because no email: #{JSON.stringify(req.body, null, '\t')}")
|
||||
return res.end()
|
||||
|
||||
unless post['data[email]'] is 'sderickson@gmail.com'
|
||||
badLog("Ignoring because this is a test: #{JSON.stringify(req.body, null, '\t')}")
|
||||
return res.end()
|
||||
|
||||
User.findOne {'mailChimp.euid':post['data[id]']}, (err, user) ->
|
||||
return errors.serverError(res) if err
|
||||
if not user
|
||||
badLog("could not find user for...: #{{'mailChimp.euid':post['data[id]']}}")
|
||||
return res.end()
|
||||
|
||||
handleProfileUpdate(post, user) if post.type is 'profile'
|
||||
handleUnsubscribe(post, user) if post.type is 'unsubscribe'
|
||||
|
||||
res.end()
|
||||
user.updatedMailChimp = true # so as not to echo back to mailchimp
|
||||
user.save (err) ->
|
||||
badLog("Error updating profile: #{error.message or error}") if err
|
||||
res.end()
|
||||
|
||||
|
||||
handleProfileUpdate = (data, user) ->
|
||||
groups = data['data[merges][INTERESTS]'].split(', ')
|
||||
groups = (map[g] for g in groups when map[g])
|
||||
user.set 'emailSubscriptions', groups
|
||||
|
||||
mailChimpInfo = user.get 'mailChimp'
|
||||
mailChimpInfo.email = data['data[email]']
|
||||
user.set 'mailChimp', mailChimpInfo
|
||||
|
||||
badLog("Updating user object to: #{JSON.stringify(user.toObject(), null, '\t')}")
|
||||
|
||||
handleUnsubscribe = (data, user) ->
|
||||
user.set 'emailSubscriptions', []
|
||||
|
||||
badLog("Unsubscribing user object to: #{JSON.stringify(user.toObject(), null, '\t')}")
|
|
@ -1,7 +1,8 @@
|
|||
mongoose = require('mongoose')
|
||||
jsonschema = require('../schemas/user')
|
||||
jsonschema = require('./user_schema')
|
||||
crypto = require('crypto')
|
||||
{salt, isProduction} = require('../../server_config')
|
||||
mail = require '../commons/mail'
|
||||
|
||||
sendwithus = require '../sendwithus'
|
||||
|
||||
|
@ -34,16 +35,17 @@ UserSchema.statics.updateMailChimp = (doc, callback) ->
|
|||
existingProps = doc.get('mailChimp')
|
||||
emailChanged = (not existingProps) or existingProps?.email isnt doc.get('email')
|
||||
emailSubs = doc.get('emailSubscriptions')
|
||||
newGroups = (groupingMap[name] for name in emailSubs when groupingMap[name]?)
|
||||
gm = mail.MAILCHIMP_GROUP_MAP
|
||||
newGroups = (gm[name] for name in emailSubs when gm[name]?)
|
||||
if (not existingProps) and newGroups.length is 0
|
||||
return callback?() # don't add totally unsubscribed people to the list
|
||||
subsChanged = doc.currentSubscriptions isnt JSON.stringify(emailSubs)
|
||||
return callback?() unless emailChanged or subsChanged
|
||||
|
||||
params = {}
|
||||
params.id = MAILCHIMP_LIST_ID
|
||||
params.id = mail.MAILCHIMP_LIST_ID
|
||||
params.email = if existingProps then {leid:existingProps.leid} else {email:doc.get('email')}
|
||||
params.merge_vars = { groupings: [ {id: MAILCHIMP_GROUP_ID, groups: newGroups} ] }
|
||||
params.merge_vars = { groupings: [ {id: mail.MAILCHIMP_GROUP_ID, groups: newGroups} ] }
|
||||
params.update_existing = true
|
||||
params.double_optin = false
|
||||
|
||||
|
@ -79,18 +81,6 @@ UserSchema.pre('save', (next) ->
|
|||
next()
|
||||
)
|
||||
|
||||
MAILCHIMP_LIST_ID = 'e9851239eb'
|
||||
MAILCHIMP_GROUP_ID = '4529'
|
||||
|
||||
groupingMap =
|
||||
announcement: 'Announcements'
|
||||
tester: 'Adventurers'
|
||||
level_creator: 'Artisans'
|
||||
developer: 'Archmages'
|
||||
article_editor: 'Scribes'
|
||||
translator: 'Diplomats'
|
||||
support: 'Ambassadors'
|
||||
|
||||
UserSchema.post 'save', (doc) ->
|
||||
UserSchema.statics.updateMailChimp(doc)
|
||||
|
|
@ -1,10 +1,9 @@
|
|||
winston = require('winston')
|
||||
schema = require('../schemas/user')
|
||||
schema = require('./user_schema')
|
||||
crypto = require('crypto')
|
||||
request = require('request')
|
||||
User = require('../models/User')
|
||||
Handler = require('./Handler')
|
||||
languages = require '../languages'
|
||||
User = require('./User')
|
||||
Handler = require('../commons/Handler')
|
||||
languages = require '../routes/languages'
|
||||
mongoose = require 'mongoose'
|
||||
config = require '../../server_config'
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
c = require './common'
|
||||
c = require '../commons/schemas'
|
||||
emailSubscriptions = ['announcement', 'tester', 'level_creator', 'developer', 'article_editor', 'translator', 'support', 'notification']
|
||||
|
||||
UserSchema = c.object {},
|
|
@ -6,24 +6,25 @@ _.str = require('underscore.string')
|
|||
_.mixin(_.str.exports())
|
||||
GLOBAL.mongoose = require 'mongoose'
|
||||
mongoose.connect('mongodb://localhost/coco_unittest')
|
||||
path = require('path')
|
||||
|
||||
models_path = '../../server/models/'
|
||||
|
||||
include_models = [
|
||||
'Article'
|
||||
'Campaign'
|
||||
'CampaignStatus'
|
||||
'Level'
|
||||
'LevelComponent'
|
||||
'LevelSystem'
|
||||
'LevelDraft'
|
||||
'LevelSession'
|
||||
'LevelThangType'
|
||||
'User'
|
||||
models_path = [
|
||||
'../../server/articles/Article'
|
||||
'../../server/campaigns/Campaign'
|
||||
'../../server/campaigns/CampaignStatus'
|
||||
'../../server/levels/Level'
|
||||
'../../server/levels/components/LevelComponent'
|
||||
'../../server/levels/systems/LevelSystem'
|
||||
'../../server/levels/drafts/LevelDraft'
|
||||
'../../server/levels/sessions/LevelSession'
|
||||
'../../server/levels/thangs/LevelThangType'
|
||||
'../../server/users/User'
|
||||
]
|
||||
|
||||
for m in include_models
|
||||
GLOBAL[m] = require models_path+m
|
||||
for m in models_path
|
||||
model = path.basename(m)
|
||||
#console.log('model=' + model)
|
||||
GLOBAL[model] = require m
|
||||
|
||||
async = require 'async'
|
||||
|
||||
|
|
|
@ -77,3 +77,10 @@ describe '/db/article', ->
|
|||
expect(res.statusCode).toBe(200)
|
||||
expect(body.name).toBe(new_article.name)
|
||||
done()
|
||||
|
||||
it 'get schema', (done) ->
|
||||
request.get {uri:url+'/schema'}, (err, res, body) ->
|
||||
expect(res.statusCode).toBe(200)
|
||||
body = JSON.parse(body)
|
||||
expect(body.type).toBeDefined()
|
||||
done()
|
||||
|
|
|
@ -7,7 +7,7 @@ describe 'Level', ->
|
|||
description: 'Climb a mountain.'
|
||||
permissions: simplePermissions
|
||||
|
||||
url = getURL('/db/level')
|
||||
urlLevel = '/db/level'
|
||||
|
||||
it 'clears things first', (done) ->
|
||||
clearModels [Level], (err) ->
|
||||
|
@ -16,6 +16,13 @@ describe 'Level', ->
|
|||
|
||||
it 'can make a Level.', (done) ->
|
||||
loginJoe ->
|
||||
request.post {uri:url, json:level}, (err, res, body) ->
|
||||
request.post {uri:getURL(urlLevel), json:level}, (err, res, body) ->
|
||||
expect(res.statusCode).toBe(200)
|
||||
done()
|
||||
done()
|
||||
|
||||
it 'get schema', (done) ->
|
||||
request.get {uri:getURL(urlLevel+'/schema')}, (err, res, body) ->
|
||||
expect(res.statusCode).toBe(200)
|
||||
body = JSON.parse(body)
|
||||
expect(body.type).toBeDefined()
|
||||
done()
|
||||
|
|
|
@ -139,3 +139,10 @@ describe 'LevelComponent', ->
|
|||
request.del {uri:url+'/'+components[0]._id}, (err, res) ->
|
||||
expect(res.statusCode).toBe(404)
|
||||
done()
|
||||
|
||||
it 'get schema', (done) ->
|
||||
request.get {uri:url+'/schema'}, (err, res, body) ->
|
||||
expect(res.statusCode).toBe(200)
|
||||
body = JSON.parse(body)
|
||||
expect(body.type).toBeDefined()
|
||||
done()
|
||||
|
|
12
test/server/handlers/level_feedback.spec.coffee
Normal file
12
test/server/handlers/level_feedback.spec.coffee
Normal file
|
@ -0,0 +1,12 @@
|
|||
require '../common'
|
||||
|
||||
describe 'LevelFeedback', ->
|
||||
|
||||
url = getURL('/db/level.feedback')
|
||||
|
||||
it 'get schema', (done) ->
|
||||
request.get {uri:url+'/schema'}, (err, res, body) ->
|
||||
expect(res.statusCode).toBe(200)
|
||||
body = JSON.parse(body)
|
||||
expect(body.type).toBeDefined()
|
||||
done()
|
12
test/server/handlers/level_session.spec.coffee
Normal file
12
test/server/handlers/level_session.spec.coffee
Normal file
|
@ -0,0 +1,12 @@
|
|||
require '../common'
|
||||
|
||||
describe 'LevelFeedback', ->
|
||||
|
||||
url = getURL('/db/level.session')
|
||||
|
||||
it 'get schema', (done) ->
|
||||
request.get {uri:url+'/schema'}, (err, res, body) ->
|
||||
expect(res.statusCode).toBe(200)
|
||||
body = JSON.parse(body)
|
||||
expect(body.type).toBeDefined()
|
||||
done()
|
|
@ -128,3 +128,10 @@ describe 'LevelSystem', ->
|
|||
request.del {uri:url+'/'+systems[0]._id}, (err, res) ->
|
||||
expect(res.statusCode).toBe(404)
|
||||
done()
|
||||
|
||||
it 'get schema', (done) ->
|
||||
request.get {uri:url+'/schema'}, (err, res, body) ->
|
||||
expect(res.statusCode).toBe(200)
|
||||
body = JSON.parse(body)
|
||||
expect(body.type).toBeDefined()
|
||||
done()
|
||||
|
|
12
test/server/handlers/level_thang_component.spec.coffee
Normal file
12
test/server/handlers/level_thang_component.spec.coffee
Normal file
|
@ -0,0 +1,12 @@
|
|||
require '../common'
|
||||
|
||||
describe 'Level Thang Component', ->
|
||||
|
||||
url = getURL('/db/thang.component')
|
||||
|
||||
it 'get schema', (done) ->
|
||||
request.get {uri:url+'/schema'}, (err, res, body) ->
|
||||
expect(res.statusCode).toBe(200)
|
||||
body = JSON.parse(body)
|
||||
expect(body.type).toBeDefined()
|
||||
done()
|
12
test/server/handlers/level_thang_type.spec.coffee
Normal file
12
test/server/handlers/level_thang_type.spec.coffee
Normal file
|
@ -0,0 +1,12 @@
|
|||
require '../common'
|
||||
|
||||
describe 'Level Thang Type', ->
|
||||
|
||||
url = getURL('/db/thang.type')
|
||||
|
||||
it 'get schema', (done) ->
|
||||
request.get {uri:url+'/schema'}, (err, res, body) ->
|
||||
expect(res.statusCode).toBe(200)
|
||||
body = JSON.parse(body)
|
||||
expect(body.type).toBeDefined()
|
||||
done()
|
|
@ -136,6 +136,13 @@ describe 'GET /db/user', ->
|
|||
form.append('username', 'admin@afc.com')
|
||||
form.append('password', '80yqxpb38j')
|
||||
|
||||
it 'get schema', (done) ->
|
||||
request.get {uri:getURL(urlUser+'/schema')}, (err, res, body) ->
|
||||
expect(res.statusCode).toBe(200)
|
||||
body = JSON.parse(body)
|
||||
expect(body.type).toBeDefined()
|
||||
done()
|
||||
|
||||
it 'is able to do a sweet query', (done) ->
|
||||
conditions = [
|
||||
['limit', 20]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue