Skip to content
This repository has been archived by the owner on Jul 31, 2024. It is now read-only.

Commit

Permalink
Merge pull request #22 from Vyctor661/fe-auth
Browse files Browse the repository at this point in the history
Fe auth
  • Loading branch information
vycdev authored Jul 11, 2020
2 parents 75f0a5a + 8587ed5 commit 712a103
Show file tree
Hide file tree
Showing 12 changed files with 248 additions and 15 deletions.
2 changes: 1 addition & 1 deletion packages/api/src/modules/auth/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ router.get("/logout", requireAuthenticated(), async (ctx, next) => {

router.get("/isLoggedIn", async (ctx, next) => {
ctx.status = 200;
ctx.body = !!ctx.session;
ctx.body = !!ctx.session!.user;
await next();
});

Expand Down
3 changes: 2 additions & 1 deletion packages/api/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
"strictNullChecks": true,
"noImplicitThis": true,
"moduleResolution": "node",
"esModuleInterop": true
"esModuleInterop": true,
"noImplicitAny": false
},
"exclude": ["node_modules"],
"include": ["src", "db"]
Expand Down
1 change: 1 addition & 0 deletions packages/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"@types/koa": "^2.11.0",
"@types/koa-static": "^4.0.1",
"@types/react-router-dom": "^5.1.3",
"dotenv": "^8.2.0",
"koa": "^2.11.0",
"koa-static": "^5.0.0",
"react": "^16.11.0",
Expand Down
35 changes: 32 additions & 3 deletions packages/web/src/components/common/navbar/navBar.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,33 @@
import * as React from "react";
import React, { useEffect, useState } from "react";

import { Link } from "react-router-dom";

import { Ul, Li, Fix, LoginLi } from "./style";

import { apiUrl } from "../../../utils/constants";

// Navbar component

export const Navbar = () => {
const [isLogged, setIsLogged] = useState(false);

const isLoggedFunc = async () => {
const response = await (
await fetch(`${apiUrl}/auth/isloggedin`, {
method: "GET",
credentials: "include",
headers: {
"Content-Type": "application/json"
}
})
).json();
setIsLogged(response);
};

useEffect(() => {
isLoggedFunc();
}, []);

return (
<Fix>
<Ul>
Expand All @@ -19,9 +40,17 @@ export const Navbar = () => {
<Li>
<Link to="/stats">Statistics</Link>
</Li>

<LoginLi>
{" "}
<Link to="/loginregister/login">Login</Link>
<Link
onClick={async () => {
console.log(isLogged);
isLoggedFunc();
}}
to={isLogged ? "/profile" : "/loginregister/login"}
>
{isLogged ? "Profile" : "Login"}
</Link>
</LoginLi>
</Ul>
</Fix>
Expand Down
156 changes: 146 additions & 10 deletions packages/web/src/components/loginPage/loginPage.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from "react";
import React, { useState, useRef } from "react";
import { Link, Route, Switch } from "react-router-dom";

import {
Expand All @@ -9,50 +9,186 @@ import {
FixCrown,
Title,
FormWrapper,
Button
Button,
StatusDiv,
StatusDivWrapper
} from "./style";
import { LogoSvg } from "../common/logo/logo";
import { apiUrl } from "../../utils/constants";

const LoginForm = () => {
const [loginEmail, setLoginEmail] = useState("");
const [loginPassword, setLoginPassword] = useState("");
const statusDiv = useRef(null);

const login = async (email: string, password: string) => {
const response = await fetch(`${apiUrl}/auth/login`, {
method: "POST",
credentials: "include",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({ email, password })
});
if (response.status === 200) {
location.replace("");
} else if (response.status === 401) {
statusDiv.current.innerHTML = "You are already logged in.";
} else if (response.status === 400) {
statusDiv.current.innerHTML = "Invalid user or password.";
} else {
statusDiv.current.innerHTML =
"Oops, looks like something went wrong.";
}
};

return (
<FormWrapper>
<form
onSubmit={() => {
alert("works fine");
login(loginEmail, loginPassword);
}}
>
<label>
<input type="text" placeholder="Username" />
<input
type="text"
placeholder="Email"
onChange={e => {
setLoginEmail(e.target.value);
}}
/>
</label>
<label>
<input type="password" placeholder="Password" />
<input
type="password"
placeholder="Password"
onChange={e => {
setLoginPassword(e.target.value);
}}
/>
</label>
<StatusDivWrapper>
<StatusDiv ref={statusDiv}></StatusDiv>
</StatusDivWrapper>

<input type="submit" value="Login" />
</form>
</FormWrapper>
);
};

const RegiserForm = () => {
const [registerEmail, setRegisterEmail] = useState("");
const [registerName, setRegisterName] = useState("");
const [registerPassword, setRegisterPassword] = useState("");
const [registerConfirmPassword, setRegisterConfirmPassword] = useState("");

const statusDiv = useRef(null);

const checkRegisterFields = (): boolean => {
const regexPassword = new RegExp(
/^((?=.*[a-z])(?=.*[A-Z\d])(?=.*[a-zA-Z]).{8,})$/
);

const regexEmail = new RegExp( // eslint-disable-next-line no-useless-escape
/[a-z0-9!#$%&'*+\=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+\=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/
);

statusDiv.current.innerHTML = "";
if (
registerEmail === "" ||
registerName === "" ||
registerPassword === "" ||
registerConfirmPassword === ""
) {
statusDiv.current.innerHTML = "Please fill out all the boxes.";
return false;
} else if (!regexEmail.test(registerEmail)) {
statusDiv.current.innerHTML = "Please enter a valid email adress.";
return false;
} else if (registerPassword != registerConfirmPassword) {
statusDiv.current.innerHTML = "The two passwords do not match.";
return false;
} else if (!regexPassword.test(registerPassword)) {
statusDiv.current.innerHTML =
"Password must at least 8 characters long and have at least 1 lowercase letter, 1 uppercase letter and 1 number.";
return false;
}

statusDiv.current.innerHTML = "";
return true;
};

const register = async (email: string, name: string, password: string) => {
if (checkRegisterFields()) {
const response = await fetch(`${apiUrl}/users/createuser`, {
method: "POST",
credentials: "include",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({ email, password, name })
});
if (response.status === 201) {
location.replace("");
} else if (response.status === 400) {
statusDiv.current.innerHTML =
"Username or Email already taken.";
} else if (response.status === 401) {
statusDiv.current.innerHTML =
"You can't register while you are logged in.";
} else {
statusDiv.current.innerHTML =
"Oops, looks like something went wrong.";
}
}
};
return (
<FormWrapper>
<form
onSubmit={() => {
alert("works fine");
register(registerEmail, registerName, registerPassword);
}}
>
<label>
<input type="text" placeholder="Username" />
<input
type="text"
placeholder="Username"
onChange={e => {
setRegisterName(e.target.value);
}}
/>
</label>
<label>
<input type="email" placeholder="Email" />
<input
type="email"
placeholder="Email"
onChange={e => {
setRegisterEmail(e.target.value);
}}
/>
</label>
<label>
<input type="password" placeholder="Password" />
<input
type="password"
placeholder="Password"
onChange={e => {
setRegisterPassword(e.target.value);
}}
/>
</label>
<label>
<input type="password" placeholder="Confirm Password" />
<input
type="password"
placeholder="Confirm Password"
onChange={e => {
setRegisterConfirmPassword(e.target.value);
}}
/>
</label>
<StatusDivWrapper>
<StatusDiv ref={statusDiv}></StatusDiv>
</StatusDivWrapper>
<input type="submit" value="Register" />
</form>
</FormWrapper>
Expand Down
15 changes: 15 additions & 0 deletions packages/web/src/components/loginPage/style.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,18 @@ export const Button = styled.div`
color: ${theme.text.secondary};
}
`;

export const StatusDivWrapper = styled.div`
margin: 5px;
max-width: 100%;
position: relative;
`;

export const StatusDiv = styled.div`
width: 100%;
word-wrap: wrap;
position: absolute;
font-family: "Verdana";
font-size: 12px;
color: ${theme.status.negative};
`;
22 changes: 22 additions & 0 deletions packages/web/src/components/profilePage/profilePage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React from "react";

import { apiUrl } from "../../utils/constants";

export const ProfilePage = () => {
return (
<button
onClick={async () => {
await fetch(`${apiUrl}/auth/logout`, {
method: "GET",
credentials: "include",
headers: {
"Content-Type": "application/json"
}
});
location.replace("");
}}
>
Logout
</button>
);
};
4 changes: 4 additions & 0 deletions packages/web/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { StatisticsPage } from "./components/statisticsPage/statisticsPage";
import { StartTypingPage } from "./components/startTypingPage/startTypingPage";

import { LoginRegisterPage } from "./components/loginPage/loginPage";
import { ProfilePage } from "./components/profilePage/profilePage";

import { Global } from "@emotion/core";
import { globalStyle, Container, Content } from "./style";
Expand All @@ -34,6 +35,9 @@ const App = () => {
<Route exact path="/stats">
<StatisticsPage />
</Route>
<Route exact path="/profile">
<ProfilePage />
</Route>
<Route path="/loginregister">
<LoginRegisterPage />
</Route>
Expand Down
12 changes: 12 additions & 0 deletions packages/web/src/utils/constants.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { TypingBoxProps } from "../components/common/typingBox/helpers/interfaces";
import { config } from "dotenv";

config();

export type TypingBoxColorCodes = TypingBoxProps["colorCodes"];

Expand All @@ -18,5 +21,14 @@ export interface ThemeType {
lighter: number;
darker: number;
};
status: {
positive: string;
negative: string;
};
boxColorCodes: TypingBoxColorCodes;
}

export const apiUrl =
process.env.NODE_ENV === "development"
? "http://localhost:8090/api"
: "https://king-typer-api.herokuapp.com/api";
8 changes: 8 additions & 0 deletions packages/web/src/utils/getTheme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ const lightTheme: ThemeType = {
wrong: "#f54242",
correct: "#4290f5",
notTyped: "#111"
},
status: {
positive: "#0f4f00",
negative: "#cc0000"
}
};

Expand All @@ -43,6 +47,10 @@ const darkTheme: ThemeType = {
wrong: "#f54242",
correct: "#4290f5",
notTyped: "#f7f7f7"
},
status: {
positive: "#37ff0a",
negative: "#ff5252"
}
};

Expand Down
3 changes: 3 additions & 0 deletions packages/web/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ const baseConfig = {
children: false,
entrypoints: false,
modules: false
},
node: {
fs: "empty"
}
};

Expand Down
Loading

0 comments on commit 712a103

Please sign in to comment.