Merge pull request #342 from codecombat/master

Merge server refactor into task queue
This commit is contained in:
Michael Schmatz 2014-02-05 09:38:18 -08:00
commit 177eb60e48
41 changed files with 159 additions and 127 deletions

View file

@ -69,8 +69,10 @@ def which(cmd, mode=os.F_OK | os.X_OK, path=None):
#TODO: Upgrade this so it works on windows
#These scripts will be placed in coco/bin
current_directory = os.path.dirname(os.path.realpath(sys.argv[0]))
if which("mongod") and "v2.5.4" in subprocess.check_output("mongod --version",shell=True):
allowedMongoVersions = ["v2.5.4","v2.5.5"]
if which("mongod") and any(i in subprocess.check_output("mongod --version",shell=True) for i in allowedMongoVersions):
mongo_executable = "mongod"
else:
mongo_executable = None

View file

@ -5,13 +5,13 @@ do (setupLodash = this) ->
express = require 'express'
http = require 'http'
winston = require 'winston'
log = require 'winston'
serverSetup = require './server_setup'
module.exports.startServer = ->
app = createAndConfigureApp()
http.createServer(app).listen(app.get('port'))
winston.info("Express SSL server listening on port " + app.get('port'))
log.info("Express SSL server listening on port " + app.get('port'))
return app
createAndConfigureApp = ->

View file

@ -0,0 +1,24 @@
config = require '../../server_config'
winston = require 'winston'
mongoose = require 'mongoose'
Grid = require 'gridfs-stream'
testing = '--unittest' in process.argv
module.exports.connect = () ->
if config.mongo.mongoose_replica_string
address = config.mongo.mongoose_replica_string
winston.info "Connecting to replica set: #{address}"
else
dbName = config.mongo.db
dbName += '_unittest' if testing
address = config.mongo.host + ":" + config.mongo.port
if config.mongo.username and config.mongo.password
address = config.mongo.username + ":" + config.mongo.password + "@" + address
# address = config.mongo.username + "@" + address # if connecting to production server
address = "mongodb://#{address}/#{dbName}"
winston.info "Connecting to standalone server #{address}"
mongoose.connect address
mongoose.connection.once 'open', ->
Grid.gfs = Grid(mongoose.connection.db, mongoose.mongo)

View file

@ -0,0 +1,41 @@
module.exports.handlers =
'article': 'articles/article_handler'
'campaign': 'campaigns/campaign_handler'
'campaign_status': 'campaigns/campaign_status_handler'
'file': 'files/file_handler'
'level': 'levels/level_handler'
'level_component': 'levels/components/level_component_handler'
'level_draft': 'levels/drafts/level_draft_handler'
'level_feedback': 'levels/feedbacks/level_feedback_handler'
'level_session': 'levels/sessions/level_session_handler'
'level_system': 'levels/systems/level_system_handler'
'thang_type': 'levels/thangs/thang_type_handler'
'user': 'users/user_handler'
module.exports.schemas =
'article': 'articles/article_schema'
'common': 'commons/schemas'
#'file': 'files/file_schema'
'i18n': 'commons/i18n_schema'
'level': 'levels/level_schema'
'level_component': 'levels/components/level_component_schema'
'level_feedback': 'levels/feedbacks/level_feedback_schema'
'level_session': 'levels/sessions/level_session_schema'
'level_system': 'levels/systems/level_system_schema'
'metaschema': 'commons/metaschema'
'thang_component': 'levels/thangs/thang_component_schema'
'thang_type': 'levels/thangs/thang_type_schema'
'user': 'users/user_schema'
module.exports.routes =
[
'routes/auth'
'routes/contact'
'routes/db'
'routes/file'
'routes/folder'
'routes/languages'
'routes/mail'
'routes/sprites'
]

View file

@ -1,5 +1,3 @@
winston = require('winston')
request = require('request')
ThangType = require('./ThangType')
Handler = require('../../commons/Handler')

View file

