diff --git a/client/src/App.jsx b/client/src/App.jsx index 21c5571b..042e44ef 100644 --- a/client/src/App.jsx +++ b/client/src/App.jsx @@ -2,7 +2,6 @@ import "./theme.scss"; // Global Style (includes normalize.css) import "./assets/styles/global/global.scss"; - // Import Routes import Routes from "./routes"; diff --git a/client/src/assets/styles/components/logIn.css b/client/src/assets/styles/components/logIn.css new file mode 100644 index 00000000..133f3432 --- /dev/null +++ b/client/src/assets/styles/components/logIn.css @@ -0,0 +1,64 @@ +.hero { + display: flex; + width: 22.5rem; + height: 40rem; + flex-direction: column; + align-items: center; + justify-content: center; + margin: auto; + padding: 1.75rem 0.25rem; + gap: 1.1875rem; +} + +.card { + background-color: #1f2a37; + border-radius: 1.875rem; + display: flex; + width: 16.9375rem; + padding: 1.0625rem 0rem; + margin-top: 3rem; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 0.875rem; +} +.card .input-field { + display: flex; + width: 14.16319rem; + padding: 0.125rem 0.75rem; + justify-content: flex-end; + align-items: center; + align-content: center; + gap: 0rem 9.25rem; + flex-wrap: wrap; +} +.card .input-field input { + background: #374151; + margin-block: 0.3rem; + border: 1px solid #4b5563; + border-radius: 0.25rem; + width: 12.66319rem; + height: 1.75rem; + flex-shrink: 0; +} + +.no-account { + color: #0694A2; + font-family: "Noto Kufi Arabic"; + margin-bottom: 1rem; +} + +button { + color: #e2efee; + font-family: "Noto Kufi Arabic"; + background: #046C4E; + border: 0px solid; + border-radius: 0.3125rem; + display: flex; + width: 7.25rem; + height: 1.875rem; + padding: 0.8125rem 0.625rem; + justify-content: center; + align-items: center; + gap: 1.25rem; +}/*# sourceMappingURL=logIn.css.map */ \ No newline at end of file diff --git a/client/src/assets/styles/components/logIn.scss b/client/src/assets/styles/components/logIn.scss new file mode 100644 index 00000000..7b4053b1 --- /dev/null +++ b/client/src/assets/styles/components/logIn.scss @@ -0,0 +1,74 @@ +$Teal-900: #014451; +$Teal-500: #0694A2; +$grey-800: #1f2a37; +$grey-700: #374151; +$grey-600: #4b5563; +$green-700: #046C4E; +$Primary-900: #0e0218; +$text-color: #e2efee; +$font: 'Noto Kufi Arabic'; + +.hero { + display: flex; + width: 22.5rem; + height: 40rem; + flex-direction: column; + align-items: center; + justify-content: center; + margin: auto; + padding: 1.75rem 0.25rem; + gap: 1.1875rem; +} + +.card { + background-color: $grey-800; + border-radius: 1.875rem; + display: flex; + width: 16.9375rem; + padding: 1.0625rem 0rem; + margin-top: 3rem; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 0.875rem; + .input-field { + display: flex; + width: 14.16319rem; + padding: 0.125rem 0.75rem; + justify-content: flex-end; + align-items: center; + align-content: center; + gap: 0rem 9.25rem; + flex-wrap: wrap; + input { + background: $grey-700; + margin-block: 0.3rem; + border: 1px solid $grey-600; + border-radius: 0.25rem; + width: 12.66319rem; + height: 1.75rem; + flex-shrink: 0; + } + } +} + +.no-account { + color: $Teal-500; + font-family: $font; + margin-bottom: 1rem; +} + +button { + color: $text-color; + font-family: $font; + background: $green-700; + border: 0px solid; + border-radius: 0.3125rem; + display: flex; + width: 7.25rem; + height: 1.875rem; + padding: 0.8125rem 0.625rem; + justify-content: center; + align-items: center; + gap: 1.25rem; +} diff --git a/client/src/assets/styles/components/signUp.css b/client/src/assets/styles/components/signUp.css new file mode 100644 index 00000000..e40032e3 --- /dev/null +++ b/client/src/assets/styles/components/signUp.css @@ -0,0 +1,87 @@ +.hero { + display: flex; + width: 22.5rem; + height: 93.375rem; + flex-direction: column; + align-items: center; + margin: auto; + padding: 1.75rem 0.25rem; + gap: 1.1875rem; +} + +.container { + background: #014451; + border-radius: 1.25rem; + display: flex; + width: 19rem; + padding: 1.5rem 0.4375rem; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 1.0625rem; +} + +.card { + background-color: #1f2a37; + border-radius: 1.875rem; + display: flex; + width: 16.9375rem; + padding: 1.0625rem 0rem; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 0.875rem; +} +.card .input-field { + display: flex; + width: 14.16319rem; + padding: 0.125rem 0.75rem; + justify-content: flex-end; + align-items: center; + align-content: center; + gap: 0rem 9.25rem; + flex-wrap: wrap; +} +.card .input-field input { + background: #374151; + margin-block: 0.3rem; + border: 1px solid #4b5563; + border-radius: 0.25rem; + width: 12.66319rem; + height: 1.75rem; + flex-shrink: 0; +} +.card .radio-field { + display: flex; + width: 14.16319rem; + padding: 0.5625rem 0.75rem; + flex-direction: column; + justify-content: flex-end; + align-items: flex-end; + flex-wrap: wrap; + gap: 0.0625rem; +} +.card .radio-field .radio-buttons { + display: flex; + padding: 0.3125rem 0.5rem; + margin: auto; + gap: 3.1875rem; +} +.card .radio-field .radio-buttons small input { + margin: 0.5rem; +} + +button { + color: #e2efee; + font-family: "Noto Kufi Arabic"; + background: #0e0218; + border: 0px solid; + border-radius: 0.3125rem; + display: flex; + width: 12.5rem; + height: 3.125rem; + padding: 0.8125rem 0.6875rem 0.8125rem 0.625rem; + justify-content: center; + align-items: center; + gap: 2.5rem; +}/*# sourceMappingURL=signUp.css.map */ \ No newline at end of file diff --git a/client/src/assets/styles/components/signUp.scss b/client/src/assets/styles/components/signUp.scss new file mode 100644 index 00000000..9705ee79 --- /dev/null +++ b/client/src/assets/styles/components/signUp.scss @@ -0,0 +1,97 @@ +$Teal-900: #014451; +$grey-800: #1f2a37; +$grey-700: #374151; +$grey-600: #4b5563; +$Primary-900: #0e0218; +$text-color: #e2efee; +$font: 'Noto Kufi Arabic'; + +.hero { + display: flex; + width: 22.5rem; + height: 93.375rem; + flex-direction: column; + align-items: center; + margin: auto; + padding: 1.75rem 0.25rem; + gap: 1.1875rem; +} + +.container { + background: $Teal-900; + border-radius: 1.25rem; + display: flex; + width: 19rem; + padding: 1.5rem 0.4375rem; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 1.0625rem; +} + +.card { + background-color: $grey-800; + border-radius: 1.875rem; + display: flex; + width: 16.9375rem; + padding: 1.0625rem 0rem; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 0.875rem; + .input-field { + display: flex; + width: 14.16319rem; + padding: 0.125rem 0.75rem; + justify-content: flex-end; + align-items: center; + align-content: center; + gap: 0rem 9.25rem; + flex-wrap: wrap; + input { + background: $grey-700; + margin-block: 0.3rem; + border: 1px solid $grey-600; + border-radius: 0.25rem; + width: 12.66319rem; + height: 1.75rem; + flex-shrink: 0; + } + } + + .radio-field { + display: flex; + width: 14.16319rem; + padding: 0.5625rem 0.75rem; + flex-direction: column; + justify-content: flex-end; + align-items: flex-end; + flex-wrap: wrap; + gap: 0.0625rem; + .radio-buttons { + display: flex; + padding: 0.3125rem 0.5rem; + margin: auto; + gap: 3.1875rem; + small input { + margin: 0.5rem; + } + } + } +} + + +button { + color: $text-color; + font-family: $font; + background: $Primary-900; + border: 0px solid; + border-radius: 0.3125rem; + display: flex; + width: 12.5rem; + height: 3.125rem; + padding: 0.8125rem 0.6875rem 0.8125rem 0.625rem; + justify-content: center; + align-items: center; + gap: 2.5rem; +} diff --git a/client/src/components/module_OR_PAGE/DELETEME.txt b/client/src/components/module_OR_PAGE/DELETEME.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/client/src/components/module_OR_PAGE/logIn.jsx b/client/src/components/module_OR_PAGE/logIn.jsx new file mode 100644 index 00000000..65533d91 --- /dev/null +++ b/client/src/components/module_OR_PAGE/logIn.jsx @@ -0,0 +1,21 @@ +import '../../assets/styles/components/logIn.css' + +export default function LogIn() { + return ( +
+

