eslinted everything and moved db around
Signed-off-by: James Ketrenos <james_eikona@ketrenos.com>
This commit is contained in:
parent
e5ab93e092
commit
c7435c4bb1
@ -26,20 +26,43 @@ const App = () => {
|
|||||||
const [ csrfToken, setCsrfToken ] = useState(undefined);
|
const [ csrfToken, setCsrfToken ] = useState(undefined);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
window.fetch(`${base}/api/v1/users/csrf`, {
|
const effect = async () => {
|
||||||
method: 'GET',
|
const res = await window.fetch(`${base}/api/v1/users/csrf`, {
|
||||||
cache: 'no-cache',
|
method: 'GET',
|
||||||
credentials: 'same-origin',
|
cache: 'no-cache',
|
||||||
headers: {
|
credentials: 'same-origin',
|
||||||
'Content-Type': 'application/json'
|
headers: {
|
||||||
},
|
'Content-Type': 'application/json'
|
||||||
}).then((res) => {
|
},
|
||||||
return res.json();
|
});
|
||||||
}).then((data) => {
|
const data = await res.json();
|
||||||
setCsrfToken(data.csrfToken);
|
setCsrfToken(data.csrfToken);
|
||||||
});
|
}
|
||||||
|
|
||||||
|
effect();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (csrfToken) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const effect = async () => {
|
||||||
|
const res = await window.fetch(`${base}/api/v1/users`, {
|
||||||
|
method: 'GET',
|
||||||
|
cache: 'no-cache',
|
||||||
|
credentials: 'same-origin',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'CSRF-Token': csrfToken
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const data = await res.json();
|
||||||
|
setUser(data);
|
||||||
|
};
|
||||||
|
|
||||||
|
effect();
|
||||||
|
}, [csrfToken, setUser]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="App">
|
<div className="App">
|
||||||
<GlobalContext.Provider value={{user, setUser, csrfToken }}>
|
<GlobalContext.Provider value={{user, setUser, csrfToken }}>
|
||||||
|
16
server/.eslintrc.json
Normal file
16
server/.eslintrc.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"env": {
|
||||||
|
"es2021": true
|
||||||
|
},
|
||||||
|
"extends": "eslint:recommended",
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaVersion": "latest",
|
||||||
|
"sourceType": "module"
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
"indent": [
|
||||||
|
"error",
|
||||||
|
2
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
144
server/app.js
144
server/app.js
@ -1,73 +1,41 @@
|
|||||||
"use strict";
|
'use strict';
|
||||||
|
|
||||||
process.env.TZ = "Etc/GMT";
|
process.env.TZ = 'Etc/GMT';
|
||||||
|
|
||||||
console.log("Loading Goodtimes");
|
console.log('Loading Goodtimes');
|
||||||
|
|
||||||
const express = require("express"),
|
const express = require('express'),
|
||||||
bodyParser = require("body-parser"),
|
bodyParser = require('body-parser'),
|
||||||
config = require("config"),
|
config = require('config'),
|
||||||
session = require('express-session'),
|
session = require('express-session'),
|
||||||
basePath = require("./basepath"),
|
basePath = require('./basepath'),
|
||||||
cookieParser = require("cookie-parser"),
|
cookieParser = require('cookie-parser'),
|
||||||
app = express(),
|
app = express(),
|
||||||
fs = require('fs'),
|
csrf = require('csurf'),
|
||||||
csrf = require('csurf');
|
http = require('http'),
|
||||||
|
{ goodTimesDB } = require('./db.js');
|
||||||
|
|
||||||
const server = require("http").createServer(app);
|
require('./console-line.js'); /* Monkey-patch console.log with line numbers */
|
||||||
|
|
||||||
|
/* App is behind an nginx proxy which we trust, so use the remote address
|
||||||
|
* set in the headers */
|
||||||
|
app.set('trust proxy', true);
|
||||||
app.use(session({
|
app.use(session({
|
||||||
secret: 'm@g1x!',
|
secret: 'm@g1x!',
|
||||||
resave: false,
|
resave: false,
|
||||||
saveUninitialized: false,
|
saveUninitialized: false,
|
||||||
cookie: { secure: true }
|
cookie: { secure: true }
|
||||||
}));
|
}));
|
||||||
app.use(bodyParser.urlencoded({ extended: false }))
|
app.use(bodyParser.urlencoded({ extended: false }));
|
||||||
app.use(cookieParser())
|
app.use(cookieParser());
|
||||||
app.use(csrf({
|
app.use(csrf({
|
||||||
cookie: true
|
cookie: true
|
||||||
}));
|
}));
|
||||||
|
app.use(bodyParser.json());
|
||||||
|
|
||||||
//const ws = require('express-ws')(app, server);
|
//const ws = require('express-ws')(app, server);
|
||||||
|
|
||||||
require("./console-line.js"); /* Monkey-patch console.log with line numbers */
|
app.use(function (err, req, res) {
|
||||||
|
|
||||||
const frontendPath = config.get("frontendPath").replace(/\/$/, "") + "/",
|
|
||||||
serverConfig = config.get("server");
|
|
||||||
|
|
||||||
console.log("Hosting server from: " + basePath);
|
|
||||||
|
|
||||||
let userDB, groupDB;
|
|
||||||
|
|
||||||
app.use(bodyParser.json());
|
|
||||||
|
|
||||||
/* App is behind an nginx proxy which we trust, so use the remote address
|
|
||||||
* set in the headers */
|
|
||||||
app.set("trust proxy", true);
|
|
||||||
|
|
||||||
app.set("basePath", basePath);
|
|
||||||
app.use(basePath, require("./routes/basepath.js"));
|
|
||||||
|
|
||||||
/* Handle static files first so excessive logging doesn't occur */
|
|
||||||
app.use(basePath, express.static(frontendPath, { index: false }));
|
|
||||||
|
|
||||||
const index = require("./routes/index");
|
|
||||||
|
|
||||||
if (config.has("admin")) {
|
|
||||||
const admin = config.get("admin");
|
|
||||||
app.set("admin", admin);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Allow loading of the app w/out being logged in */
|
|
||||||
app.use(basePath, index);
|
|
||||||
|
|
||||||
/* Allow access to the 'users' API w/out being logged in */
|
|
||||||
/*
|
|
||||||
const users = require("./routes/users");
|
|
||||||
app.use(basePath + "api/v1/users", users.router);
|
|
||||||
*/
|
|
||||||
|
|
||||||
app.use(function(err, req, res, next) {
|
|
||||||
console.error(err.message);
|
console.error(err.message);
|
||||||
res.status(err.status || 500).json({
|
res.status(err.status || 500).json({
|
||||||
message: err.message,
|
message: err.message,
|
||||||
@ -75,55 +43,47 @@ app.use(function(err, req, res, next) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
app.use(`${basePath}api/v1/groups`, require("./routes/groups"));
|
/* Initialize the data base, configure routes, and open server */
|
||||||
app.use(`${basePath}api/v1/users`, require("./routes/users"));
|
goodTimesDB.init().then((db) => {
|
||||||
|
console.log('DB connected. Configuring routes.');
|
||||||
|
|
||||||
|
app.locals.db = db;
|
||||||
|
app.set('basePath', basePath);
|
||||||
|
app.use(`${basePath}api/v1/groups`, require('./routes/groups'));
|
||||||
|
app.use(`${basePath}api/v1/users`, require('./routes/users'));
|
||||||
|
}).then(() => {
|
||||||
|
const server = http.createServer(app),
|
||||||
|
serverConfig = config.get('server');
|
||||||
|
|
||||||
/* Declare the "catch all" index route last; the final route is a 404 dynamic router */
|
console.log('Hosting server from: ' + basePath);
|
||||||
app.use(basePath, index);
|
app.set('port', serverConfig.port);
|
||||||
|
|
||||||
/**
|
process.on('SIGINT', () => {
|
||||||
* Create HTTP server and listen for new connections
|
console.log('Gracefully shutting down from SIGINT (Ctrl-C) in 2 seconds');
|
||||||
*/
|
setTimeout(() => process.exit(-1), 2000);
|
||||||
app.set("port", serverConfig.port);
|
server.close(() => process.exit(1));
|
||||||
|
|
||||||
process.on('SIGINT', () => {
|
|
||||||
console.log("Gracefully shutting down from SIGINT (Ctrl-C) in 2 seconds");
|
|
||||||
setTimeout(() => process.exit(-1), 2000);
|
|
||||||
server.close(() => process.exit(1));
|
|
||||||
});
|
|
||||||
|
|
||||||
require("./db/groups").then(function(db) {
|
|
||||||
groupDB = db;
|
|
||||||
}).then(function() {
|
|
||||||
return require("./db/users").then(function(db) {
|
|
||||||
userDB = db;
|
|
||||||
});
|
});
|
||||||
}).then(function() {
|
|
||||||
console.log("DB connected. Opening server.");
|
|
||||||
server.listen(serverConfig.port, () => {
|
|
||||||
console.log(`http server listening on ${serverConfig.port}`);
|
|
||||||
});
|
|
||||||
}).catch(function(error) {
|
|
||||||
console.error(error);
|
|
||||||
process.exit(-1);
|
|
||||||
});
|
|
||||||
|
|
||||||
server.on("error", function(error) {
|
server.on('error', function (error) {
|
||||||
if (error.syscall !== "listen") {
|
if (error.syscall !== 'listen') {
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle specific listen errors with friendly messages
|
// handle specific listen errors with friendly messages
|
||||||
switch (error.code) {
|
switch (error.code) {
|
||||||
case "EACCES":
|
case 'EACCES':
|
||||||
console.error(serverConfig.port + " requires elevated privileges");
|
console.error(serverConfig.port + ' requires elevated privileges');
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
break;
|
break;
|
||||||
case "EADDRINUSE":
|
case 'EADDRINUSE':
|
||||||
console.error(serverConfig.port + " is already in use");
|
console.error(serverConfig.port + ' is already in use');
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
server.listen(serverConfig.port, () => {
|
||||||
|
console.log(`http server listening on ${serverConfig.port}`);
|
||||||
|
});
|
||||||
|
});
|
@ -1,7 +1,7 @@
|
|||||||
let basePath = process.env.REACT_APP_basePath;
|
let basePath = process.env.REACT_APP_basePath;
|
||||||
basePath = "/" + basePath.replace(/^\/+/, "").replace(/\/+$/, "") + "/";
|
basePath = '/' + basePath.replace(/^\/+/, '').replace(/\/+$/, '') + '/';
|
||||||
if (basePath == "//") {
|
if (basePath == '//') {
|
||||||
basePath = "/";
|
basePath = '/';
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`Using basepath ${basePath}`);
|
console.log(`Using basepath ${basePath}`);
|
||||||
|
@ -1,15 +1,9 @@
|
|||||||
{
|
{
|
||||||
"db": {
|
"db": {
|
||||||
"groups": {
|
"goodtimes": {
|
||||||
"dialect": "sqlite",
|
"dialect": "sqlite",
|
||||||
"storage": "../db/groups.db",
|
"storage": "../db/goodtimes.db",
|
||||||
"logging" : false,
|
"logging": false,
|
||||||
"timezone": "+00:00"
|
|
||||||
},
|
|
||||||
"users": {
|
|
||||||
"dialect": "sqlite",
|
|
||||||
"storage": "../db/users.db",
|
|
||||||
"logging" : false,
|
|
||||||
"timezone": "+00:00"
|
"timezone": "+00:00"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
/* monkey-patch console.log to prefix with file/line-number */
|
/* monkey-patch console.log to prefix with file/line-number */
|
||||||
if (process.env.LOG_LINE) {
|
if (process.env.LOG_LINE) {
|
||||||
let cwd = process.cwd(),
|
let cwd = process.cwd(),
|
||||||
cwdRe = new RegExp("^[^/]*" + cwd.replace("/", "\\/") + "\/([^:]*:[0-9]*).*$");
|
cwdRe = new RegExp('^[^/]*' + cwd.replace('/', '\\/') + '\/([^:]*:[0-9]*).*$');
|
||||||
[ "log", "warn", "error" ].forEach(function(method) {
|
[ 'log', 'warn', 'error' ].forEach(function(method) {
|
||||||
console[method] = (function () {
|
console[method] = (function () {
|
||||||
let orig = console[method];
|
let orig = console[method];
|
||||||
return function () {
|
return function () {
|
||||||
@ -15,8 +15,8 @@ if (process.env.LOG_LINE) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let err = getErrorObject(),
|
let err = getErrorObject(),
|
||||||
caller_line = err.stack.split("\n")[3],
|
caller_line = err.stack.split('\n')[3],
|
||||||
args = [caller_line.replace(cwdRe, "$1 -")];
|
args = [caller_line.replace(cwdRe, '$1 -')];
|
||||||
|
|
||||||
/* arguments.unshift() doesn't exist... */
|
/* arguments.unshift() doesn't exist... */
|
||||||
for (var i = 0; i < arguments.length; i++) {
|
for (var i = 0; i < arguments.length; i++) {
|
||||||
|
50
server/db/users.js → server/db.js
Executable file → Normal file
50
server/db/users.js → server/db.js
Executable file → Normal file
@ -1,15 +1,30 @@
|
|||||||
"use strict";
|
'use strict';
|
||||||
|
|
||||||
const Sequelize = require('sequelize'),
|
const Sequelize = require('sequelize'),
|
||||||
config = require('config');
|
config = require('config');
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
const db = {
|
const db = {
|
||||||
sequelize: new Sequelize(config.get("db.users")),
|
sequelize: new Sequelize(config.get('db.goodtimes')),
|
||||||
Sequelize: Sequelize
|
Sequelize: Sequelize
|
||||||
};
|
};
|
||||||
|
|
||||||
return db.sequelize.authenticate().then(function () {
|
return db.sequelize.authenticate().then(function () {
|
||||||
|
const Group = db.sequelize.define('group', {
|
||||||
|
id: {
|
||||||
|
type: Sequelize.INTEGER,
|
||||||
|
primaryKey: true,
|
||||||
|
autoIncrement: true
|
||||||
|
},
|
||||||
|
name: Sequelize.STRING,
|
||||||
|
ownerId: Sequelize.INTEGER
|
||||||
|
}, {
|
||||||
|
timestamps: false,
|
||||||
|
classMethods: {
|
||||||
|
associate: function() {}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const User = db.sequelize.define('users', {
|
const User = db.sequelize.define('users', {
|
||||||
id: {
|
id: {
|
||||||
type: Sequelize.INTEGER,
|
type: Sequelize.INTEGER,
|
||||||
@ -32,6 +47,7 @@ function init() {
|
|||||||
timestamps: false
|
timestamps: false
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
const Authentication = db.sequelize.define('authentication', {
|
const Authentication = db.sequelize.define('authentication', {
|
||||||
key: {
|
key: {
|
||||||
type: Sequelize.STRING,
|
type: Sequelize.STRING,
|
||||||
@ -41,7 +57,7 @@ function init() {
|
|||||||
issued: Sequelize.DATE,
|
issued: Sequelize.DATE,
|
||||||
type: {
|
type: {
|
||||||
type: Sequelize.ENUM,
|
type: Sequelize.ENUM,
|
||||||
values: [ 'account-setup', 'password-reset' ]
|
values: ['account-setup', 'password-reset']
|
||||||
},
|
},
|
||||||
userId: {
|
userId: {
|
||||||
type: Sequelize.INTEGER,
|
type: Sequelize.INTEGER,
|
||||||
@ -54,6 +70,28 @@ function init() {
|
|||||||
}, {
|
}, {
|
||||||
timestamps: false
|
timestamps: false
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
const GroupUsers = db.sequelize.define('groupuser', {
|
||||||
|
groupId: {
|
||||||
|
type: Sequelize.INTEGER,
|
||||||
|
allowNull: false,
|
||||||
|
references: {
|
||||||
|
model: Group,
|
||||||
|
key: 'id'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
userId: {
|
||||||
|
type: Sequelize.INTEGER,
|
||||||
|
allowNull: false,
|
||||||
|
references: {
|
||||||
|
model: User,
|
||||||
|
key: 'id'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
timestamps: false
|
||||||
|
});
|
||||||
|
|
||||||
return db.sequelize.sync({
|
return db.sequelize.sync({
|
||||||
force: false
|
force: false
|
||||||
@ -61,11 +99,11 @@ function init() {
|
|||||||
return db;
|
return db;
|
||||||
});
|
});
|
||||||
}).catch(function (error) {
|
}).catch(function (error) {
|
||||||
console.log("ERROR: Failed to authenticate with USER DB");
|
console.log('ERROR: Failed to authenticate with GROUP DB');
|
||||||
console.log("ERROR: " + JSON.stringify(config.get("db"), null, 2));
|
console.log('ERROR: ' + JSON.stringify(config.get('db'), null, 2));
|
||||||
console.log(error);
|
console.log(error);
|
||||||
throw error;
|
throw error;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = init();
|
module.exports = { goodTimesDB: { init } };
|
@ -1,58 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
const Sequelize = require('sequelize'),
|
|
||||||
config = require('config');
|
|
||||||
|
|
||||||
function init() {
|
|
||||||
const db = {
|
|
||||||
sequelize: new Sequelize(config.get("db.groups")),
|
|
||||||
Sequelize: Sequelize
|
|
||||||
};
|
|
||||||
|
|
||||||
return db.sequelize.authenticate().then(function () {
|
|
||||||
const Group = db.sequelize.define('group', {
|
|
||||||
id: {
|
|
||||||
type: Sequelize.INTEGER,
|
|
||||||
primaryKey: true,
|
|
||||||
autoIncrement: true
|
|
||||||
},
|
|
||||||
name: Sequelize.STRING,
|
|
||||||
ownerId: Sequelize.INTEGER
|
|
||||||
}, {
|
|
||||||
timestamps: false,
|
|
||||||
classMethods: {
|
|
||||||
associate: function() {}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const GroupUsers = db.sequelize.define('groupuser', {
|
|
||||||
groupId: {
|
|
||||||
type: Sequelize.INTEGER,
|
|
||||||
allowNull: false,
|
|
||||||
references: {
|
|
||||||
model: Group,
|
|
||||||
key: 'id'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
userId: {
|
|
||||||
type: Sequelize.INTEGER,
|
|
||||||
allowNull: false,
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
timestamps: false
|
|
||||||
});
|
|
||||||
|
|
||||||
return db.sequelize.sync({
|
|
||||||
force: false
|
|
||||||
}).then(function () {
|
|
||||||
return db;
|
|
||||||
});
|
|
||||||
}).catch(function (error) {
|
|
||||||
console.log("ERROR: Failed to authenticate with GROUP DB");
|
|
||||||
console.log("ERROR: " + JSON.stringify(config.get("db"), null, 2));
|
|
||||||
console.log(error);
|
|
||||||
throw error;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = init();
|
|
@ -1,61 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
const createTransport = require('nodemailer').createTransport,
|
|
||||||
{ timestamp } = require("./timestamp");
|
|
||||||
|
|
||||||
const transporter = createTransport({
|
|
||||||
host: 'email.ketrenos.com',
|
|
||||||
pool: true,
|
|
||||||
port: 25
|
|
||||||
});
|
|
||||||
|
|
||||||
function sendMail(to, subject, message, cc) {
|
|
||||||
let envelope = {
|
|
||||||
subject: subject,
|
|
||||||
from: 'Ketr.Ketran <james_ketran@ketrenos.com>',
|
|
||||||
to: to || '',
|
|
||||||
cc: cc || ''
|
|
||||||
};
|
|
||||||
|
|
||||||
/* If there isn't a To: but there is a Cc:, promote Cc: to To: */
|
|
||||||
if (!envelope.to && envelope.cc) {
|
|
||||||
envelope.to = envelope.cc;
|
|
||||||
delete envelope.cc;
|
|
||||||
}
|
|
||||||
|
|
||||||
envelope.text = message
|
|
||||||
envelope.html = message.replace(/\n/g, "<br>\n");
|
|
||||||
|
|
||||||
return new Promise(function (resolve, reject) {
|
|
||||||
let attempts = 10;
|
|
||||||
|
|
||||||
function attemptSend(envelope) {
|
|
||||||
/* Rate limit to ten per second */
|
|
||||||
transporter.sendMail(envelope, function (error, info) {
|
|
||||||
if (error) {
|
|
||||||
if (attempts) {
|
|
||||||
attempts--;
|
|
||||||
console.warn(timestamp() + " Unable to send mail. Trying again in 100ms (" + attempts + " attempts remain): ", error);
|
|
||||||
setTimeout(send.bind(undefined, envelope), 100);
|
|
||||||
} else {
|
|
||||||
console.error(timestamp() + " Error sending email: ", error)
|
|
||||||
return reject(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(timestamp() + " Mail sent to: " + envelope.to);
|
|
||||||
return resolve(true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
attemptSend(envelope);
|
|
||||||
}).then(function(success) {
|
|
||||||
if (!success) {
|
|
||||||
console.error(timestamp() + " Mail not sent to: " + envelope.to);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
sendMail: sendMail
|
|
||||||
};
|
|
1401
server/package-lock.json
generated
1401
server/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -38,5 +38,8 @@
|
|||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git@git.ketrenos.com:jketreno/goodtimes"
|
"url": "git@git.ketrenos.com:jketreno/goodtimes"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"eslint": "^8.12.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
const express = require("express"),
|
|
||||||
fs = require("fs"),
|
|
||||||
url = require("url");
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
/* This router only handles HTML files and is used
|
|
||||||
* to replace BASEPATH */
|
|
||||||
router.get("/*", (req, res, next) => {
|
|
||||||
const parts = url.parse(req.url),
|
|
||||||
basePath = req.app.get("basePath");
|
|
||||||
|
|
||||||
if (!/^\/[^/]+\.html$/.exec(parts.pathname)) {
|
|
||||||
return next();
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("Attempting to parse 'frontend" + parts.pathname + "'");
|
|
||||||
|
|
||||||
/* Replace <script>'<base href="/BASEPATH/">';</script> in index.html with
|
|
||||||
* the basePath */
|
|
||||||
fs.readFile("frontend" + parts.pathname, "utf8", function(error, content) {
|
|
||||||
if (error) {
|
|
||||||
return next();
|
|
||||||
}
|
|
||||||
res.send(content.replace(
|
|
||||||
/<script>'<base href="BASEPATH">';<\/script>/,
|
|
||||||
"<base href='" + basePath + "'>"));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
module.exports = router;
|
|
@ -1,30 +1,10 @@
|
|||||||
"use strict";
|
const express = require('express'),
|
||||||
|
|
||||||
const express = require("express"),
|
|
||||||
router = express.Router(),
|
router = express.Router(),
|
||||||
crypto = require("crypto"),
|
crypto = require('crypto');
|
||||||
{ readFile, writeFile } = require("fs").promises,
|
|
||||||
fs = require("fs"),
|
|
||||||
accessSync = fs.accessSync,
|
|
||||||
randomWords = require("random-words"),
|
|
||||||
equal = require("fast-deep-equal");
|
|
||||||
|
|
||||||
const debug = {
|
|
||||||
audio: false,
|
|
||||||
get: true,
|
|
||||||
set: true,
|
|
||||||
update: false
|
|
||||||
};
|
|
||||||
|
|
||||||
let groupDB;
|
|
||||||
|
|
||||||
require("../db/groups").then(function(db) {
|
|
||||||
groupDB = db;
|
|
||||||
});
|
|
||||||
|
|
||||||
/* Simple NO-OP to set session cookie so user-id can use it as the
|
/* Simple NO-OP to set session cookie so user-id can use it as the
|
||||||
* index */
|
* index */
|
||||||
router.get("/", (req, res/*, next*/) => {
|
router.get('/', (req, res/*, next*/) => {
|
||||||
let userId;
|
let userId;
|
||||||
if (!req.cookies.user) {
|
if (!req.cookies.user) {
|
||||||
userId = crypto.randomBytes(16).toString('hex');
|
userId = crypto.randomBytes(16).toString('hex');
|
||||||
@ -38,19 +18,19 @@ router.get("/", (req, res/*, next*/) => {
|
|||||||
return res.status(200).send({ user: userId });
|
return res.status(200).send({ user: userId });
|
||||||
});
|
});
|
||||||
|
|
||||||
router.post("/", async (req, res/*, next*/) => {
|
router.get('/', async (req, res/*, next*/) => {
|
||||||
console.log(`POST /groups/`, req.session.userId);
|
console.log('GET /groups/', req.session.userId);
|
||||||
return res.status(200).send(
|
return res.status(200).send(
|
||||||
[ {
|
[ {
|
||||||
id: 1,
|
id: 1,
|
||||||
ownerId: 1,
|
ownerId: 1,
|
||||||
name: "Beer Tuesday",
|
name: 'Beer Tuesday',
|
||||||
nextEvent: Date.now() + 86400 * 14 * 1000 /* 2 weeks from now */
|
nextEvent: Date.now() + 86400 * 14 * 1000 /* 2 weeks from now */
|
||||||
} ]
|
} ]
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
router.post("/:id", async (req, res/*, next*/) => {
|
router.post('/:id', async (req, res) => {
|
||||||
const { id } = req.params;
|
const { id } = req.params;
|
||||||
|
|
||||||
let userId;
|
let userId;
|
||||||
@ -61,6 +41,10 @@ router.post("/:id", async (req, res/*, next*/) => {
|
|||||||
userId = req.cookies.user;
|
userId = req.cookies.user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const group = {
|
||||||
|
id: 1
|
||||||
|
};
|
||||||
|
|
||||||
if (id) {
|
if (id) {
|
||||||
console.log(`[${userId.substring(0,8)}]: Attempting load of ${id}`);
|
console.log(`[${userId.substring(0,8)}]: Attempting load of ${id}`);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,65 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
const express = require("express"),
|
|
||||||
fs = require("fs"),
|
|
||||||
url = require("url"),
|
|
||||||
config = require("config"),
|
|
||||||
basePath = require("../basepath");
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
/* List of filename extensions we know are "potential" file extensions for
|
|
||||||
* assets we don"t want to return "index.html" for */
|
|
||||||
const extensions = [
|
|
||||||
"html", "js", "css", "eot", "gif", "ico", "jpeg", "jpg", "mp4",
|
|
||||||
"md", "ttf", "txt", "woff", "woff2", "yml", "svg"
|
|
||||||
];
|
|
||||||
|
|
||||||
/* Build the extension match RegExp from the list of extensions */
|
|
||||||
const extensionMatch = new RegExp("^.*?(" + extensions.join("|") + ")$", "i");
|
|
||||||
|
|
||||||
/* To handle dynamic routes, we return index.html to every request that
|
|
||||||
* gets this far -- so this needs to be the last route.
|
|
||||||
*
|
|
||||||
* However, that introduces site development problems when assets are
|
|
||||||
* referenced which don't yet exist (due to bugs, or sequence of adds) --
|
|
||||||
* the server would return HTML content instead of the 404.
|
|
||||||
*
|
|
||||||
* So, check to see if the requested path is for an asset with a recognized
|
|
||||||
* file extension.
|
|
||||||
*
|
|
||||||
* If so, 404 because the asset isn't there. otherwise assume it is a
|
|
||||||
* dynamic client side route and *then* return index.html.
|
|
||||||
*/
|
|
||||||
router.get("/*", function(req, res, next) {
|
|
||||||
const parts = url.parse(req.url);
|
|
||||||
|
|
||||||
/* If req.user isn't set yet (authentication hasn't happened) then
|
|
||||||
* only allow / to be loaded--everything else chains to the next
|
|
||||||
* handler */
|
|
||||||
if (!req.user &&
|
|
||||||
req.url !== "/") {
|
|
||||||
return next();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (req.url == "/" || req.url.indexOf("/games") == 0 || !extensionMatch.exec(parts.pathname)) {
|
|
||||||
console.log("Returning index for " + req.url);
|
|
||||||
|
|
||||||
/* Replace <script>'<base href="BASEPATH">';</script> in index.html with
|
|
||||||
* the basePath */
|
|
||||||
const frontendPath = config.get("frontendPath").replace(/\/$/, "") + "/",
|
|
||||||
index = fs.readFileSync(frontendPath + "index.html", "utf8");
|
|
||||||
res.send(index.replace(
|
|
||||||
/<script>'<base href="BASEPATH">';<\/script>/,
|
|
||||||
"<base href='" + basePath + "'>"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("Page not found: " + req.url);
|
|
||||||
return res.status(404).json({
|
|
||||||
message: "Page not found",
|
|
||||||
status: 404
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
module.exports = router;
|
|
@ -1,31 +1,26 @@
|
|||||||
"use strict";
|
'use strict';
|
||||||
|
|
||||||
const express = require("express"),
|
const express = require('express'),
|
||||||
config = require("config"),
|
{ sendVerifyMail, sendPasswordChangedMail, sendVerifiedMail } =
|
||||||
{ sendVerifyMail, sendPasswordChangedMail, sendVerifiedMail } = require("../lib/mail"),
|
require('../lib/mail'),
|
||||||
crypto = require("crypto");
|
crypto = require('crypto');
|
||||||
|
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const autoAuthenticate = 1;
|
const autoAuthenticate = 1;
|
||||||
|
|
||||||
let userDB;
|
router.get('/', function(req, res/*, next*/) {
|
||||||
|
console.log('GET /users/');
|
||||||
require("../db/users.js").then(function(db) {
|
|
||||||
userDB = db;
|
|
||||||
});
|
|
||||||
|
|
||||||
router.get("/", function(req, res/*, next*/) {
|
|
||||||
console.log("/users/");
|
|
||||||
return getSessionUser(req).then((user) => {
|
return getSessionUser(req).then((user) => {
|
||||||
return res.status(200).send(user);
|
return res.status(200).send(user);
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
console.log("User not logged in: " + error);
|
console.log('User not logged in: ' + error);
|
||||||
return res.status(200).send({});
|
return res.status(200).send({});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
router.put("/password", function(req, res) {
|
router.put('/password', function(req, res) {
|
||||||
console.log("/users/password");
|
console.log('/users/password');
|
||||||
|
const db = req.app.locals.db;
|
||||||
|
|
||||||
const changes = {
|
const changes = {
|
||||||
currentPassword: req.query.c || req.body.c,
|
currentPassword: req.query.c || req.body.c,
|
||||||
@ -33,21 +28,21 @@ router.put("/password", function(req, res) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (!changes.currentPassword || !changes.newPassword) {
|
if (!changes.currentPassword || !changes.newPassword) {
|
||||||
return res.status(400).send("Missing current password and/or new password.");
|
return res.status(400).send('Missing current password and/or new password.');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changes.currentPassword == changes.newPassword) {
|
if (changes.currentPassword == changes.newPassword) {
|
||||||
return res.status(400).send("Attempt to set new password to current password.");
|
return res.status(400).send('Attempt to set new password to current password.');
|
||||||
}
|
}
|
||||||
|
|
||||||
return getSessionUser(req).then(function(user) {
|
return getSessionUser(req).then(function(user) {
|
||||||
return userDB.sequelize.query("SELECT id FROM users " +
|
return db.sequelize.query('SELECT id FROM users ' +
|
||||||
"WHERE uid=:username AND password=:password", {
|
'WHERE uid=:username AND password=:password', {
|
||||||
replacements: {
|
replacements: {
|
||||||
username: user.username,
|
username: user.username,
|
||||||
password: crypto.createHash('sha256').update(changes.currentPassword).digest('base64')
|
password: crypto.createHash('sha256').update(changes.currentPassword).digest('base64')
|
||||||
},
|
},
|
||||||
type: userDB.Sequelize.QueryTypes.SELECT,
|
type: db.Sequelize.QueryTypes.SELECT,
|
||||||
raw: true
|
raw: true
|
||||||
}).then(function(users) {
|
}).then(function(users) {
|
||||||
if (users.length != 1) {
|
if (users.length != 1) {
|
||||||
@ -57,34 +52,35 @@ router.put("/password", function(req, res) {
|
|||||||
});
|
});
|
||||||
}).then(function(user) {
|
}).then(function(user) {
|
||||||
if (!user) {
|
if (!user) {
|
||||||
console.log("Invalid password");
|
console.log('Invalid password');
|
||||||
/* Invalid password */
|
/* Invalid password */
|
||||||
res.status(401).send("Invalid password");
|
res.status(401).send('Invalid password');
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return userDB.sequelize.query("UPDATE users SET password=:password WHERE uid=:username", {
|
return db.sequelize.query('UPDATE users SET password=:password WHERE uid=:username', {
|
||||||
replacements: {
|
replacements: {
|
||||||
username: user.username,
|
username: user.username,
|
||||||
password: crypto.createHash('sha256').update(changes.newPassword).digest('base64')
|
password: crypto.createHash('sha256').update(changes.newPassword).digest('base64')
|
||||||
}
|
}
|
||||||
}).then(function() {
|
}).then(function() {
|
||||||
console.log("Password changed for user " + user.username + " to '" + changes.newPassword + "'.");
|
console.log('Password changed for user ' + user.username + ' to \'' + changes.newPassword + '\'.');
|
||||||
|
|
||||||
res.status(200).send(user);
|
res.status(200).send(user);
|
||||||
user.id = req.session.userId;
|
user.id = req.session.userId;
|
||||||
return sendPasswordChangedMail(userDB, req, user);
|
return sendPasswordChangedMail(db, req, user);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get("/csrf", (req, res) => {
|
router.get('/csrf', (req, res) => {
|
||||||
console.log("/users/csrf");
|
console.log('/users/csrf');
|
||||||
res.json({ csrfToken: req.csrfToken() });
|
res.json({ csrfToken: req.csrfToken() });
|
||||||
});
|
});
|
||||||
|
|
||||||
router.post("/signup", function(req, res) {
|
router.post('/signup', function(req, res) {
|
||||||
console.log("/users/signup");
|
console.log('/users/signup');
|
||||||
|
const db = req.app.locals.db;
|
||||||
|
|
||||||
const user = {
|
const user = {
|
||||||
uid: req.body.email,
|
uid: req.body.email,
|
||||||
@ -100,7 +96,7 @@ router.post("/signup", function(req, res) {
|
|||||||
|| !user.familyName
|
|| !user.familyName
|
||||||
|| !user.firstName) {
|
|| !user.firstName) {
|
||||||
return res.status(400).send({
|
return res.status(400).send({
|
||||||
message: `Missing email address, password, and/or name.`
|
message: 'Missing email address, password, and/or name.'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,18 +105,18 @@ router.post("/signup", function(req, res) {
|
|||||||
user.md5 = crypto.createHash('md5')
|
user.md5 = crypto.createHash('md5')
|
||||||
.update(user.email).digest('base64');
|
.update(user.email).digest('base64');
|
||||||
|
|
||||||
return userDB.sequelize.query("SELECT * FROM users WHERE uid=:uid", {
|
return db.sequelize.query('SELECT * FROM users WHERE uid=:uid', {
|
||||||
replacements: user,
|
replacements: user,
|
||||||
type: userDB.Sequelize.QueryTypes.SELECT,
|
type: db.Sequelize.QueryTypes.SELECT,
|
||||||
raw: true
|
raw: true
|
||||||
}).then(async function(results) {
|
}).then(async function(results) {
|
||||||
if (results.length != 0 && results[0].mailVerified) {
|
if (results.length != 0 && results[0].mailVerified) {
|
||||||
return res.status(400).send({
|
return res.status(400).send({
|
||||||
message: `Email address already used.`
|
message: 'Email address already used.'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
let re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
||||||
if (!re.exec(user.email)) {
|
if (!re.exec(user.email)) {
|
||||||
const error = `Invalid email address: ${user.email}.`;
|
const error = `Invalid email address: ${user.email}.`;
|
||||||
console.log(error);
|
console.log(error);
|
||||||
@ -131,14 +127,14 @@ router.post("/signup", function(req, res) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (results.length != 0) {
|
if (results.length != 0) {
|
||||||
await userDB.sequelize.query("UPDATE users " +
|
await db.sequelize.query('UPDATE users ' +
|
||||||
"SET mailVerified=0");
|
'SET mailVerified=0');
|
||||||
req.session.userId = results[0].id;
|
req.session.userId = results[0].id;
|
||||||
} else {
|
} else {
|
||||||
let [, metadata] = await userDB.sequelize.query("INSERT INTO users " +
|
let [, metadata] = await db.sequelize.query('INSERT INTO users ' +
|
||||||
"(uid,firstName,familyName,password,email,memberSince," +
|
'(uid,firstName,familyName,password,email,memberSince,' +
|
||||||
"authenticated,md5) " +
|
'authenticated,md5) ' +
|
||||||
`VALUES(:uid,:firstName,:familyName,:password,` +
|
'VALUES(:uid,:firstName,:familyName,:password,' +
|
||||||
`:email,CURRENT_TIMESTAMP,${autoAuthenticate},:md5)`, {
|
`:email,CURRENT_TIMESTAMP,${autoAuthenticate},:md5)`, {
|
||||||
replacements: user
|
replacements: user
|
||||||
});
|
});
|
||||||
@ -147,7 +143,7 @@ router.post("/signup", function(req, res) {
|
|||||||
return getSessionUser(req).then(function(user) {
|
return getSessionUser(req).then(function(user) {
|
||||||
res.status(200).send(user);
|
res.status(200).send(user);
|
||||||
user.id = req.session.userId;
|
user.id = req.session.userId;
|
||||||
return sendVerifyMail(userDB, req, user);
|
return sendVerifyMail(db, req, user);
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
@ -156,34 +152,35 @@ router.post("/signup", function(req, res) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const getSessionUser = function(req) {
|
const getSessionUser = function(req) {
|
||||||
|
const db = req.app.locals.db;
|
||||||
return Promise.resolve().then(function() {
|
return Promise.resolve().then(function() {
|
||||||
if (!req.session || !req.session.userId) {
|
if (!req.session || !req.session.userId) {
|
||||||
throw "Unauthorized. You must be logged in.";
|
throw 'Unauthorized. You must be logged in.';
|
||||||
}
|
}
|
||||||
|
|
||||||
let query = "SELECT " +
|
let query = 'SELECT ' +
|
||||||
"uid AS username,firstName,familyName,mailVerified,authenticated,memberSince,email,md5 " +
|
'uid AS username,firstName,familyName,mailVerified,authenticated,memberSince,email,md5 ' +
|
||||||
"FROM users WHERE id=:id";
|
'FROM users WHERE id=:id';
|
||||||
return userDB.sequelize.query(query, {
|
return db.sequelize.query(query, {
|
||||||
replacements: {
|
replacements: {
|
||||||
id: req.session.userId
|
id: req.session.userId
|
||||||
},
|
},
|
||||||
type: userDB.Sequelize.QueryTypes.SELECT,
|
type: db.Sequelize.QueryTypes.SELECT,
|
||||||
raw: true
|
raw: true
|
||||||
}).then(function(results) {
|
}).then(function(results) {
|
||||||
if (results.length != 1) {
|
if (results.length != 1) {
|
||||||
throw "Invalid account.";
|
throw 'Invalid account.';
|
||||||
}
|
}
|
||||||
|
|
||||||
let user = results[0];
|
let user = results[0];
|
||||||
|
|
||||||
if (!user.mailVerified) {
|
if (!user.mailVerified) {
|
||||||
user.restriction = user.restriction || "Email address not verified.";
|
user.restriction = user.restriction || 'Email address not verified.';
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!user.authenticated) {
|
if (!user.authenticated) {
|
||||||
user.restriction = user.restriction || "Accout not authorized.";
|
user.restriction = user.restriction || 'Accout not authorized.';
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,7 +189,7 @@ const getSessionUser = function(req) {
|
|||||||
}).then(function(user) {
|
}).then(function(user) {
|
||||||
/* Strip out any fields that shouldn't be there. The allowed fields are: */
|
/* Strip out any fields that shouldn't be there. The allowed fields are: */
|
||||||
let allowed = [
|
let allowed = [
|
||||||
"maintainer", "username", "firstName", "familyName", "mailVerified", "authenticated", "name", "email", "restriction", "md5"
|
'maintainer', 'username', 'firstName', 'familyName', 'mailVerified', 'authenticated', 'name', 'email', 'restriction', 'md5'
|
||||||
];
|
];
|
||||||
for (let field in user) {
|
for (let field in user) {
|
||||||
if (allowed.indexOf(field) == -1) {
|
if (allowed.indexOf(field) == -1) {
|
||||||
@ -201,114 +198,114 @@ const getSessionUser = function(req) {
|
|||||||
}
|
}
|
||||||
return user;
|
return user;
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
router.post("/verify-email", async (req, res) => {
|
router.post('/verify-email', async (req, res) => {
|
||||||
console.log("/users/verify-email");
|
console.log('/users/verify-email');
|
||||||
const key = req.body.token;
|
const key = req.body.token;
|
||||||
|
const db = req.app.locals.db;
|
||||||
|
|
||||||
let results = await userDB.sequelize.query(
|
let results = await db.sequelize.query(
|
||||||
"SELECT * FROM authentications WHERE key=:key", {
|
'SELECT * FROM authentications WHERE key=:key', {
|
||||||
replacements: { key },
|
replacements: { key },
|
||||||
type: userDB.sequelize.QueryTypes.SELECT
|
type: db.sequelize.QueryTypes.SELECT
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
let token;
|
let token;
|
||||||
if (results.length == 0) {
|
if (results.length == 0) {
|
||||||
console.log("Invalid key. Ignoring.");
|
console.log('Invalid key. Ignoring.');
|
||||||
return res.status(400).send({
|
return res.status(400).send({
|
||||||
message: `Invalid authentication token.`
|
message: 'Invalid authentication token.'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
token = results[0];
|
token = results[0];
|
||||||
console.log(token);
|
console.log(token);
|
||||||
console.log("Matched token: " + JSON.stringify(token, null, 2));
|
console.log('Matched token: ' + JSON.stringify(token, null, 2));
|
||||||
switch (token.type) {
|
switch (token.type) {
|
||||||
case "account-setup":
|
case 'account-setup':
|
||||||
return userDB.sequelize.query(
|
return db.sequelize.query(
|
||||||
"UPDATE users SET mailVerified=1 WHERE id=:userId", {
|
'UPDATE users SET mailVerified=1 WHERE id=:userId', {
|
||||||
replacements: token
|
replacements: token
|
||||||
})
|
}
|
||||||
.then(function () {
|
).then(function () {
|
||||||
return userDB.sequelize.query(
|
return db.sequelize.query(
|
||||||
"DELETE FROM authentications WHERE key=:key", {
|
'DELETE FROM authentications WHERE key=:key', {
|
||||||
replacements: { key }
|
replacements: { key }
|
||||||
});
|
}
|
||||||
})
|
);
|
||||||
.then(function () {
|
}).then(function () {
|
||||||
return userDB.sequelize.query(
|
return db.sequelize.query(
|
||||||
"SELECT * FROM users WHERE id=:userId", {
|
'SELECT * FROM users WHERE id=:userId', {
|
||||||
replacements: token,
|
replacements: token,
|
||||||
type: userDB.sequelize.QueryTypes.SELECT
|
type: db.sequelize.QueryTypes.SELECT
|
||||||
});
|
}
|
||||||
})
|
);
|
||||||
.then(function (results) {
|
}).then(function (results) {
|
||||||
if (results.length == 0) {
|
if (results.length == 0) {
|
||||||
return res.status(500).send({
|
return res.status(500).send({
|
||||||
message: `Internal authentication error.`
|
message: 'Internal authentication error.'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return results[0];
|
return results[0];
|
||||||
})
|
}).then((user) => {
|
||||||
.then((user) => {
|
sendVerifiedMail(db, req, user);
|
||||||
sendVerifiedMail(userDB, req, user);
|
|
||||||
req.session.userId = user.id;
|
req.session.userId = user.id;
|
||||||
}).then(function (user) {
|
}).then(() => {
|
||||||
return getSessionUser(req).then(function (user) {
|
return getSessionUser(req).then((user) => {
|
||||||
return res.status(200).send(user);
|
return res.status(200).send(user);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
router.post("/signin", function(req, res) {
|
router.post('/signin', function(req, res) {
|
||||||
console.log("/users/signin");
|
console.log('/users/signin');
|
||||||
|
const db = req.app.locals.db;
|
||||||
|
|
||||||
let { email, password } = req.body;
|
let { email, password } = req.body;
|
||||||
|
|
||||||
if (!email || !password) {
|
if (!email || !password) {
|
||||||
return res.status(400).send({
|
return res.status(400).send({
|
||||||
message: `Missing email and/or password`
|
message: 'Missing email and/or password'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("Looking up user in DB.");
|
console.log('Looking up user in DB.');
|
||||||
|
|
||||||
let query = "SELECT " +
|
let query = 'SELECT ' +
|
||||||
"id,mailVerified,authenticated," +
|
'id,mailVerified,authenticated,' +
|
||||||
"uid AS username," +
|
'uid AS username,' +
|
||||||
"familyName,firstName,email " +
|
'familyName,firstName,email ' +
|
||||||
"FROM users WHERE uid=:username AND password=:password";
|
'FROM users WHERE uid=:username AND password=:password';
|
||||||
return userDB.sequelize.query(query, {
|
return db.sequelize.query(query, {
|
||||||
replacements: {
|
replacements: {
|
||||||
username: email,
|
username: email,
|
||||||
password: crypto.createHash('sha256').update(password).digest('base64')
|
password: crypto.createHash('sha256').update(password).digest('base64')
|
||||||
},
|
},
|
||||||
type: userDB.Sequelize.QueryTypes.SELECT
|
type: db.Sequelize.QueryTypes.SELECT
|
||||||
})
|
}).then(function(users) {
|
||||||
.then(function(users) {
|
|
||||||
if (users.length != 1) {
|
if (users.length != 1) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
let user = users[0];
|
let user = users[0];
|
||||||
req.session.userId = user.id;
|
req.session.userId = user.id;
|
||||||
return user;
|
return user;
|
||||||
})
|
}).then(function(user) {
|
||||||
.then(function(user) {
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
console.log(email + " not found (or invalid password.)");
|
console.log(email + ' not found (or invalid password.)');
|
||||||
req.session.userId = null;
|
req.session.userId = null;
|
||||||
return res.status(401).send({
|
return res.status(401).send({
|
||||||
message: `Invalid sign in credentials`
|
message: 'Invalid sign in credentials'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let message = "Logged in as " + user.email + " (" + user.id + ")";
|
let message = 'Logged in as ' + user.email + ' (' + user.id + ')';
|
||||||
if (!user.mailVerified) {
|
if (!user.mailVerified) {
|
||||||
console.log(message + ", who is not verified email.");
|
console.log(message + ', who is not verified email.');
|
||||||
} else if (!user.authenticated) {
|
} else if (!user.authenticated) {
|
||||||
console.log(message + ", who is not authenticated.");
|
console.log(message + ', who is not authenticated.');
|
||||||
} else {
|
} else {
|
||||||
console.log(message);
|
console.log(message);
|
||||||
}
|
}
|
||||||
@ -316,15 +313,14 @@ router.post("/signin", function(req, res) {
|
|||||||
return getSessionUser(req).then(function(user) {
|
return getSessionUser(req).then(function(user) {
|
||||||
return res.status(200).send(user);
|
return res.status(200).send(user);
|
||||||
});
|
});
|
||||||
})
|
}).catch(function(error) {
|
||||||
.catch(function(error) {
|
|
||||||
console.log(error);
|
console.log(error);
|
||||||
return res.status(403).send(error);
|
return res.status(403).send(error);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
router.post("/signout", (req, res) => {
|
router.post('/signout', (req, res) => {
|
||||||
console.log("/users/signout");
|
console.log('/users/signout');
|
||||||
if (req.session && req.session.userId) {
|
if (req.session && req.session.userId) {
|
||||||
req.session.userId = null;
|
req.session.userId = null;
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,12 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
function twoDigit(number) {
|
function twoDigit(number) {
|
||||||
return ("0" + number).slice(-2);
|
return ('0' + number).slice(-2);
|
||||||
}
|
}
|
||||||
|
|
||||||
function timestamp(date) {
|
function timestamp(date) {
|
||||||
date = date || new Date();
|
date = date || new Date();
|
||||||
return [ date.getFullYear(), twoDigit(date.getMonth() + 1), twoDigit(date.getDate()) ].join("-") +
|
return [ date.getFullYear(), twoDigit(date.getMonth() + 1), twoDigit(date.getDate()) ].join('-') +
|
||||||
" " +
|
' ' +
|
||||||
[ twoDigit(date.getHours()), twoDigit(date.getMinutes()), twoDigit(date.getSeconds()) ].join(":");
|
[ twoDigit(date.getHours()), twoDigit(date.getMinutes()), twoDigit(date.getSeconds()) ].join(':');
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user