logout
parent
ff0699e61f
commit
6cf57df008
9
index.ts
9
index.ts
|
@ -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");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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_-]+$/;
|
||||||
|
|
|
@ -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" });
|
||||||
|
|
|
@ -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}`);
|
Reference in New Issue