تسجيل الدخول

+
+ + + +
+ ليس لديك حساب؟ +
+ ) +} diff --git a/client/src/components/module_OR_PAGE/signUp.jsx b/client/src/components/module_OR_PAGE/signUp.jsx new file mode 100644 index 00000000..8316d4fb --- /dev/null +++ b/client/src/components/module_OR_PAGE/signUp.jsx @@ -0,0 +1,62 @@ +import '../../assets/styles/components/signUp.css' + +export default function SignUp() { + return ( +
+

تسجيل حساب

+
+
+
الاسم
+ + + +
+
+
معلومات الحساب
+ + + +
+
+
معلومات أخرى
+ + +
+ +
+
+ ) +} diff --git a/client/src/redux/DELETEME.txt b/client/src/redux/DELETEME.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/client/src/services/DELETEME.txt b/client/src/services/DELETEME.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/client/src/theme.css b/client/src/theme.css new file mode 100644 index 00000000..e8dd6711 --- /dev/null +++ b/client/src/theme.css @@ -0,0 +1,52 @@ +* { + margin: 0; + padding: 0; +} + +:root { + text-align: center; + background-color: #111928; + color: #E2EFEE; + font-family: "Noto Kufi Arabic"; +} + +h1 { + font-size: 2.98625rem; + font-weight: 800; + line-height: 139.429%; /* 4.16369rem */ +} + +h2 { + font-size: 2.48813rem; + font-weight: 700; +} + +h3 { + font-size: 2.07375rem; + font-weight: 700; +} + +h4 { + font-size: 1.72813rem; + font-weight: 600; +} + +h5 { + font-size: 1.44rem; + font-weight: 600; +} + +h6 { + font-size: 1.2rem; + font-weight: 500; +} + +p, label { + font-size: 1rem; + font-weight: 500; +} + +small { + font-size: 0.83313rem; + font-weight: 400; +}/*# sourceMappingURL=theme.css.map */ \ No newline at end of file diff --git a/client/src/theme.scss b/client/src/theme.scss index 493db32c..f3bda648 100644 --- a/client/src/theme.scss +++ b/client/src/theme.scss @@ -5,6 +5,11 @@ // Import the fonts @import url("https://fonts.googleapis.com/css2?family=Noto+Kufi+Arabic:wght@100;200;300;400;500;600;700;800;900&display=swap"); +* { + margin: 0; + padding: 0; +} + :root { //----------------------------// // Colors diff --git a/server/.env.example b/server/.env.example index e69de29b..59dfe3ad 100644 --- a/server/.env.example +++ b/server/.env.example @@ -0,0 +1,22 @@ +# DB Config Variables +DB_HOST= +DB_PORT= +DB_USER= +DB_PASS= +DB_DATABASE= + +# Token Config Variables +JWT_SECRET= +JWT_EXPIRES_IN= + +########## Example ########## +# DB_HOST=localhost +# DB_PORT=5432 +# DB_USER=postgres +# DB_PASS=******** +# DB_DATABASE=scoutsManagementSystem + +# To get a random string for JWT_SECRET +# Run This in terminal => node -e "console.log(require('crypto').randomBytes(32).toString('hex'))" + +# JWT_EXPIRES_IN='48h' \ No newline at end of file diff --git a/server/app.js b/server/app.js index 6db794e2..622cdf5b 100644 --- a/server/app.js +++ b/server/app.js @@ -1,21 +1,25 @@ -const {Client} = require('pg') +const express = require('express') +const cors = require('cors') +const db = require('./database/db') +const app = express() +const PORT = process.env.PORT || 3000 +const authRouter = require('./routes/auth.route') -const client = new Client({ - host: "localhost", - user: "postgres", - port: 5432, - password: "admin123", - database: "scoutsmanagementsystem" -}) +db.connect() + .then(() => { + console.log('Database is connected') + }) + .catch((err) => { + if (err) return console.error(err) + }) -client.connect(); +app.use(cors()) +app.use(express.json()) -client.query('SELECT * FROM public."Activity"', (err, res) => { - if (!err) { - console.log(res.rows); - } - else - { - console.log(err.message) - } +// Routes +app.use("/auth", authRouter); + +app.listen(PORT, (err) => { + if (err) return console.error(err) + console.log(`Server started listening at port ${PORT}`) }) \ No newline at end of file diff --git a/server/controllers/auth.controller.js b/server/controllers/auth.controller.js new file mode 100644 index 00000000..27840b52 --- /dev/null +++ b/server/controllers/auth.controller.js @@ -0,0 +1,125 @@ +const bcrypt = require('bcryptjs') +const jwt = require('jsonwebtoken') +const db = require('../database/db') +const { jsonToArray, arrayToJson } = require('../utils/convert') + +const authController = { + signup: async (req, res) => { + try { + // get email and password from request body + const email = req.body['email'] + const password = req.body['password'] + + // Check if email already exists + const captain = await db.query( + `SELECT "email", "password" + FROM "Captain" + WHERE "email" = $1;`, + [email] + ) + if (captain.rows.length) { + return res.status(400).json({ error: 'Email is taken!!' }) + } + + // Hash the password + const hashedPassword = await bcrypt.hash(password, 10) + + // Create a new Captain + req.body = { ...req.body, password: hashedPassword } + const params = jsonToArray(req.body) + const result = await db.query( + `INSERT INTO "Captain"("firstName", "middleName", "lastName", "email", "password", "phoneNumber", "gender", "type") + VALUES($1, $2, $3, $4, $5, $6, $7, $8) RETURNING *;`, + params.concat(['regular']) + ) + const newCaptain = result.rows[0] + + // Generate a JWT token containing the captain's id + // Bearer token is the token that we will send to the client + const token = jwt.sign( + { id: newCaptain.captainId }, // Payload + process.env.JWT_SECRET, + { + expiresIn: process.env.JWT_EXPIRES_IN, + } + ) + + // Send the response + res.status(201).json({ + message: 'Captain created successfully', + newCaptain, + token, + }) + } catch (error) { + console.log(error) + res.status(500).json({ + error: 'An error occurred while creating a new captain!!', + }) + } + }, + + login: async (req, res) => { + try { + // Deconstruct the request body + const { email, password } = req.body + + // Check if email already exists + const result = await db.query( + `SELECT "email", "password" + FROM "Captain" + WHERE "email" = $1;`, + [email] + ) + if (!result.rows.length) { + return res.status(400).json({ + error: 'Invalid email', + }) + } + + // Get Captain's data + const captain = result.rows[0] + + // Check if the password is correct + const isCorrect = await bcrypt.compare(password, captain.password) + if (!isCorrect) { + return res.status(400).json({ + error: 'Invalid password', + }) + } + + // Generate a JWT token containing the captain's id + // Bearer token is the token that we will send to the client + const token = jwt.sign( + { id: captain.captainId }, // Payload + process.env.JWT_SECRET, + { + expiresIn: process.env.JWT_EXPIRES_IN, + } + ) + + // Send the response + res.status(200).json({ + message: 'Logged in successfully', + token, + }) + } catch (error) { + console.log(error) + res.status(500).json({ + error: 'An error occurred while logging you in', + }) + } + }, + + // This controller is responsible for fetching data of the logged-in captain + me: (req, res) => { + try { + res.status(200).json({ user: req.captain }) + } catch (error) { + console.log(error) + res.status(500).json({ + error: 'An error occurred while fetching data.', + }) + } + }, +} +module.exports = authController diff --git a/server/controllers/example.controller.js b/server/controllers/example.controller.js deleted file mode 100644 index e69de29b..00000000 diff --git a/server/database/createDatabase.psql b/server/database/createDatabase.psql index 9fa189cf..dcc0f22d 100644 --- a/server/database/createDatabase.psql +++ b/server/database/createDatabase.psql @@ -245,8 +245,8 @@ CREATE TABLE public."Captain" ( "middleName" character varying(255) NOT NULL, "lastName" character varying(255) NOT NULL, "phoneNumber" character varying(255) NOT NULL, - email character varying(255) NOT NULL, - passward character varying(255) NOT NULL, + "email" character varying(255) NOT NULL, + "password" character varying(255) NOT NULL, "rSectorBaseName" character varying(255), "rSectorSuffixName" character varying(255), gender public."Gender" NOT NULL, @@ -1150,4 +1150,4 @@ ALTER TABLE ONLY public."Week" -- -- PostgreSQL database dump complete --- +-- \ No newline at end of file diff --git a/server/database/db.js b/server/database/db.js new file mode 100644 index 00000000..bacd5a53 --- /dev/null +++ b/server/database/db.js @@ -0,0 +1,13 @@ +const pg = require('pg') +const dotenv = require('dotenv') + +dotenv.config() +const db = new pg.Pool({ + host: process.env.DB_HOST, + port: process.env.DB_PORT, + user: process.env.DB_USER, + password: process.env.DB_PASS, + database: process.env.DB_DATABASE, +}) + +module.exports = db \ No newline at end of file diff --git a/server/middlewares/auth.middleware.js b/server/middlewares/auth.middleware.js new file mode 100644 index 00000000..ac5cbb34 --- /dev/null +++ b/server/middlewares/auth.middleware.js @@ -0,0 +1,47 @@ +const jwt = require('jsonwebtoken') +const db = require('../database/db') + +const authMiddleware = async (req, res, next) => { + // Get authorization header and check if it exists + const auth = req.headers.authorization + if (!auth) { + return res.status(401).json({ error: 'No token provided' }) + } + + // Check if the authorization header is "Bearer " + if (!auth.startsWith('Bearer') || auth.split(' ').length !== 2) { + return res.status(401).json({ error: 'Invalid token, not Bearer' }) + } + + // Get token from the authorization header + const token = auth.split(' ')[1] + + try { + // Verify token and get captain's id + const id = jwt.verify(token, process.env.JWT_SECRET).id + + // Get captain's data + const result = await db.query( + `SELECT * + FROM "Captain" + WHERE "captainId" = $1;`, + [id] + ) + if (!result.rows.length) { + return res.status(404).json({ error: 'Captain not found' }) + } + + // Attach captain to the request object + req.captain = result.rows[0] + + next() + } catch (err) { + console.log(err) + if (err.name === 'TokenExpiredError') { + return res.status(401).json({ error: 'Provided token has expired' }) + } + res.status(401).json({ error: 'Invalid token' }) + } +} + +module.exports = authMiddleware diff --git a/server/middlewares/example.middleware.js b/server/middlewares/example.middleware.js deleted file mode 100644 index e69de29b..00000000 diff --git a/server/models/example.model.js b/server/models/example.model.js deleted file mode 100644 index e69de29b..00000000 diff --git a/server/package-lock.json b/server/package-lock.json index 11ca95fd..a6128cfd 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -9,9 +9,11 @@ "version": "1.0.0", "license": "ISC", "dependencies": { + "bcryptjs": "^2.4.3", "cors": "^2.8.5", "dotenv": "^16.3.1", "express": "^4.18.2", + "jsonwebtoken": "^9.0.2", "pg": "^8.11.3" }, "devDependencies": { @@ -60,6 +62,11 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==" + }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -114,6 +121,11 @@ "node": ">=8" } }, + "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==" + }, "node_modules/buffer-writer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", @@ -269,6 +281,14 @@ "url": "https://github.com/motdotla/dotenv?sponsor=1" } }, + "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==", + "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", @@ -580,11 +600,90 @@ "node": ">=0.12.0" } }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "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/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "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==", + "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==", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "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==" + }, + "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==" + }, + "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==" + }, + "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==" + }, + "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==" + }, + "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==" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -1012,7 +1111,6 @@ "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -1222,8 +1320,7 @@ "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } } diff --git a/server/package.json b/server/package.json index 5c476c07..9cac5295 100644 --- a/server/package.json +++ b/server/package.json @@ -10,9 +10,11 @@ "author": "", "license": "ISC", "dependencies": { + "bcryptjs": "^2.4.3", "cors": "^2.8.5", "dotenv": "^16.3.1", "express": "^4.18.2", + "jsonwebtoken": "^9.0.2", "pg": "^8.11.3" }, "devDependencies": { diff --git a/server/routes/auth.route.js b/server/routes/auth.route.js new file mode 100644 index 00000000..880e7482 --- /dev/null +++ b/server/routes/auth.route.js @@ -0,0 +1,9 @@ +const authRouter = require("express").Router(); +const authController = require("../controllers/auth.controller"); +const authMiddleware = require("../middlewares/auth.middleware"); + +authRouter.post("/signUp", authController.signup); +authRouter.post("/logIn", authController.login); +authRouter.get("/me", authMiddleware, authController.me); + +module.exports = authRouter; \ No newline at end of file diff --git a/server/routes/example.route.js b/server/routes/example.route.js deleted file mode 100644 index e69de29b..00000000 diff --git a/server/utils/convert.js b/server/utils/convert.js new file mode 100644 index 00000000..69ac8ce7 --- /dev/null +++ b/server/utils/convert.js @@ -0,0 +1,20 @@ +const jsonToArray = (json) => { + const arr = [] + for (const key in json) { + arr.push(json[key]) + } + return arr +} + +const arrayToJson = (arr) => { + const json = {} + for (const key in arr) { + json[key] = arr[key] + } + return json +} + +module.exports = { + jsonToArray, + arrayToJson, +} diff --git a/server/utils/fileExample.js b/server/utils/fileExample.js deleted file mode 100644 index e69de29b..00000000