Signup data is reaching the server code

This commit is contained in:
2021-01-22 00:55:17 +11:00
parent 30a5251400
commit a983d60b32
17 changed files with 3251 additions and 15 deletions
+4
View File
@@ -1,3 +1,7 @@
//polyfills
import 'core-js/stable';
import 'regenerator-runtime/runtime';
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
+10 -2
View File
@@ -9,15 +9,23 @@ import LazyRoute from './lazy-route';
//TODO: styling import //TODO: styling import
//common components //common components
//TODO: header import Header from './panels/header.jsx';
//TODO: footer import Footer from './panels/footer.jsx';
const App = props => { const App = props => {
return ( return (
<BrowserRouter> <BrowserRouter>
<Header />
<Switch> <Switch>
<LazyRoute exact path='/' component={() => import('./pages/homepage')} /> <LazyRoute exact path='/' component={() => import('./pages/homepage')} />
<LazyRoute path='/signup' component={() => import('./pages/signup')} />
<LazyRoute path='/login' component={() => import('./pages/login')} />
<LazyRoute path='/account' component={() => import('./pages/account')} />
<LazyRoute path='*' component={() => import('./pages/not-found')} />
</Switch> </Switch>
<Footer />
</BrowserRouter> </BrowserRouter>
); );
}; };
+11
View File
@@ -0,0 +1,11 @@
import React from 'react';
const Account = props => {
return (
<div className='page'>
<h1 className='middle centered'>Account</h1>
</div>
);
};
export default Account;
+10 -1
View File
@@ -1,7 +1,16 @@
import React from 'react'; import React from 'react';
const HomePage = props => { const HomePage = props => {
return <p>Hello world!</p>; return (
<div className='page'>
<p>This is the MERN template homepage.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>
);
}; };
export default HomePage; export default HomePage;
+11
View File
@@ -0,0 +1,11 @@
import React from 'react';
const LogIn = props => {
return (
<div className='page'>
<h1 className='middle centered'>Log In</h1>
</div>
);
};
export default LogIn;
+11
View File
@@ -0,0 +1,11 @@
import React from 'react';
const NotFound = props => {
return (
<div className='page'>
<h1 className='middle centered'>Not Found</h1>
</div>
);
};
export default NotFound;
+98
View File
@@ -0,0 +1,98 @@
import React, { useState } from 'react';
//utilities
const validateEmail = require('../../../common/utilities/validate-email.js');
const validateUsername = require('../../../common/utilities/validate-username.js');
const SignUp = props => {
//refs
let emailElement, usernameElement, passwordElement, retypeElement;
return (
<div className='page'>
<h1 className='middle centered'>Signup</h1>
<form className='constricted' onSubmit={
evt => {
evt.preventDefault();
handleSubmit(emailElement.value, usernameElement.value, passwordElement.value, retypeElement.value)
.then(res => alert(res))
.then(() => emailElement.value = usernameElement.value = passwordElement.value = retypeElement.value = '') //clear input
.catch(e => console.error(e))
;
}
}>
<div>
<label htmlFor="email">Email:</label>
<input type="email" name="email" ref={e => emailElement = e} />
</div>
<div>
<label htmlFor="username">Username:</label>
<input type="text" name="username" ref={e => usernameElement = e} />
</div>
<div>
<label htmlFor="password">Password:</label>
<input type="password" name="password" ref={e => passwordElement = e} />
</div>
<div>
<label htmlFor="retype">Retype Password:</label>
<input type="password" name="retype" ref={e => retypeElement = e} />
</div>
<button type='submit'>Signup</button>
</form>
</div>
);
};
const handleSubmit = async (email, username, password, retype) => {
email = email.trim();
username = username.trim();
const err = handleValidation(email, username, password, retype);
if (err) {
alert(err);
return;
}
//generate a new formdata payload
let formData = new FormData();
formData.append('email', email);
formData.append('username', username);
formData.append('password', password);
const result = await fetch('/api/accounts/signup', { method: 'POST', body: formData });
if (result.ok) {
return result.text();
} else {
return result.text();
}
};
//returns an error message, or null on success
const handleValidation = (email, username, password, retype) => {
if (!validateEmail(email)) {
return 'invalid email';
}
if (!validateUsername(username)) {
return 'invalid username';
}
if (password.length < 8) {
return 'invalid password (Must be at least 8 characters long)';
}
if (password !== retype) {
return 'passwords do not match';
}
return null;
};
export default SignUp;
+11
View File
@@ -0,0 +1,11 @@
import React from 'react';
const Footer = () => {
return (
<footer>
<p className='centered'>MERN template designed by Kayne Ruse, KR Game Studios</p>
</footer>
);
};
export default Footer;
+30
View File
@@ -0,0 +1,30 @@
import React from 'react';
const Visitor = () => {
return (
<div>
<a href='/signup'>Sign Up</a>
<a href='/login'>Log In</a>
</div>
);
};
const Member = () => {
return (
<div>
<a href='/account'>Account</a>
<a href='/logout'>Log out</a>
</div>
);
};
const Header = () => {
return (
<header>
<h1><a href='/'>MERN Template</a></h1>
<Visitor />
</header>
);
};
export default Header;
+5
View File
@@ -0,0 +1,5 @@
const emailRegex = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
module.exports = email => {
return emailRegex.test(email);
}
+23
View File
@@ -0,0 +1,23 @@
module.exports = username => {
if (!username) {
return false;
}
if (username.length < 8 && username.length > 100) {
return false;
}
if (!isAlpha(username)) {
return false;
}
return true;
}
const isAlpha = (str) => {
//starting from beginning ^
//to the end $
//check first letter is alpha or underscore [A-Za-z_]
//check the remaining 0 or more (*) letters are alpha, numeric or underscore [A-Za-z0-9_]
return /^[A-Za-z_][A-Za-z0-9_]*$/.test(str);
}
+2942 -2
View File
File diff suppressed because it is too large Load Diff
+12 -3
View File
@@ -5,10 +5,12 @@
"main": "server/server.js", "main": "server/server.js",
"scripts": { "scripts": {
"start": "npm run build && node server/server.js", "start": "npm run build && node server/server.js",
"dev": "npm run build && nodemon server/server.js --ext js,jsx,json",
"build": "npm run build:server && npm run build:client", "build": "npm run build:server && npm run build:client",
"build:server": "exit 0", "build:server": "exit 0",
"build:client": "webpack --env=production --config webpack.config.js", "build:client": "webpack --env=production --config webpack.config.js",
"dev": "concurrently npm:watch:server npm:watch:client",
"watch:server": "nodemon server/server.js --ext js,jsx,json",
"watch:client": "webpack serve --env=development --config webpack.config.js",
"analyzer": "webpack --env=production --analyzer --config webpack.config.js" "analyzer": "webpack --env=production --analyzer --config webpack.config.js"
}, },
"repository": { "repository": {
@@ -22,8 +24,13 @@
}, },
"homepage": "https://github.com/KRGameStudios/MERN-template#readme", "homepage": "https://github.com/KRGameStudios/MERN-template#readme",
"dependencies": { "dependencies": {
"bcryptjs": "^2.4.3",
"core-js": "^3.8.3",
"dotenv": "^8.2.0", "dotenv": "^8.2.0",
"express": "^4.17.1" "express": "^4.17.1",
"express-formidable": "^1.2.0",
"regenerator-runtime": "^0.13.7",
"sendmail": "^1.6.1"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.12.10", "@babel/core": "^7.12.10",
@@ -31,6 +38,7 @@
"@babel/preset-react": "^7.12.10", "@babel/preset-react": "^7.12.10",
"babel-loader": "^8.2.2", "babel-loader": "^8.2.2",
"clean-webpack-plugin": "^3.0.0", "clean-webpack-plugin": "^3.0.0",
"concurrently": "^5.3.0",
"html-webpack-plugin": "^5.0.0-alpha.14", "html-webpack-plugin": "^5.0.0-alpha.14",
"nodemon": "^2.0.7", "nodemon": "^2.0.7",
"react": "^17.0.1", "react": "^17.0.1",
@@ -40,6 +48,7 @@
"react-router-dom": "^5.2.0", "react-router-dom": "^5.2.0",
"webpack": "^5.15.0", "webpack": "^5.15.0",
"webpack-bundle-analyzer": "^4.3.0", "webpack-bundle-analyzer": "^4.3.0",
"webpack-cli": "^4.3.1" "webpack-cli": "^4.3.1",
"webpack-dev-server": "^3.11.2"
} }
} }
+7
View File
@@ -0,0 +1,7 @@
const express = require('express');
const router = express.Router();
//basic account management
router.post('/signup', require('./signup'));
module.exports = router;
+16
View File
@@ -0,0 +1,16 @@
//libraries
const util = require('util');
const bcrypt = require('bcryptjs');
const sendmail = require('sendmail')({silent: true});
//utilities
const validateEmail = require('../../common/utilities/validate-email.js');
const validateUsername = require('../../common/utilities/validate-username.js');
//api/accounts/signup
const route = (req, res) => {
res.status(200).send("The server has received your information.");
}
module.exports = route;
+10 -4
View File
@@ -4,20 +4,26 @@ require('dotenv').config();
//create the server //create the server
const express = require('express'); const express = require('express');
const app = express(); const app = express();
const http = require('http').Server(app); const server = require('http').Server(app);
//libraries used here //libraries used here
const path = require('path'); const path = require('path');
const formidable = require('express-formidable');
app.use(formidable());
//account management
app.use('/api/accounts', require('./accounts'));
//send static files //send static files
app.use('/', express.static(path.resolve(__dirname, '../public'))); app.use('/', express.static(path.resolve('../public')));
//fallback to the index file //fallback to the index file
app.get('*', (req, res) => { app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, `../public/index.html`)); res.sendFile(path.resolve(`../public/index.html`));
}); });
//startup //startup
http.listen(process.env.WEB_PORT || 3000, (err) => { server.listen(process.env.WEB_PORT || 3000, (err) => {
console.log(`listening to localhost:${process.env.WEB_PORT || 3000}`); console.log(`listening to localhost:${process.env.WEB_PORT || 3000}`);
}); });
+40 -3
View File
@@ -17,7 +17,7 @@ module.exports = ({ production, analyzer }) => {
filename: '[name].[chunkhash].js', filename: '[name].[chunkhash].js',
sourceMapFilename: '[name].[chunkhash].js.map' sourceMapFilename: '[name].[chunkhash].js.map'
}, },
devtool: 'source-map', devtool: 'eval-source-map',
resolve: { resolve: {
extensions: ['.js', '.jsx'] extensions: ['.js', '.jsx']
}, },
@@ -53,6 +53,43 @@ module.exports = ({ production, analyzer }) => {
new BundleAnalyzerPlugin({ new BundleAnalyzerPlugin({
analyzerMode: analyzer ? 'server' : 'disabled' analyzerMode: analyzer ? 'server' : 'disabled'
}) })
] ],
}; devServer: {
contentBase: path.resolve(__dirname, 'public'),
compress: true,
port: 3001,
proxy: {
'/api/': 'http://localhost:3000/'
},
overlay: {
errors: true
},
stats: {
colors: true,
hash: false,
version: false,
timings: false,
assets: false,
chunks: false,
modules: false,
reasons: false,
children: false,
source: false,
errors: true,
errorDetails: false,
warnings: true,
publicPath: false
},
host: '0.0.0.0',
disableHostCheck: true,
clientLogLevel: 'silent',
historyApiFallback: true,
hot: true,
injectHot: true
},
watchOptions: {
ignored: /(node_modules)/
}
}
}; };