diff --git a/.envdev b/.envdev
index 6e4b945..8ba1f5d 100644
--- a/.envdev
+++ b/.envdev
@@ -12,4 +12,5 @@ DB_USERNAME=template
DB_PASSWORD=pikachu
DB_TIMEZONE=Australia/Sydney
-SESSION_SECRET=secret
\ No newline at end of file
+SESSION_SECRET=secret
+SESSION_ADMIN=adminsecret
\ No newline at end of file
diff --git a/client/components/app.jsx b/client/components/app.jsx
index 876b1e4..4b6fd95 100644
--- a/client/components/app.jsx
+++ b/client/components/app.jsx
@@ -38,11 +38,13 @@ const App = props => {
import('./pages/homepage')} />
-
+
import('./pages/signup')} />
import('./pages/login')} />
import('./pages/account')} />
-
+
+ import('./pages/admin')} />
+
import('./pages/not-found')} />
diff --git a/client/components/pages/account.jsx b/client/components/pages/account.jsx
index 11cf8e0..b2020ff 100644
--- a/client/components/pages/account.jsx
+++ b/client/components/pages/account.jsx
@@ -5,7 +5,7 @@ import { useCookies } from 'react-cookie';
import DeleteAccount from '../panels/delete-account';
const Account = props => {
- const [cookies, setCookie] = useCookies(['loggedin']);
+ const [cookies, setCookie] = useCookies();
//check for logged in redirect
if (!cookies['loggedin']) {
diff --git a/client/components/pages/admin.jsx b/client/components/pages/admin.jsx
new file mode 100644
index 0000000..d108429
--- /dev/null
+++ b/client/components/pages/admin.jsx
@@ -0,0 +1,25 @@
+import React from 'react';
+import { Redirect } from 'react-router-dom';
+import { useCookies } from 'react-cookie';
+
+import BannedEmails from '../panels/banned-emails';
+import NewsPublisher from '../panels/news-publisher';
+
+const Admin = props => {
+ const [cookies, setCookie] = useCookies();
+
+ //check for logged in redirect
+ if (!cookies['admin']) {
+ return ;
+ }
+
+ return (
+
+
Administration
+
+
+
+ );
+};
+
+export default Admin;
diff --git a/client/components/pages/login.jsx b/client/components/pages/login.jsx
index 6971cfc..a90420f 100644
--- a/client/components/pages/login.jsx
+++ b/client/components/pages/login.jsx
@@ -6,7 +6,7 @@ import { useCookies } from 'react-cookie';
const validateEmail = require('../../../common/utilities/validate-email.js');
const LogIn = props => {
- const [cookies, setCookie] = useCookies(['loggedin']);
+ const [cookies, setCookie] = useCookies();
//check for logged in redirect
if (cookies['loggedin']) {
diff --git a/client/components/pages/signup.jsx b/client/components/pages/signup.jsx
index 8369718..8559b52 100644
--- a/client/components/pages/signup.jsx
+++ b/client/components/pages/signup.jsx
@@ -7,7 +7,7 @@ const validateEmail = require('../../../common/utilities/validate-email.js');
const validateUsername = require('../../../common/utilities/validate-username.js');
const SignUp = props => {
- const [cookies, setCookie] = useCookies(['loggedin']);
+ const [cookies, setCookie] = useCookies();
//check for logged in redirect
if (cookies['loggedin']) {
diff --git a/client/components/panels/banned-emails.jsx b/client/components/panels/banned-emails.jsx
new file mode 100644
index 0000000..f3fa273
--- /dev/null
+++ b/client/components/panels/banned-emails.jsx
@@ -0,0 +1,108 @@
+import React, { useState, useEffect } from 'react';
+
+const BannedEmails = props => {
+ const [data, setData] = useState(null);
+ let usernameElement, emailElement, dateElement, reasonElement;
+ let unbanElement;
+
+ fetch('/api/admin/banned', { method: 'POST' })
+ .then(banned => banned.json())
+ .then(banned => !data ? setData(banned) : null)
+ .catch(e => console.error(e))
+ ;
+
+ return (
+
+
Banned Accounts
+
+
+
+ | Username |
+ Email |
+ Privilege |
+ Expiry |
+ Reason |
+
+
+
+ {(data || []).map((entry, index) =>
+
+ | {entry.username} |
+ {entry.email} |
+ {entry.privilege} |
+ {entry.expiry} |
+ {entry.reason} |
+
+ )}
+
+
+
+
Ban
+
+
+
Unban
+
+
+ );
+};
+
+const handleBan = async (username, email, date, 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('date', date);
+ formData.append('reason', reason);
+
+ const result = await fetch('/api/admin/ban', { method: 'POST', body: formData });
+
+ alert(await result.text());
+};
+
+const handleUnban = async (username) => {
+ username = username.trim();
+
+ let formData = new FormData();
+
+ formData.append('username', username);
+
+ const result = await fetch('/api/admin/unban', { method: 'POST', body: formData });
+
+ alert(await result.text());
+};
+
+export default BannedEmails;
\ No newline at end of file
diff --git a/client/components/panels/news-publisher.jsx b/client/components/panels/news-publisher.jsx
new file mode 100644
index 0000000..1fcc701
--- /dev/null
+++ b/client/components/panels/news-publisher.jsx
@@ -0,0 +1,5 @@
+const NewsPublisher = props => {
+ return null;
+};
+
+export default NewsPublisher;
\ No newline at end of file
diff --git a/server/accounts/login.js b/server/accounts/login.js
index 07a2095..8320a67 100644
--- a/server/accounts/login.js
+++ b/server/accounts/login.js
@@ -40,6 +40,10 @@ const route = async (req, res) => {
req.session.account = account;
res.cookie('loggedin', process.env.WEB_ADDRESS);
+ if (account.privilege == 'administrator') {
+ res.cookie('admin', process.env.SESSION_ADMIN);
+ }
+
//cancel deletion if any
await accounts.update({ deletion: null }, {
where: {
diff --git a/server/admin/ban.js b/server/admin/ban.js
new file mode 100644
index 0000000..e69de29
diff --git a/server/admin/banned.js b/server/admin/banned.js
new file mode 100644
index 0000000..4d8d955
--- /dev/null
+++ b/server/admin/banned.js
@@ -0,0 +1,39 @@
+const { Op } = require('sequelize');
+const { bannedEmails, accounts } = require('../database/models');
+
+const route = async (req, res) => {
+ //make sure the account is an admin
+ if (req.cookies['admin'] !== process.env.SESSION_ADMIN) {
+ return res.status(401).send('invalid admin status');
+ }
+
+ //merge the banned accounts with the account data, if any
+ const data = await bannedEmails.findAll()
+ .then(bans => bans.map(async ban => {
+ //find a matching account
+ const account = await accounts.findOne({
+ attrubutes: ['username', 'privilege'],
+ where: {
+ email: {
+ [Op.eq]: ban.email
+ }
+ }
+ }) || {};
+
+ //merge the data and return (becomes a promise)
+ return {
+ username: account.username,
+ email: ban.email,
+ privilege: account.privilege,
+ expiry: ban.expiry,
+ reason: ban.reason
+ };
+ }))
+ .then(promises => Promise.all(promises)) //resolve promises
+ .catch(e => console.error(e))
+ ;
+
+ res.status(200).json(data);
+};
+
+module.exports = route;
\ No newline at end of file
diff --git a/server/admin/index.js b/server/admin/index.js
new file mode 100644
index 0000000..f250cb9
--- /dev/null
+++ b/server/admin/index.js
@@ -0,0 +1,9 @@
+const express = require('express');
+const router = express.Router();
+
+//basic account management
+router.post('/banned', require('./banned'));
+//router.post('/ban', require('./ban'));
+//router.post('/unban', require('./unban'));
+
+module.exports = router;
diff --git a/server/admin/unban.js b/server/admin/unban.js
new file mode 100644
index 0000000..e69de29
diff --git a/server/server.js b/server/server.js
index 375c6b3..ad64948 100644
--- a/server/server.js
+++ b/server/server.js
@@ -22,6 +22,9 @@ const database = require('./database');
//account management
app.use('/api/accounts', require('./accounts'));
+//administration
+app.use('/api/admin', require('./admin'));
+
//send static files
app.use('/', express.static(path.resolve(__dirname, 'public')));