Files

287 lines
11 KiB
JavaScript
Raw Permalink Normal View History

2021-12-18 02:34:52 +02:00
const config = require('config');
const express = require('express');
2022-06-19 02:17:55 +02:00
const fileUpload = require('express-fileupload');
2021-12-18 02:34:52 +02:00
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();
2022-06-19 02:17:55 +02:00
app.use(fileUpload());
2021-12-18 02:34:52 +02:00
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;
2022-06-22 04:16:01 +02:00
options.query = request.query;
2021-12-18 02:34:52 +02:00
// 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,
2021-12-19 18:17:51 +02:00
// required: true,
// where: {
// type: {
// [db.Sequelize.Op.or]: roles
// }
// }
2021-12-18 02:34:52 +02:00
}
]
}
]
}).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,
2021-12-19 18:17:51 +02:00
// required: true,
// where: {
// type: {
// [db.Sequelize.Op.or]: roles
// }
// }
2021-12-18 02:34:52 +02:00
}
]
},
{
association: db.User.IndividualEntityUser,
include: [
{
association: db.IndividualEntityUser.EntityUser,
include: [
{
association: db.EntityUser.Entity
}
]
}
]
2021-12-18 02:34:52 +02:00
}
]
})
.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....
2021-12-18 02:34:52 +02:00
var router = require('./router/index.js')({
app: app,
express: express,
db: db,
passport: passport
});
app.use('/', router);
2021-12-18 02:34:52 +02:00
// 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;
};