Stripped out a whole bunch of pages, read more

The purpose of this branch is to bring this project in line with the JWT
protcol that the microservice is using. For the time being, it's easier
to get a stripped-down and stable build and replace the lost parts, one-
by-one.
This commit is contained in:
2021-03-08 12:34:41 +11:00
parent e3e5af4af0
commit 7c09ac46da
46 changed files with 310 additions and 4150 deletions
-108
View File
@@ -1,108 +0,0 @@
import React, { useState, useEffect } from 'react';
const BannedEmails = props => {
const [data, setData] = useState(null);
let usernameElement, emailElement, expiryElement, reasonElement;
let unbanElement;
fetch('/api/admin/banned', { method: 'GET' })
.then(banned => banned.json())
.then(banned => !data ? setData(banned) : null)
.catch(e => console.error(e))
;
return (
<div>
<h2>Banned Accounts</h2>
<table>
<thead>
<tr>
<th>Username</th>
<th>Email</th>
<th>Privilege</th>
<th>Expiry</th>
<th>Reason</th>
</tr>
</thead>
<tbody>
{(data || []).map((entry, index) =>
<tr key={index}>
<td>{entry.username}</td>
<td>{entry.email}</td>
<td>{entry.privilege}</td>
<td>{entry.expiry ? (new Date(entry.expiry)).toISOString() : null}</td>
<td>{entry.reason}</td>
</tr>
)}
</tbody>
</table>
<h2>Ban</h2>
<form onSubmit={async e => { e.preventDefault(); await handleBan(usernameElement.value, emailElement.value, expiryElement.value, reasonElement.value); }}>
<div>
<label htmlFor='username'>Username: </label>
<input type='text' name='username' ref={e => usernameElement = e} />
</div>
<div>
<label htmlFor='email'>Email: </label>
<input type='email' name='email' ref={e => emailElement = e} />
</div>
<div>
<label htmlFor='expiry'>Expiry: </label>
<input type='date' name='expiry' ref={e => expiryElement = e} />
</div>
<div>
<label htmlFor='reason'>Reason: </label>
<textarea rows='4' cols='50' name='reason' ref={e => reasonElement = e} />
</div>
<button type='submit'>Drop The Banhammer</button>
</form>
<h2>Unban</h2>
<form onSubmit={async e => { e.preventDefault(); await handleUnban(unbanElement.value); }}>
<div>
<label htmlFor='entry'>Unban User: </label>
<input type='text' name='entry' ref={e => unbanElement = e} />
</div>
<button type='submit'>Release From Horny Jail</button>
</form>
</div>
);
};
const handleBan = async (username, email, expiry, reason) => {
username = username.trim();
email = email.trim();
reason = reason.trim();
//generate a new formdata payload
let formData = new FormData();
formData.append('username', username);
formData.append('email', email);
formData.append('expiry', expiry);
formData.append('reason', reason);
const result = await fetch('/api/admin/ban', { method: 'POST', body: formData });
alert(await result.text());
};
const handleUnban = async (entry) => {
entry = entry.trim();
let formData = new FormData();
formData.append('entry', entry);
const result = await fetch('/api/admin/unban', { method: 'POST', body: formData });
alert(await result.text());
};
export default BannedEmails;
-32
View File
@@ -1,32 +0,0 @@
import React from 'react';
import { useCookies } from 'react-cookie';
const Chat = props => {
requestPseudonym();
return (
<div className='chat'>
<p>Chat URI: {props.uri}</p>
<p>Chat Paragraph TODO</p>
</div>
);
};
const requestPseudonym = () => {
const [cookies, setCookie] = useCookies();
//if your username hasn't been reserved
if (!cookies['pseudonym']) {
fetch('/api/chat/reserve', { method: 'POST' })
.then(msg => msg.json())
.then(json => {
if (!json.ok) { //I don't like doing this
console.error(json.error);
}
})
.catch(e => console.error(e))
;
}
};
export default Chat;
@@ -1,51 +0,0 @@
import React, { useState } from 'react';
//DOCS: isolated the delete account button into it's own panel, so it can be easily moved as needed
const DeleteAccount = props => {
const [open, setOpen] = useState(false);
if (!open) {
return <button onClick={() => setOpen(true)} className={props.className}>Delete Account</button>
}
let passwordElement;
return (
<form className={props.className} onSubmit={async evt => {
evt.preventDefault();
const password = passwordElement.value;
passwordElement.value = '';
await handleSubmit(password);
}}>
<div>
<label htmlFor="password">Password:</label>
<input type="password" name="password" ref={e => passwordElement = e} />
</div>
<button type='submit'>Delete Account</button>
<button type='cancel' onClick={() => { passwordElement.value = ''; setOpen(false); }}>Cancel</button>
</form>
);
};
const handleSubmit = async (password) => {
//generate a new formdata payload
let formData = new FormData();
formData.append('password', password);
const result = await fetch('/api/accounts/deletion', { method: 'DELETE', body: formData });
if (!result.ok) {
alert(await result.text());
} else {
//force logout
fetch('/api/accounts/logout', { method: 'POST' })
.then(alert(await result.text()))
.then(() => window.location.reload(true)) //BUFGIX: force reload of the header element
.catch(e => console.error(e))
;
}
};
export default DeleteAccount;
+8 -16
View File
@@ -1,12 +1,12 @@
import React from 'react';
import { useCookies } from 'react-cookie';
import { Link } from 'react-router-dom';
const Visitor = () => {
return (
<div>
<a href='/signup'>Sign Up</a>
<Link to='/signup'>Sign Up</Link>
<em> - </em>
<a href='/login'>Log In</a>
<Link to='/login'>Log In</Link>
</div>
);
};
@@ -14,34 +14,26 @@ const Visitor = () => {
const Member = () => {
return (
<div>
<a href='/account'>Account</a>
<Link to='/account'>Account</Link>
<em> - </em>
<a href='/' onClick={logout}>Log out</a>
<Link to='/' onClick={logout}>Log out</Link>
</div>
);
};
const logout = async () => {
//TODO: update API
await fetch('/api/accounts/logout', { method: 'POST' })
.catch(e => console.error(e))
;
};
const Header = () => {
const [cookies, setCookie] = useCookies(['loggedin']);
let Options;
//check for logged in/out status
if (cookies['loggedin']) {
Options = Member;
} else {
Options = Visitor;
}
let Options = Visitor;
return (
<header>
<h1><a href='/'>MERN Template</a></h1>
<h1><Link to='/'>MERN Template</Link></h1>
<Options />
</header>
);
-116
View File
@@ -1,116 +0,0 @@
import React, { useState } from 'react';
import Select from 'react-dropdown-select';
//DOCS: props.uri is the address of a live news-server
//DOCS: props.newsKey is the key of the live news-server
const NewsEditor = props => {
let titleElement, authorElement, bodyElement;
const [articles, setArticles] = useState(null);
const [index, setIndex] = useState(null);
if (!articles) {
fetch(`${props.uri}/titles?limit=999`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
})
.then(a => {
if (!a.ok) {
throw `Network error ${a.status}: ${a.statusText} ${a.url}`;
}
return a.json();
})
.then(a => setArticles(a))
.catch(e => console.error(e))
;
}
return (
<div>
<h2 className='centered'>News Editor</h2>
<div>
<label htmlFor='article'>Article: </label>
<Select
options={(articles || []).map(article => { return { label: article.title, value: article.index }; })}
onChange={values => setIndex(fetchSelection(values[0].value, titleElement, authorElement, bodyElement, props.uri))}
/>
</div>
<form onSubmit={async e => {
e.preventDefault();
await handleSubmit(index, titleElement.value, authorElement.value, bodyElement.value, props.uri, props.newsKey);
titleElement.value = authorElement.value = bodyElement.value = '';
}}>
<div>
<label htmlFor='title'>Title: </label>
<input type='text' name='title' ref={ e => titleElement = e } />
</div>
<div>
<label htmlFor='author'>Author: </label>
<input type='text' name='author' ref={ e => authorElement = e } />
</div>
<div>
<label htmlFor='body'>Body: </label>
<textarea name='body' rows='10' cols='150' ref={ e => bodyElement = e } />
</div>
<button type='submit'>Update</button>
</form>
</div>
);
};
const fetchSelection = (index, titleElement, authorElement, bodyElement, uri) => {
fetch(`${uri}/archive/${index}`, {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
})
.then(blob => blob.json())
.then(article => {
titleElement.value = article.title;
authorElement.value = article.author;
bodyElement.value = article.body;
})
.catch(e => console.error(e))
;
return index; //this is admittedly odd
};
const handleSubmit = async (index, title, author, body, uri, newsKey) => {
title = title.trim();
author = author.trim();
body = body.trim();
uri = uri.trim();
newsKey = newsKey.trim();
//fetch POST json data
const raw = await fetch(
`${uri}/${index}`,
{
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
body: JSON.stringify({ title: title, author: author, body: body, key: newsKey })
}
);
if (raw.ok) {
const result = await raw.json();
if (result.ok) {
alert(`Updated article index ${index}`);
} else {
alert(result.error);
}
} else {
alert(raw.statusText);
}
};
export default NewsEditor;
+1 -6
View File
@@ -13,12 +13,7 @@ const NewsFeed = props => {
'Access-Control-Allow-Origin': '*'
},
})
.then(a => {
if (!a.ok) {
throw `Network error ${a.status}: ${a.statusText} ${a.url}`;
}
return a.json();
})
.then(blob => blob.json())
.then(a => setArticles(a))
.catch(e => console.error(e))
;
@@ -1,70 +0,0 @@
import React from 'react';
//DOCS: props.uri is the address of a live news-server
//DOCS: props.newsKey is the key of the live news-server
const NewsPublisher = props => {
let titleElement, authorElement, bodyElement;
return (
<div>
<h2 className='centered'>News Publisher</h2>
<form onSubmit={async e => {
e.preventDefault();
await handleSubmit(titleElement.value, authorElement.value, bodyElement.value, props.uri, props.newsKey);
titleElement.value = authorElement.value = bodyElement.value = '';
}}>
<div>
<label htmlFor='title'>Title: </label>
<input type='text' name='title' ref={ e => titleElement = e } />
</div>
<div>
<label htmlFor='author'>Author: </label>
<input type='text' name='author' ref={ e => authorElement = e } />
</div>
<div>
<label htmlFor='body'>Body: </label>
<textarea name='body' rows='10' cols='150' ref={ e => bodyElement = e } />
</div>
<button type='submit'>Publish</button>
</form>
</div>
);
};
const handleSubmit = async (title, author, body, uri, newsKey) => {
title = title.trim();
author = author.trim();
body = body.trim();
uri = uri.trim();
newsKey = newsKey.trim();
//fetch POST json data
const raw = await fetch(
uri,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
body: JSON.stringify({ title: title, author: author, body: body, key: newsKey })
}
);
if (raw.ok) {
const result = await raw.json();
if (result.ok) {
alert(`Published article index ${result.index}`);
} else {
alert(result.error);
}
} else {
alert(raw.statusText);
}
};
export default NewsPublisher;