diff --git a/.env b/.env
index 8f5abf1..ceeb379 100644
--- a/.env
+++ b/.env
@@ -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
\ No newline at end of file
+LOG_LINE=1
diff --git a/client/package.json b/client/package.json
index 0e4c889..83435fe 100644
--- a/client/package.json
+++ b/client/package.json
@@ -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"
diff --git a/client/src/Group.js b/client/src/Group.js
index c94ebd1..b0b8db1 100644
--- a/client/src/Group.js
+++ b/client/src/Group.js
@@ -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 =>
-
{field}
-
- {location[field]}
-
-
- );
- return { fields }
;
- }));
+ setLocations(data);
};
effect();
}, [user, setGroup, groupId, csrfToken]);
@@ -114,7 +86,8 @@ function Group() {
{ !error && <>
Group: {groupId}
Locations
- { locations }
+ { locations.map(location =>
+ ) }
> }
diff --git a/client/src/Location.css b/client/src/Location.css
new file mode 100644
index 0000000..e8ac05b
--- /dev/null
+++ b/client/src/Location.css
@@ -0,0 +1,4 @@
+.Location {
+ text-align: center;
+}
+
diff --git a/client/src/Location.js b/client/src/Location.js
new file mode 100644
index 0000000..fbcdc45
--- /dev/null
+++ b/client/src/Location.js
@@ -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 =>
+
{field}
+
+ {location[field]}
+
+
+ );
+ return {fields}
;
+ };
+
+ return (
+
+ { error && {error}
}
+ { !error && <>
+ { createLocation(location) }
+ > }
+
+ );
+}
+
+export { Location };
diff --git a/server/app.js b/server/app.js
index 6341f53..227efdf 100755
--- a/server/app.js
+++ b/server/app.js
@@ -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: ', {
- token: req.header('CSRF-Token'),
- method: req.method
+ method: req.method,
+ path: req.path,
+ token: req.header('CSRF-Token'),
+ 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,
diff --git a/server/routes/locations.js b/server/routes/locations.js
index 147915a..208b218 100644
--- a/server/routes/locations.js
+++ b/server/routes/locations.js
@@ -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);
diff --git a/server/routes/users.js b/server/routes/users.js
index fa4aed2..64c6021 100755
--- a/server/routes/users.js
+++ b/server/routes/users.js
@@ -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 });
});