Implemented username reserve feature
This commit is contained in:
@@ -13,5 +13,7 @@ DB_USERNAME=template
|
||||
DB_PASSWORD=pikachu
|
||||
DB_TIMEZONE=Australia/Sydney
|
||||
|
||||
CHAT_URI=http://example.com:3200/chat
|
||||
|
||||
SESSION_SECRET=secret
|
||||
SESSION_ADMIN=adminsecret
|
||||
@@ -43,6 +43,7 @@ const App = props => {
|
||||
<LazyRoute path='/signup' component={() => import('./pages/signup')} />
|
||||
<LazyRoute path='/login' component={() => import('./pages/login')} />
|
||||
<LazyRoute path='/account' component={() => import('./pages/account')} />
|
||||
<LazyRoute path='/chat' component={() => import('./pages/chat')} />
|
||||
|
||||
<LazyRoute path='/admin' component={() => import('./pages/admin')} />
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import React from 'react';
|
||||
import { Redirect } from 'react-router-dom';
|
||||
import { useCookies } from 'react-cookie';
|
||||
|
||||
import Chat from '../panels/chat';
|
||||
|
||||
//Temporary chat page
|
||||
const ChatPage = props => {
|
||||
const [cookies, setCookie] = useCookies();
|
||||
|
||||
//check for logged in redirect
|
||||
if (!cookies['loggedin']) {
|
||||
return <Redirect to='/' />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='page'>
|
||||
<Chat uri={process.env.CHAT_URI} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ChatPage;
|
||||
@@ -3,7 +3,6 @@ import React from 'react';
|
||||
import NewsFeed from '../panels/news-feed';
|
||||
|
||||
const HomePage = props => {
|
||||
//TODO: move the URIs into the config files
|
||||
return (
|
||||
<div className='page'>
|
||||
<p>This is the MERN template homepage.</p>
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
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;
|
||||
+14
-1
@@ -39,7 +39,12 @@ const question = (prompt, def) => {
|
||||
const newsDBPass = await question('News Database Password', 'charizard');
|
||||
const newsKey = await question('News Query Key', uuid());
|
||||
|
||||
//TODO: chat configuration
|
||||
//chat configuration
|
||||
const chatName = await question('Chat Name', 'chat');
|
||||
const chatWebAddress = await question('Chat Web Address', 'chat.example.com');
|
||||
const chatDBUser = await question('Chat Database Username', chatName);
|
||||
const chatDBPass = await question('Chat Database Password', 'blastoise');
|
||||
const chatKey = await question('Chat Reservation Key', uuid());
|
||||
|
||||
//database configuration
|
||||
const databaseRootPassword = await question('Database Root Password', 'password');
|
||||
@@ -52,6 +57,8 @@ const question = (prompt, def) => {
|
||||
const sessionSecret = uuid(); //for session randomness
|
||||
const sessionAdmin = uuid(128); //for checking if user is admin
|
||||
|
||||
//TODO: Implement chat-server as a docker container
|
||||
|
||||
const yml = `
|
||||
version: "3.6"
|
||||
services:
|
||||
@@ -83,6 +90,8 @@ services:
|
||||
- SESSION_ADMIN=${sessionAdmin}
|
||||
- NEWS_URI=https://${newsWebAddress}/news
|
||||
- NEWS_KEY=${newsKey}
|
||||
- CHAT_URI=https://${chatWebAddress}/chat
|
||||
- CHAT_KEY=${chatKey}
|
||||
networks:
|
||||
- app-network
|
||||
depends_on:
|
||||
@@ -180,6 +189,10 @@ CREATE DATABASE IF NOT EXISTS ${newsName};
|
||||
CREATE USER IF NOT EXISTS '${newsDBUser}'@'%' IDENTIFIED BY '${newsDBPass}';
|
||||
GRANT ALL PRIVILEGES ON ${newsName}.* TO '${newsDBUser}'@'%';
|
||||
|
||||
CREATE DATABASE IF NOT EXISTS ${chatName};
|
||||
CREATE USER IF NOT EXISTS '${chatDBUser}'@'%' IDENTIFIED BY '${chatDBPass}';
|
||||
GRANT ALL PRIVILEGES ON ${chatName}.* TO '${chatDBUser}'@'%';
|
||||
|
||||
FLUSH PRIVILEGES;
|
||||
`;
|
||||
|
||||
|
||||
Generated
+80
@@ -18,8 +18,10 @@
|
||||
"express": "^4.17.1",
|
||||
"express-formidable": "^1.2.0",
|
||||
"express-session": "^1.17.1",
|
||||
"form-data": "^4.0.0",
|
||||
"mariadb": "^2.5.2",
|
||||
"node-cron": "^2.0.3",
|
||||
"node-fetch": "^2.6.1",
|
||||
"nodemailer": "^6.4.17",
|
||||
"react-cookie": "^4.0.3",
|
||||
"react-dropdown-select": "^4.7.3",
|
||||
@@ -1949,6 +1951,11 @@
|
||||
"integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
|
||||
},
|
||||
"node_modules/atob": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
|
||||
@@ -2670,6 +2677,17 @@
|
||||
"integrity": "sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"dependencies": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/commander": {
|
||||
"version": "2.20.3",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||
@@ -3376,6 +3394,14 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/denque": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/denque/-/denque-1.5.0.tgz",
|
||||
@@ -4319,6 +4345,19 @@
|
||||
"resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
|
||||
"integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k="
|
||||
},
|
||||
"node_modules/form-data": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
|
||||
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"mime-types": "^2.1.12"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/formidable": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz",
|
||||
@@ -6547,6 +6586,14 @@
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/node-fetch": {
|
||||
"version": "2.6.1",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
|
||||
"integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==",
|
||||
"engines": {
|
||||
"node": "4.x || >=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/node-forge": {
|
||||
"version": "0.10.0",
|
||||
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz",
|
||||
@@ -12384,6 +12431,11 @@
|
||||
"integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==",
|
||||
"dev": true
|
||||
},
|
||||
"asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
|
||||
},
|
||||
"atob": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
|
||||
@@ -12983,6 +13035,14 @@
|
||||
"integrity": "sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==",
|
||||
"dev": true
|
||||
},
|
||||
"combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"requires": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"commander": {
|
||||
"version": "2.20.3",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||
@@ -13555,6 +13615,11 @@
|
||||
"rimraf": "^2.6.3"
|
||||
}
|
||||
},
|
||||
"delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
|
||||
},
|
||||
"denque": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/denque/-/denque-1.5.0.tgz",
|
||||
@@ -14354,6 +14419,16 @@
|
||||
"resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
|
||||
"integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k="
|
||||
},
|
||||
"form-data": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
|
||||
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
|
||||
"requires": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"mime-types": "^2.1.12"
|
||||
}
|
||||
},
|
||||
"formidable": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz",
|
||||
@@ -16100,6 +16175,11 @@
|
||||
"tz-offset": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node-fetch": {
|
||||
"version": "2.6.1",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
|
||||
"integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw=="
|
||||
},
|
||||
"node-forge": {
|
||||
"version": "0.10.0",
|
||||
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz",
|
||||
|
||||
@@ -35,8 +35,10 @@
|
||||
"express": "^4.17.1",
|
||||
"express-formidable": "^1.2.0",
|
||||
"express-session": "^1.17.1",
|
||||
"form-data": "^4.0.0",
|
||||
"mariadb": "^2.5.2",
|
||||
"node-cron": "^2.0.3",
|
||||
"node-fetch": "^2.6.1",
|
||||
"nodemailer": "^6.4.17",
|
||||
"react-cookie": "^4.0.3",
|
||||
"react-dropdown-select": "^4.7.3",
|
||||
|
||||
@@ -3,6 +3,7 @@ const route = (req, res) => {
|
||||
req.session.account = null;
|
||||
res.clearCookie('loggedin');
|
||||
res.clearCookie('admin');
|
||||
res.clearCookie('pseudonym');
|
||||
|
||||
return res.status(200).end();
|
||||
};
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
|
||||
//reserve the name on the chat server (then get out of the way)
|
||||
router.post('/reserve', require('./reserve'));
|
||||
|
||||
module.exports = router;
|
||||
@@ -0,0 +1,23 @@
|
||||
const fetch = require('node-fetch');
|
||||
const FormData = require('form-data');
|
||||
|
||||
const route = async (req, res) => {
|
||||
//build the fake form data object
|
||||
let form = new FormData();
|
||||
form.append('username', req.session?.account?.username);
|
||||
|
||||
try {
|
||||
//reserve the UUID with the chat server (hop 1)
|
||||
const result = await fetch(`http://${process.env.CHAT_URI}/reserve`, { method: 'POST', body: form });
|
||||
|
||||
const json = await result.json();
|
||||
res.cookie('pseudonym', json.pseudonym);
|
||||
res.status(200).send({ ok: true });
|
||||
} catch(e) {
|
||||
console.error('Chat server not found');
|
||||
res.cookie('pseudonym', '.null');
|
||||
res.status(200).send({ ok: false, error: 'Chat server not found' });
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = route;
|
||||
@@ -31,6 +31,9 @@ app.use(session({
|
||||
//account management
|
||||
app.use('/api/accounts', require('./accounts'));
|
||||
|
||||
//chat management
|
||||
app.use('/api/chat', require('./chat'));
|
||||
|
||||
//administration
|
||||
app.use('/api/admin', require('./admin'));
|
||||
require('./admin/bookkeeper')(); //BUGFIX
|
||||
|
||||
@@ -51,7 +51,9 @@ module.exports = ({ production, analyzer }) => {
|
||||
new DefinePlugin({
|
||||
'process.env': {
|
||||
'NEWS_URI': production ? `"${process.env.NEWS_URI}"` : '"http://dev-news.eggtrainer.com:3100/news"',
|
||||
/* TODO: (1) NEWS_KEY needs to be set in the server, and auth'd via admin accounts, NOT embedded in the client */
|
||||
'NEWS_KEY': production ? `"${process.env.NEWS_KEY}"` : '"key"',
|
||||
'CHAT_URI': production ? `"${process.env.NEWS_URI}"` : '"http://dev-chat.eggtrainer.com:3200/chat"',
|
||||
}
|
||||
}),
|
||||
new CleanWebpackPlugin({
|
||||
|
||||
Reference in New Issue
Block a user