Compare commits

..

8 Commits

Author SHA1 Message Date
Kayne Ruse 56fc50d3b9 Bumped version number 2023-01-04 12:57:53 +00:00
Kayne Ruse d29e3397a6 Switched to a slim docker distro 2023-01-04 23:52:11 +11:00
Kayne Ruse 335c7008aa Bumped version number 2022-12-31 19:19:38 +00:00
Kayne Ruse e89b0645ca Fixed URLSearchParams 2022-12-04 12:08:12 +00:00
Kayne Ruse 36e79a513f Fixed reset page 2022-12-04 11:48:23 +00:00
Kayne Ruse 6ef0affcf6 Fixed useEffect() usage 2022-12-01 12:48:04 +00:00
Kayne Ruse cb0c1284bf You're now kicked out to the root page when the refresh token expires 2022-12-01 12:05:43 +00:00
Kayne Ruse 5cf4b66894 Fixed redirect issue 2022-11-29 04:53:29 +00:00
9 changed files with 394 additions and 410 deletions
+6 -3
View File
@@ -1,5 +1,5 @@
import React, { useContext, useRef } from 'react'; import React, { useContext, useRef } from 'react';
import { Link, Navigate } from 'react-router-dom'; import { Link, useNavigate } from 'react-router-dom';
import ApplyToBody from '../utilities/apply-to-body'; import ApplyToBody from '../utilities/apply-to-body';
@@ -9,12 +9,15 @@ import { TokenContext } from '../utilities/token-provider';
const validateEmail = require('../../../common/utilities/validate-email'); const validateEmail = require('../../../common/utilities/validate-email');
const Recover = props => { const Recover = props => {
//history
const navigate = useNavigate();
//context //context
const authTokens = useContext(TokenContext); const authTokens = useContext(TokenContext);
//misplaced? //misplaced?
if (authTokens.accessToken) { if (authTokens.accessToken) {
return <Navigate to='/' />; navigate("/");
} }
//refs //refs
@@ -39,7 +42,7 @@ const Recover = props => {
//redirect //redirect
if (redirect) { if (redirect) {
props.history.push('/'); navigate("/");
} }
} }
}> }>
+13 -11
View File
@@ -1,21 +1,23 @@
import React, { useContext, useRef } from 'react'; import React, { useContext, useRef } from 'react';
import { Link, Navigate } from 'react-router-dom'; import { Link, useNavigate, useSearchParams } from 'react-router-dom';
import queryString from 'query-string';
import ApplyToBody from '../utilities/apply-to-body'; import ApplyToBody from '../utilities/apply-to-body';
import { TokenContext } from '../utilities/token-provider'; import { TokenContext } from '../utilities/token-provider';
const Reset = props => { const Reset = props => {
//params
const [params, setParams] = useSearchParams(); //the URLSearchParams API
//history
const navigate = useNavigate();
//context //context
const authTokens = useContext(TokenContext); const authTokens = useContext(TokenContext);
//query
const query = queryString.parse(props.location.search);
//misplaced? //misplaced?
if (authTokens.accessToken || !query.email || !query.token) { if (authTokens.accessToken || !params.has('email') || !params.has('token')) {
return <Navigate to='/' />; navigate("/");
} }
//refs //refs
@@ -31,7 +33,7 @@ const Reset = props => {
<h1 className='text centered'>Reset Password</h1> <h1 className='text centered'>Reset Password</h1>
<form className='constrained' onSubmit={async evt => { <form className='constrained' onSubmit={async evt => {
evt.preventDefault(); evt.preventDefault();
const [err, redirect] = await update(passwordRef.current.value, retypeRef.current.value, query); const [err, redirect] = await update(passwordRef.current.value, retypeRef.current.value, params);
if (err) { if (err) {
alert(err); alert(err);
@@ -42,7 +44,7 @@ const Reset = props => {
//redirect //redirect
if (redirect) { if (redirect) {
props.history.push('/'); navigate("/");
} }
}}> }}>
<input type='password' name='password' placeholder='New Password' ref={passwordRef} /> <input type='password' name='password' placeholder='New Password' ref={passwordRef} />
@@ -56,7 +58,7 @@ const Reset = props => {
); );
}; };
const update = async (password, retype, query) => { const update = async (password, retype, params) => {
if (password != retype) { if (password != retype) {
return ['Passwords do not match']; return ['Passwords do not match'];
} }
@@ -65,7 +67,7 @@ const update = async (password, retype, query) => {
return ['Password is too short']; return ['Password is too short'];
} }
const result = await fetch(`${process.env.AUTH_URI}/auth/reset?email=${query.email}&token=${query.token}`, { const result = await fetch(`${process.env.AUTH_URI}/auth/reset?email=${params.get('email')}&token=${params.get('token')}`, {
method: 'PATCH', method: 'PATCH',
headers: { headers: {
'Content-Type': 'application/json' 'Content-Type': 'application/json'
+6 -3
View File
@@ -1,5 +1,5 @@
import React, { useContext, useRef } from 'react'; import React, { useContext, useRef } from 'react';
import { Link, Navigate } from 'react-router-dom'; import { Link, useNavigate } from 'react-router-dom';
import ApplyToBody from '../utilities/apply-to-body'; import ApplyToBody from '../utilities/apply-to-body';
@@ -10,12 +10,15 @@ const validateEmail = require('../../../common/utilities/validate-email');
const validateUsername = require('../../../common/utilities/validate-username'); const validateUsername = require('../../../common/utilities/validate-username');
const Signup = props => { const Signup = props => {
//history
const navigate = useNavigate();
//context //context
const authTokens = useContext(TokenContext); const authTokens = useContext(TokenContext);
//misplaced? //misplaced?
if (authTokens.accessToken) { if (authTokens.accessToken) {
return <Navigate to='/' />; navigate("/");
} }
//refs //refs
@@ -44,7 +47,7 @@ const Signup = props => {
//redirect //redirect
if (redirect) { if (redirect) {
props.history.push('/'); navigate("/");
} }
} }
}> }>
@@ -7,16 +7,13 @@ const ChatReports = props => {
const authTokens = useContext(TokenContext); const authTokens = useContext(TokenContext);
useEffect(async () => { useEffect(() => {
const result = await authTokens.tokenFetch(`${process.env.CHAT_URI}/admin/reports`); authTokens.tokenFetch(`${process.env.CHAT_URI}/admin/reports`)
.then(res => res.json())
if (!result.ok) { .then(json => {
const err = `${result.status}: ${await result.text()}`; setReports(json);
console.log(err); })
alert(err); ;
} else {
setReports(await result.json());
}
}, []); }, []);
return ( return (
@@ -17,16 +17,13 @@ const NewsEditor = props => {
const [index, setIndex] = useState(null); const [index, setIndex] = useState(null);
//run once //run once
useEffect(async () => { useEffect(() => {
const result = await fetch(`${process.env.NEWS_URI}/news/metadata?limit=999`); fetch(`${process.env.NEWS_URI}/news/metadata?limit=999`)
.then(res => res.json())
if (!result.ok) { .then(json => {
const err = `${result.status}: ${await result.text()}`; setArticles(json)
console.log(err); })
alert(err); ;
} else {
setArticles(await result.json());
}
}, []); }, []);
return ( return (
+12
View File
@@ -9,6 +9,12 @@ const TokenProvider = props => {
//state to be used //state to be used
const [accessToken, setAccessToken] = useState(''); const [accessToken, setAccessToken] = useState('');
//force a logout under certain conditions
const forceLogout = () => {
localStorage.removeItem("accessToken");
setAccessToken("");
};
//make the access token persist between reloads //make the access token persist between reloads
useEffect(() => { useEffect(() => {
setAccessToken(localStorage.getItem("accessToken") || ''); setAccessToken(localStorage.getItem("accessToken") || '');
@@ -47,6 +53,9 @@ const TokenProvider = props => {
//any errors, throw them //any errors, throw them
if (!response.ok) { if (!response.ok) {
if (response.status == 403) {
forceLogout();
}
throw `${response.status}: ${await response.text()}`; throw `${response.status}: ${await response.text()}`;
} }
@@ -82,6 +91,9 @@ const TokenProvider = props => {
//any errors, throw them //any errors, throw them
if (!response.ok) { if (!response.ok) {
if (response.status == 403) {
forceLogout();
}
throw `${response.status}: ${await response.text()}`; throw `${response.status}: ${await response.text()}`;
} }
+1 -1
View File
@@ -278,7 +278,7 @@ networks:
`; `;
const dockerfile = ` const dockerfile = `
FROM node:18 FROM node:18-bullseye-slim
WORKDIR "/app" WORKDIR "/app"
COPY . /app COPY . /app
RUN mkdir /app/public RUN mkdir /app/public
+335 -364
View File
File diff suppressed because it is too large Load Diff
+7 -8
View File
@@ -1,6 +1,6 @@
{ {
"name": "mern-template", "name": "mern-template",
"version": "1.3.3", "version": "1.4.1",
"description": "A website template using the MERN stack.", "description": "A website template using the MERN stack.",
"main": "server/server.js", "main": "server/server.js",
"scripts": { "scripts": {
@@ -27,28 +27,27 @@
}, },
"homepage": "https://github.com/KRGameStudios/MERN-template#readme", "homepage": "https://github.com/KRGameStudios/MERN-template#readme",
"dependencies": { "dependencies": {
"@babel/core": "^7.20.2", "@babel/core": "^7.20.5",
"@babel/preset-env": "^7.20.2", "@babel/preset-env": "^7.20.2",
"@babel/preset-react": "^7.18.6", "@babel/preset-react": "^7.18.6",
"babel-loader": "^8.3.0", "babel-loader": "^8.3.0",
"clean-webpack-plugin": "^4.0.0", "clean-webpack-plugin": "^4.0.0",
"compression-webpack-plugin": "^10.0.0", "compression-webpack-plugin": "^10.0.0",
"concurrently": "^7.5.0", "concurrently": "^7.6.0",
"css-loader": "^6.7.1", "css-loader": "^6.7.2",
"dateformat": "^5.0.3", "dateformat": "^5.0.3",
"dotenv": "^16.0.3", "dotenv": "^16.0.3",
"express": "^4.18.2", "express": "^4.18.2",
"html-webpack-plugin": "^5.5.0", "html-webpack-plugin": "^5.5.0",
"jwt-decode": "^3.1.2", "jwt-decode": "^3.1.2",
"mariadb": "^3.0.2", "mariadb": "^3.0.2",
"query-string": "^7.1.1",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-router": "^6.3.0", "react-router": "^6.3.0",
"react-router-dom": "^6.4.3", "react-router-dom": "^6.4.3",
"react-select": "^5.6.0", "react-select": "^5.6.1",
"sequelize": "^6.25.5", "sequelize": "^6.25.8",
"socket.io-client": "^4.5.3", "socket.io-client": "^4.5.4",
"style-loader": "^3.3.1", "style-loader": "^3.3.1",
"webpack": "^5.75.0", "webpack": "^5.75.0",
"webpack-bundle-analyzer": "^4.7.0", "webpack-bundle-analyzer": "^4.7.0",