apps/strider/dist-lib/app.js
// The Strider (web) app.
const debug = require('debug')('strider');
const chalk = require('chalk');
const express = require('express');
const EventEmitter = require('events').EventEmitter;
require('everypaas');
const cors = require('cors');
const path = require('path');
const swig = require('swig');
// middleware
const morganDebug = require('morgan-debug');
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser');
const compression = require('compression');
const expressSession = require('express-session');
const serveFavicon = require('serve-favicon');
const errorHandler = require('errorhandler');
const methodOverride = require('method-override');
const connectFlash = require('connect-flash');
const connectMongo = require('connect-mongo');
const csrf = require('csurf');
const setupDb = require('./utils/setup-db');
const Backchannel = require('./backchannel');
const common = require('./common');
require('./logging');
const middleware = require('./middleware');
const routes = require('./routes');
const providerRouter = require('./routes/provider');
const websockets = require('./websockets');
const models = require('./models');
const auth = require('./auth');
const pluginTemplates = require('./plugin-templates');
const pjson = require('../package.json');
const routesAdmin = require('./routes/admin');
const routesJobs = require('./routes/jobs');
const api = require('./routes/api');
const apiV2 = require('./routes/v2');
const collaboratorsRouter = require('./routes/collaborators');
const apiBranches = require('./routes/api/branches');
const apiJobs = require('./routes/api/jobs');
const apiRepo = require('./routes/api/repo');
const apiConfig = require('./routes/api/config');
const mongoStore = connectMongo(expressSession);
const MONTH_IN_MILLISECONDS = 2629743000;
const env = process.env.NODE_ENV || 'development';
const isDevelopment = env === 'development';
const isProduction = env === 'production';
const isTest = env === 'test';
const csrfProtection = csrf({ cookie: true });
let sessionStore;
exports.init = function (config) {
const mongoose = setupDb(config, (err) => {
if (err) {
process.exit(1);
}
});
sessionStore = new mongoStore({
mongooseConnection: mongoose.connection,
});
swig.init({
root: config.viewpath,
// allows errors to be thrown and caught by express instead of suppressed by Swig
allowErrors: true,
cache: false,
filters: require('./utils/swig-filters'),
tags: require('./utils/swig-tags').tags,
extensions: { plugin: pluginTemplates },
});
const app = express();
if (isDevelopment) {
app.use(morganDebug('strider:http', 'dev'));
}
if (isTest) {
// awesome view testingness
require('./views-test')(app);
}
// During development we build to an ignored file, only during release we do normal build
const viewDirs = [path.join(__dirname, 'views')];
if (config.developing) {
viewDirs.push(path.join(__dirname, '..', '.dev-dist'));
}
viewDirs.push(path.join(__dirname, '..', 'dist'));
debug('view dirs', viewDirs);
app.set('views', viewDirs);
app.engine('html', pluginTemplates.engine);
if (config.cors) {
app.use(cors(config.cors));
}
app.use(middleware.bodySetter);
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false, limit: config.body_parser_limit }));
// parse application/json
app.use(bodyParser.json({ limit: config.body_parser_limit }));
app.use(cookieParser());
app.use(compression());
app.use(methodOverride());
app.use(serveFavicon(path.join(__dirname, '..', 'public', 'favicon.ico'), {
maxAge: 2592000000,
}));
app.use(expressSession({
secret: config.session_secret,
store: sessionStore,
cookie: { maxAge: MONTH_IN_MILLISECONDS },
resave: false,
saveUninitialized: true,
}));
app.use(connectFlash());
app.use(function (req, res, next) {
res.locals.models = models;
next();
});
auth.setup(app); // app.use(passport) is included
app.use('/vendor', express.static(path.join(__dirname, '..', '..', '..', 'clients', 'classic-ui', 'vendor'), {
maxAge: MONTH_IN_MILLISECONDS,
}));
if (config.developing) {
app.use(express.static(path.join(__dirname, '..', '.dev-dist', 'ember'), {
maxAge: MONTH_IN_MILLISECONDS,
index: false,
}));
}
else {
app.use(express.static(path.join(__dirname, '..', 'dist', 'ember'), {
maxAge: MONTH_IN_MILLISECONDS,
index: false,
}));
}
app.use(express.static(path.join(__dirname, '..', 'dist'), {
maxAge: MONTH_IN_MILLISECONDS,
}));
app.use(express.static(path.join(__dirname, '..', 'public'), {
maxAge: MONTH_IN_MILLISECONDS,
}));
if (!config.smtp) {
debug('No SMTP creds - forgot password flow will not work');
}
// Routes
apiV2.default(app);
app.get('/', routes.index);
app.get('/about', function (req, res) {
res.render('about');
});
app.get('/status', routes.status);
app.post('/login', function (req, res, next) {
if (!req.user) {
auth.authenticate(function (err, user) {
if (err) {
return next(err);
}
if (!user) {
return res
.status(401)
.json({ errors: ['Password incorrect or user does not exist'] });
}
req.login(user, function (err) {
if (err) {
return next(err);
}
return res.redirect('/');
});
})(req, res, next);
return;
}
res.redirect('/');
}, auth.authenticate);
app.get('/logout', auth.logout);
app.post('/forgot', auth.forgot);
app.get('/reset/:token', auth.reset);
app.post('/reset/:token', auth.resetPost);
// Compiled plugin config assets
app.get('/scripts/plugin-config-compiled.js', apiConfig.server('config', 'js'));
app.get('/styles/plugin-config-compiled.css', apiConfig.server('config', 'css'));
app.get('/scripts/account-plugins-compiled.js', apiConfig.server('account', 'js'));
app.get('/styles/account-plugins-compiled.css', apiConfig.server('account', 'css'));
app.get('/scripts/plugin-status-compiled.js', apiConfig.server('status', 'js'));
app.get('/styles/plugin-status-compiled.css', apiConfig.server('status', 'css'));
app.get('/admin/projects', auth.requireAdminOr401, routesAdmin.projects);
app.get('/admin/users', auth.requireAdminOr401, csrfProtection, routesAdmin.users);
app.get('/admin/jobs', auth.requireAdminOr401, function (req, res) {
res.render('admin/jobs.html', {
version: pjson.version,
});
});
app.post('/admin/make_admin', auth.requireAdminOr401, csrfProtection, middleware.csrfErrorHandler, routesAdmin.makeAdmin);
app.post('/admin/remove_user', auth.requireAdminOr401, csrfProtection, middleware.csrfErrorHandler, routesAdmin.removeUser);
app.get('/admin/invites', auth.requireAdminOr401, csrfProtection, routesAdmin.invites);
app.get('/admin/:org/:repo/job/:job_id', auth.requireAdminOr401, routesAdmin.job);
app.get('/admin/plugins', auth.requireAdminOr401, routesAdmin.plugins.get);
app.put('/admin/plugins', auth.requireAdminOr401, routesAdmin.plugins.put);
app.use('/account', auth.requireUser, require('./routes/account'));
app.use('/projects', auth.requireUser, require('./routes/projects'));
// Requires at least read-only access to the repository in the path
// app.get('/:org/:repo/', middleware.project, routesJobs.html);
app.put('/:org/:repo/', auth.requireUser, apiRepo.createProject);
// app.get('/:org/:repo/job/:job_id?', middleware.project, routesJobs.multijob);
app.get('/:org/:repo/jobs/', middleware.project, routesJobs.jobs);
app.post('/:org/:repo/start', auth.requireUser, middleware.project, auth.requireProjectAdmin, apiJobs.jobsStart);
app.delete('/:org/:repo/cache', auth.requireUser, middleware.project, auth.requireProjectAdmin, apiRepo.clearCache);
app.delete('/:org/:repo/', middleware.project, auth.requireProjectAdmin, apiRepo.deleteProject);
// provider
app.use(providerRouter);
// collaborators
app.use(collaboratorsRouter);
// branches
app.use('/:org/:repo/branches/', auth.requireUserOr401, middleware.project, auth.requireProjectAdmin, apiBranches);
// keygen
app.post('/:org/:repo/keygen/', auth.requireUser, middleware.project, auth.requireProjectAdmin, apiConfig.keygen);
/* Requires admin access to the repository in the path */
if ('development' === app.get('env')) {
console.log('dev config');
app.get(['/:org/:repo/config', '/:org/:repo/config/'], auth.requireUser, middleware.project, auth.requireProjectAdmin, routes.reloadConfig, routes.config);
}
else {
console.log('prod config');
app.get(['/:org/:repo/config', '/:org/:repo/config/'], auth.requireUser, middleware.project, auth.requireProjectAdmin, routes.config);
}
app.put('/:org/:repo/config', auth.requireUser, middleware.project, auth.requireProjectAdmin, routes.setConfig);
app.all('/:org/:repo/config/branch/runner', auth.requireUser, middleware.project, auth.requireProjectAdmin);
app.get('/:org/:repo/config/branch/runner', routes.getRunnerConfig);
app.put('/:org/:repo/config/branch/runner', routes.setRunnerConfig);
app.put('/:org/:repo/config/branch/runner/id', routes.setRunnerId);
app.all('/:org/:repo/config/branch/:plugin', auth.requireUser, middleware.project, auth.requireProjectAdmin, middleware.projectPlugin);
app.get('/:org/:repo/config/branch/:plugin', routes.getPluginConfig);
app.put('/:org/:repo/config/branch/:plugin', routes.setPluginConfig);
app.put('/:org/:repo/config/branch/', auth.requireUser, middleware.project, auth.requireProjectAdmin, routes.configureBranch);
// app.get('/api/job/:id', apiJobs.raw);
app.use('/api', api);
app.get('/api/jobs', auth.requireUserOr401, apiJobs.jobs);
// app.get('/api/jobs/:org/:repo', middleware.project, apiJobs.repoJobs);
app.use(function (req, res, next) {
let userCreatedTimestamp = 0;
if (req.user !== undefined) {
userCreatedTimestamp = parseInt(req.user.id.substr(0, 8), 16);
}
res.locals.user_created_timestamp = userCreatedTimestamp;
next();
});
common.app = app;
common.session_store = sessionStore;
//
// ### Strider Webapp Event Emitter
//
// Strider has a Node.Js Event Emitter which emits many events. This can be
// used by extensions to add extremely flexible custom handling for just about
// anything.
//
common.emitter = new EventEmitter();
return app;
};
exports.run = function (app) {
const config = require('./config');
app.get('/*', routes.emberIndex);
if (isDevelopment) {
app.use(errorHandler({ dumpExceptions: true, showStack: true }));
}
if (isProduction) {
app.use(errorHandler({ dumpExceptions: true, showStack: false }));
}
// Custom 404 handler.
// Run after extensions, which might load static middlewares.
app.use(middleware.custom404);
// Initialize socket.io
const server = app.listen(config.port, config.host);
const sockets = websockets.init(server, sessionStore);
new Backchannel(common.emitter, sockets);
console.log(chalk.green('Express server listening on port %s in %s mode'), config.port, app.settings.env);
};
//# sourceMappingURL=app.js.map