diff --git a/functions/handlers/users.js b/functions/handlers/users.js
index cdeb3f6..1c217e5 100644
--- a/functions/handlers/users.js
+++ b/functions/handlers/users.js
@@ -121,11 +121,11 @@ exports.login = (req, res) => {
return data.user.getIdToken();
})
.then((token) => {
- return res.json({ token });
+ return res.status(200).json({ token });
})
.catch((err) => {
console.error(err);
- if (err.code === "auth/wrong-password") {
+ if (err.code === "auth/wrong-password" || err.code === "auth/invalid-email") {
return res
.status(403)
.json({ general: "Invalid credentials. Please try again." });
diff --git a/twistter-frontend/package-lock.json b/twistter-frontend/package-lock.json
index 2fb6aa4..8b43be3 100644
--- a/twistter-frontend/package-lock.json
+++ b/twistter-frontend/package-lock.json
@@ -5277,6 +5277,11 @@
"resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-1.4.1.tgz",
"integrity": "sha1-OGchPo3Xm/Ho8jAMDPwe+xgsDfE="
},
+ "jwt-decode": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-2.2.0.tgz",
+ "integrity": "sha1-fYa9VmefWM5qhHBKZX3TkruoGnk="
+ },
"kind-of": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
diff --git a/twistter-frontend/package.json b/twistter-frontend/package.json
index bc4672f..a83c175 100644
--- a/twistter-frontend/package.json
+++ b/twistter-frontend/package.json
@@ -8,6 +8,7 @@
"clsx": "^1.0.4",
"create-react-app": "^3.1.2",
"install": "^0.13.0",
+ "jwt-decode": "^2.2.0",
"node-pre-gyp": "^0.13.0",
"react": "^16.9.0",
"react-dom": "^16.9.0",
@@ -36,5 +37,5 @@
"last 1 safari version"
]
},
- "proxy": "https://us-central1-twistter-e4649.cloudfunctions.net/api"
+ "proxy": "https://us-central1-twistter-e4649.cloudfunctions.net/api"
}
diff --git a/twistter-frontend/src/App.js b/twistter-frontend/src/App.js
index a0a4720..4a13d53 100644
--- a/twistter-frontend/src/App.js
+++ b/twistter-frontend/src/App.js
@@ -6,16 +6,31 @@ import './App.css';
import { BrowserRouter as Router } from 'react-router-dom';
import Route from 'react-router-dom/Route';
import Navbar from './components/layout/NavBar';
+import jwtDecode from 'jwt-decode';
+
+// Components
+import AuthRoute from './util/AuthRoute';
import home from './pages/Home';
import register from './pages/Register';
import login from './pages/Login';
-import user from './pages/User';
-
+import user from './pages/user';
import writeMicroblog from './Writing_Microblogs.js';
import edit from './pages/edit.js';
import userLine from './Userline.js';
+let authenticated;
+const token = localStorage.FBIdToken;
+if (token) {
+ const decodedToken = jwtDecode(token);
+ if (decodedToken.exp * 1000 < Date.now()) {
+ window.location.href = '/login';
+ authenticated = false;
+ } else {
+ authenticated = true;
+ }
+}
+
class App extends Component {
render() {
return (
@@ -24,9 +39,9 @@ class App extends Component {
-
-
-
+
+
+
diff --git a/twistter-frontend/src/pages/Login.js b/twistter-frontend/src/pages/Login.js
index 76531d2..2686e84 100644
--- a/twistter-frontend/src/pages/Login.js
+++ b/twistter-frontend/src/pages/Login.js
@@ -1,26 +1,171 @@
-/* eslint-disable */
-import React, { Component } from 'react';
-import '../App.css';
-
+import React, { Component } from "react";
+import axios from "axios";
+import PropTypes from "prop-types";
import logo from '../images/twistter-logo.png';
-import TextField from '@material-ui/core/TextField';
-class Login extends Component {
- render() {
- return (
-
-

-
-
Log in to Twistter
-
-
-
-
-
-
-
- );
+// Material-UI stuff
+import Button from "@material-ui/core/Button";
+import CircularProgress from "@material-ui/core/CircularProgress";
+import Grid from "@material-ui/core/Grid";
+import TextField from "@material-ui/core/TextField";
+import Typography from "@material-ui/core/Typography";
+import withStyles from "@material-ui/core/styles/withStyles";
+
+const styles = {
+ form: {
+ textAlign: "center"
+ },
+ textField: {
+ marginBottom: 30
+ },
+ pageTitle: {
+ // marginTop: 20,
+ marginBottom: 40
+ },
+ button: {
+ positon: "relative",
+ marginBottom: 30
+ },
+ progress: {
+ position: "absolute"
+ }
+};
+
+export class Login extends Component {
+ // componentDidMount() {
+ // axios
+ // .get("/getProfileInfo")
+ // .then((res) => {
+ // this.setState({
+ // firstName: res.data.firstName,
+ // lastName: res.data.lastName,
+ // email: res.data.email,
+ // handle: res.data.handle,
+ // bio: res.data.bio
+ // });
+ // })
+ // .catch((err) => {
+ // console.error(err);
+ // });
+ // }
+
+ // Constructor for the state
+ constructor() {
+ super();
+ this.state = {
+ email: "",
+ password:"",
+ loading: false,
+ errors: {}
+ };
+ }
+
+ // Runs whenever the submit button is clicked.
+ // Updates the database entry of the signed in user with the
+ // data stored in the state.
+ handleSubmit = (event) => {
+ event.preventDefault();
+ this.setState({
+ loading: true
+ });
+ const loginData = {
+ email: this.state.email,
+ password: this.state.password,
+ };
+ axios
+ .post("/login", loginData)
+ .then((res) => {
+ // Save the login token
+ localStorage.setItem('FBIdToken', `Bearer ${res.data.token}`);
+ this.setState({
+ loading: false
+ });
+ // Redirects to home page
+ this.props.history.push('/home');
+ })
+ .catch((err) => {
+ this.setState({
+ errors: err.response.data,
+ loading: false
+ });
+ });
};
+
+ // Updates the state whenever one of the textboxes changes.
+ // The key is the name of the textbox and the value is the
+ // value in the text box.
+ handleChange = (event) => {
+ this.setState({
+ [event.target.name]: event.target.value,
+ errors: {
+ [event.target.name]: null
+ }
+ });
+ };
+
+ render() {
+ const { classes } = this.props;
+ const { errors, loading } = this.state;
+
+ return (
+
+
+
+
+
+ Log in to Twistter
+
+
+
+
+
+ );
+ }
}
-export default Login;
\ No newline at end of file
+Login.propTypes = {
+ classes: PropTypes.object.isRequired
+};
+
+export default withStyles(styles)(Login);
diff --git a/twistter-frontend/src/util/AuthRoute.js b/twistter-frontend/src/util/AuthRoute.js
new file mode 100644
index 0000000..8cc2395
--- /dev/null
+++ b/twistter-frontend/src/util/AuthRoute.js
@@ -0,0 +1,11 @@
+import React from 'react'
+import { Route, Redirect} from 'react-router-dom';
+
+const AuthRoute = ({ component: Component, authenticated, ...rest}) => (
+ authenticated === true ? : }
+ />
+)
+
+export default AuthRoute;