diff --git a/package-lock.json b/package-lock.json index 96925d4..1585926 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,13 +13,16 @@ "@ijl/cli": "^5.1.0", "@types/react": "^18.3.5", "@types/react-dom": "^18.3.0", + "dotenv": "^16.4.5", "emoji-mart": "^5.6.0", "express": "^4.19.2", + "jsonwebtoken": "^9.0.2", "react": "^18.3.1", "react-dom": "^18.3.1", "react-emoji-picker": "^1.0.13", "react-icons": "^5.3.0", "react-router-dom": "^6.26.1", + "react-toastify": "^10.0.5", "styled-components": "^6.1.13", "typescript": "^5.5.4", "ws": "^8.18.0" @@ -3843,6 +3846,12 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "license": "BSD-3-Clause" + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -4078,6 +4087,15 @@ "node": ">=6" } }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", @@ -4684,6 +4702,18 @@ "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==" }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, "node_modules/duplexer": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", @@ -4694,6 +4724,15 @@ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -6695,6 +6734,40 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "license": "MIT", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jsonwebtoken/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/jstransform": { "version": "11.0.3", "resolved": "https://registry.npmjs.org/jstransform/-/jstransform-11.0.3.tgz", @@ -6735,6 +6808,27 @@ "node": ">=0.8.0" } }, + "node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "license": "MIT", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, "node_modules/keygrip": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz", @@ -6815,6 +6909,48 @@ "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "license": "MIT" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "license": "MIT" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", + "license": "MIT" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "license": "MIT" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "license": "MIT" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "license": "MIT" + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -8140,6 +8276,19 @@ "react-dom": ">=16.8" } }, + "node_modules/react-toastify": { + "version": "10.0.5", + "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-10.0.5.tgz", + "integrity": "sha512-mNKt2jBXJg4O7pSdbNUfDdTsK9FIdikfsIE/yUCxbAEXl4HMyJaivrVFcn3Elvt5xvCQYhUZm+hqTIu1UXM3Pw==", + "license": "MIT", + "dependencies": { + "clsx": "^2.1.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", diff --git a/package.json b/package.json index fe92ab7..a0cee93 100644 --- a/package.json +++ b/package.json @@ -7,11 +7,13 @@ "@types/react-dom": "^18.3.0", "emoji-mart": "^5.6.0", "express": "^4.19.2", + "jsonwebtoken": "^9.0.2", "react": "^18.3.1", "react-dom": "^18.3.1", "react-emoji-picker": "^1.0.13", "react-icons": "^5.3.0", "react-router-dom": "^6.26.1", + "react-toastify": "^10.0.5", "styled-components": "^6.1.13", "typescript": "^5.5.4", "ws": "^8.18.0" diff --git a/src/app.tsx b/src/app.tsx index e0758d2..fc17077 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -1,21 +1,39 @@ -import React from 'react'; -import { BrowserRouter } from 'react-router-dom'; +import React, {useEffect} from 'react'; +import { BrowserRouter } from 'react-router-dom'; import { Dashboard } from './dashboard'; -import { getConfigValue } from "@brojs/cli"; +import {ToastContainer} from "react-toastify"; +import 'react-toastify/dist/ReactToastify.css'; + import './index.css' - -const BASE_API_URL = getConfigValue("enterfront.api"); - -// fetch(`${BASE_API_URL}/books/list`) +import {displayMessage} from "./backend/notifications/notifications.js"; +import {MessageType} from "./backend/notifications/message"; const App = () => { + useEffect(() => { + document.title = 'Enterfront'; + }, []); + + useEffect(() => { + const msg = localStorage.getItem('message'); + + if (!msg) return; + + displayMessage(msg, MessageType.SUCCESS); + localStorage.removeItem('message'); + }, []); + return( - - - +
+ + + + + +
+ ) } diff --git a/src/backend/api.js b/src/backend/api.js new file mode 100644 index 0000000..86ab0ff --- /dev/null +++ b/src/backend/api.js @@ -0,0 +1,45 @@ +import {getConfigValue} from "@brojs/cli"; + +export const BASE_API_URL = "http://localhost:8099" + getConfigValue("enterfront.api"); + +// fetch(`${BASE_API_URL}/books/list`) + +export async function post(path, body) { + const res = await fetch(`${BASE_API_URL}${path}`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(body) + }); + + if (res.status === 200) { + const data = await res.json(); + console.log("Received post:", data); + + return {ok: true, data: data}; + } else { + const errorData = await res.json(); + console.log("Error during post:", errorData.message); + + return {ok: false, data: errorData}; + } +} + +export async function get(path){ + const res = await fetch(`${BASE_API_URL}${path}`, { + method: "GET" + }); + + if (res.status === 200) { + const data = await res.json(); + console.log("Received get:", data); + + return {ok: true, data: data}; + } else { + const errorData = await res.json(); + console.log("Error during get:", errorData.message); + + return {ok: false, data: errorData}; + } +} diff --git a/src/backend/notifications/message.tsx b/src/backend/notifications/message.tsx new file mode 100644 index 0000000..5bc346e --- /dev/null +++ b/src/backend/notifications/message.tsx @@ -0,0 +1,6 @@ +export enum MessageType { + ERROR, + SUCCESS, + INFO, + WARN +} \ No newline at end of file diff --git a/src/backend/notifications/notifications.js b/src/backend/notifications/notifications.js new file mode 100644 index 0000000..1d05d3c --- /dev/null +++ b/src/backend/notifications/notifications.js @@ -0,0 +1,28 @@ +import {toast} from "react-toastify"; +import {MessageType} from "./message.tsx"; + +export const displayMessage = (message, type) => { + switch (type) { + default: + case MessageType.ERROR: + toast.error(message, { + position: 'bottom-right', + }); + break; + case MessageType.INFO: + toast.info(message, { + position: 'bottom-right', + }); + break; + case MessageType.SUCCESS: + toast.success(message, { + position: 'bottom-right', + }); + break; + case MessageType.WARN: + toast.warn(message, { + position: 'bottom-right', + }); + break; + } +} \ No newline at end of file diff --git a/src/components/account/AccountButtons.jsx b/src/components/account/AccountButtons.jsx index 057a39a..6c9539e 100644 --- a/src/components/account/AccountButtons.jsx +++ b/src/components/account/AccountButtons.jsx @@ -5,10 +5,13 @@ import ActionButton from "./ActionButton.jsx"; const AccountButtons = (props) => { return (
- - - - + {props.registered ? ( + <> + + + + + ) : null} Back
); diff --git a/src/components/account/HelloItem.jsx b/src/components/account/HelloItem.jsx new file mode 100644 index 0000000..0651710 --- /dev/null +++ b/src/components/account/HelloItem.jsx @@ -0,0 +1,18 @@ +import React from 'react'; + +const HelloItem = (props) => { + return ( +
+ {!!props.nickname ? ( + <> +

Hello, {props.nickname}!

+

Your ID: {props.id}

+ + ) : ( +

You don't have account :(

+ )} +
+ ); +}; + +export default HelloItem; diff --git a/src/components/account/index.css b/src/components/account/index.css index 24a314b..bb2292b 100644 --- a/src/components/account/index.css +++ b/src/components/account/index.css @@ -3,6 +3,8 @@ flex-direction: column; align-items: center; justify-content: center; + + margin-bottom: 30px; } .account-buttons a { @@ -20,10 +22,33 @@ color: black; } +.hello-item-class { + display: flex; + flex-direction: column; + align-items: center; +} + +.hello-item-class h1 { + font-size: 4vw; + margin-bottom: 0; +} + +.hello-item-class p { + font-size: 1.5vw; +} + @media only screen and (max-width: 800px) { .account-buttons a { font-size: 2.5vh; width: 60vw; margin-top: 3vh; } + + .hello-item-class h1 { + font-size: 5vh; + } + + .hello-item-class p { + font-size: 2vh; + } } diff --git a/src/pages/Account.jsx b/src/pages/Account.jsx index 6a9e154..c6d51c8 100644 --- a/src/pages/Account.jsx +++ b/src/pages/Account.jsx @@ -1,19 +1,53 @@ -import React from "react"; +import React, {useEffect, useState} from "react"; import AccountButtons from "../components/account/AccountButtons.jsx"; import userIcon from "../../images/user.svg"; +import {get} from "../backend/api"; +import {displayMessage} from "../backend/notifications/notifications"; +import {MessageType} from "../backend/notifications/message"; +import HelloItem from "../components/account/HelloItem.jsx"; const Account = () => { - const exitHandler = () => {} - const changeNameHandler = () => {} - const changePassHandler = () => {} + const exitHandler = () => { + localStorage.removeItem("username"); + localStorage.removeItem("token"); + + localStorage.setItem("message", "Exited successfully!"); + window.location.href = "/"; + } + const changeNameHandler = () => {} + const changePassHandler = () => {} + + const [nickname, setNickname] = useState(""); + const [id, setId] = useState(""); + + async function getUser() { + const username = localStorage.getItem("username"); + if (!username) { + displayMessage("You're not logged in!", MessageType.WARN); + return; + } + + const {ok, data} = await get('/auth/' + username); + if (!ok) { + displayMessage("Some error with auth", MessageType.ERROR); + return; + } + + setNickname(data.user.nickname); + setId(username); + } + + useEffect(() => {getUser().then()}, []) return (
user +
); diff --git a/src/pages/SignIn.jsx b/src/pages/SignIn.jsx index fa11d9d..878a297 100644 --- a/src/pages/SignIn.jsx +++ b/src/pages/SignIn.jsx @@ -3,12 +3,41 @@ import InputField from "../components/reg/InputField.jsx"; import LoginButtons from "../components/reg/LoginButtons.jsx"; import LoginTitle from "../components/reg/loginTitle.jsx"; +import {MessageType} from "../backend/notifications/message.tsx"; +import {displayMessage} from "../backend/notifications/notifications.js"; +import {post} from "../backend/api.js"; + const SignIn = () => { const [name, setName] = useState(""); const [password, setPassword] = useState(""); - const submit = (e) => { - console.log('Sign In!') + const [nameErrorsCounter, setNameErrorsCounter] = useState(0); + + async function submit() { + console.log('Sign In!') + + const {ok, data} = await post('/auth/login', {name: name, password: password}); + + if (!ok) { + displayMessage(data.message, MessageType.ERROR); + + if (nameErrorsCounter >= 1) { + displayMessage("Note that you need to enter your ID name", MessageType.INFO); + setNameErrorsCounter(0); + } else { + setNameErrorsCounter(nameErrorsCounter + 1); + } + + return; + } + + localStorage.setItem('token', data.token); + localStorage.setItem('username', name); + + setNameErrorsCounter(0); + + localStorage.setItem('message', 'Successfully logged in!'); + window.location.href = "/"; } return ( diff --git a/src/pages/SignUp.jsx b/src/pages/SignUp.jsx index 3d102a6..24a517d 100644 --- a/src/pages/SignUp.jsx +++ b/src/pages/SignUp.jsx @@ -2,20 +2,59 @@ import React, {useState} from 'react'; import InputField from "../components/reg/InputField.jsx"; import LoginButtons from "../components/reg/LoginButtons.jsx"; import LoginTitle from "../components/reg/loginTitle.jsx"; +import {post} from "../backend/api"; +import {displayMessage} from "../backend/notifications/notifications"; +import {MessageType} from "../backend/notifications/message"; + const SignUp = () => { const [name, setName] = useState(""); + const [nickname, setNickname] = useState(""); const [password, setPassword] = useState(""); const [repeatPassword, setRepeatPassword] = useState(""); - const submit = (e) => { - console.log('Sign Up!') + async function login(name, password) { + const {ok, data} = await post('/auth/login', {name: name, password: password}); + return {loginStatus: ok, loginData: data}; + } + + async function submit () { + console.log('Sign Up!'); + + if (password !== repeatPassword) { + displayMessage("Passwords don't match", MessageType.WARN); + return; + } + + const {ok, data} = await post('/auth/reg', + {name: name, password: password, nickname: nickname}); + + if (!ok) { + displayMessage(data.message, MessageType.ERROR); + return; + } + + const { loginStatus, loginData } = await login(name, password); + + console.log(loginStatus, loginData) + + if (!loginStatus) { + displayMessage(loginData.message, MessageType.ERROR); + return; + } + + localStorage.setItem('token', loginData.token); + localStorage.setItem('username', name); + + localStorage.setItem('message', 'Successfully signed up!'); + window.location.href = "/"; } return (
+ diff --git a/stubs/api/auth/index.js b/stubs/api/auth/index.js new file mode 100644 index 0000000..0d9731f --- /dev/null +++ b/stubs/api/auth/index.js @@ -0,0 +1,87 @@ +const authRouter = require('express').Router(); + +// For cryptography +// const bcrypt = require('bcrypt'); + +// For creating tokens +const jwt = require('jsonwebtoken'); +const TOKEN_KEY = "5frv12e4few3r" + + +module.exports = authRouter; + +// Read already defined users (pseudo-DB) +const users = require('./users.json'); + +const getUserFromDB = (userID) => { + if (!userID) {return false;} + + // Accessing 'DB' + const user = users.find((user) => user.id === userID); + + if (user) { + return user; + } else { + return false; + } +} + +// Get a user by its id +authRouter.get('/:id', (req, res) => { + const user = getUserFromDB(req.params.id); + console.log("Request get in /auth:", req.params.id); + + if (user) { + res.status(200).send({user}); + } else { + res.status(404).send({message: 'User was not found'}); + } +}) + +// For login (authorization) +authRouter.post('/login', (req, res) => { + const { name, password } = req.body; + console.log("Request login in /auth:", name); + + const user = getUserFromDB(name); + + // Invalid identification + if (!user) { + res.status(401).send({message: 'Invalid credentials (id)'}); + } + + // Invalid authentication + if (!password || password !== user.password) { + res.status(401).send({message: 'Invalid credentials (password)'}); + } + + // Now, authorization + const token = jwt.sign({id: name}, TOKEN_KEY, { + expiresIn: '1h' + }) + + res.status(200).send({token}); +}) + + +authRouter.post('/reg', (req, res) => { + const { name, password, nickname } = req.body; + console.log("Request reg in /auth:", name); + + const user = getUserFromDB(name); + + // Invalid identification + if (user) { + res.status(409).send({message: 'Such id already exists'}); + } + + if (!name || !password || !nickname) { + res.status(401).send({message: 'Empty or invalid fields'}); + } + + // Add to 'DB' + const newUser = {id: name, password: password, nickname: nickname}; + users.push(newUser); + + res.status(200).send({user: newUser}); +}) diff --git a/stubs/api/auth/users.json b/stubs/api/auth/users.json new file mode 100644 index 0000000..c502b5d --- /dev/null +++ b/stubs/api/auth/users.json @@ -0,0 +1,12 @@ +[ + { + "nickname": "Nick", + "password": "1234", + "id": "Nickolaus_SDR" + }, + { + "nickname": "User", + "password": "1234", + "id": "id" + } +] \ No newline at end of file diff --git a/stubs/api/index.js b/stubs/api/index.js index 2dd59fa..9e2ef60 100644 --- a/stubs/api/index.js +++ b/stubs/api/index.js @@ -1,8 +1,13 @@ const booksRouter = require("./books"); +const authRouter = require("./auth"); + const router = require('express').Router(); + const delay = require('./middlewares/delay'); module.exports = router; // router.use(delay(300)); -router.use('/books', delay, booksRouter); +// router.use('/books', delay, booksRouter); + +router.use('/auth', authRouter);