286 lines
11 KiB
JavaScript
286 lines
11 KiB
JavaScript
const config = require('config');
|
|
const express = require('express');
|
|
const fileUpload = require('express-fileupload');
|
|
const pug = require("pug");
|
|
const session = require("express-session");
|
|
const SequelizeSessionStore = require('connect-session-sequelize')(session.Store);
|
|
const bodyParser = require("body-parser");
|
|
const path = require("path");
|
|
|
|
const passport = require('passport');
|
|
const LocalStrategy = require('passport-local').Strategy;
|
|
const fs = require('fs');
|
|
|
|
module.exports = function () {
|
|
var server = {};
|
|
|
|
server.run = (db) => {
|
|
console.log("Starting Server")
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
|
const app = express();
|
|
|
|
app.use(fileUpload());
|
|
|
|
app.set("view engine", "pug");
|
|
app.set("views", path.resolve("server/views"));
|
|
|
|
// compile pug views below so that they are rendered quicker
|
|
var pugPages = {};
|
|
|
|
var modelDir = path.join(__dirname, './views');
|
|
fs.readdirSync(modelDir)
|
|
.filter(file => {
|
|
return file.endsWith(".pug");
|
|
})
|
|
.forEach(file => {
|
|
const name = file.split(".pug")[0];
|
|
|
|
pugPages[name] = pug.compileFile(path.join(modelDir, file))
|
|
});
|
|
|
|
// Set up middleware to make use of the compiled pugjs views
|
|
app.use((request, response, next) => {
|
|
// This is cheating...
|
|
response.display = (view, options) => {
|
|
options.domain = config.get("server.domain");
|
|
options.urlEndpoint = request.originalUrl;
|
|
// Set a default pageTitle...
|
|
options.pageTitle = options.pageTitle ? options.pageTitle : "Mantra";
|
|
options.errorMessage = (error) => {
|
|
// TODO: Make error human readable...
|
|
return error.message;
|
|
}
|
|
if(config.get("server.compiled-render")) {
|
|
if(pugPages[view]) {
|
|
response.send(pugPages[view](options))
|
|
} else {
|
|
response.send(pugPages["404"](options))
|
|
}
|
|
} else {
|
|
response.render(view, options);
|
|
}
|
|
}
|
|
next();
|
|
})
|
|
app.use('/static', express.static("server/static"));
|
|
|
|
// Session related stuff...
|
|
function extendDefaultFields(defaults, session) {
|
|
return {
|
|
data: defaults.data,
|
|
expires: session.cookie && session.cookie.expires ? session.cookie.expires : defaults.expires, // 157680000
|
|
userId: session.passport.user
|
|
};
|
|
}
|
|
|
|
var sessionStore = new SequelizeSessionStore({
|
|
db: db.sequelize,
|
|
table: 'session',
|
|
extendDefaultFields: extendDefaultFields
|
|
// TODO: Define expiry and clean up...
|
|
});
|
|
|
|
app.use(session({
|
|
store: sessionStore,
|
|
secret: config.get("server.secret"),
|
|
resave: false,
|
|
saveUninitialized: false,
|
|
cookie: config.get("server.cookie")
|
|
}));
|
|
|
|
app.use(bodyParser.urlencoded({ extended: true }));
|
|
app.use(bodyParser.json());
|
|
|
|
|
|
passport.use(new LocalStrategy(
|
|
function(username, password, done) {
|
|
username = username != null ? username.trim().toLowerCase() : "";
|
|
password = password != null ? password : "";
|
|
return db.User.findOne({
|
|
include: [
|
|
{
|
|
association: db.User.Passwords
|
|
},
|
|
{
|
|
association: db.User.UserEmails,
|
|
required: true,
|
|
where: {
|
|
emailAddress: {
|
|
[db.Sequelize.Op.like]: username
|
|
}
|
|
}
|
|
},
|
|
{
|
|
association: db.User.UserRoles,
|
|
// required: true,
|
|
include: [
|
|
{
|
|
association: db.UserRole.Role,
|
|
// required: true,
|
|
// where: {
|
|
// type: {
|
|
// [db.Sequelize.Op.or]: roles
|
|
// }
|
|
// }
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}).then(
|
|
user => {
|
|
// Validate Password
|
|
if(user) {
|
|
if (!user.passwords[0].validPassword(password)) {
|
|
return done(null, false, {
|
|
username: username,
|
|
message: 'Invalid username or password.'
|
|
});
|
|
} else {
|
|
return done(null, user);
|
|
}
|
|
} else {
|
|
console.error("User Doesn't Exist: ", username);
|
|
return done(null, false, {
|
|
username: username,
|
|
message: 'Invalid username or password.'
|
|
});
|
|
}
|
|
|
|
},
|
|
err => {
|
|
console.error("Authentication Failed: " + err);
|
|
|
|
return done(null, false, { message: 'Incorrect username or password.' });
|
|
}
|
|
).catch(error => {
|
|
console.log("Passport Error: ", error);
|
|
return done(error);
|
|
})
|
|
}
|
|
));
|
|
|
|
passport.serializeUser(function(user, done) {
|
|
done(null, user.id);
|
|
});
|
|
|
|
passport.deserializeUser(function(id, done) {
|
|
// TODO: Add memberships and things like that...
|
|
return db.User.findByPk(id, {
|
|
include: [
|
|
{
|
|
association: db.User.UserRoles,
|
|
// required: true,
|
|
include: [
|
|
{
|
|
association: db.UserRole.Role,
|
|
// required: true,
|
|
// where: {
|
|
// type: {
|
|
// [db.Sequelize.Op.or]: roles
|
|
// }
|
|
// }
|
|
}
|
|
]
|
|
},
|
|
{
|
|
association: db.User.IndividualEntityUser,
|
|
include: [
|
|
{
|
|
association: db.IndividualEntityUser.EntityUser,
|
|
include: [
|
|
{
|
|
association: db.EntityUser.Entity
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
})
|
|
.then(user => {
|
|
return done(null, user);
|
|
}).catch(error => {
|
|
return done(error);
|
|
})
|
|
});
|
|
|
|
app.use(passport.initialize());
|
|
app.use(passport.session());
|
|
|
|
sessionStore.sync();
|
|
|
|
// TODO: check that user has an individualEntityUser....
|
|
var router = require('./router/index.js')({
|
|
app: app,
|
|
express: express,
|
|
db: db,
|
|
passport: passport
|
|
});
|
|
app.use('/', router);
|
|
|
|
|
|
|
|
// 404 pages...
|
|
app.use((request, response, next) => {
|
|
|
|
if(!response.headersSent) {
|
|
response.status(404);
|
|
|
|
if (request.accepts('html')) {
|
|
response.display("404", {
|
|
user: request.user,
|
|
pageTitle: "Page Not Found - Mantra"
|
|
})
|
|
return;
|
|
}
|
|
|
|
if (request.accepts('application/json')) {
|
|
response.json({
|
|
message: "URL not accessible"
|
|
});
|
|
return;
|
|
}
|
|
|
|
response.type('txt').send('Resource Not found');
|
|
}
|
|
});
|
|
|
|
// 500 pages...
|
|
app.use((error, request, response, next) => {
|
|
console.error(`${response.getHeader("id")} - `, error);
|
|
if(error && !response.headersSent) {
|
|
response.status(500);
|
|
|
|
// TODO: Check if production and then show stack...
|
|
if (request.accepts('html')) {
|
|
response.display("error", {
|
|
user: request.user,
|
|
pageTitle: "Internal Error - Mantra",
|
|
error: error
|
|
})
|
|
return;
|
|
}
|
|
|
|
if (request.xhr) {
|
|
response.json({
|
|
message: "Internal Error, Please check your tires.",
|
|
error: error
|
|
});
|
|
return;
|
|
}
|
|
|
|
response.type('txt').send('Internal server error');
|
|
}
|
|
});
|
|
|
|
const port = process.env.PORT || config.get("server.port");
|
|
|
|
app.listen(port);
|
|
resolve(port);
|
|
});
|
|
}
|
|
|
|
return server;
|
|
}; |