main
Netcup Gituser 2023-12-09 21:54:34 +01:00
parent ff0699e61f
commit 6cf57df008
8 changed files with 131 additions and 19 deletions

View File

@ -1,6 +1,7 @@
import express, { Express } from "express"; import express, { Express } from "express";
import dotenv from "dotenv"; import dotenv from "dotenv";
import bodyParser = require("body-parser"); import bodyParser from "body-parser";
import morgan from "morgan";
dotenv.config(); dotenv.config();
@ -42,16 +43,22 @@ const options = {
}; };
app.use(bodyParser.json()); app.use(bodyParser.json());
app.use(morgan("combined"));
app.use("/api/v1/user", userRoutes); app.use("/api/v1/user", userRoutes);
app.use("/api/v1/users", usersRoutes); app.use("/api/v1/users", usersRoutes);
app.use("/api/v1/admin", adminRoutes); app.use("/api/v1/admin", adminRoutes);
app.use("/api/v1/events", eventsRoutes); 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); const specs = swaggerJsDoc(options);
app.use("/api-docs", swaggerUI.serve, swaggerUI.setup(specs)); app.use("/api-docs", swaggerUI.serve, swaggerUI.setup(specs));
app.use((req, res, next) => { app.use((req, res, next) => {
console.log("req", req);
res.status(404).send("not found"); res.status(404).send("not found");
}); });

61
package-lock.json generated
View File

