diff --git a/index.ts b/index.ts index 94dd7c4..b33e525 100644 --- a/index.ts +++ b/index.ts @@ -1,6 +1,7 @@ import express, { Express } from "express"; import dotenv from "dotenv"; -import bodyParser = require("body-parser"); +import bodyParser from "body-parser"; +import morgan from "morgan"; dotenv.config(); @@ -42,16 +43,22 @@ const options = { }; app.use(bodyParser.json()); +app.use(morgan("combined")); app.use("/api/v1/user", userRoutes); app.use("/api/v1/users", usersRoutes); app.use("/api/v1/admin", adminRoutes); app.use("/api/v1/events", eventsRoutes); +app.use("/api/v1/appstart", (req, res, next) => { + console.log("appstart"); + res.status(200).json({ status: "ok" }); +}); const specs = swaggerJsDoc(options); app.use("/api-docs", swaggerUI.serve, swaggerUI.setup(specs)); app.use((req, res, next) => { + console.log("req", req); res.status(404).send("not found"); }); diff --git a/package-lock.json b/package-lock.json index 239cb4d..50265b0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,12 +14,14 @@ "dotenv": "^16.3.1", "express": "^4.18.2", "mongoose": "^8.0.2", + "morgan": "^1.10.0", "swagger-jsdoc": "^6.2.8", "swagger-ui-express": "^5.0.0" }, "devDependencies": { "@types/bcrypt": "^5.0.2", "@types/express": "^4.17.21", + "@types/morgan": "^1.9.9", "@types/node": "^20.10.2", "@types/swagger-jsdoc": "^6.0.4", "@types/swagger-ui-express": "^4.1.6", @@ -195,6 +197,15 @@ "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", "dev": true }, + "node_modules/@types/morgan": { + "version": "1.9.9", + "resolved": "https://registry.npmjs.org/@types/morgan/-/morgan-1.9.9.tgz", + "integrity": "sha512-iRYSDKVaC6FkGSpEVVIvrRGw0DfJMiQzIn3qr2G5B3C//AWkulhXgaBd7tS9/J79GWSYMTHGs7PfI5b3Y8m+RQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/node": { "version": "20.10.2", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.2.tgz", @@ -383,6 +394,22 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "node_modules/basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/basic-auth/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, "node_modules/bcrypt": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", @@ -1513,6 +1540,32 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, + "node_modules/morgan": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", + "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", + "dependencies": { + "basic-auth": "~2.0.1", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-finished": "~2.3.0", + "on-headers": "~1.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/morgan/node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/mpath": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", @@ -1743,6 +1796,14 @@ "node": ">= 0.8" } }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", diff --git a/package.json b/package.json index 367f42a..4110a14 100644 --- a/package.json +++ b/package.json @@ -17,12 +17,14 @@ "dotenv": "^16.3.1", "express": "^4.18.2", "mongoose": "^8.0.2", + "morgan": "^1.10.0", "swagger-jsdoc": "^6.2.8", "swagger-ui-express": "^5.0.0" }, "devDependencies": { "@types/bcrypt": "^5.0.2", "@types/express": "^4.17.21", + "@types/morgan": "^1.9.9", "@types/node": "^20.10.2", "@types/swagger-jsdoc": "^6.0.4", "@types/swagger-ui-express": "^4.1.6", diff --git a/src/controllers/userController.ts b/src/controllers/userController.ts index 592d2ad..1117867 100644 --- a/src/controllers/userController.ts +++ b/src/controllers/userController.ts @@ -20,7 +20,7 @@ export async function SignUp(req: Request, res: Response) { } const existingUser = await User.findOne({ accountName }) - .select(`accountName ${MONGODB_IGNORED_FIELDS}`) + .select(MONGODB_IGNORED_FIELDS) .lean(); if (existingUser) { @@ -42,7 +42,7 @@ export async function SignUp(req: Request, res: Response) { user .save() - .then(() => saveSession(res, accountName)) + .then(() => saveSession(res, accountName, username)) .catch((err) => { console.log(err); res.status(500).json({ status: "err" }); @@ -55,14 +55,14 @@ export async function SignUp(req: Request, res: Response) { export async function Login(req: Request, res: Response) { try { - if (!req.body.accountName || !req.body.password) { + const { AccountName, Password } = req.body; + + if (!AccountName || !Password) { return res.status(400).json({ status: "err" }); } - const { accountName, password } = req.body; - - const user = await User.findOne({ accountName }) - .select(MONGODB_IGNORED_FIELDS) + const user = await User.findOne({ accountName: AccountName }) + .select(`accountName username password -_id`) .lean(); if (!user) { @@ -78,14 +78,14 @@ export async function Login(req: Request, res: Response) { return res.status(401).json({ status: "err" }); } - const decodedPassword = decodeBase64(password); + const decodedPassword = decodeBase64(Password); const isPasswordValid = await matchPassword(decodedPassword, user.password); if (!isPasswordValid) { return res.status(401).json({ status: "err" }); } - saveSession(res, user.accountName); + saveSession(res, user.accountName, user.username); } catch (error) { console.error("error on login:", error); res.status(500).json({ status: "err" }); @@ -179,3 +179,20 @@ export async function ChangePassword(req: Request, res: Response) { res.status(500).json({ status: "err" }); } } + +export async function Logout(req: Request, res: Response) { + try { + const session = await getUserSession(req); + + if (!session) { + return res.status(401).json({ status: "err" }); + } + + await Session.deleteOne({ sessionId: session.sessionId }); + + res.status(200).json({ status: "ok" }); + } catch (error) { + console.error("error on logout", error); + res.status(500).json({ status: "err" }); + } +} diff --git a/src/routes/userRoutes.ts b/src/routes/userRoutes.ts index 21f58c0..5dc7c7d 100644 --- a/src/routes/userRoutes.ts +++ b/src/routes/userRoutes.ts @@ -129,7 +129,6 @@ router.post("/login", userController.Login); router.post("/username", sessionProtection, userController.ChangeUsername); router.post("/password", sessionProtection, userController.ChangePassword); - -//router.post("/logout", sessionProtection, userController.Logout); +router.post("/logout", sessionProtection, userController.Logout); export default router; diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 175c8ca..986d6ad 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -12,15 +12,15 @@ export const MONGODB_IGNORED_FIELDS_USER: string = // Header name for the session ID export const HEADER_X_AUTHORIZATION: string = "x-authorization"; -export const USERNAME_MIN_LENGTH: number = 3; -export const USERNAME_MAX_LENGTH: number = 20; +export const USERNAME_MIN_LENGTH: number = 2; +export const USERNAME_MAX_LENGTH: number = 24; export const USERNAME_REGEX: RegExp = /^[a-zA-Z0-9_]+$/; // Alphanumeric and underscore -export const PASSWORD_MIN_LENGTH: number = 8; +export const PASSWORD_MIN_LENGTH: number = 6; export const PASSWORD_MAX_LENGTH: number = 64; export const PASSWORD_REGEX: RegExp = /^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$/; -export const ACCOUNT_NAME_MIN_LENGTH: number = 3; -export const ACCOUNT_NAME_MAX_LENGTH: number = 20; +export const ACCOUNT_NAME_MIN_LENGTH: number = 4; +export const ACCOUNT_NAME_MAX_LENGTH: number = 24; // alphanumerics, numbers, underscores, and dashes export const ACCOUNT_NAME_REGEX: RegExp = /^[a-zA-Z0-9_-]+$/; diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 55bafbe..b2c10bd 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -4,7 +4,11 @@ import { Request, Response } from "express"; import bcrypt from "bcrypt"; import { HEADER_X_AUTHORIZATION } from "./constants"; -export async function saveSession(res: Response, accountName: string) { +export async function saveSession( + res: Response, + accountName: string, + username: string +) { try { // Generate a random session ID const sessionId = crypto.randomBytes(32).toString("hex"); @@ -19,7 +23,7 @@ export async function saveSession(res: Response, accountName: string) { await session.save(); // Respond with the session ID - res.status(200).json({ sessionId }); + res.status(200).json({ XAuthorization: sessionId, Username: username }); } catch (error) { console.error("Error saving session:", error); res.status(500).json({ status: "err" }); diff --git a/test.js b/test.js new file mode 100644 index 0000000..d2a2deb --- /dev/null +++ b/test.js @@ -0,0 +1,22 @@ +function decimalToCharEncoder(decimalNumber) { + const characters = + "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + const base = characters.length; + + if (decimalNumber === 0) { + return characters[0]; + } + + let result = ""; + while (decimalNumber > 0) { + const remainder = decimalNumber % base; + result = characters[remainder] + result; + decimalNumber = Math.floor(decimalNumber / base); + } + + return result; +} + +const decimalNumber = 10002; +const encodedString = decimalToCharEncoder(decimalNumber); +console.log(`Decimal: ${decimalNumber}, Encoded: ${encodedString}`);