1
0
mirror of /repos/Prototyper.git synced 2025-12-30 06:31:32 +01:00
Prototyper/server.js
2020-03-11 23:00:46 +01:00

350 lines
9.8 KiB
JavaScript

'use strict';
process.title = 'Prototyper';
var connect = require('connect');
var express = require('express');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var ConnectRoles = require('connect-roles');
var MongoClient = require('mongodb').MongoClient;
var rethink = require('rethinkdb');
var addRoutes = require('./lib/routes.js');
var shareServer = require('./lib/share.js');
var shareHandlers = require('./lib/shareHandlers.js');
var updateShareDocument = require('./lib/updateShareDocument.js');
var rethinkData = require('./lib/rethinkData.js');
var dataAccessor = require('./lib/data.js');
var preview = require('./lib/preview.js');
var importer = require('./lib/importer.js');
var handlers = require('./lib/handlers.js');
var markers = require('./lib/markers.js');
var helpers = require('./lib/helpers.js');
var config = {
debug: function () {
if (process.env.DEBUG) {
var error = arguments[0] && arguments[0].message ||
arguments[1] && arguments[1].message ||
arguments[2] && arguments[2].message;
var args = Array.prototype.slice.call(arguments);
var log = {
level: 'debug',
message: args,
timestamp: Date.now(),
error: error
};
console.log(JSON.stringify(log));
}
},
info: function () {
var error = arguments[0] && arguments[0].message ||
arguments[1] && arguments[1].message ||
arguments[2] && arguments[2].message;
var args = Array.prototype.slice.call(arguments);
var log = {
level: 'info',
message: args,
timestamp: Date.now(),
error: error
};
console.log(JSON.stringify(log));
},
warn: function () {
var error = arguments[0] && arguments[0].message ||
arguments[1] && arguments[1].message ||
arguments[2] && arguments[2].message;
var args = Array.prototype.slice.call(arguments);
var log = {
level: 'warn',
message: args,
timestamp: Date.now(),
error: error
};
console.warn(JSON.stringify(log));
},
error: function () {
var error = arguments[0] && arguments[0].message ||
arguments[1] && arguments[1].message ||
arguments[2] && arguments[2].message;
var args = Array.prototype.slice.call(arguments);
var log = {
level: 'error',
message: args,
timestamp: Date.now(),
error: error
};
console.error(JSON.stringify(log));
},
port: process.env.npm_package_config_port || 8000,
mongo: {
server: 'mongodb://localhost:27017/Prototyper',
options: {
db: {
native_parser: false,
fsync: true
},
server: {
maxPoolSize: 10,
auto_reconnect: true
}
},
savedelay: 200
},
rethink: {
server: {
host: 'rethinkdb.40n8.me',
port: 28015,
db: 'Prototyper'
}
},
database: {
// pk: '_id' // mongo
pk: 'id' // rethink
},
share: {
sockjs: {
prefix: '',
response_limit: 128 * 1024,
websocket: true,
jsessionid: false,
heartbeat_delay: 25000,
disconnect_delay: 5000,
log: function (severity, line) {
if (process.env.DEBUG) {
if (severity === 'info') {
config.info && config.info(severity, line);
} else if (severity === 'error') {
config.error && config.error(severity, line);
} else {
config.debug && config.debug(severity, line);
}
}
},
sockjs_url: 'https://d1fxtkz8shb9d2.cloudfront.net/sockjs-0.3.4.min.js'
},
staticpath: '/lib/share',
db: {type: 'none'}
// db: {
// type: 'mongo',
// opsCollectionPerDoc: false
// }
},
api: {
content: '/content',
data: '/data',
preview: '/page',
importer: '/importer'
},
users: {
admin: {
password: 'admin',
roles: 'admin'
}
},
statics: {
dev_favicon_path: __dirname + '/public/favicon_dev.ico',
importer_path: __dirname + '/public',
public_path: __dirname + '/public',
doc_path: __dirname + '/doc',
markdown_client: __dirname + '/node_modules/markdown/lib',
ace_client: __dirname + '/node_modules/share/examples/lib/ace',
async_client: __dirname + '/node_modules/async/lib'
}
};
config.debug && config.debug('config loaded');
var app = express();
var roles = new ConnectRoles();
express.static.mime.define({
'text/css': ['css', 'less']
});
if (process.env.DEBUG) {
//app.use(connect.logger());
var stream = {
write: function (str) {
config.debug && config.debug(str);
}
};
app.use(connect.logger({immediate: false, format: 'dev', stream: stream}));
}
//noinspection JSUnresolvedFunction
app.use(express.compress());
//noinspection JSUnresolvedFunction
app.use(express.cookieParser());
//noinspection JSUnresolvedFunction
app.use(express.bodyParser());
//noinspection JSUnresolvedFunction
// app.use(express.session({ secret: 'keyboard cat' }));
//noinspection JSUnresolvedFunction
app.use(passport.initialize());
//noinspection JSUnresolvedFunction
//app.use(passport.session());
//noinspection JSUnresolvedFunction
app.use(roles.middleware());
app.post('/login',
passport.authenticate('local', {
session: false,
successRedirect: '/editor.html',
failureRedirect: '/login.html',
failureFlash: false })
);
if (!process.env.NODE_ENV) {
app.get('/favicon.ico', function (req, res) {
res.sendfile(config.statics.dev_favicon_path, null, null);
});
}
//noinspection JSUnresolvedFunction
app.use(express.static(config.statics.public_path));
//noinspection JSUnresolvedFunction
app.use('/doc', express.static(config.statics.doc_path));
//noinspection JSUnresolvedFunction
app.use('/lib/markdown', express.static(config.statics.markdown_client));
//noinspection JSUnresolvedFunction
app.use('/lib/ace', express.static(config.statics.ace_client));
//noinspection JSUnresolvedFunction
app.use('/lib/async', express.static(config.statics.async_client));
config.debug && config.debug('static routes set');
var markerInstance = markers(config);
var helperInstance = helpers(markerInstance);
//MongoClient.connect(config.mongo.server, config.mongo.options, function connection(err, db) {
// if (err) {
// config.error && config.error('ERR connection to database', err);
// return process.exit(3);
// }
// function exit(code) {
// db.close();
// process.exit(code);
// }
rethink.connect(config.rethink.server, function connection_result(err, connection) {
if (err) {
config.error && config.error('ERR connection to database', err);
return process.exit(3);
}
function exit(code) {
connection.close(function () {
// Probably there are also some other listeners for uncaughtException,
// so we postpone process.exit
process.nextTick(function () {
process.exit(code);
});
});
}
config.debug && config.debug('database connected');
passport.unuse("session");
passport.use(new LocalStrategy({ passReqToCallback: true},
function(req, username, password, done) {
config.error('check user',username, password);
if (config.users[username]) {
var user = config.users[username];
config.error(user);
if (user.password === password) {
return done(null, user);
}
return done(null, false, {message: 'Incorrect password.'});
} else {
User.findOne({username: username}, function (err, user) {
if (err) {
return done(err);
}
if (!user) {
return done(null, false, {message: 'Incorrect username.'});
}
if (!user.validPassword(password)) {
return done(null, false, {message: 'Incorrect password.'});
}
return done(null, user);
});
}
}
));
//Create the database if needed.
rethink.dbList().contains(config.rethink.server.db).do(function (containsDb) {
return rethink.branch(
containsDb,
{created: 0},
rethink.dbCreate(config.rethink.server.db)
);
}).run(connection, function (err) {
connection.use(config.rethink.server.db);
if (err) {
config.error && config.error('ERR creating table in database', err);
return exit(4);
}
var share = shareServer(config, app);
var model = share.model;
var server = share.server;
config.debug && config.debug('share attached');
var updateShare = updateShareDocument(config, model);
var dataBaseInstance = rethinkData(config, rethink, connection);
// var dataBaseInstance = mongoData(config, db, model);
var dataInstance = dataAccessor(config, dataBaseInstance, updateShare);
config.debug && config.debug('dataInstance initialized');
shareHandlers(config, model, dataInstance);
config.debug && config.debug('shareHandlers attached');
var previewInstance = preview(config, dataInstance, helperInstance, markerInstance);
config.debug && config.debug('previews initialized');
var importerInstance = importer(config, dataInstance, helperInstance, markerInstance, updateShare);
config.debug && config.debug('importer initialized');
var handlerInstance = handlers(dataInstance, previewInstance, importerInstance);
config.debug && config.debug('handlers initialized');
app = addRoutes(app, handlerInstance, markerInstance, config);
config.debug && config.debug('routes added');
process.on('uncaughtException', function (err) {
config.error && config.error('HALTING ON UNCAUGHT EXCEPTION:' + err.message, err);
config.error && config.error(err.stack);
config.error && config.error('EXIT 1');
return exit(1);
});
server.on('error', function (err) {
config.error && config.error('Server error', err);
if (err.code && err.code === 'EADDRINUSE') {
return exit(2);
}
});
return server.listen(config.port, function handleServerResult(err) {
if (err) {
console.error('Server error', err);
return exit(1);
}
config.debug && config.debug('routes', app.routes);
return config.info && config.info('Server running at http://127.0.0.1:' + config.port);
});
});
});