From 2f1174c21b58cdec4b1971da8937a8cec85876f8 Mon Sep 17 00:00:00 2001 From: sorrelbri Date: Fri, 26 Jun 2020 17:35:13 -0700 Subject: [PATCH 1/5] stub guest creation on server --- packages/server/controllers/auth.js | 69 ++++++++++++++++++----------- packages/server/routes/auth.js | 22 ++++++--- 2 files changed, 58 insertions(+), 33 deletions(-) diff --git a/packages/server/controllers/auth.js b/packages/server/controllers/auth.js index 77091ba..216b77e 100644 --- a/packages/server/controllers/auth.js +++ b/packages/server/controllers/auth.js @@ -1,15 +1,15 @@ -const { validationResult } = require('express-validator'); +const { validationResult } = require("express-validator"); -const userQueries = require('../data/queries/user'); -const { hashPassword, compareHash } = require('../services/bcrypt'); -const signToken = require('../services/signToken'); +const userQueries = require("../data/queries/user"); +const { hashPassword, compareHash } = require("../services/bcrypt"); +const signToken = require("../services/signToken"); const checkValidationErrors = (req, res) => { const errors = validationResult(req); if (!errors.isEmpty()) { return res.status(422).json({ errors: errors.array() }); } -} +}; const signup = async (req, res, next) => { checkValidationErrors(req, res); @@ -20,51 +20,66 @@ const signup = async (req, res, next) => { const hashedPassword = await hashPassword(user.password); const secureUser = { ...user, password: hashedPassword }; if (existingUser.length) { - return res.status(409).json({errors: [{auth: 'User already exists!'}]}) + return res + .status(409) + .json({ errors: [{ auth: "User already exists!" }] }); } const newUser = await userQueries.insertUser(secureUser); - signToken(res, newUser) - res.status(201).json({...newUser}); - } - - catch (err) { + signToken(res, newUser); + res.status(201).json({ ...newUser }); + } catch (err) { res.status(500).json(err); } -} +}; const login = async (req, res, next) => { checkValidationErrors(req, res); const user = req.body; - + try { const queryResults = await userQueries.findUserByNameOrEmail(user); const savedUser = queryResults[0] || null; - + if (!savedUser) { - return res.status(401).send({errors: 'bad credentials'}); + return res.status(401).send({ errors: "bad credentials" }); } - + const hashedPassword = savedUser.password; const passwordMatch = await compareHash(user.password, hashedPassword); if (!passwordMatch) { - return res.status(401).send({errors: 'bad credentials'}); + return res.status(401).send({ errors: "bad credentials" }); } - - const authorizedUser = {...savedUser}; + + const authorizedUser = { ...savedUser }; delete authorizedUser.password; - + signToken(res, authorizedUser); - res.send({...authorizedUser}).status(200); + res.send({ ...authorizedUser }).status(200); + } catch (e) { + res.status(500).send({ errors: e }); } - - catch (err) { - res.status(500).send({errors: err}); +}; + +const guest = async (req, res, next) => { + try { + // username generator returns `Guest-${num}` + const username = "guest"; + // generateGuestUser(); + const email = null; + // id generator returns ` + const id = null; + const user = { username, email, id }; + signToken(res, user); + res.send(user); + } catch (e) { + res.status(500).send({ errors: e }); } -} +}; module.exports = { signup, - login -} \ No newline at end of file + login, + guest, +}; diff --git a/packages/server/routes/auth.js b/packages/server/routes/auth.js index dfa96f9..6f1f2fb 100644 --- a/packages/server/routes/auth.js +++ b/packages/server/routes/auth.js @@ -1,10 +1,20 @@ -const express = require('express'); +const express = require("express"); const router = express.Router(); -const app = require('../server'); -const authController = require('../controllers/auth'); -const { signupValidationRules, loginValidationRules, validate } = require('../middleware/userValidator'); +const app = require("../server"); +const authController = require("../controllers/auth"); +const { + signupValidationRules, + loginValidationRules, + validate, +} = require("../middleware/userValidator"); -router.post('/signup', signupValidationRules(), validate, authController.signup); -router.post('/login', loginValidationRules(), validate, authController.login); +router.post( + "/signup", + signupValidationRules(), + validate, + authController.signup +); +router.post("/login", loginValidationRules(), validate, authController.login); +router.post("/guest", authController.guest); module.exports = router; From 1e6050a4869f0f44b8d9339ae686e94ed6e728ce Mon Sep 17 00:00:00 2001 From: sorrelbri Date: Fri, 26 Jun 2020 17:55:52 -0700 Subject: [PATCH 2/5] add FE service to post to auth/guest --- .../src/components/Button/Guest/Guest.js | 34 ++++++++++ .../src/components/Form/Auth/Auth.js | 56 +++++++++-------- .../src/reducers/auth/reducer.auth.js | 21 ++++--- .../play-node-go/src/services/authServices.js | 63 ++++++++++++------- 4 files changed, 115 insertions(+), 59 deletions(-) create mode 100644 packages/play-node-go/src/components/Button/Guest/Guest.js diff --git a/packages/play-node-go/src/components/Button/Guest/Guest.js b/packages/play-node-go/src/components/Button/Guest/Guest.js new file mode 100644 index 0000000..7989092 --- /dev/null +++ b/packages/play-node-go/src/components/Button/Guest/Guest.js @@ -0,0 +1,34 @@ +import React from "react"; +import authServices from "../../../services/authServices"; + +const Guest = ({ dispatch }) => { + const handleClick = async (e) => { + e.preventDefault(); + // dispatch to guest endpoint + const guestResponse = await authServices.guestService(); + + if (guestResponse.errors) { + const authError = guestResponse.errors[0].auth; + return dispatch({ + type: "ERR", + message: "AUTH_ERROR", + body: { authError }, + }); + } + + return dispatch({ + type: "AUTH", + message: "GUEST", + body: guestResponse, + }); + }; + return ( + <> + + + ); +}; + +export default Guest; diff --git a/packages/play-node-go/src/components/Form/Auth/Auth.js b/packages/play-node-go/src/components/Form/Auth/Auth.js index 87d0234..c567db6 100644 --- a/packages/play-node-go/src/components/Form/Auth/Auth.js +++ b/packages/play-node-go/src/components/Form/Auth/Auth.js @@ -1,45 +1,49 @@ -import React, { useState } from 'react'; +import React, { useState } from "react"; -import Login from '../Login/Login'; -import Signup from '../Signup/Signup'; +import Login from "../Login/Login"; +import Signup from "../Signup/Signup"; +import Guest from "../../Button/Guest/Guest"; const Auth = (props) => { - const [ showForm, setShowForm ] = useState('login') + const [showForm, setShowForm] = useState("login"); const { state, dispatch } = props; return ( <> -
{setShowForm('login')}} +
{ + setShowForm("login"); + }} > -

Login

+

Login

- { - showForm === 'login' - ? - : <> - } + {showForm === "login" ? ( + + ) : ( + <> + )}
{setShowForm('signup')}} + className="nav__section nav__section--auth" + onClick={() => { + setShowForm("signup"); + }} > -