@ -1,5 +1,4 @@
passport = require('passport')
winston = require('winston')
authentication = require('passport')
LocalStrategy = require('passport-local').Strategy
User = require('../users/User')
UserHandler = require('../users/user_handler')
@ -7,12 +6,12 @@ config = require '../../server_config'
errors = require '../commons/errors'
mail = require '../commons/mail'
module.exports.setupRoutes = (app) ->
passport.serializeUser((user, done) -> done(null, user._id))
passport.deserializeUser((id, done) ->
module.exports.setup = (app) ->
authentication.serializeUser((user, done) -> done(null, user._id))
authentication.deserializeUser((id, done) ->
User.findById(id, (err, user) -> done(err, user)))
passport.use(new LocalStrategy(
authentication.use(new LocalStrategy(
(username, password, done) ->
User.findOne({emailLower:username.toLowerCase()}).exec((err, user) ->
return done(err) if err
@ -30,7 +29,7 @@ module.exports.setupRoutes = (app) ->
))
app.post('/auth/login', (req, res, next) ->
passport.authenticate('local', (err, user, info) ->
authentication.authenticate('local', (err, user, info) ->
return next(err) if err
if not user
return errors.unauthorized(res, [{message:info.message, property:info.property}])

View file

@ -0,0 +1,9 @@
log = require 'winston'
routes = require('../commons/mapping').routes
module.exports.setup = (app) ->
for route in routes
do (route) ->
module = require('../'+route)
module.setup app
log.debug "route module #{route} setup"

View file

@ -1,17 +1,17 @@
config = require '../../server_config'
winston = require 'winston'
log = require 'winston'
mail = require '../commons/mail'
module.exports.setupRoutes = (app) ->
module.exports.setup = (app) ->
app.post '/contact', (req, res) ->
winston.info "Sending mail from #{req.body.email} saying #{req.body.message}"
log.info "Sending mail from #{req.body.email} saying #{req.body.message}"
if config.isProduction
options = createMailOptions req.body.email, req.body.message, req.user
mail.transport.sendMail options, (error, response) ->
if error
winston.error "Error sending mail: #{error.message or error}"
log.error "Error sending mail: #{error.message or error}"
else
winston.info "Mail sent successfully. Response: #{response.message}"
log.info "Mail sent successfully. Response: #{response.message}"
return res.end()
createMailOptions = (sender, message, user) ->

View file

@ -1,61 +1,9 @@
config = require '../../server_config'
winston = require 'winston'
mongoose = require 'mongoose'
Grid = require 'gridfs-stream'
async = require 'async'
log = require 'winston'
errors = require '../commons/errors'
handlers = require('../commons/mapping').handlers
schemas = require('../commons/mapping').schemas
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 = () ->
if config.mongo.mongoose_replica_string
address = config.mongo.mongoose_replica_string
winston.info "Connecting to replica set: #{address}"
else
dbName = config.mongo.db
dbName += '_unittest' if testing
address = config.mongo.host + ":" + config.mongo.port
if config.mongo.username and config.mongo.password
address = config.mongo.username + ":" + config.mongo.password + "@" + address
# address = config.mongo.username + "@" + address # if connecting to production server
address = "mongodb://#{address}/#{dbName}"
winston.info "Connecting to standalone server #{address}"
mongoose.connect address
mongoose.connection.once 'open', ->
Grid.gfs = Grid(mongoose.connection.db, mongoose.mongo)
module.exports.setupRoutes = (app) ->
module.exports.setup = (app) ->
app.all '/db/*', (req, res) ->
res.setHeader('Content-Type', 'application/json')
module = req.path[4..]
@ -67,28 +15,28 @@ module.exports.setupRoutes = (app) ->
try
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'
return module.files(req, res, parts[1]) if parts[2] is 'files'
return module.search(req, res) if req.route.method is 'get' and parts[1] is 'search'
return module.getByRelationship(req, res, parts[1..]...) if parts.length > 2
return module.getById(req, res, parts[1]) if req.route.method is 'get' and parts[1]?
return module.patch(req, res, parts[1]) if req.route.method is 'patch' and parts[1]?
module[req.route.method](req, res)
handler = require('../' + name)
return handler.getLatestVersion(req, res, parts[1], parts[3]) if parts[2] is 'version'
return handler.versions(req, res, parts[1]) if parts[2] is 'versions'
return handler.files(req, res, parts[1]) if parts[2] is 'files'
return handler.search(req, res) if req.route.method is 'get' and parts[1] is 'search'
return handler.getByRelationship(req, res, parts[1..]...) if parts.length > 2
return handler.getById(req, res, parts[1]) if req.route.method is 'get' and parts[1]?
return handler.patch(req, res, parts[1]) if req.route.method is 'patch' and parts[1]?
handler[req.route.method](req, res)
catch error
winston.error("Error trying db method #{req.route.method} route #{parts} from #{name}: #{error}")
winston.error(error)
log.error("Error trying db method #{req.route.method} route #{parts} from #{name}: #{error}")
log.error(error)
errors.notFound(res, "Route #{req.path} not found.")
getSchema = (req, res, moduleName) ->
try
name = schemas[moduleName.replace '.', '_']
schema = require(name)
schema = require('../' + name)
res.send(schema)
res.end()
catch error
winston.error("Error trying to grab schema from #{name}: #{error}")
log.error("Error trying to grab schema from #{name}: #{error}")
errors.notFound(res, "Schema #{moduleName} not found.")

View file

@ -1,11 +1,10 @@
winston = require 'winston'
Grid = require 'gridfs-stream'
fs = require 'fs'
request = require 'request'
mongoose = require('mongoose')
errors = require '../commons/errors'
module.exports.setupRoutes = (app) ->
module.exports.setup = (app) ->
app.all '/file*', (req, res) ->
return fileGet(req, res) if req.route.method is 'get'
return filePost(req, res) if req.route.method is 'post'

View file

@ -1,7 +1,7 @@
mongoose = require('mongoose')
errors = require '../commons/errors'
module.exports.setupRoutes = (app) ->
module.exports.setup = (app) ->
app.all '/folder*', (req, res) ->
return folderGet(req, res) if req.route.method is 'get'
return errors.badMethod(res)

View file

@ -1,11 +1,11 @@
errors = require '../commons/errors'
winston = require 'winston'
log = require 'winston'
locale = require '../../app/locale/locale' # requiring from app; will break if we stop serving from where app lives
module.exports.setupRoutes = (app) ->
module.exports.setup = (app) ->
app.all '/languages/add/:lang/:namespace', (req, res) ->
# Should probably store these somewhere
winston.info "#{req.params.lang}.#{req.params.namespace} missing an i18n key:", req.body
log.info "#{req.params.lang}.#{req.params.namespace} missing an i18n key:", req.body
res.send('')
res.end()

View file

@ -9,7 +9,7 @@ config = require '../../server_config'
# console.log text
# request.post 'http://requestb.in/1brdpaz1', { form: {log: text} }
module.exports.setupRoutes = (app) ->
module.exports.setup = (app) ->
app.all config.mail.mailchimpWebhook, (req, res) ->
post = req.body
# badLog("Got post data: #{JSON.stringify(post, null, '\t')}")

View file

@ -2,7 +2,7 @@
# order the sprites and make the more recent ones
# show up at the top
module.exports.setupRoutes = (app) ->
module.exports.setup = (app) ->
app.get('/server/sprite-info', (req, res) ->
exec = require('child_process').exec

View file

@ -1,19 +1,13 @@
express = require 'express'
path = require 'path'
passport = require 'passport'
authentication = require 'passport'
useragent = require 'express-useragent'
fs = require 'graceful-fs'
auth = require './server/routes/auth'
db = require './server/routes/db'
file = require './server/routes/file'
folder = require './server/routes/folder'
database = require './server/commons/database'
baseRoute = require './server/routes/base'
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'
config = require './server_config'
@ -39,8 +33,8 @@ setupExpressMiddleware = (app) ->
app.use(express.cookieSession({secret:'defenestrate'}))
setupPassportMiddleware = (app) ->
app.use(passport.initialize())
app.use(passport.session())
app.use(authentication.initialize())
app.use(authentication.session())
setupOneSecondDelayMiddlware = (app) ->
if(config.slow_down)
@ -86,14 +80,7 @@ setupFacebookCrossDomainCommunicationRoute = (app) ->
exports.setupRoutes = (app) ->
app.use app.router
auth.setupRoutes app
db.setupRoutes app
sprites.setupRoutes app
contact.setupRoutes app
file.setupRoutes app
folder.setupRoutes app
languages.setupRoutes app
mail.setupRoutes app
baseRoute.setup app
setupFacebookCrossDomainCommunicationRoute app
setupFallbackRouteToIndex app
@ -103,7 +90,7 @@ exports.setupLogging = ->
logging.setup()
exports.connectToDatabase = ->
db.connectDatabase()
database.connect()
exports.setupMailchimp = ->
mcapi = require 'mailchimp-api'

View file

@ -1,4 +1,4 @@
require './common'
require '../common'
request = require 'request'
urlLogin = getURL('/auth/login')

View file

@ -1,4 +1,4 @@
require './common'
require '../common'
describe '/file', ->
url = getURL('/file')
@ -33,7 +33,8 @@ describe '/file', ->
expect(body.metadata).toBeUndefined()
done()
request.post(options, func)
loginJoe ->
request.post(options, func)
it 'can\'t be created if invalid (property path is required)', (done) ->
func = (err, res, body) ->

View file

@ -1,4 +1,4 @@
require '../common'
require '../../common'
describe 'CampaignStatus', ->

View file

@ -1,4 +1,4 @@
require '../common'
require '../../common'
describe 'Level', ->

View file

@ -1,4 +1,4 @@
require '../common'
require '../../common'
describe 'LevelComponent', ->

View file

@ -1,4 +1,4 @@
require '../common'
require '../../common'
describe 'LevelDraft', ->

View file

@ -1,4 +1,4 @@
require '../common'
require '../../common'
describe 'LevelSession', ->

View file

@ -1,4 +1,4 @@
require '../common'
require '../../common'
describe 'LevelSystem', ->

View file

@ -1,4 +1,4 @@
require '../common'
require '../../common'
describe 'LevelThangType', ->

View file

@ -1,4 +1,4 @@
require '../common'
require '../../common'
describe 'Article', ->

View file

@ -1,4 +1,4 @@
require '../common'
require '../../common'
describe 'Campaign', ->

View file

@ -1,4 +1,4 @@
require '../common'
require '../../common'
describe 'NamePlugin', ->

View file

@ -0,0 +1,24 @@
GLOBAL._ = require('lodash')
User = require '../../../server/users/User'
describe 'user', ->
it 'is Admin if it has admin permission', (done) ->
adminUser = new User()
adminUser.set('permissions', ['whatever', 'admin', 'user'])
expect(adminUser.isAdmin()).toBeTruthy()
done()
it 'isn\'t Admin if it has no permission', (done) ->
myUser = new User()
myUser.set('permissions', [])
expect(myUser.isAdmin()).toBeFalsy()
done()
it 'isn\'t Admin if it has only user permission', (done) ->
classicUser = new User()
classicUser.set('permissions', ['user'])
expect(classicUser.isAdmin()).toBeFalsy()
done()