Auth is working again with express-session for user tracking
Signed-off-by: James Ketrenos <james_eikona@ketrenos.com>
This commit is contained in:
parent
d21946cb9e
commit
4c6040e3bc
1
.env
1
.env
@ -1,2 +1,3 @@
|
|||||||
REACT_APP_basePath="/"
|
REACT_APP_basePath="/"
|
||||||
NODE_CONFIG_ENV='production'
|
NODE_CONFIG_ENV='production'
|
||||||
|
LOG_LINE=1
|
@ -2,3 +2,4 @@ PORT=3001
|
|||||||
PUBLIC_URL=/
|
PUBLIC_URL=/
|
||||||
HOST=nuc.ketrenos.com
|
HOST=nuc.ketrenos.com
|
||||||
DANGEROUSLY_DISABLE_HOST_CHECK='true'
|
DANGEROUSLY_DISABLE_HOST_CHECK='true'
|
||||||
|
LOG_LINE=1
|
@ -24,6 +24,7 @@ import { base } from "./Common.js";
|
|||||||
const App = () => {
|
const App = () => {
|
||||||
const [ user, setUser ] = useState(null);
|
const [ user, setUser ] = useState(null);
|
||||||
const [ csrfToken, setCsrfToken ] = useState(undefined);
|
const [ csrfToken, setCsrfToken ] = useState(undefined);
|
||||||
|
const [ loading, setLoading ] = useState(true);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const effect = async () => {
|
const effect = async () => {
|
||||||
@ -43,7 +44,7 @@ const App = () => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (csrfToken) {
|
if (!csrfToken) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const effect = async () => {
|
const effect = async () => {
|
||||||
@ -57,6 +58,12 @@ const App = () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
|
setLoading(false);
|
||||||
|
if (res.status >= 400) {
|
||||||
|
console.log(data.message ? data.message : res.statusText);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
setUser(data);
|
setUser(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -83,9 +90,12 @@ const App = () => {
|
|||||||
<Route path="/" element={
|
<Route path="/" element={
|
||||||
<Paper style={{padding: "0.5rem"}}>You need to verify your email via the link sent to {user.email}.</Paper>}/>
|
<Paper style={{padding: "0.5rem"}}>You need to verify your email via the link sent to {user.email}.</Paper>}/>
|
||||||
}
|
}
|
||||||
{ !user &&
|
{ !user && !loading &&
|
||||||
<Route path="/" element={<SignIn />} />
|
<Route path="/" element={<SignIn />} />
|
||||||
}
|
}
|
||||||
|
{ !user && loading &&
|
||||||
|
<Route path="/" element={<div>Loading...</div>} />
|
||||||
|
}
|
||||||
</Routes>
|
</Routes>
|
||||||
</Container>
|
</Container>
|
||||||
</GlobalContext.Provider>
|
</GlobalContext.Provider>
|
||||||
|
@ -23,7 +23,7 @@ function Dashboard() {
|
|||||||
const effect = async () => {
|
const effect = async () => {
|
||||||
const res = await window.fetch(
|
const res = await window.fetch(
|
||||||
`${base}/api/v1/groups`, {
|
`${base}/api/v1/groups`, {
|
||||||
method: 'POST',
|
method: 'GET',
|
||||||
cache: 'no-cache',
|
cache: 'no-cache',
|
||||||
credentials: 'same-origin',
|
credentials: 'same-origin',
|
||||||
headers: {
|
headers: {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { useContext, useState } from 'react';
|
import React, { useContext, useState, useCallback } from 'react';
|
||||||
import Avatar from '@mui/material/Avatar';
|
import Avatar from '@mui/material/Avatar';
|
||||||
import Button from '@mui/material/Button';
|
import Button from '@mui/material/Button';
|
||||||
import CssBaseline from '@mui/material/CssBaseline';
|
import CssBaseline from '@mui/material/CssBaseline';
|
||||||
@ -37,10 +37,10 @@ export default function SignIn() {
|
|||||||
const [ error, setError ] = useState(undefined);
|
const [ error, setError ] = useState(undefined);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const handleSubmit = (event) => {
|
const handleSubmit = useCallback(async (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const data = new FormData(event.currentTarget);
|
const form = new FormData(event.currentTarget);
|
||||||
window.fetch(`${base}/api/v1/users/signin`, {
|
const res = await window.fetch(`${base}/api/v1/users/signin`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
cache: 'no-cache',
|
cache: 'no-cache',
|
||||||
credentials: 'same-origin',
|
credentials: 'same-origin',
|
||||||
@ -49,28 +49,22 @@ export default function SignIn() {
|
|||||||
'CSRF-Token': csrfToken
|
'CSRF-Token': csrfToken
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
email: data.get('email'),
|
email: form.get('email'),
|
||||||
password: data.get('password')
|
password: form.get('password')
|
||||||
})
|
})
|
||||||
})
|
});
|
||||||
.then(async (res) => {
|
const data = await res.json();
|
||||||
return [ res.status, res.statusText, await res.json() ];
|
if (res.status >= 400) {
|
||||||
})
|
setError(data.message ? data.message : res.statusText);
|
||||||
.then(([ status, statusText, data ]) => {
|
|
||||||
if (status >= 400) {
|
|
||||||
setError(data.message ? data.message : statusText);
|
|
||||||
return null;
|
return null;
|
||||||
} if (!data) {
|
}
|
||||||
|
|
||||||
|
if (!data) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setUser(data);
|
setUser(data);
|
||||||
navigate("/");
|
navigate("/");
|
||||||
})
|
}, [csrfToken, navigate, setUser ]);
|
||||||
.catch((error) => {
|
|
||||||
console.error(`Error: `, error);
|
|
||||||
setError(`Error authenticating.`);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ThemeProvider theme={theme}>
|
<ThemeProvider theme={theme}>
|
||||||
|
@ -11,6 +11,9 @@
|
|||||||
"indent": [
|
"indent": [
|
||||||
"error",
|
"error",
|
||||||
2
|
2
|
||||||
]
|
],
|
||||||
|
"quotes": [ 2, "single", {
|
||||||
|
"allowTemplateLiterals": true
|
||||||
|
} ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,12 +8,16 @@ 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'),
|
||||||
|
sqliteStoreFactory = require('express-session-sqlite').default,
|
||||||
basePath = require('./basepath'),
|
basePath = require('./basepath'),
|
||||||
cookieParser = require('cookie-parser'),
|
|
||||||
app = express(),
|
app = express(),
|
||||||
csrf = require('csurf'),
|
csrf = require('csurf'),
|
||||||
http = require('http'),
|
http = require('http'),
|
||||||
{ goodTimesDB } = require('./db.js');
|
methodOverride = require('method-override'),
|
||||||
|
cookieParser = require('cookie-parser'),
|
||||||
|
{ goodTimesDB } = require('./db.js'),
|
||||||
|
sqlite3 = require('sqlite3'),
|
||||||
|
SqliteStore = sqliteStoreFactory(session);
|
||||||
|
|
||||||
require('./console-line.js'); /* Monkey-patch console.log with line numbers */
|
require('./console-line.js'); /* Monkey-patch console.log with line numbers */
|
||||||
|
|
||||||
@ -21,12 +25,27 @@ require('./console-line.js'); /* Monkey-patch console.log with line numbers */
|
|||||||
* set in the headers */
|
* set in the headers */
|
||||||
app.set('trust proxy', true);
|
app.set('trust proxy', true);
|
||||||
app.use(session({
|
app.use(session({
|
||||||
secret: 'm@g1x!',
|
secret: 'm@g1x!c00k13$',
|
||||||
resave: false,
|
maxAge: 14 * 24 * 60 * 60 * 1000, /* 2 weeks */
|
||||||
|
resave: true,
|
||||||
saveUninitialized: false,
|
saveUninitialized: false,
|
||||||
cookie: { secure: true }
|
cookie: { secure: true },
|
||||||
|
store: new SqliteStore({
|
||||||
|
driver: sqlite3.Database,
|
||||||
|
path: config.get('sessions.db'),
|
||||||
|
ttl: 5000,
|
||||||
|
cleanupInterval: 300000
|
||||||
|
}),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
app.use(bodyParser.urlencoded({ extended: false }));
|
app.use(bodyParser.urlencoded({ extended: false }));
|
||||||
|
app.use((req, res, next) => {
|
||||||
|
console.log('CSRF debug: ', {
|
||||||
|
token: req.header('CSRF-Token'),
|
||||||
|
method: req.method
|
||||||
|
});
|
||||||
|
next();
|
||||||
|
});
|
||||||
app.use(cookieParser());
|
app.use(cookieParser());
|
||||||
app.use(csrf({
|
app.use(csrf({
|
||||||
cookie: true
|
cookie: true
|
||||||
@ -35,22 +54,30 @@ app.use(bodyParser.json());
|
|||||||
|
|
||||||
//const ws = require('express-ws')(app, server);
|
//const ws = require('express-ws')(app, server);
|
||||||
|
|
||||||
app.use(function (err, req, res) {
|
|
||||||
console.error(err.message);
|
|
||||||
res.status(err.status || 500).json({
|
|
||||||
message: err.message,
|
|
||||||
error: {}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
/* Initialize the data base, configure routes, and open server */
|
/* Initialize the data base, configure routes, and open server */
|
||||||
goodTimesDB.init().then((db) => {
|
goodTimesDB.init().then((db) => {
|
||||||
console.log('DB connected. Configuring routes.');
|
console.log('DB connected. Configuring routes.');
|
||||||
|
|
||||||
app.locals.db = db;
|
app.locals.db = db;
|
||||||
app.set('basePath', basePath);
|
app.set('basePath', basePath);
|
||||||
|
|
||||||
app.use(`${basePath}api/v1/groups`, require('./routes/groups'));
|
app.use(`${basePath}api/v1/groups`, require('./routes/groups'));
|
||||||
app.use(`${basePath}api/v1/users`, require('./routes/users'));
|
app.use(`${basePath}api/v1/users`, require('./routes/users'));
|
||||||
|
|
||||||
|
/* Error handler and catch for 404 */
|
||||||
|
app.use(methodOverride());
|
||||||
|
app.use((err, req, res, next) => {
|
||||||
|
console.log('CSRF debug: ', {
|
||||||
|
token: req.header('CSRF-Token'),
|
||||||
|
csrf: req.csrfToken(),
|
||||||
|
method: req.method
|
||||||
|
});
|
||||||
|
console.error(err);
|
||||||
|
res.status(err.status || 500).json({
|
||||||
|
message: err.message,
|
||||||
|
error: {}
|
||||||
|
});
|
||||||
|
});
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
const server = http.createServer(app),
|
const server = http.createServer(app),
|
||||||
serverConfig = config.get('server');
|
serverConfig = config.get('server');
|
||||||
|
126
server/package-lock.json
generated
126
server/package-lock.json
generated
@ -18,9 +18,11 @@
|
|||||||
"csurf": "^1.11.0",
|
"csurf": "^1.11.0",
|
||||||
"express": "^4.17.3",
|
"express": "^4.17.3",
|
||||||
"express-session": "^1.17.1",
|
"express-session": "^1.17.1",
|
||||||
|
"express-session-sqlite": "^2.0.10",
|
||||||
"express-ws": "^5.0.2",
|
"express-ws": "^5.0.2",
|
||||||
"fast-deep-equal": "^3.1.3",
|
"fast-deep-equal": "^3.1.3",
|
||||||
"handlebars": "^4.7.7",
|
"handlebars": "^4.7.7",
|
||||||
|
"method-override": "^3.0.0",
|
||||||
"moment": "^2.24.0",
|
"moment": "^2.24.0",
|
||||||
"morgan": "^1.9.1",
|
"morgan": "^1.9.1",
|
||||||
"node-fetch": "^2.6.0",
|
"node-fetch": "^2.6.0",
|
||||||
@ -31,7 +33,7 @@
|
|||||||
"pluralize": "^8.0.0",
|
"pluralize": "^8.0.0",
|
||||||
"random-words": "^1.1.2",
|
"random-words": "^1.1.2",
|
||||||
"sequelize": "^5.21.6",
|
"sequelize": "^5.21.6",
|
||||||
"sqlite3": "^4.1.1",
|
"sqlite3": "^4.2.0",
|
||||||
"typeface-roboto": "0.0.75",
|
"typeface-roboto": "0.0.75",
|
||||||
"ws": "^8.5.0"
|
"ws": "^8.5.0"
|
||||||
},
|
},
|
||||||
@ -1135,6 +1137,37 @@
|
|||||||
"node": ">= 0.8.0"
|
"node": ">= 0.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/express-session-sqlite": {
|
||||||
|
"version": "2.0.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/express-session-sqlite/-/express-session-sqlite-2.0.10.tgz",
|
||||||
|
"integrity": "sha512-VBNvSlVUqAHHYU4Cca4Q1waJe1CeW2VFlW/PDtGY/cyJUV5Zy+qkN4A18SNvNR//SDZO+Pc3qd/AgVVQw2/W2Q==",
|
||||||
|
"dependencies": {
|
||||||
|
"debug": "^4.2.0",
|
||||||
|
"sql-template-strings": "^2.2.2",
|
||||||
|
"sqlite": "^4.0.14"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/express-session-sqlite/node_modules/debug": {
|
||||||
|
"version": "4.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||||
|
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"ms": "2.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"supports-color": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/express-session-sqlite/node_modules/ms": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||||
|
},
|
||||||
"node_modules/express-ws": {
|
"node_modules/express-ws": {
|
||||||
"version": "5.0.2",
|
"version": "5.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/express-ws/-/express-ws-5.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/express-ws/-/express-ws-5.0.2.tgz",
|
||||||
@ -1990,6 +2023,28 @@
|
|||||||
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
|
||||||
"integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
|
"integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
|
||||||
},
|
},
|
||||||
|
"node_modules/method-override": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/method-override/-/method-override-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-IJ2NNN/mSl9w3kzWB92rcdHpz+HjkxhDJWNDBqSlas+zQdP8wBiJzITPg08M/k2uVvMow7Sk41atndNtt/PHSA==",
|
||||||
|
"dependencies": {
|
||||||
|
"debug": "3.1.0",
|
||||||
|
"methods": "~1.1.2",
|
||||||
|
"parseurl": "~1.3.2",
|
||||||
|
"vary": "~1.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/method-override/node_modules/debug": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
|
||||||
|
"dependencies": {
|
||||||
|
"ms": "2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/methods": {
|
"node_modules/methods": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
|
||||||
@ -3003,6 +3058,19 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/sql-template-strings": {
|
||||||
|
"version": "2.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/sql-template-strings/-/sql-template-strings-2.2.2.tgz",
|
||||||
|
"integrity": "sha1-PxFQiiWt384hejBCqdMAwxk7lv8=",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/sqlite": {
|
||||||
|
"version": "4.0.25",
|
||||||
|
"resolved": "https://registry.npmjs.org/sqlite/-/sqlite-4.0.25.tgz",
|
||||||
|
"integrity": "sha512-gqCEcLF8FOTeW/na3SRYWLQkw2jZXgVj1DdgRJbm0jvrhnUgBIuNDUUm649AnBNDNHhI5XskwT8dvc8vearRLQ=="
|
||||||
|
},
|
||||||
"node_modules/sqlite3": {
|
"node_modules/sqlite3": {
|
||||||
"version": "4.2.0",
|
"version": "4.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.2.0.tgz",
|
||||||
@ -4330,6 +4398,31 @@
|
|||||||
"uid-safe": "~2.1.5"
|
"uid-safe": "~2.1.5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"express-session-sqlite": {
|
||||||
|
"version": "2.0.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/express-session-sqlite/-/express-session-sqlite-2.0.10.tgz",
|
||||||
|
"integrity": "sha512-VBNvSlVUqAHHYU4Cca4Q1waJe1CeW2VFlW/PDtGY/cyJUV5Zy+qkN4A18SNvNR//SDZO+Pc3qd/AgVVQw2/W2Q==",
|
||||||
|
"requires": {
|
||||||
|
"debug": "^4.2.0",
|
||||||
|
"sql-template-strings": "^2.2.2",
|
||||||
|
"sqlite": "^4.0.14"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"debug": {
|
||||||
|
"version": "4.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||||
|
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||||
|
"requires": {
|
||||||
|
"ms": "2.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ms": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"express-ws": {
|
"express-ws": {
|
||||||
"version": "5.0.2",
|
"version": "5.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/express-ws/-/express-ws-5.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/express-ws/-/express-ws-5.0.2.tgz",
|
||||||
@ -4939,6 +5032,27 @@
|
|||||||
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
|
||||||
"integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
|
"integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
|
||||||
},
|
},
|
||||||
|
"method-override": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/method-override/-/method-override-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-IJ2NNN/mSl9w3kzWB92rcdHpz+HjkxhDJWNDBqSlas+zQdP8wBiJzITPg08M/k2uVvMow7Sk41atndNtt/PHSA==",
|
||||||
|
"requires": {
|
||||||
|
"debug": "3.1.0",
|
||||||
|
"methods": "~1.1.2",
|
||||||
|
"parseurl": "~1.3.2",
|
||||||
|
"vary": "~1.1.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"debug": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
|
||||||
|
"requires": {
|
||||||
|
"ms": "2.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"methods": {
|
"methods": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
|
||||||
@ -5728,6 +5842,16 @@
|
|||||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
|
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
|
||||||
},
|
},
|
||||||
|
"sql-template-strings": {
|
||||||
|
"version": "2.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/sql-template-strings/-/sql-template-strings-2.2.2.tgz",
|
||||||
|
"integrity": "sha1-PxFQiiWt384hejBCqdMAwxk7lv8="
|
||||||
|
},
|
||||||
|
"sqlite": {
|
||||||
|
"version": "4.0.25",
|
||||||
|
"resolved": "https://registry.npmjs.org/sqlite/-/sqlite-4.0.25.tgz",
|
||||||
|
"integrity": "sha512-gqCEcLF8FOTeW/na3SRYWLQkw2jZXgVj1DdgRJbm0jvrhnUgBIuNDUUm649AnBNDNHhI5XskwT8dvc8vearRLQ=="
|
||||||
|
},
|
||||||
"sqlite3": {
|
"sqlite3": {
|
||||||
"version": "4.2.0",
|
"version": "4.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.2.0.tgz",
|
||||||
|
@ -18,9 +18,11 @@
|
|||||||
"csurf": "^1.11.0",
|
"csurf": "^1.11.0",
|
||||||
"express": "^4.17.3",
|
"express": "^4.17.3",
|
||||||
"express-session": "^1.17.1",
|
"express-session": "^1.17.1",
|
||||||
|
"express-session-sqlite": "^2.0.10",
|
||||||
"express-ws": "^5.0.2",
|
"express-ws": "^5.0.2",
|
||||||
"fast-deep-equal": "^3.1.3",
|
"fast-deep-equal": "^3.1.3",
|
||||||
"handlebars": "^4.7.7",
|
"handlebars": "^4.7.7",
|
||||||
|
"method-override": "^3.0.0",
|
||||||
"moment": "^2.24.0",
|
"moment": "^2.24.0",
|
||||||
"morgan": "^1.9.1",
|
"morgan": "^1.9.1",
|
||||||
"node-fetch": "^2.6.0",
|
"node-fetch": "^2.6.0",
|
||||||
@ -31,7 +33,7 @@
|
|||||||
"pluralize": "^8.0.0",
|
"pluralize": "^8.0.0",
|
||||||
"random-words": "^1.1.2",
|
"random-words": "^1.1.2",
|
||||||
"sequelize": "^5.21.6",
|
"sequelize": "^5.21.6",
|
||||||
"sqlite3": "^4.1.1",
|
"sqlite3": "^4.2.0",
|
||||||
"typeface-roboto": "0.0.75",
|
"typeface-roboto": "0.0.75",
|
||||||
"ws": "^8.5.0"
|
"ws": "^8.5.0"
|
||||||
},
|
},
|
||||||
|
@ -2,22 +2,6 @@ const express = require('express'),
|
|||||||
router = express.Router(),
|
router = express.Router(),
|
||||||
crypto = require('crypto');
|
crypto = require('crypto');
|
||||||
|
|
||||||
/* Simple NO-OP to set session cookie so user-id can use it as the
|
|
||||||
* index */
|
|
||||||
router.get('/', (req, res/*, next*/) => {
|
|
||||||
let userId;
|
|
||||||
if (!req.cookies.user) {
|
|
||||||
userId = crypto.randomBytes(16).toString('hex');
|
|
||||||
res.cookie('user', userId);
|
|
||||||
} else {
|
|
||||||
userId = req.cookies.user;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`[${userId.substring(0, 8)}]: Browser hand-shake achieved.`);
|
|
||||||
|
|
||||||
return res.status(200).send({ user: userId });
|
|
||||||
});
|
|
||||||
|
|
||||||
router.get('/', async (req, res/*, next*/) => {
|
router.get('/', async (req, res/*, next*/) => {
|
||||||
console.log('GET /groups/', req.session.userId);
|
console.log('GET /groups/', req.session.userId);
|
||||||
return res.status(200).send(
|
return res.status(200).send(
|
||||||
|
@ -8,17 +8,18 @@ const express = require('express'),
|
|||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const autoAuthenticate = 1;
|
const autoAuthenticate = 1;
|
||||||
|
|
||||||
router.get('/', function(req, res/*, next*/) {
|
router.get('/', (req, res/*, next*/) => {
|
||||||
console.log('GET /users/');
|
console.log('GET /users/');
|
||||||
|
|
||||||
return getSessionUser(req).then((user) => {
|
return getSessionUser(req).then((user) => {
|
||||||
|
if (typeof user === 'string') {
|
||||||
|
return res.status(403).send({ message: user });
|
||||||
|
}
|
||||||
return res.status(200).send(user);
|
return res.status(200).send(user);
|
||||||
}).catch((error) => {
|
|
||||||
console.log('User not logged in: ' + error);
|
|
||||||
return res.status(200).send({});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
router.put('/password', function(req, res) {
|
router.put('/password', async (req, res) => {
|
||||||
console.log('/users/password');
|
console.log('/users/password');
|
||||||
const db = req.app.locals.db;
|
const db = req.app.locals.db;
|
||||||
|
|
||||||
@ -28,14 +29,19 @@ 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) {
|
const user = await getSessionUser(req);
|
||||||
|
if (typeof user === 'string') {
|
||||||
|
return res.status(403).send({ message: user });
|
||||||
|
}
|
||||||
return db.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: {
|
||||||
@ -49,7 +55,6 @@ router.put('/password', function(req, res) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return user;
|
return user;
|
||||||
});
|
|
||||||
}).then(function(user) {
|
}).then(function(user) {
|
||||||
if (!user) {
|
if (!user) {
|
||||||
console.log('Invalid password');
|
console.log('Invalid password');
|
||||||
@ -74,8 +79,9 @@ router.put('/password', function(req, res) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.get('/csrf', (req, res) => {
|
router.get('/csrf', (req, res) => {
|
||||||
console.log('/users/csrf');
|
const token = req.csrfToken();
|
||||||
res.json({ csrfToken: req.csrfToken() });
|
console.log('/users/csrf', token);
|
||||||
|
res.json({ csrfToken: token });
|
||||||
});
|
});
|
||||||
|
|
||||||
router.post('/signup', function(req, res) {
|
router.post('/signup', function(req, res) {
|
||||||
@ -141,6 +147,9 @@ router.post('/signup', function(req, res) {
|
|||||||
req.session.userId = metadata.lastID;
|
req.session.userId = metadata.lastID;
|
||||||
}
|
}
|
||||||
return getSessionUser(req).then(function(user) {
|
return getSessionUser(req).then(function(user) {
|
||||||
|
if (typeof user === 'string') {
|
||||||
|
return res.status(403).send({ message: user });
|
||||||
|
}
|
||||||
res.status(200).send(user);
|
res.status(200).send(user);
|
||||||
user.id = req.session.userId;
|
user.id = req.session.userId;
|
||||||
return sendVerifyMail(db, req, user);
|
return sendVerifyMail(db, req, user);
|
||||||
@ -151,44 +160,40 @@ router.post('/signup', function(req, res) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const getSessionUser = function(req) {
|
const getSessionUser = async (req) => {
|
||||||
const db = req.app.locals.db;
|
const db = req.app.locals.db;
|
||||||
return Promise.resolve().then(function() {
|
|
||||||
|
console.log(req.session);
|
||||||
if (!req.session || !req.session.userId) {
|
if (!req.session || !req.session.userId) {
|
||||||
throw 'Unauthorized. You must be logged in.';
|
return '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 db.sequelize.query(query, {
|
const results = await db.sequelize.query(query, {
|
||||||
replacements: {
|
replacements: {
|
||||||
id: req.session.userId
|
id: req.session.userId
|
||||||
},
|
},
|
||||||
type: db.Sequelize.QueryTypes.SELECT,
|
type: db.Sequelize.QueryTypes.SELECT,
|
||||||
raw: true
|
raw: true
|
||||||
}).then(function(results) {
|
});
|
||||||
|
|
||||||
if (results.length != 1) {
|
if (results.length != 1) {
|
||||||
throw 'Invalid account.';
|
return 'Invalid account.';
|
||||||
}
|
}
|
||||||
|
|
||||||
let user = results[0];
|
const 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;
|
} else if (!user.authenticated) {
|
||||||
}
|
|
||||||
|
|
||||||
if (!user.authenticated) {
|
|
||||||
user.restriction = user.restriction || 'Accout not authorized.';
|
user.restriction = user.restriction || 'Accout not authorized.';
|
||||||
return user;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return user;
|
/* Strip out any fields that shouldn't be there.
|
||||||
});
|
* The allowed fields are: */
|
||||||
}).then(function(user) {
|
const allowed = [
|
||||||
/* Strip out any fields that shouldn't be there. The allowed fields are: */
|
|
||||||
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) {
|
||||||
@ -197,7 +202,6 @@ const getSessionUser = function(req) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return user;
|
return user;
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
router.post('/verify-email', async (req, res) => {
|
router.post('/verify-email', async (req, res) => {
|
||||||
@ -254,13 +258,16 @@ router.post('/verify-email', async (req, res) => {
|
|||||||
req.session.userId = user.id;
|
req.session.userId = user.id;
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
return getSessionUser(req).then((user) => {
|
return getSessionUser(req).then((user) => {
|
||||||
|
if (typeof user === 'string') {
|
||||||
|
return res.status(403).send({ message: user });
|
||||||
|
}
|
||||||
return res.status(200).send(user);
|
return res.status(200).send(user);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
router.post('/signin', function(req, res) {
|
router.post('/signin', (req, res) => {
|
||||||
console.log('/users/signin');
|
console.log('/users/signin');
|
||||||
const db = req.app.locals.db;
|
const db = req.app.locals.db;
|
||||||
|
|
||||||
@ -310,12 +317,12 @@ router.post('/signin', function(req, res) {
|
|||||||
console.log(message);
|
console.log(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
return getSessionUser(req).then(function(user) {
|
return getSessionUser(req).then((user) => {
|
||||||
|
if (typeof user === 'string') {
|
||||||
|
return res.status(403).send({ message: user });
|
||||||
|
}
|
||||||
return res.status(200).send(user);
|
return res.status(200).send(user);
|
||||||
});
|
});
|
||||||
}).catch(function(error) {
|
|
||||||
console.log(error);
|
|
||||||
return res.status(403).send(error);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user