Signup data is reaching the server code
This commit is contained in:
@@ -1,3 +1,7 @@
|
||||
//polyfills
|
||||
import 'core-js/stable';
|
||||
import 'regenerator-runtime/runtime';
|
||||
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
|
||||
|
||||
@@ -9,15 +9,23 @@ import LazyRoute from './lazy-route';
|
||||
//TODO: styling import
|
||||
|
||||
//common components
|
||||
//TODO: header
|
||||
//TODO: footer
|
||||
import Header from './panels/header.jsx';
|
||||
import Footer from './panels/footer.jsx';
|
||||
|
||||
const App = props => {
|
||||
return (
|
||||
<BrowserRouter>
|
||||
<Header />
|
||||
<Switch>
|
||||
<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>
|
||||
<Footer />
|
||||
</BrowserRouter>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
@@ -1,7 +1,16 @@
|
||||
import React from 'react';
|
||||
|
||||
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;
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
Generated
+2942
-2
File diff suppressed because it is too large
Load Diff
+12
-3
@@ -5,10 +5,12 @@
|
||||
"main": "server/server.js",
|
||||
"scripts": {
|
||||
"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:server": "exit 0",
|
||||
"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"
|
||||
},
|
||||
"repository": {
|
||||
@@ -22,8 +24,13 @@
|
||||
},
|
||||
"homepage": "https://github.com/KRGameStudios/MERN-template#readme",
|
||||
"dependencies": {
|
||||
"bcryptjs": "^2.4.3",
|
||||
"core-js": "^3.8.3",
|
||||
"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": {
|
||||
"@babel/core": "^7.12.10",
|
||||
@@ -31,6 +38,7 @@
|
||||
"@babel/preset-react": "^7.12.10",
|
||||
"babel-loader": "^8.2.2",
|
||||
"clean-webpack-plugin": "^3.0.0",
|
||||
"concurrently": "^5.3.0",
|
||||
"html-webpack-plugin": "^5.0.0-alpha.14",
|
||||
"nodemon": "^2.0.7",
|
||||
"react": "^17.0.1",
|
||||
@@ -40,6 +48,7 @@
|
||||
"react-router-dom": "^5.2.0",
|
||||
"webpack": "^5.15.0",
|
||||
"webpack-bundle-analyzer": "^4.3.0",
|
||||
"webpack-cli": "^4.3.1"
|
||||
"webpack-cli": "^4.3.1",
|
||||
"webpack-dev-server": "^3.11.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
|
||||
//basic account management
|
||||
router.post('/signup', require('./signup'));
|
||||
|
||||
module.exports = router;
|
||||
@@ -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
@@ -4,20 +4,26 @@ require('dotenv').config();
|
||||
//create the server
|
||||
const express = require('express');
|
||||
const app = express();
|
||||
const http = require('http').Server(app);
|
||||
const server = require('http').Server(app);
|
||||
|
||||
//libraries used here
|
||||
const path = require('path');
|
||||
const formidable = require('express-formidable');
|
||||
|
||||
app.use(formidable());
|
||||
|
||||
//account management
|
||||
app.use('/api/accounts', require('./accounts'));
|
||||
|
||||
//send static files
|
||||
app.use('/', express.static(path.resolve(__dirname, '../public')));
|
||||
app.use('/', express.static(path.resolve('../public')));
|
||||
|
||||
//fallback to the index file
|
||||
app.get('*', (req, res) => {
|
||||
res.sendFile(path.resolve(__dirname, `../public/index.html`));
|
||||
res.sendFile(path.resolve(`../public/index.html`));
|
||||
});
|
||||
|
||||
//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}`);
|
||||
});
|
||||
|
||||
+40
-3
@@ -17,7 +17,7 @@ module.exports = ({ production, analyzer }) => {
|
||||
filename: '[name].[chunkhash].js',
|
||||
sourceMapFilename: '[name].[chunkhash].js.map'
|
||||
},
|
||||
devtool: 'source-map',
|
||||
devtool: 'eval-source-map',
|
||||
resolve: {
|
||||
extensions: ['.js', '.jsx']
|
||||
},
|
||||
@@ -53,6 +53,43 @@ module.exports = ({ production, analyzer }) => {
|
||||
new BundleAnalyzerPlugin({
|
||||
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)/
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user