@ -14,12 +14,14 @@
"dotenv": "^16.3.1", "dotenv": "^16.3.1",
"express": "^4.18.2", "express": "^4.18.2",
"mongoose": "^8.0.2", "mongoose": "^8.0.2",
"morgan": "^1.10.0",
"swagger-jsdoc": "^6.2.8", "swagger-jsdoc": "^6.2.8",
"swagger-ui-express": "^5.0.0" "swagger-ui-express": "^5.0.0"
}, },
"devDependencies": { "devDependencies": {
"@types/bcrypt": "^5.0.2", "@types/bcrypt": "^5.0.2",
"@types/express": "^4.17.21", "@types/express": "^4.17.21",
"@types/morgan": "^1.9.9",
"@types/node": "^20.10.2", "@types/node": "^20.10.2",
"@types/swagger-jsdoc": "^6.0.4", "@types/swagger-jsdoc": "^6.0.4",
"@types/swagger-ui-express": "^4.1.6", "@types/swagger-ui-express": "^4.1.6",
@ -195,6 +197,15 @@
"integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==",
"dev": true "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": { "node_modules/@types/node": {
"version": "20.10.2", "version": "20.10.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.2.tgz", "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", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" "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": { "node_modules/bcrypt": {
"version": "5.1.1", "version": "5.1.1",
"resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", "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", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" "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": { "node_modules/mpath": {
"version": "0.9.0", "version": "0.9.0",
"resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz",
@ -1743,6 +1796,14 @@
"node": ">= 0.8" "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": { "node_modules/once": {
"version": "1.4.0", "version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",

View File

@ -17,12 +17,14 @@
"dotenv": "^16.3.1", "dotenv": "^16.3.1",
"express": "^4.18.2", "express": "^4.18.2",
"mongoose": "^8.0.2", "mongoose": "^8.0.2",
"morgan": "^1.10.0",
"swagger-jsdoc": "^6.2.8", "swagger-jsdoc": "^6.2.8",
"swagger-ui-express": "^5.0.0" "swagger-ui-express": "^5.0.0"
}, },
"devDependencies": { "devDependencies": {
"@types/bcrypt": "^5.0.2", "@types/bcrypt": "^5.0.2",
"@types/express": "^4.17.21", "@types/express": "^4.17.21",
"@types/morgan": "^1.9.9",
"@types/node": "^20.10.2", "@types/node": "^20.10.2",
"@types/swagger-jsdoc": "^6.0.4", "@types/swagger-jsdoc": "^6.0.4",
"@types/swagger-ui-express": "^4.1.6", "@types/swagger-ui-express": "^4.1.6",

View File

@ -20,7 +20,7 @@ export async function SignUp(req: Request, res: Response) {
} }
const existingUser = await User.findOne({ accountName }) const existingUser = await User.findOne({ accountName })
.select(`accountName ${MONGODB_IGNORED_FIELDS}`) .select(MONGODB_IGNORED_FIELDS)
.lean(); .lean();
if (existingUser) { if (existingUser) {
@ -42,7 +42,7 @@ export async function SignUp(req: Request, res: Response) {
user user
.save() .save()
.then(() => saveSession(res, accountName)) .then(() => saveSession(res, accountName, username))
.catch((err) => { .catch((err) => {
console.log(err); console.log(err);
res.status(500).json({ status: "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) { export async function Login(req: Request, res: Response) {
try { try {
if (!req.body.accountName || !req.body.password) { const { AccountName, Password } = req.body;
if (!AccountName || !Password) {
return res.status(400).json({ status: "err" }); return res.status(400).json({ status: "err" });
} }
const { accountName, password } = req.body; const user = await User.findOne({ accountName: AccountName })
.select(`accountName username password -_id`)
const user = await User.findOne({ accountName })
.select(MONGODB_IGNORED_FIELDS)
.lean(); .lean();
if (!user) { if (!user) {
@ -78,14 +78,14 @@ export async function Login(req: Request, res: Response) {
return res.status(401).json({ status: "err" }); return res.status(401).json({ status: "err" });
} }
const decodedPassword = decodeBase64(password); const decodedPassword = decodeBase64(Password);
const isPasswordValid = await matchPassword(decodedPassword, user.password); const isPasswordValid = await matchPassword(decodedPassword, user.password);
if (!isPasswordValid) { if (!isPasswordValid) {
return res.status(401).json({ status: "err" }); return res.status(401).json({ status: "err" });
} }
saveSession(res, user.accountName); saveSession(res, user.accountName, user.username);
} catch (error) { } catch (error) {
console.error("error on login:", error); console.error("error on login:", error);
res.status(500).json({ status: "err" }); res.status(500).json({ status: "err" });
@ -179,3 +179,20 @@ export async function ChangePassword(req: Request, res: Response) {
res.status(500).json({ status: "err" }); 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" });
}
}

View File

@ -129,7 +129,6 @@ router.post("/login", userController.Login);
router.post("/username", sessionProtection, userController.ChangeUsername); router.post("/username", sessionProtection, userController.ChangeUsername);
router.post("/password", sessionProtection, userController.ChangePassword); router.post("/password", sessionProtection, userController.ChangePassword);
router.post("/logout", sessionProtection, userController.Logout);
//router.post("/logout", sessionProtection, userController.Logout);
export default router; export default router;

View File

@ -12,15 +12,15 @@ export const MONGODB_IGNORED_FIELDS_USER: string =
// Header name for the session ID // Header name for the session ID
export const HEADER_X_AUTHORIZATION: string = "x-authorization"; export const HEADER_X_AUTHORIZATION: string = "x-authorization";
export const USERNAME_MIN_LENGTH: number = 3; export const USERNAME_MIN_LENGTH: number = 2;
export const USERNAME_MAX_LENGTH: number = 20; export const USERNAME_MAX_LENGTH: number = 24;
export const USERNAME_REGEX: RegExp = /^[a-zA-Z0-9_]+$/; // Alphanumeric and underscore 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_MAX_LENGTH: number = 64;
export const PASSWORD_REGEX: RegExp = 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}==)$/; /^([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_MIN_LENGTH: number = 4;
export const ACCOUNT_NAME_MAX_LENGTH: number = 20; export const ACCOUNT_NAME_MAX_LENGTH: number = 24;
// alphanumerics, numbers, underscores, and dashes // alphanumerics, numbers, underscores, and dashes
export const ACCOUNT_NAME_REGEX: RegExp = /^[a-zA-Z0-9_-]+$/; export const ACCOUNT_NAME_REGEX: RegExp = /^[a-zA-Z0-9_-]+$/;

View File

@ -4,7 +4,11 @@ import { Request, Response } from "express";
import bcrypt from "bcrypt"; import bcrypt from "bcrypt";
import { HEADER_X_AUTHORIZATION } from "./constants"; 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 { try {
// Generate a random session ID // Generate a random session ID
const sessionId = crypto.randomBytes(32).toString("hex"); const sessionId = crypto.randomBytes(32).toString("hex");
@ -19,7 +23,7 @@ export async function saveSession(res: Response, accountName: string) {
await session.save(); await session.save();
// Respond with the session ID // Respond with the session ID
res.status(200).json({ sessionId }); res.status(200).json({ XAuthorization: sessionId, Username: username });
} catch (error) { } catch (error) {
console.error("Error saving session:", error); console.error("Error saving session:", error);
res.status(500).json({ status: "err" }); res.status(500).json({ status: "err" });

22
test.js Normal file
View File

@ -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}`);