popcorn.webmaker.org/server.js

289 строки
11 KiB
JavaScript

// Newrelic *must* be the first module loaded. Do not move this require module!
if ( process.env.NEW_RELIC_HOME ) {
require( 'newrelic' );
}
var express = require('express'),
path = require('path'),
helmet = require( "helmet" ),
nunjucks = require('nunjucks'),
nunjucksEnv = new nunjucks.Environment(new nunjucks.FileSystemLoader( __dirname + '/views' )),
app = express(),
lessMiddleware = require( 'less-middleware' ),
requirejsMiddleware = require( 'requirejs-middleware' ),
config = require( './lib/config' ),
Project,
filter,
sanitizer = require( './lib/sanitizer' ),
metrics = require('./lib/metrics.js'),
middleware,
APP_HOSTNAME = config.hostname,
WWW_ROOT = __dirname + '/public',
i18n = require( 'webmaker-i18n' ),
emulate_s3 = config.S3_EMULATION || !config.S3_KEY;
nunjucksEnv.addFilter( "instantiate", function( input ) {
var tmpl = new nunjucks.Template( input );
return tmpl.render( this.getVariables() );
});
nunjucksEnv.express( app );
// List of supported languages - Please add them here in an alphabetical order
var listDropdownLang = config.SUPPORTED_LANGS,
// We create another array based on listDropdownLang to use it in the i18n.middleware
// supported_language which will be modified from the i18n mapping function
supportedLanguages = listDropdownLang.slice(0);
app.locals({
config: {
app_hostname: APP_HOSTNAME,
audience: config.AUDIENCE,
ga_account: config.GA_ACCOUNT,
ga_domain: config.GA_DOMAIN,
jwplayer_key: config.JWPLAYER_KEY,
make_endpoint: config.MAKE_ENDPOINT,
user_bar: config.USER_BAR,
sync_limit: config.SYNC_LIMIT
},
supportedLanguages: supportedLanguages,
listDropdownLang: listDropdownLang
});
app.configure( function() {
var tmpDir = path.normalize( require( "os" ).tmpDir() + "/mozilla.butter/" );
app.use( express.logger( config.logger ) );
app.use( "/static/bower", express.static( path.join( __dirname, "/bower_components" ), {
maxAge: "31556952000" // one year
}));
if ( !!config.FORCE_SSL ) {
app.use( helmet.hsts() );
app.enable( "trust proxy" );
}
app.use( express.compress() )
.use( lessMiddleware({
once: config.OPTIMIZE_CSS,
dest: tmpDir,
src: WWW_ROOT,
compress: config.OPTIMIZE_CSS,
yuicompress: config.OPTIMIZE_CSS,
optimization: config.OPTIMIZE_CSS ? 0 : 2
}))
.use( requirejsMiddleware({
src: WWW_ROOT,
dest: tmpDir,
debug: config.DEBUG,
once: config.OPTIMIZE_JS,
modules: {
"/src/butter.js": {
include: [ "butter" ],
mainConfigFile: WWW_ROOT + "/src/popcorn.js",
paths: {
"make-api": path.resolve( __dirname, "node_modules/makeapi-client/src/make-api" ),
"sso-include": path.resolve( __dirname, "node_modules/webmaker-sso/include" )
}
},
"/src/embed.js": {
include: [ "embed" ],
mainConfigFile: WWW_ROOT + "/src/popcorn.js",
},
"/templates/assets/editors/editorhelper.js": {
include: [ "../templates/assets/editors/editorhelper" ],
mainConfigFile: WWW_ROOT + "/src/popcorn.js"
}
},
defaults: {
name: "../external/require/require",
baseUrl: WWW_ROOT + "/src/",
findNestedDependencies: true,
optimize: "none",
preserveLicenseComments: false,
paths: {
"localized": path.resolve( __dirname, "bower_components/webmaker-i18n/localized" ),
"WebmakerUI": path.resolve( __dirname, "bower_components/webmaker-ui/ui" ),
"webmaker-ui-fragments": path.resolve( __dirname, "bower_components/webmaker-ui/webmaker-ui-fragments" )
},
wrap: {
startFile: __dirname + "/tools/wrap.start",
endFile: __dirname + "/tools/wrap.end"
}
}
}))
.use( express.static( tmpDir, JSON.parse( JSON.stringify( config.staticMiddleware ) ) ) )
.use( express.static( WWW_ROOT, JSON.parse( JSON.stringify( config.staticMiddleware ) ) ) );
// Setup locales with i18n
app.use( i18n.middleware({
supported_languages: supportedLanguages,
default_lang: "en-US",
mappings: config.LANG_MAPPINGS,
translation_directory: path.resolve( __dirname, "locale" )
}));
app.use( express.json() )
.use( express.urlencoded() )
.use( express.cookieParser() )
.use( express.cookieSession( config.session ) )
.use( express.csrf() )
.use( helmet.xframe() )
/* Show Zeus who's boss
* This only affects requests under /api and /persona, not static files
* because the static file writes the response header before we hit this middleware
*/
.use( function( req, res, next ) {
res.header( 'Cache-Control', 'no-store' );
return next();
})
.use( app.router )
.use( function( err, req, res, next) {
if ( !err.status ) {
err.status = 500;
}
middleware.errorHandler( err, req, res );
})
.use( function( req, res, next ) {
var err = {
message: req.gettext( "This page doesn't exist" ),
status: 404
};
middleware.errorHandler( err, req, res );
});
Project = require( './lib/project' )( config.database );
filter = require( './lib/filter' )( Project.isDBOnline );
});
require( './lib/loginapi' )( app, {
audience: config.AUDIENCE,
loginURL: config.LOGIN_SERVER_URL_WITH_AUTH
});
require( 'webmaker-mediasync' )( app, {
serviceKeys: {
soundcloud: config.SYNC_SOUNDCLOUD,
flickr: config.SYNC_FLICKR,
giphy: config.SYNC_GIPHY
},
limit: config.SYNC_LIMIT
});
middleware = require( './lib/middleware' );
var routes = require( './routes' );
app.param( "myproject", middleware.loadOwnProject( Project ));
app.param( "anyproject", middleware.loadAnyProject( Project ));
app.post( '/api/publish/:myproject',
filter.isLoggedIn, filter.isStorageAvailable,
routes.api.publish
);
app.get( '/dashboard/:lang', function( req, res ) {
res.redirect( config.AUDIENCE + "/" + req.params.lang + "/me?app=popcorn" );
});
app.get( '/', routes.pages.editor );
app.get( '/index.html', routes.pages.editor );
app.get( '/editor', routes.pages.editor );
app.get( '/editor/:id', routes.pages.editor );
app.get( '/editor/:id/edit', routes.pages.editor );
app.get( '/editor/:id/remix', routes.pages.editor );
app.get( '/templates/basic', routes.pages.editor );
app.get( '/templates/basic/index.html', routes.pages.editor );
app.get( '/external/make-api.js', function( req, res ) {
res.sendfile( path.resolve( __dirname, "node_modules/makeapi-client/src/make-api.js" ) );
});
app.get( '/external/sso-include.js', function( req, res ) {
res.sendfile( path.resolve( __dirname, "node_modules/webmaker-sso/include.js" ) );
});
app.get( '/external/jwplayer.js', function( req, res ) {
res.redirect( "//jwpsrv.com/library/" + app.locals.config.jwplayer_key + ".js" );
});
// Project Endpoints
app.post( '/api/project/:id?',
filter.isLoggedIn,
filter.isStorageAvailable,
routes.api.synchronize( Project ),
routes.make.synchronize
);
app.post( '/api/delete/:myproject', filter.isLoggedIn, filter.isStorageAvailable, routes.make.remove, routes.api.remove );
app.get( '/api/remix/:anyproject', filter.isStorageAvailable, routes.api.remix, routes.api.projectResponse( Project ) );
app.get( '/api/project/:myproject', filter.isLoggedIn, filter.isStorageAvailable, routes.api.find, routes.api.projectResponse( Project ) );
// Firehose Endpoints
//app.get( '/api/project/:id/remixes', filter.isStorageAvailable, filter.crossOriginAccessible, routes.firehose.remixes );
//app.get( '/api/projects/recentlyUpdated/:limit?', filter.isStorageAvailable, filter.crossOriginAccessible, routes.firehose.recentlyUpdated );
//app.get( '/api/projects/recentlyCreated/:limit?', filter.isStorageAvailable, filter.crossOriginAccessible, //routes.firehose.recentlyCreated );
//app.get( '/api/projects/recentlyRemixed/:limit?', filter.isStorageAvailable, filter.crossOriginAccessible, routes.firehose.recentlyRemixed );
app.post( '/crash', routes.api.crash );
app.post( '/feedback', routes.api.feedback );
app.get( '/healthcheck', routes.api.healthcheck );
app.get( '/api/butterconfig', function( req, res ) {
res.json({
"audience": app.locals.config.audience,
"make_endpoint": app.locals.config.make_endpoint,
"user_bar": app.locals.config.user_bar,
"sync_limit": app.locals.config.sync_limit
});
});
// routes to be used in text!
app.get( '/layouts/header.html', function( req, res ) {
res.render( '/layouts/header.html', {
user_bar: app.locals.config.user_bar,
audience: app.locals.config.audience,
togetherjsEnabled: config.TOGETHERJS_ENABLED
});
});
app.get( '/layouts/status-area.html', routes.path( '/layouts/status-area.html' ) );
app.get( '/layouts/media-editor.html', routes.path( '/layouts/media-editor.html' ) );
app.get( '/layouts/controls.html', routes.path( '/layouts/controls.html' ) );
app.get( '/layouts/media-instance.html', routes.path( '/layouts/media-instance.html' ) );
app.get( '/layouts/project-editor.html', routes.path( '/layouts/project-editor.html' ) );
app.get( '/layouts/editor-area.html', routes.path( '/layouts/editor-area.html' ) );
app.get( '/layouts/plugin-list-editor.html', routes.path( '/layouts/plugin-list-editor.html' ) );
app.get( '/layouts/sequencer-editor.html', routes.path( '/layouts/sequencer-editor.html' ) );
app.get( '/layouts/trackevent-editor-defaults.html', routes.path( '/layouts/trackevent-editor-defaults.html' ) );
app.get( '/dialog/dialogs/backup.html', routes.path( '/dialog/dialogs/backup.html' ) );
app.get( '/dialog/dialogs/crash.html', routes.path( '/dialog/dialogs/crash.html' ) );
app.get( '/dialog/dialogs/delete-track-events.html', routes.path( '/dialog/dialogs/delete-track-events.html' ) );
app.get( '/dialog/dialogs/delete-track.html', routes.path( '/dialog/dialogs/delete-track.html' ) );
app.get( '/dialog/dialogs/error-message.html', routes.path( '/dialog/dialogs/error-message.html' ) );
app.get( '/dialog/dialogs/feedback.html', routes.path( '/dialog/dialogs/feedback.html' ) );
app.get( '/dialog/dialogs/first-run.html', routes.path( '/dialog/dialogs/first-run.html' ) );
app.get( '/dialog/dialogs/track-data.html', routes.path( '/dialog/dialogs/track-data.html' ) );
app.get( '/dialog/dialogs/remove-project.html', routes.path( '/dialog/dialogs/remove-project.html' ) );
app.get( '/editors/default.html', routes.path( '/editor/default.html' ) );
app.get( '/templates/assets/editors/googlemap/googlemap-editor.html', routes.path( '/plugins/googlemap-editor.html' ) );
app.get( '/templates/assets/editors/popup/popup-editor.html', routes.path( '/plugins/popup-editor.html' ) );
app.get( '/templates/assets/editors/image/image-editor.html', routes.path( '/plugins/image-editor.html' ) );
app.get( '/templates/assets/editors/text/text-editor.html', routes.path( '/plugins/text-editor.html' ) );
app.get( '/templates/assets/editors/sketchfab/sketchfab-editor.html', routes.path( '/plugins/sketchfab-editor.html' ) );
// Localized Strings
app.get( "/strings/:lang?", middleware.crossOrigin, i18n.stringsRoute( 'en-US' ) );
app.put( "/api/image", middleware.processForm, filter.isImage, routes.api.image );
app.listen( config.PORT, function() {
console.log( 'HTTP Server started on ' + APP_HOSTNAME );
console.log( 'Press Ctrl+C to stop' );
});
// If we're in running in emulated S3 mode, run a mini
// server for serving up the "s3" published content.
if ( emulate_s3 ) {
require( 'mox-server' ).runServer( config.MOX_PORT || 12319 );
}