Compare commits

..

5 Commits

Author SHA1 Message Date
Kayne Ruse 8e81dccef6 Added cookies 2022-07-26 10:18:49 +01:00
Kayne Ruse adeb8c4267 Updated dependencies 2022-07-23 11:45:33 +01:00
Kayne Ruse eb6c3a40d7 Added hook array to auth config 2022-06-15 23:50:58 +01:00
Kayne Ruse 4d4a0b5401 Updated dependencies 2022-06-10 17:07:56 +01:00
Kayne Ruse 490860159e Cleaned up usage of fetch 2022-06-10 16:53:42 +01:00
13 changed files with 1700 additions and 3139 deletions
+1 -1
View File
@@ -39,7 +39,7 @@ docker-compose up --build
To set up this template in development mode: To set up this template in development mode:
1. Ensure mariadb is running in your development environment 1. Ensure mariadb is running in your development environment
2. Run `mariadb sql/create_database.sql` as the root user 2. Run `mariadb tools/create_database.sql` as the root user
3. Run `npm install` 3. Run `npm install`
4. Run `cp .envdev .env` and enter your details into the `.env` file 4. Run `cp .envdev .env` and enter your details into the `.env` file
5. Execute `npm run dev` 5. Execute `npm run dev`
+1 -3
View File
@@ -23,9 +23,7 @@ const Account = props => {
//grab the user's info //grab the user's info
useEffect(() => { useEffect(() => {
authTokens.tokenFetch(`${process.env.AUTH_URI}/auth/account`, { authTokens.tokenFetch(`${process.env.AUTH_URI}/auth/account`)
method: 'GET'
})
.then(blob => blob.json()) .then(blob => blob.json())
.then(json => contactRef.current.checked = json.contact) .then(json => contactRef.current.checked = json.contact)
.catch(e => console.error(e)) .catch(e => console.error(e))
+7 -7
View File
@@ -31,15 +31,14 @@ const Login = props => {
async evt => { async evt => {
//on submit //on submit
evt.preventDefault(); evt.preventDefault();
const [err, newTokens] = await handleSubmit(emailRef.current.value, passwordRef.current.value); const [err, accessToken] = await handleSubmit(emailRef.current.value, passwordRef.current.value);
if (err) { if (err) {
alert(err); alert(err);
} }
//save auth tokens and redirect //save auth tokens and redirect
if (newTokens) { if (accessToken) {
authTokens.setAccessToken(newTokens.accessToken); authTokens.setAccessToken(accessToken);
authTokens.setRefreshToken(newTokens.refreshToken);
props.history.push('/'); props.history.push('/');
} }
@@ -77,7 +76,8 @@ const handleSubmit = async (email, password) => {
body: JSON.stringify({ body: JSON.stringify({
email, email,
password, password,
}) }),
credentials: 'include'
}); });
//handle errors //handle errors
@@ -88,8 +88,8 @@ const handleSubmit = async (email, password) => {
} }
//return the new auth tokens //return the new auth tokens
const newTokens = await result.json(); const accessToken = await result.text();
return [null, newTokens]; return [null, accessToken];
}; };
//returns an error message, or null on success //returns an error message, or null on success
@@ -51,13 +51,7 @@ const handleSubmit = async (password, authTokens) => {
//force a logout //force a logout
const result2 = await authTokens.tokenFetch(`${process.env.AUTH_URI}/auth/logout`, { const result2 = await authTokens.tokenFetch(`${process.env.AUTH_URI}/auth/logout`, {
method: 'DELETE', method: 'DELETE'
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
token: authTokens.refreshToken
})
}); });
if (!result2.ok) { if (!result2.ok) {
@@ -65,7 +59,6 @@ const handleSubmit = async (password, authTokens) => {
} }
authTokens.setAccessToken(''); authTokens.setAccessToken('');
authTokens.setRefreshToken('');
return [null]; return [null];
}; };
+1 -8
View File
@@ -12,13 +12,7 @@ const Logout = () => {
{ /* Logout logs you out of the server too */ } { /* Logout logs you out of the server too */ }
<Link to='/' onClick={async () => { <Link to='/' onClick={async () => {
const result = await authTokens.tokenFetch(`${process.env.AUTH_URI}/auth/logout`, { //NOTE: this gets overwritten as a bugfix const result = await authTokens.tokenFetch(`${process.env.AUTH_URI}/auth/logout`, { //NOTE: this gets overwritten as a bugfix
method: 'DELETE', method: 'DELETE'
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
token: authTokens.refreshToken
})
}); });
//any problems? //any problems?
@@ -26,7 +20,6 @@ const Logout = () => {
console.error(await result.text()); console.error(await result.text());
} else { } else {
authTokens.setAccessToken(''); authTokens.setAccessToken('');
authTokens.setRefreshToken('');
} }
}}>Logout</Link> }}>Logout</Link>
</> </>
@@ -18,12 +18,7 @@ const NewsEditor = props => {
//run once //run once
useEffect(async () => { useEffect(async () => {
const result = await fetch(`${process.env.NEWS_URI}/news/metadata?limit=999`, { const result = await fetch(`${process.env.NEWS_URI}/news/metadata?limit=999`);
method: 'GET',
headers: {
'Content-Type': 'application/json'
},
});
if (!result.ok) { if (!result.ok) {
const err = `${result.status}: ${await result.text()}`; const err = `${result.status}: ${await result.text()}`;
-4
View File
@@ -8,10 +8,6 @@ const NewsFeed = props => {
useEffect(() => { useEffect(() => {
//this... um... //this... um...
fetch(`${process.env.NEWS_URI}/news`, { fetch(`${process.env.NEWS_URI}/news`, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
},
signal: aborter.current.signal //oh dear signal: aborter.current.signal //oh dear
}) })
.then(blob => blob.json()) .then(blob => blob.json())
+6 -4
View File
@@ -1,16 +1,18 @@
import React from 'react'; import React from 'react';
import { Link } from 'react-router-dom';
const Static = props => { const Static = props => {
return ( return (
<> <div className='page central'>
<header> <header>
<h1 className='text centered'>Credits</h1> <h1 className='text centered'>Credits</h1>
</header> </header>
<h2>MERN-template</h2> <h2 className='text centered'>MERN-template</h2>
<p>The <a href='https://github.com/krgamestudios/MERN-template'>MERN-template</a> developed by Kayne Ruse, KR Game Studios</p> <p>The <a href='https://github.com/krgamestudios/MERN-template'>MERN-template</a> developed by Kayne Ruse, KR Game Studios</p>
</>
<Link className='text centered' to='/'>Return Home</Link>
</div>
); );
}; };
export default Static; export default Static;
+8 -4
View File
@@ -1,12 +1,16 @@
import React from 'react'; import React from 'react';
import { Link } from 'react-router-dom';
const Static = props => { const Static = props => {
return ( return (
<header> <div className='page central'>
<h1 className="text centered">Privacy Policy</h1> <header>
</header> <h1 className="text centered">Privacy Policy</h1>
<Link className='text centered' to='/'>Return Home</Link>
</header>
</div>
); );
}; };
export default Static; export default Static;
+9 -26
View File
@@ -8,19 +8,16 @@ export const TokenContext = createContext();
const TokenProvider = props => { const TokenProvider = props => {
//state to be used //state to be used
const [accessToken, setAccessToken] = useState(''); const [accessToken, setAccessToken] = useState('');
const [refreshToken, setRefreshToken] = useState('');
//make the access and refresh tokens persist between reloads //make the access token persist between reloads
useEffect(() => { useEffect(() => {
setAccessToken(localStorage.getItem("accessToken") || ''); setAccessToken(localStorage.getItem("accessToken") || '');
setRefreshToken(localStorage.getItem("refreshToken") || '');
}, []); }, []);
//update the stored copies //update the stored copies
useEffect(() => { useEffect(() => {
localStorage.setItem("accessToken", accessToken); localStorage.setItem("accessToken", accessToken);
localStorage.setItem("refreshToken", refreshToken); }, [accessToken]);
}, [accessToken, refreshToken]);
//wrap the default fetch function //wrap the default fetch function
const tokenFetch = async (url, options) => { const tokenFetch = async (url, options) => {
@@ -36,24 +33,16 @@ const TokenProvider = props => {
return fetch(url, { return fetch(url, {
method: 'DELETE', method: 'DELETE',
headers: { headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${bearer}` 'Authorization': `Bearer ${bearer}`
}, },
body: JSON.stringify({ credentials: 'include'
token: refreshToken
})
}); });
} }
//ping the auth server for a new token //ping the auth server for a new access token
const response = await fetch(`${process.env.AUTH_URI}/auth/token`, { const response = await fetch(`${process.env.AUTH_URI}/auth/token`, {
method: 'POST', method: 'POST',
headers: { credentials: 'include'
'Content-Type': 'application/json'
},
body: JSON.stringify({
token: refreshToken
})
}); });
//any errors, throw them //any errors, throw them
@@ -65,7 +54,6 @@ const TokenProvider = props => {
const newAuth = await response.json(); const newAuth = await response.json();
setAccessToken(newAuth.accessToken); setAccessToken(newAuth.accessToken);
setRefreshToken(newAuth.refreshToken);
bearer = newAuth.accessToken; bearer = newAuth.accessToken;
} }
@@ -75,7 +63,8 @@ const TokenProvider = props => {
headers: { headers: {
...(options || { headers: {} }).headers, ...(options || { headers: {} }).headers,
'Authorization': `Bearer ${bearer}` 'Authorization': `Bearer ${bearer}`
} },
credentials: 'include'
}); });
}; };
@@ -88,12 +77,7 @@ const TokenProvider = props => {
//ping the auth server for a new token //ping the auth server for a new token
const response = await fetch(`${process.env.AUTH_URI}/auth/token`, { const response = await fetch(`${process.env.AUTH_URI}/auth/token`, {
method: 'POST', method: 'POST',
headers: { credentials: 'include'
'Content-Type': 'application/json'
},
body: JSON.stringify({
token: refreshToken
})
}); });
//any errors, throw them //any errors, throw them
@@ -105,7 +89,6 @@ const TokenProvider = props => {
const newAuth = await response.json(); const newAuth = await response.json();
setAccessToken(newAuth.accessToken); setAccessToken(newAuth.accessToken);
setRefreshToken(newAuth.refreshToken);
//finally //finally
return cb(newAuth.accessToken); return cb(newAuth.accessToken);
@@ -115,7 +98,7 @@ const TokenProvider = props => {
}; };
return ( return (
<TokenContext.Provider value={{ accessToken, refreshToken, setAccessToken, setRefreshToken, tokenFetch, tokenCallback, getPayload: () => decode(accessToken) }}> <TokenContext.Provider value={{ accessToken, setAccessToken, tokenFetch, tokenCallback, getPayload: () => decode(accessToken) }}>
{props.children} {props.children}
</TokenContext.Provider> </TokenContext.Provider>
) )
+2 -2
View File
@@ -70,7 +70,7 @@ See https://github.com/krgamestudios/MERN-template/wiki for help.
//auth configuration //auth configuration
const authName = await question('Auth Name', 'auth'); const authName = await question('Auth Name', 'auth');
const authWebAddress = await question('Auth Web Address', `${authName}.${projectWebAddress}`); const authWebAddress = await question('Auth Web Address', `${authName}.${projectWebAddress}`);
const authPostValidationHook = await question('Auth Post Validation Hook', ''); const authPostValidationHookArray = await question('Auth Post Validation Hook Array', '');
const authResetAddress = await question('Auth Reset Addr', `${projectWebAddress}/reset`); const authResetAddress = await question('Auth Reset Addr', `${projectWebAddress}/reset`);
const authDBUser = await question('Auth DB Username', authName); const authDBUser = await question('Auth DB Username', authName);
const authDBPass = await question('Auth DB Password', 'charizard'); const authDBPass = await question('Auth DB Password', 'charizard');
@@ -189,7 +189,7 @@ services:
environment: environment:
- WEB_PROTOCOL=https - WEB_PROTOCOL=https
- WEB_ADDRESS=${authWebAddress} - WEB_ADDRESS=${authWebAddress}
- HOOK_POST_VALIDATION=${authPostValidationHook} - HOOK_POST_VALIDATION_ARRAY=${authPostValidationHookArray}
- WEB_RESET_ADDRESS=${authResetAddress} - WEB_RESET_ADDRESS=${authResetAddress}
- WEB_PORT=${authPort} - WEB_PORT=${authPort}
- DB_HOSTNAME=database - DB_HOSTNAME=database
+1662 -3065
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "mern-template", "name": "mern-template",
"version": "1.2.0", "version": "1.3.0",
"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": {