diff --git a/backend/routes/index.js b/backend/routes/index.js index eb728d0..386a61b 100644 --- a/backend/routes/index.js +++ b/backend/routes/index.js @@ -1,45 +1,14 @@ +// backend/routes/index.js const express = require('express'); const router = express.Router(); + const apiRouter = require('./api'); router.use('/api', apiRouter); -// Static routes -// Serve React build files in production -if (process.env.NODE_ENV === "production") { - const path = require("path"); - // Serve the frontend's index.html file at the root route - router.get("/", (req, res) => { - res.cookie("XSRF-TOKEN", req.csrfToken()); - return res.sendFile( - path.resolve(__dirname, "../../frontend", "build", "index.html") - ); - }) - - // Serve the static assets in the frontend's build folder - router.use(express.static(path.resolve("../frontend/build"))); - - // Serve the frontend's index.html file at all other routes NOT starting with /api - router.get(/^(?!\/?api).*/, (req, res) => { - res.cookie("XSRF-TOKEN", req.csrfToken()); - res.sendFile( - path.resolve(__dirname, "../../frontend", "build", "index.html") - ); - }) -} - -// Add a XSRF-TOKEN cookie in development -if (process.env.NODE_ENV !== "production") { - router.get("/api/csrf/restore", (req, res) => { - res.cookie("XSRF-TOKEN", req.csrfToken()); - return res.json({}); - }) -} - -// for testing purposes -// router.get('/hello/world', function(req, res) { -// res.cookie('XSRF-TOKEN', req.csrfToken()); -// res.send('Hello World!'); +// router.get('/hello/world', function (req, res) { +// res.cookie('XSRF-TOKEN', req.csrfToken()); +// res.send('Hello World!'); // }); // Add a XSRF-TOKEN cookie @@ -50,5 +19,7 @@ router.get("/api/csrf/restore", (req, res) => { 'XSRF-Token': csrfToken }); }); +// ... + module.exports = router; diff --git a/frontend/package.json b/frontend/package.json index 6d10005..f3f5a97 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -38,6 +38,5 @@ }, "devDependencies": { "redux-logger": "^3.0.6" - }, - "proxy": "http://localhost:8000" + } } diff --git a/frontend/src/App.js b/frontend/src/App.js index 7dd9976..84cc12d 100644 --- a/frontend/src/App.js +++ b/frontend/src/App.js @@ -1,27 +1,6 @@ -// frontend/src/App.js -import React, { useState, useEffect } from "react"; -import { useDispatch } from "react-redux"; -import { Route, Switch } from "react-router-dom"; -import LoginFormPage from "./components/LoginFormPage"; -import SignupFormPage from "./components/SignupFormPage"; -import * as sessionActions from "./store/session"; - function App() { - const dispatch = useDispatch(); - const [isLoaded, setIsLoaded] = useState(false); - useEffect(() => { - dispatch(sessionActions.restoreUser()).then(() => setIsLoaded(true)); - }, [dispatch]); - - return isLoaded && ( - - - - - - - - + return ( +

Hello from App

); } diff --git a/frontend/src/components/LoginFormPage/LoginForm.css b/frontend/src/components/LoginFormPage/LoginForm.css deleted file mode 100644 index e69de29..0000000 diff --git a/frontend/src/components/LoginFormPage/index.js b/frontend/src/components/LoginFormPage/index.js deleted file mode 100644 index ec61984..0000000 --- a/frontend/src/components/LoginFormPage/index.js +++ /dev/null @@ -1,57 +0,0 @@ -// frontend/src/components/LoginFormPage/index.js -import React, { useState } from 'react'; -import * as sessionActions from '../../store/session'; -import { useDispatch, useSelector } from 'react-redux'; -import { Redirect } from 'react-router-dom'; -import './LoginForm.css'; - -function LoginFormPage() { - const dispatch = useDispatch(); - const sessionUser = useSelector(state => state.session.user); - const [credential, setCredential] = useState(''); - const [password, setPassword] = useState(''); - const [errors, setErrors] = useState([]); - - if (sessionUser) return ( - - ); - - const handleSubmit = (e) => { - e.preventDefault(); - setErrors([]); - return dispatch(sessionActions.login({ credential, password })) - .catch(async (res) => { - const data = await res.json(); - if (data && data.errors) setErrors(data.errors); - }); - } - - return ( -
- - - - -
- ); -} - -export default LoginFormPage; diff --git a/frontend/src/components/SignupFormPage/SignupForm.css b/frontend/src/components/SignupFormPage/SignupForm.css deleted file mode 100644 index e69de29..0000000 diff --git a/frontend/src/components/SignupFormPage/index.js b/frontend/src/components/SignupFormPage/index.js deleted file mode 100644 index 905bfdb..0000000 --- a/frontend/src/components/SignupFormPage/index.js +++ /dev/null @@ -1,98 +0,0 @@ -// frontend/src/components/SignupFormPage/index.js -import React, { useState } from "react"; -import { useDispatch, useSelector } from "react-redux"; -import { Redirect } from "react-router-dom"; -import * as sessionActions from "../../store/session"; -import './SignupForm.css'; - -function SignupFormPage() { - const dispatch = useDispatch(); - const sessionUser = useSelector((state) => state.session.user); - const [email, setEmail] = useState(""); - const [username, setUsername] = useState(""); - const [firstName, setFirstName] = useState(""); - const [lastName, setLastName] = useState(""); - const [password, setPassword] = useState(""); - const [confirmPassword, setConfirmPassword] = useState(""); - const [errors, setErrors] = useState([]); - - if (sessionUser) return ; - - const handleSubmit = (e) => { - e.preventDefault(); - if (password === confirmPassword) { - setErrors([]); - return dispatch(sessionActions.signup({ email, username, firstName, lastName, password })) - .catch(async (res) => { - const data = await res.json(); - if (data && data.errors) setErrors(data.errors); - }); - } - return setErrors(['Confirm Password field must be the same as the Password field']); - }; - - return ( -
-
    - {errors.map((error, idx) =>
  • {error}
  • )} -
