1
0

Added location element

Fixed TTL in DB to match maxAge of session

Signed-off-by: James Ketrenos <james_eikona@ketrenos.com>
This commit is contained in:
James Ketrenos 2022-04-09 15:40:29 -07:00
parent d8b15e50af
commit cf83d2b95b
8 changed files with 132 additions and 51 deletions

3
.env
View File

@ -1,3 +1,6 @@
HTTPS=true
SSL_CRT_FILE=/etc/letsencrypt/live/ketrenos.com/cert.pem
SSL_KEY_FILE=/etc/letsencrypt/live/ketrenos.com/privkey.pem
REACT_APP_basePath="/"
NODE_CONFIG_ENV='production'
LOG_LINE=1

View File

@ -32,7 +32,7 @@
"web-vitals": "^2.1.2"
},
"scripts": {
"start": "HTTPS=true react-scripts start",
"start": "export $(cat ../.env | xargs) && react-scripts start",
"build": "export $(cat ../.env | xargs) && react-scripts build",
"test": "export $(cat ../.env | xargs) && react-scripts test",
"eject": "export $(cat ../.env | xargs) && react-scripts eject"

View File

@ -8,6 +8,7 @@ import {
import './Group.css';
import { GlobalContext } from "./GlobalContext.js";
import { base } from "./Common.js";
import { Location } from "./Location.js";
function Group() {
const { csrfToken, user, setUser } = useContext(GlobalContext);
@ -40,36 +41,7 @@ function Group() {
if (!data) {
return;
}
setLocations(data.map(location => {
const fields = Object.getOwnPropertyNames(location)
.map(field => <div key={field}
style={{
display: 'flex',
flexDirection: 'row',
alignItems: 'flex-start',
width: '100%'
}}>
<div style={{
display: 'flex',
alignSelf: 'flex-start',
fontWeight: 'bold',
minWidth: '8rem'
}}>{field}</div>
<div style={{
display: 'flex',
alignSelf: 'flex-start',
textAlign: 'left'
}}>
{location[field]}
</div>
</div>
);
return <div key={location.id} style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center'
}}>{ fields }</div>;
}));
setLocations(data);
};
effect();
}, [user, setGroup, groupId, csrfToken]);
@ -114,7 +86,8 @@ function Group() {
{ !error && <>
<div>Group: {groupId}</div>
<div>Locations</div>
{ locations }
{ locations.map(location =>
<Location location={location} key={location.id}/>) }
</> }
</GlobalContext.Provider>
</Paper>

4
client/src/Location.css Normal file
View File

@ -0,0 +1,4 @@
.Location {
text-align: center;
}

94
client/src/Location.js Normal file
View File

@ -0,0 +1,94 @@
import React, { useState, useEffect, useContext } from "react";
import Paper from '@mui/material/Paper';
import {
useParams,
useNavigate
} from "react-router-dom";
import './Location.css';
import { GlobalContext } from "./GlobalContext.js";
import { base } from "./Common.js";
function Location(props) {
const propLocation = props.location;
const { csrfToken } = useContext(GlobalContext);
const [ location, setLocation ] = useState(
typeof propLocation === 'object' ? propLocation : undefined);
const locationId =
typeof propLocation === 'number' ? propLocation : undefined;
const [ error, setError ] = useState(null);
useEffect(() => {
if (!csrfToken && (location || !locationId)) {
return;
}
const effect = async () => {
const res = await window.fetch(
`${base}/api/v1/locations/${locationId}`, {
method: 'GET',
cache: 'no-cache',
credentials: 'same-origin',
headers: {
'Content-Type': 'application/json',
'CSRF-Token': csrfToken
}
});
const data = await res.json();
if (res.status >= 400) {
setError(data.message ? data.message : res.statusText);
return;
}
if (!data) {
return;
}
setLocation(data);
}
effect();
}, [locationId, csrfToken, location]);
const createLocation = (location) => {
const fields = Object.getOwnPropertyNames(location)
.map(field => <div key={field}
style={{
display: 'flex',
flexDirection: 'row',
alignItems: 'flex-start',
width: '100%'
}}>
<div style={{
display: 'flex',
alignSelf: 'flex-start',
fontWeight: 'bold',
minWidth: '8rem'
}}>{field}</div>
<div style={{
display: 'flex',
alignSelf: 'flex-start',
textAlign: 'left'
}}>
{location[field]}
</div>
</div>
);
return <div key={location.id} style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center'
}}>{fields}</div>;
};
return (
<Paper className="Location" style={{
display: 'flex',
flexDirection: 'column'
}}>
{ error && <div>{error}</div>}
{ !error && <>
{ createLocation(location) }
</> }
</Paper>
);
}
export { Location };

View File

@ -26,30 +26,40 @@ require('./console-line.js'); /* Monkey-patch console.log with line numbers */
app.set('trust proxy', true);
app.use(session({
secret: 'm@g1x!c00k13$',
maxAge: 14 * 24 * 60 * 60 * 1000, /* 2 weeks */
resave: true,
saveUninitialized: false,
maxAge: 30 * 24 * 60 * 60 * 1000, /* 1 month */
resave: false,
saveUninitialized: true,
cookie: { secure: true },
store: new SqliteStore({
driver: sqlite3.Database,
path: config.get('sessions.db'),
ttl: 5000,
ttl: 30 * 24 * 60 * 60 * 1000, /* 1 month */
cleanupInterval: 300000
}),
}));
app.use(bodyParser.urlencoded({ extended: false }));
app.use((req, res, next) => {
const csrfDebug = (req) => {
console.log('CSRF debug: ', {
method: req.method,
path: req.path,
token: req.header('CSRF-Token'),
method: req.method
csrf: req.csrfToken ? req.csrfToken() : 'CSRF not initialized',
user: (req.session && req.session.userId)
? req.session.userId
: 'Not logged in'
});
next();
});
};
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(csrf({
cookie: true
}));
app.use((req, res, next) => {
csrfDebug(req);
next();
});
app.use(bodyParser.json());
//const ws = require('express-ws')(app, server);
@ -84,11 +94,7 @@ goodTimesDB.init().then((db) => {
app.use(methodOverride());
// eslint-disable-next-line no-unused-vars
app.use((err, req, res, _next) => {
console.log('CSRF debug: ', {
token: req.header('CSRF-Token'),
csrf: req.csrfToken(),
method: req.method
});
csrfDebug(req);
console.error(err);
res.status(err.status || 500).json({
message: err.message,

View File

@ -5,7 +5,6 @@ const router = express.Router();
const originalLocations = require('../location-data.js');
router.put('/', (req, res) => {
const location = req.body;
location.id = originalLocations.length;
@ -20,9 +19,9 @@ router.get('/:locationId?', (req, res) => {
item => item.id === locationId
);
if (!location) {
res.status(404).send({ message: `Location ${locationId} not found.`});
return res.status(404).send({ message: `Location ${locationId} not found.`});
}
res.status(200).send([ location ]);
return res.status(200).send([ location ]);
}
return res.status(200).send(originalLocations);

View File

@ -77,6 +77,8 @@ router.put('/password', async (req, res) => {
router.get('/csrf', (req, res) => {
const token = req.csrfToken();
console.log(
`${req.method} ${req.path} - token`, token);
res.json({ csrfToken: token });
});