diff --git a/package-lock.json b/package-lock.json index 9bae26d..6cd8aa6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1424,29 +1424,48 @@ "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" }, "body-parser": { - "version": "1.18.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", - "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", "requires": { - "bytes": "3.0.0", + "bytes": "3.1.0", "content-type": "~1.0.4", "debug": "2.6.9", "depd": "~1.1.2", - "http-errors": "~1.6.3", - "iconv-lite": "0.4.23", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", "on-finished": "~2.3.0", - "qs": "6.5.2", - "raw-body": "2.3.3", - "type-is": "~1.6.16" + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" }, "dependencies": { - "iconv-lite": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", - "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", "requires": { - "safer-buffer": ">= 2.1.2 < 3" + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" } + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" } } }, @@ -1669,9 +1688,9 @@ "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=" }, "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" }, "cacache": { "version": "11.3.2", @@ -2563,10 +2582,51 @@ "vary": "~1.1.2" }, "dependencies": { + "body-parser": { + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", + "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", + "requires": { + "bytes": "3.0.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "~1.6.3", + "iconv-lite": "0.4.23", + "on-finished": "~2.3.0", + "qs": "6.5.2", + "raw-body": "2.3.3", + "type-is": "~1.6.16" + } + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "raw-body": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "unpipe": "1.0.0" + } } } }, @@ -3079,13 +3139,11 @@ }, "balanced-match": { "version": "1.0.0", - "bundled": true, - "optional": true + "bundled": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -3098,18 +3156,15 @@ }, "code-point-at": { "version": "1.1.0", - "bundled": true, - "optional": true + "bundled": true }, "concat-map": { "version": "0.0.1", - "bundled": true, - "optional": true + "bundled": true }, "console-control-strings": { "version": "1.1.0", - "bundled": true, - "optional": true + "bundled": true }, "core-util-is": { "version": "1.0.2", @@ -3212,8 +3267,7 @@ }, "inherits": { "version": "2.0.3", - "bundled": true, - "optional": true + "bundled": true }, "ini": { "version": "1.3.5", @@ -3223,7 +3277,6 @@ "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -3236,7 +3289,6 @@ "minimatch": { "version": "3.0.4", "bundled": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -3336,8 +3388,7 @@ }, "number-is-nan": { "version": "1.0.1", - "bundled": true, - "optional": true + "bundled": true }, "object-assign": { "version": "4.1.1", @@ -3347,7 +3398,6 @@ "once": { "version": "1.4.0", "bundled": true, - "optional": true, "requires": { "wrappy": "1" } @@ -3453,7 +3503,6 @@ "string-width": { "version": "1.0.2", "bundled": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -5318,23 +5367,37 @@ "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" }, "raw-body": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", - "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", "requires": { - "bytes": "3.0.0", - "http-errors": "1.6.3", - "iconv-lite": "0.4.23", + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", "unpipe": "1.0.0" }, "dependencies": { - "iconv-lite": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", - "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", "requires": { - "safer-buffer": ">= 2.1.2 < 3" + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" } + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" } } }, @@ -6311,6 +6374,11 @@ "repeat-string": "^1.6.1" } }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + }, "trim-right": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", diff --git a/package.json b/package.json index e6384f5..e9790e7 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "@babel/preset-react": "^7.0.0", "babel-loader": "^8.0.5", "bcrypt": "^3.0.6", + "body-parser": "^1.19.0", "dotenv": "^8.0.0", "express": "^4.16.4", "forever": "^1.0.0", diff --git a/server/accounts.js b/server/accounts.js index d5d3cdf..3c8862d 100644 --- a/server/accounts.js +++ b/server/accounts.js @@ -127,7 +127,78 @@ function verify(connection) { } } +function login(connection) { + return (req, res) => { + //formidable handles forms + let form = formidable.IncomingForm(); + + //parse form + form.parse(req, (err, fields) => { + if (err) throw err; + + //validate email, username and password + if (!validateEmail(fields.email) || fields.password.length < 8) { + res.write('
Invalid login data
'); + res.end(); + return; + } + + //find this email's information + let query = 'SELECT id, username, salt, hash FROM accounts WHERE email = ?;'; + connection.query(query, [fields.email], (err, results) => { + if (err) throw err; + + //found this email? + if (results.length === 0) { + res.status(400).write('Incorrect email or password'); + res.end(); + return; + } + + //gen a new hash from the salt and password + bcrypt.hash(fields.password, results[0].salt, (err, newHash) => { + if (err) throw err; + + //compare the passwords + if (results[0].hash !== newHash) { + res.status(400).write('Incorrect email or password'); + res.end(); + return; + } + + //create the new session + let rand = Math.floor(Math.random() * 100000); + + let query = 'INSERT INTO sessions (accountId, token) VALUES (?, ?);'; + connection.query(query, [results[0].id, rand], (err) => { + if (err) throw err; + + //send json containing the account info + res.status(200).json({ + id: results[0].id, + email: fields.email, + username: results[0].username, + token: rand + }); + }); + }); + }); + }); + } +} + +function logout(connection) { + return (req, res) => { + let query = 'DELETE FROM sessions WHERE sessions.accountId IN (SELECT accounts.id FROM accounts WHERE email = ?) AND token = ?;'; + connection.query(query, [req.body.email, req.body.token], (err) => { + if (err) throw err; + }); + } +} + module.exports = { signup: signup, - verify: verify + verify: verify, + login: login, + logout: logout }; \ No newline at end of file diff --git a/server/index.js b/server/index.js index 926451a..92619a3 100644 --- a/server/index.js +++ b/server/index.js @@ -5,8 +5,11 @@ require('dotenv').config(); let express = require('express'); let app = express(); let http = require('http').Server(app); +let bodyParser = require('body-parser'); let path = require('path'); +app.use(bodyParser.json()); + //database let { connectToDatabase } = require('./database.js'); let connection = connectToDatabase(); //uses .env @@ -15,6 +18,8 @@ let connection = connectToDatabase(); //uses .env let accounts = require('./accounts.js'); app.post('/signup', accounts.signup(connection)); app.get('/verify', accounts.verify(connection)); +app.post('/login', accounts.login(connection)); +app.post('/logout', accounts.logout(connection)); //static directories app.use('/styles', express.static(path.resolve(__dirname + '/../public/styles')) ); diff --git a/sql/create_database_structure.sql b/sql/create_database_structure.sql index ba29120..b7f4899 100644 --- a/sql/create_database_structure.sql +++ b/sql/create_database_structure.sql @@ -1,4 +1,4 @@ -CREATE TABLE signups ( +CREATE TABLE IF NOT EXISTS signups ( email VARCHAR(320) UNIQUE, username VARCHAR(100) UNIQUE, salt VARCHAR(50), @@ -7,7 +7,7 @@ CREATE TABLE signups ( verify INTEGER DEFAULT 0 ); -CREATE TABLE accounts ( +CREATE TABLE IF NOT EXISTS accounts ( id INTEGER UNSIGNED AUTO_INCREMENT PRIMARY KEY UNIQUE, td TIMESTAMP DEFAULT CURRENT_TIMESTAMP(), @@ -17,3 +17,13 @@ CREATE TABLE accounts ( hash VARCHAR(100) ); +CREATE TABLE IF NOT EXISTS sessions ( + id INTEGER UNSIGNED AUTO_INCREMENT PRIMARY KEY UNIQUE, + td TIMESTAMP DEFAULT CURRENT_TIMESTAMP(), + + accountId INTEGER UNSIGNED, + token INTEGER DEFAULT 0, + + CONSTRAINT FOREIGN KEY fk_accountId(accountId) REFERENCES accounts(id) ON UPDATE CASCADE ON DELETE CASCADE +); + diff --git a/sql/drop_everything.sql b/sql/drop_everything.sql index 6627951..847ec52 100644 --- a/sql/drop_everything.sql +++ b/sql/drop_everything.sql @@ -1,3 +1,4 @@ DROP TABLE signups; DROP TABLE accounts; -DROP TABLE profiles; +DROP TABLE sessions; +#DROP TABLE profiles; diff --git a/src/actions/accounts.js b/src/actions/accounts.js new file mode 100644 index 0000000..6388305 --- /dev/null +++ b/src/actions/accounts.js @@ -0,0 +1,18 @@ +export const LOGIN = 'LOGIN'; +export const LOGOUT = 'LOGOUT'; + +export function login(id, email, username, token) { + return { + type: LOGIN, + id: id, + email: email, + username: username, + token: token + }; +} + +export function logout() { + return { + type: LOGOUT + }; +} diff --git a/src/actions/actions.jsx b/src/actions/actions.jsx deleted file mode 100644 index 31a4400..0000000 --- a/src/actions/actions.jsx +++ /dev/null @@ -1,7 +0,0 @@ -export const ACTION_NAME = 'ACTION_NAME'; - -export function actionName() { - return { - type: ACTION_NAME - }; -} \ No newline at end of file diff --git a/src/components/pages/home.jsx b/src/components/pages/home.jsx index ee34c5e..d876fa6 100644 --- a/src/components/pages/home.jsx +++ b/src/components/pages/home.jsx @@ -5,6 +5,8 @@ import PropTypes from 'prop-types'; //panels import Signup from '../panels/signup.jsx'; +import Login from '../panels/login.jsx'; +import Logout from '../panels/logout.jsx'; class Home extends React.Component { constructor(props) { @@ -13,10 +15,33 @@ class Home extends React.Component { } render() { + //well this is goofy + let SidePanel; + + if (this.props.id) { + SidePanel = () => { + return ( +You are logged in.
+This is the home page.
-{this.state.warning}
+