- - - - - - - -
- ); -} - -export default SignupFormPage; diff --git a/frontend/src/index.js b/frontend/src/index.js index ce6f069..bc59ab1 100644 --- a/frontend/src/index.js +++ b/frontend/src/index.js @@ -5,17 +5,11 @@ import { Provider as ReduxProvider } from 'react-redux'; import './index.css'; import App from './App'; import configureStore from './store'; -import { restoreCSRF, csrfFetch } from './store/csrf'; -import * as sessionActions from './store/session'; const store = configureStore(); -if (process.env.NODE_ENV !== 'production') { - restoreCSRF(); - - window.csrfFetch = csrfFetch; +if (process.env.NODE_ENV !== "production") { window.store = store; - window.sessionActions = sessionActions; } function Root() { diff --git a/frontend/src/store/csrf.js b/frontend/src/store/csrf.js deleted file mode 100644 index c6869ee..0000000 --- a/frontend/src/store/csrf.js +++ /dev/null @@ -1,31 +0,0 @@ -import Cookies from "js-cookie"; - -export async function csrfFetch(url, options = {}) { - // set options.method to "GET" if there is no method - options.method = options.method || "GET"; - - // set options.headers to an empty object if there are no headers - options.headers = options.headers || {}; - - // if options.method is not "GET", set "Content-Type" header to "application/json" - // set "XSRF-TOKEN" header to the value of the "XSRF-TOKEN" cookie - if (options.method.toUpperCase() !== "GET") { - options.headers["Content-Type"] = - options.headers["Content-Type"] || "application/json"; - options.headers["XSRF-Token"] = Cookies.get("XSRF-TOKEN"); - } - - // call the default window's fetch with the url and the options passed in - const res = await window.fetch(url, options); - - // if the response status code is 400 or above, then throw an error with error being the response - if (res.status >= 400) throw res; - - // if the response is under 400, then return the response to the next promise chain - return res -} - -// call this to get the "XSRF-TOKEN" cookie, should only be used in development -export function restoreCSRF() { - return csrfFetch("/api/csrf/restore"); -} diff --git a/frontend/src/store/index.js b/frontend/src/store/index.js index 90a2cf6..4510e33 100644 --- a/frontend/src/store/index.js +++ b/frontend/src/store/index.js @@ -1,10 +1,8 @@ import { createStore, combineReducers, applyMiddleware, compose } from "redux"; import thunk from "redux-thunk"; -import sessionReducer from './session'; const rootReducer = combineReducers({ // add reducer functions here - session: sessionReducer, }); let enhancer; diff --git a/frontend/src/store/session.js b/frontend/src/store/session.js deleted file mode 100644 index 97b8d71..0000000 --- a/frontend/src/store/session.js +++ /dev/null @@ -1,80 +0,0 @@ -// frontend/src/store/session.js -import { csrfFetch } from './csrf'; - -const SET_USER = 'session/setUser'; -const REMOVE_USER = 'session/removeUser'; - - -// ACTIONS -const setUser = (user) => { - return { - type: SET_USER, - payload: user, - }; -}; - -const removeUser = () => { - return { - type: REMOVE_USER, - }; -}; - - -// THUNKS -export const login = (user) => async (dispatch) => { - const { credential, password } = user; - const response = await csrfFetch('/api/session', { - method: 'POST', - body: JSON.stringify({ - credential, - password, - }), - }); - const data = await response.json(); - dispatch(setUser(data.user)); - return response; -}; - -export const restoreUser = () => async dispatch => { - const response = await csrfFetch('/api/session'); - const data = await response.json(); - dispatch(setUser(data.user)); - return response; -}; - -export const signup = (user) => async (dispatch) => { - const { username, firstName, lastName, email, password } = user; - const response = await csrfFetch("/api/users", { - method: "POST", - body: JSON.stringify({ - username, - firstName, - lastName, - email, - password, - }), - }); - const data = await response.json(); - dispatch(setUser(data.user)); - return response; -}; - -const initialState = { user: null }; - -const sessionReducer = (state = initialState, action) => { - let newState; - switch (action.type) { - case SET_USER: - newState = Object.assign({}, state); - newState.user = action.payload; - return newState; - case REMOVE_USER: - newState = Object.assign({}, state); - newState.user = null; - return newState; - default: - return state; - } -}; - -export default sessionReducer;