Signup

+

Signup

- { - showForm === 'signup' - ? - : <> - } + {showForm === "signup" ? ( + + ) : ( + <> + )} +
+
+
); -} +}; export default Auth; diff --git a/packages/play-node-go/src/reducers/auth/reducer.auth.js b/packages/play-node-go/src/reducers/auth/reducer.auth.js index ce220de..9152c95 100644 --- a/packages/play-node-go/src/reducers/auth/reducer.auth.js +++ b/packages/play-node-go/src/reducers/auth/reducer.auth.js @@ -1,20 +1,23 @@ export const authReducer = (state, action) => { switch (action.message) { - case 'LOGIN': - return loginReducer(state, action); - - case 'SIGNUP': + case "LOGIN": return loginReducer(state, action); - case 'LOGOUT': + case "SIGNUP": + return loginReducer(state, action); + + case "GUEST": + return loginReducer(state, action); + + case "LOGOUT": return state; default: return state; - } -} + } +}; function loginReducer(state, action) { const newUser = action.body; - return {...state, user: newUser }; -} \ No newline at end of file + return { ...state, user: newUser }; +} diff --git a/packages/play-node-go/src/services/authServices.js b/packages/play-node-go/src/services/authServices.js index 2ecbb52..261aa77 100644 --- a/packages/play-node-go/src/services/authServices.js +++ b/packages/play-node-go/src/services/authServices.js @@ -1,43 +1,58 @@ -import config from '../config'; +import config from "../config"; const authEndpoint = config.authAddress; -const signupEndpoint = `${authEndpoint}/signup` -const loginEndpoint = `${authEndpoint}/login` +const signupEndpoint = `${authEndpoint}/signup`; +const loginEndpoint = `${authEndpoint}/login`; +const guestEndpoint = `${authEndpoint}/guest`; var headers = new Headers(); -headers.append('Content-Type', 'application/json'); -headers.append('Accept', 'application/json'); -headers.append('Sec-Fetch-Site', 'cross-site') +headers.append("Content-Type", "application/json"); +headers.append("Accept", "application/json"); +headers.append("Sec-Fetch-Site", "cross-site"); -const loginService = async(formData) => { +const loginService = async (formData) => { const response = await fetch(loginEndpoint, { - method: 'POST', - credentials: 'include', + method: "POST", + credentials: "include", body: JSON.stringify(formData), - headers: headers + headers: headers, }) - .then(res => res.text()) - .then(text => JSON.parse(text)) - .catch(err => err); - + .then((res) => res.text()) + .then((text) => JSON.parse(text)) + .catch((err) => err); + return response; -} +}; const signupService = async (formData) => { const response = await fetch(signupEndpoint, { - method: 'POST', - credentials: 'include', + method: "POST", + credentials: "include", body: JSON.stringify(formData), - headers: headers + headers: headers, }) - .then(res => res.text()) - .then(text => JSON.parse(text)) - .catch(err => err); + .then((res) => res.text()) + .then((text) => JSON.parse(text)) + .catch((err) => err); return response; -} +}; + +const guestService = async () => { + const response = await fetch(guestEndpoint, { + method: "POST", + credentials: "include", + headers, + }) + .then((res) => res.text()) + .then((text) => JSON.parse(text)) + .catch((err) => err); + + return response; +}; export default { loginService, - signupService -} \ No newline at end of file + signupService, + guestService, +}; From ff3d6c2c2415767cfe2ab4f0fb5213aa2e7c7468 Mon Sep 17 00:00:00 2001 From: sorrelbri Date: Fri, 26 Jun 2020 23:22:17 -0700 Subject: [PATCH 3/5] add service to generate guest account on server --- packages/server/controllers/auth.js | 4 +++- packages/server/services/guestServices.js | 25 +++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 packages/server/services/guestServices.js diff --git a/packages/server/controllers/auth.js b/packages/server/controllers/auth.js index 216b77e..87f797a 100644 --- a/packages/server/controllers/auth.js +++ b/packages/server/controllers/auth.js @@ -3,6 +3,7 @@ const { validationResult } = require("express-validator"); const userQueries = require("../data/queries/user"); const { hashPassword, compareHash } = require("../services/bcrypt"); const signToken = require("../services/signToken"); +const guestServices = require("../services/guestServices"); const checkValidationErrors = (req, res) => { const errors = validationResult(req); @@ -65,7 +66,7 @@ const login = async (req, res, next) => { const guest = async (req, res, next) => { try { // username generator returns `Guest-${num}` - const username = "guest"; + const { username, password } = guestServices.generateGuest(); // generateGuestUser(); const email = null; // id generator returns ` @@ -74,6 +75,7 @@ const guest = async (req, res, next) => { signToken(res, user); res.send(user); } catch (e) { + console.log(e); res.status(500).send({ errors: e }); } }; diff --git a/packages/server/services/guestServices.js b/packages/server/services/guestServices.js new file mode 100644 index 0000000..ca52616 --- /dev/null +++ b/packages/server/services/guestServices.js @@ -0,0 +1,25 @@ +const generateRandomPassword = () => { + const minLength = 8, + maxLength = 16, + minUTF = 33, + maxUTF = 126; + const randomize = (min, max) => Math.floor(Math.random() * (max - min) + min); + return Array(randomize(minLength, maxLength)) + .fill(0) + .map(() => String.fromCharCode(randomize(minUTF, maxUTF))) + .join(""); +}; + +const guestService = { + currentGuest: 0, + generateGuest() { + // generate unique username + const username = `Guest-${String(this.currentGuest++).padStart(6, 0)}`; + // generate random "password" + // this exists solely to add extra randomness to signed token and is not validated + const password = generateRandomPassword(); + return { username, password }; + }, +}; + +module.exports = guestService; From 0ec92dd5e93e159f974b42880e04cc6d314e29fd Mon Sep 17 00:00:00 2001 From: sorrelbri Date: Fri, 26 Jun 2020 23:33:56 -0700 Subject: [PATCH 4/5] add random password to guest --- packages/server/controllers/auth.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/server/controllers/auth.js b/packages/server/controllers/auth.js index 87f797a..fab82bb 100644 --- a/packages/server/controllers/auth.js +++ b/packages/server/controllers/auth.js @@ -71,8 +71,9 @@ const guest = async (req, res, next) => { const email = null; // id generator returns ` const id = null; - const user = { username, email, id }; + const user = { username, email, id, password }; signToken(res, user); + delete user.password; res.send(user); } catch (e) { console.log(e); From 9cae5ff1856283319be9544bda34904d3b76e68c Mon Sep 17 00:00:00 2001 From: sorrelbri Date: Sat, 27 Jun 2020 13:05:38 -0700 Subject: [PATCH 5/5] style Continue as Guest button, patch account display on NavBar --- packages/play-node-go/public/reset.css | 5 +++ .../pages/Layout/MainWrapper/MainWrapper.scss | 12 ++++++ .../src/pages/Layout/NavBar/NavBar.js | 37 +++++++++++-------- 3 files changed, 39 insertions(+), 15 deletions(-) diff --git a/packages/play-node-go/public/reset.css b/packages/play-node-go/public/reset.css index e91c47f..170a2f5 100644 --- a/packages/play-node-go/public/reset.css +++ b/packages/play-node-go/public/reset.css @@ -51,3 +51,8 @@ table { border-collapse: collapse; border-spacing: 0; } + +button { + background: none; + border: none; +} \ No newline at end of file diff --git a/packages/play-node-go/src/pages/Layout/MainWrapper/MainWrapper.scss b/packages/play-node-go/src/pages/Layout/MainWrapper/MainWrapper.scss index 6dbe9e0..b31fc93 100644 --- a/packages/play-node-go/src/pages/Layout/MainWrapper/MainWrapper.scss +++ b/packages/play-node-go/src/pages/Layout/MainWrapper/MainWrapper.scss @@ -1,4 +1,5 @@ @import '../../../../public/stylesheets/partials/mixins'; +@import '../../../../public/stylesheets/partials/variables'; div.main-wrapper { display: flex; @@ -33,4 +34,15 @@ div.main-wrapper { height: 100%; } } +} + +button { + color:map-get($colors, 'sidebar_link'); + cursor: pointer; + font-family: inherit; + font-size: 110%; + font-weight: bold; + margin-bottom: .5em; + padding: 0; + text-decoration: none; } \ No newline at end of file diff --git a/packages/play-node-go/src/pages/Layout/NavBar/NavBar.js b/packages/play-node-go/src/pages/Layout/NavBar/NavBar.js index 02da86e..c3e0f82 100644 --- a/packages/play-node-go/src/pages/Layout/NavBar/NavBar.js +++ b/packages/play-node-go/src/pages/Layout/NavBar/NavBar.js @@ -1,29 +1,36 @@ -import React from 'react'; -import { Link } from 'react-router-dom'; -import './NavBar.scss'; -import Logo from '../../../components/Display/Logo/Logo'; - -const NavBar = (props) => { +import React from "react"; +import { Link } from "react-router-dom"; +import "./NavBar.scss"; +import Logo from "../../../components/Display/Logo/Logo"; +const NavBar = ({ state }) => { return (
- -
+ +
+ +
- -

Find a Game

+ +
+

Find a Game

+
- + -

News

+
+

News

+
-
{props.user ? props.user.username : <>}
+
+ {state.user.username ? state.user.username : <>} +
); -} +}; -export default NavBar; \ No newline at end of file +export default NavBar;