type: style
scope: services, interfaces subject: Apply code formatting - Correct indentation and formatting to match code style standards in multiple 'interfaces' and 'services' files. - Also ensure lines at the end of the files. Signed-off-by: Mathis <yidhra@tuta.io>
This commit is contained in:
parent
cda313866f
commit
56bfd8cd0d
13
biome.json
13
biome.json
@ -3,6 +3,15 @@
|
||||
"organizeImports": {
|
||||
"enabled": true
|
||||
},
|
||||
"files": {
|
||||
"include": [
|
||||
"./src/**/*.ts"
|
||||
]
|
||||
},
|
||||
"vcs": {
|
||||
"enabled": true,
|
||||
"clientKind": "git"
|
||||
},
|
||||
"linter": {
|
||||
"enabled": true,
|
||||
"rules": {
|
||||
@ -17,8 +26,8 @@
|
||||
}
|
||||
},
|
||||
"formatter": {
|
||||
"indentStyle": "space",
|
||||
"indentStyle": "tab",
|
||||
"indentWidth": 2,
|
||||
"lineWidth": 15
|
||||
"lineWidth": 64
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,8 @@
|
||||
"author": "Mathis HERRIOT",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"bun:dev": "bun run --watch src/app.ts"
|
||||
"bun:dev": "bun run --watch src/app.ts",
|
||||
"bun:check": "bunx biome check --skip-errors --apply src"
|
||||
},
|
||||
"dependencies": {
|
||||
"@node-rs/argon2": "^1.8.3",
|
||||
|
47
src/app.ts
47
src/app.ts
@ -1,21 +1,22 @@
|
||||
import express, { type Express } from 'express';
|
||||
import cors from 'cors';
|
||||
import compression from 'compression';
|
||||
import {Logger} from "tslog";
|
||||
import helmet from "helmet";
|
||||
import * as process from "node:process";
|
||||
import AuthRouter from "@routes/auth/authRouter";
|
||||
import CatalogRouter from "@routes/catalog/catalogRouter";
|
||||
import RentRouter from "@routes/rent/rentRouter";
|
||||
import * as process from "node:process";
|
||||
import compression from "compression";
|
||||
import cors from "cors";
|
||||
import express, { type Express } from "express";
|
||||
import helmet from "helmet";
|
||||
import { Logger } from "tslog";
|
||||
|
||||
|
||||
const logger = new Logger({ name: "App" });
|
||||
const logger = new Logger({
|
||||
name: "App",
|
||||
});
|
||||
|
||||
const app: Express = express();
|
||||
|
||||
// enable cors
|
||||
app.use(cors());
|
||||
app.options('*', cors());
|
||||
app.options("*", cors());
|
||||
|
||||
// enable xss sanitizer
|
||||
app.use(
|
||||
@ -23,31 +24,35 @@ app.use(
|
||||
xXssProtection: true,
|
||||
}),
|
||||
);
|
||||
app.use(helmet.xXssProtection())
|
||||
app.use(helmet.xXssProtection());
|
||||
|
||||
// parse json request body
|
||||
app.use(express.json());
|
||||
|
||||
// parse urlencoded request body
|
||||
app.use(express.urlencoded({ extended: true }));
|
||||
app.use(
|
||||
express.urlencoded({
|
||||
extended: true,
|
||||
}),
|
||||
);
|
||||
|
||||
// gzip compression
|
||||
app.use(compression())
|
||||
app.use(compression());
|
||||
|
||||
try {
|
||||
app.use('/auth', AuthRouter)
|
||||
app.use('/catalog', CatalogRouter)
|
||||
app.use('/rent', RentRouter)
|
||||
logger.info('Routers loaded !')
|
||||
app.use("/auth", AuthRouter);
|
||||
app.use("/catalog", CatalogRouter);
|
||||
app.use("/rent", RentRouter);
|
||||
logger.info("Routers loaded !");
|
||||
} catch (err) {
|
||||
logger.error(err)
|
||||
logger.error(err);
|
||||
throw null;
|
||||
}
|
||||
|
||||
try {
|
||||
app.listen(process.env["APP_PORT"])
|
||||
logger.info('Server is running !')
|
||||
app.listen(process.env["APP_PORT"]);
|
||||
logger.info("Server is running !");
|
||||
} catch (error) {
|
||||
logger.error(`Server failed to start: ${error}`);
|
||||
process.exit(1);
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
|
@ -1,13 +1,13 @@
|
||||
import JwtService from "@services/jwt.service";
|
||||
|
||||
|
||||
import type {IReqEditUserData} from "@interfaces/IReqEditUserData";
|
||||
import type { IReqEditUserData } from "@interfaces/IReqEditUserData";
|
||||
import UserService from "@services/user.service";
|
||||
import type {Request, Response} from "express";
|
||||
import {Logger} from "tslog";
|
||||
import type { Request, Response } from "express";
|
||||
import { Logger } from "tslog";
|
||||
|
||||
|
||||
const logger = new Logger({ name: "AuthController" });
|
||||
const logger = new Logger({
|
||||
name: "AuthController",
|
||||
});
|
||||
|
||||
//FIX Better return object interface
|
||||
/**
|
||||
@ -22,60 +22,65 @@ const logger = new Logger({ name: "AuthController" });
|
||||
* - error: "exist" if the user already exists
|
||||
* - Otherwise, the registered user data
|
||||
*/
|
||||
async function registerUser(req: Request, res: Response): Promise<unknown> {
|
||||
async function registerUser(
|
||||
req: Request,
|
||||
res: Response,
|
||||
): Promise<unknown> {
|
||||
const body = req.body;
|
||||
if (!body) {
|
||||
logger.warn(`Invalid input data (${req.ip})`);
|
||||
return res
|
||||
.type('application/json')
|
||||
.status(400)
|
||||
.json({ error: 'Invalid input data' });
|
||||
return res.type("application/json").status(400).json({
|
||||
error: "Invalid input data",
|
||||
});
|
||||
}
|
||||
if (!body.password || !body.username || !body.firstName || !body.lastName || !body.displayName) {
|
||||
if (
|
||||
!body.password ||
|
||||
!body.username ||
|
||||
!body.firstName ||
|
||||
!body.lastName ||
|
||||
!body.displayName
|
||||
) {
|
||||
logger.warn(`Field(s) missing (${req.ip})`);
|
||||
return res
|
||||
.type('application/json')
|
||||
.status(400)
|
||||
.json({ error: 'Field(s) missing' });
|
||||
return res.type("application/json").status(400).json({
|
||||
error: "Field(s) missing",
|
||||
});
|
||||
}
|
||||
|
||||
let gdpr = false
|
||||
if (body.gdpr === true) {gdpr = true}
|
||||
const sanitizeData= {
|
||||
username: `${body.username}`,
|
||||
displayName: `${body.displayName}`,
|
||||
gdpr: gdpr,
|
||||
password: `${body.password}`,
|
||||
firstName: `${body.firstName}`,
|
||||
lastName: `${body.lastName}`,
|
||||
let gdpr = false;
|
||||
if (body.gdpr === true) {
|
||||
gdpr = true;
|
||||
}
|
||||
const sanitizeData = {
|
||||
username: `${body.username}`,
|
||||
displayName: `${body.displayName}`,
|
||||
gdpr: gdpr,
|
||||
password: `${body.password}`,
|
||||
firstName: `${body.firstName}`,
|
||||
lastName: `${body.lastName}`,
|
||||
};
|
||||
|
||||
const RegisterServiceResult = await UserService.register(sanitizeData)
|
||||
const RegisterServiceResult =
|
||||
await UserService.register(sanitizeData);
|
||||
|
||||
if (RegisterServiceResult.error === "gdprNotApproved") {
|
||||
logger.warn(`GDPR not approved (${req.ip})`);
|
||||
return res
|
||||
.status(400)
|
||||
.json({
|
||||
error: RegisterServiceResult.error,
|
||||
message: "GDPR not accepted."
|
||||
});
|
||||
return res.status(400).json({
|
||||
error: RegisterServiceResult.error,
|
||||
message: "GDPR not accepted.",
|
||||
});
|
||||
}
|
||||
if (RegisterServiceResult.error === "exist") {
|
||||
logger.warn(`The user already exists (${req.ip})`);
|
||||
return res
|
||||
.type('application/json')
|
||||
.status(400)
|
||||
.json({
|
||||
error: RegisterServiceResult.error,
|
||||
message: "The user already exists."
|
||||
});
|
||||
return res.type("application/json").status(400).json({
|
||||
error: RegisterServiceResult.error,
|
||||
message: "The user already exists.",
|
||||
});
|
||||
}
|
||||
|
||||
// SUCCESS
|
||||
logger.info(`User registered successfully (${req.ip})`);
|
||||
return res
|
||||
.type('application/json')
|
||||
.type("application/json")
|
||||
.status(201)
|
||||
.json(RegisterServiceResult);
|
||||
}
|
||||
@ -88,378 +93,352 @@ async function registerUser(req: Request, res: Response): Promise<unknown> {
|
||||
*
|
||||
* @return {Promise<void>} A promise that resolves when the user is logged in or rejects with an error.
|
||||
*/
|
||||
async function loginUser(req: Request, res: Response): Promise<void> {
|
||||
|
||||
async function loginUser(
|
||||
req: Request,
|
||||
res: Response,
|
||||
): Promise<void> {
|
||||
const body = req.body;
|
||||
if (!body) {
|
||||
res
|
||||
.type('application/json')
|
||||
.status(400)
|
||||
.json({ error: 'Invalid input data' });
|
||||
res.type("application/json").status(400).json({
|
||||
error: "Invalid input data",
|
||||
});
|
||||
}
|
||||
if (!body.password || !body.username) {
|
||||
logger.warn(`Field(s) missing (${req.ip})`);
|
||||
res
|
||||
.type('application/json')
|
||||
.status(400)
|
||||
.json({ error: 'Field(s) missing' });
|
||||
res.type("application/json").status(400).json({
|
||||
error: "Field(s) missing",
|
||||
});
|
||||
}
|
||||
|
||||
const loginData = {
|
||||
username: `${body.username}`,
|
||||
password: `${body.password}`
|
||||
password: `${body.password}`,
|
||||
};
|
||||
console.log(body)
|
||||
console.log(body);
|
||||
const LoginServiceResult = await UserService.login(loginData);
|
||||
console.log(LoginServiceResult)
|
||||
console.log(LoginServiceResult);
|
||||
|
||||
if (LoginServiceResult.error === "userNotFound") {
|
||||
console.log('POOL')
|
||||
res
|
||||
.type('application/json')
|
||||
.status(404)
|
||||
.json({
|
||||
error: LoginServiceResult.error,
|
||||
message: "User not found."
|
||||
});
|
||||
console.log("POOL");
|
||||
res.type("application/json").status(404).json({
|
||||
error: LoginServiceResult.error,
|
||||
message: "User not found.",
|
||||
});
|
||||
}
|
||||
if (LoginServiceResult.error === "invalidPassword") {
|
||||
res
|
||||
.type('application/json')
|
||||
.status(401)
|
||||
.json({
|
||||
error: LoginServiceResult.error,
|
||||
message: "Invalid password."
|
||||
});
|
||||
res.type("application/json").status(401).json({
|
||||
error: LoginServiceResult.error,
|
||||
message: "Invalid password.",
|
||||
});
|
||||
}
|
||||
res
|
||||
.type('application/json')
|
||||
.type("application/json")
|
||||
.status(200)
|
||||
.json(LoginServiceResult);
|
||||
}
|
||||
|
||||
async function getAllUsers(req: Request, res: Response) {
|
||||
const authHeader = req.headers.authorization;
|
||||
const bearerToken = authHeader?.split(' ')[1];
|
||||
const bearerToken = authHeader?.split(" ")[1];
|
||||
if (!bearerToken) {
|
||||
logger.warn(`Bearer token not provided (${req.ip})`);
|
||||
return res
|
||||
.type('application/json')
|
||||
.status(401)
|
||||
.json({ error: 'Unauthorized' });
|
||||
return res.type("application/json").status(401).json({
|
||||
error: "Unauthorized",
|
||||
});
|
||||
}
|
||||
const payload = await JwtService.verify(bearerToken);
|
||||
if (!payload) {
|
||||
logger.warn(`Unauthorized access attempt (${req.ip})`);
|
||||
return res
|
||||
.type('application/json')
|
||||
.status(401)
|
||||
.json({ error: 'Unauthorized' });
|
||||
return res.type("application/json").status(401).json({
|
||||
error: "Unauthorized",
|
||||
});
|
||||
}
|
||||
const sourceUser = await UserService.getFromId(payload.sub)
|
||||
const sourceUser = await UserService.getFromId(payload.sub);
|
||||
if (!sourceUser) {
|
||||
return res
|
||||
.type('application/json')
|
||||
.status(404)
|
||||
.json({ error: 'You dont exist anymore' });
|
||||
return res.type("application/json").status(404).json({
|
||||
error: "You dont exist anymore",
|
||||
});
|
||||
}
|
||||
if (!sourceUser.is_admin) {
|
||||
return res
|
||||
.type('application/json')
|
||||
.status(403)
|
||||
.json({ error: 'Unauthorized' });
|
||||
return res.type("application/json").status(403).json({
|
||||
error: "Unauthorized",
|
||||
});
|
||||
}
|
||||
const AllUserResponse = await UserService.getAll()
|
||||
const AllUserResponse = await UserService.getAll();
|
||||
if (!AllUserResponse.users) {
|
||||
return res
|
||||
.type('application/json')
|
||||
.status(500)
|
||||
.json({ error: 'Internal server error' });
|
||||
return res.type("application/json").status(500).json({
|
||||
error: "Internal server error",
|
||||
});
|
||||
}
|
||||
return res
|
||||
.type('application/json')
|
||||
.type("application/json")
|
||||
.status(200)
|
||||
.json(AllUserResponse);
|
||||
}
|
||||
|
||||
async function getUser(req: Request, res: Response) {
|
||||
const authHeader = req.headers.authorization;
|
||||
const bearerToken = authHeader?.split(' ')[1];
|
||||
const bearerToken = authHeader?.split(" ")[1];
|
||||
if (!bearerToken) {
|
||||
logger.warn(`Bearer token not provided (${req.ip})`);
|
||||
return res
|
||||
.type('application/json')
|
||||
.status(401)
|
||||
.json({ error: 'Unauthorized' });
|
||||
return res.type("application/json").status(401).json({
|
||||
error: "Unauthorized",
|
||||
});
|
||||
}
|
||||
const payload = await JwtService.verify(bearerToken);
|
||||
if (!payload) {
|
||||
logger.warn(`Unauthorized access attempt (${req.ip})`);
|
||||
return res
|
||||
.type('application/json')
|
||||
.status(401)
|
||||
.json({ error: 'Unauthorized' });
|
||||
return res.type("application/json").status(401).json({
|
||||
error: "Unauthorized",
|
||||
});
|
||||
}
|
||||
const sourceUser = await UserService.getFromId(payload.sub)
|
||||
const sourceUser = await UserService.getFromId(payload.sub);
|
||||
if (!sourceUser) {
|
||||
return res
|
||||
.type('application/json')
|
||||
.status(404)
|
||||
.json({ error: 'You dont exist anymore' });
|
||||
return res.type("application/json").status(404).json({
|
||||
error: "You dont exist anymore",
|
||||
});
|
||||
}
|
||||
if (!sourceUser.is_admin) {
|
||||
return res
|
||||
.type('application/json')
|
||||
.status(403)
|
||||
.json({ error: 'Unauthorized' });
|
||||
return res.type("application/json").status(403).json({
|
||||
error: "Unauthorized",
|
||||
});
|
||||
}
|
||||
const userId = req.params["id"];
|
||||
const dbUser = await UserService.getFromId(userId);
|
||||
if (!dbUser) {
|
||||
logger.warn(`User not found (${req.ip})`);
|
||||
return res
|
||||
.type('application/json')
|
||||
.status(404)
|
||||
.json({ error: 'User not found' });
|
||||
return res.type("application/json").status(404).json({
|
||||
error: "User not found",
|
||||
});
|
||||
}
|
||||
// @ts-ignore
|
||||
delete dbUser.passwordHash
|
||||
delete dbUser.passwordHash;
|
||||
// @ts-ignore
|
||||
delete dbUser._id
|
||||
return res
|
||||
.type('application/json')
|
||||
.status(200)
|
||||
.json(dbUser);
|
||||
delete dbUser._id;
|
||||
return res.type("application/json").status(200).json(dbUser);
|
||||
}
|
||||
|
||||
//FEAT - Implement re-auth by current password in case of password change
|
||||
async function editUser(req: Request, res: Response) {
|
||||
const body: IReqEditUserData | null = req.body;
|
||||
if (!body) {
|
||||
return res
|
||||
.type('application/json')
|
||||
.status(400)
|
||||
.json({ error: 'Field(s) missing' });
|
||||
return res.type("application/json").status(400).json({
|
||||
error: "Field(s) missing",
|
||||
});
|
||||
}
|
||||
const authHeader = req.headers.authorization;
|
||||
const bearerToken = authHeader?.split(' ')[1];
|
||||
const bearerToken = authHeader?.split(" ")[1];
|
||||
if (!bearerToken) {
|
||||
logger.warn(`Bearer token not provided (${req.ip})`);
|
||||
return res
|
||||
.type('application/json')
|
||||
.status(401)
|
||||
.json({ error: 'Unauthorized' });
|
||||
return res.type("application/json").status(401).json({
|
||||
error: "Unauthorized",
|
||||
});
|
||||
}
|
||||
const payload = await JwtService.verify(bearerToken);
|
||||
if (!payload) {
|
||||
logger.warn(`Unauthorized access attempt (${req.ip})`);
|
||||
return res
|
||||
.type('application/json')
|
||||
.status(401)
|
||||
.json({ error: 'Unauthorized' });
|
||||
return res.type("application/json").status(401).json({
|
||||
error: "Unauthorized",
|
||||
});
|
||||
}
|
||||
const sourceUser = await UserService.getFromId(payload.sub)
|
||||
const sourceUser = await UserService.getFromId(payload.sub);
|
||||
|
||||
//@ts-ignore
|
||||
const targetUserId = req.params.id || payload.sub
|
||||
console.log(targetUserId)
|
||||
const targetUserId = req.params.id || payload.sub;
|
||||
console.log(targetUserId);
|
||||
|
||||
if (!sourceUser) {
|
||||
logger.warn(`Unauthorized access attempt (${req.ip})`);
|
||||
return res
|
||||
.type('application/json')
|
||||
.status(404)
|
||||
.json({ error: 'You dont exist anymore' });
|
||||
return res.type("application/json").status(404).json({
|
||||
error: "You dont exist anymore",
|
||||
});
|
||||
}
|
||||
if (sourceUser.is_admin || sourceUser.id === payload.sub) {
|
||||
if (sourceUser.is_admin) {
|
||||
logger.info(`EDIT :> Source user is an admin (${sourceUser.firstname} ${sourceUser.lastname})`)
|
||||
logger.info(
|
||||
`EDIT :> Source user is an admin (${sourceUser.firstname} ${sourceUser.lastname})`,
|
||||
);
|
||||
} else {
|
||||
logger.info(`EDIT :> Source user modify itself (${sourceUser.firstname} ${sourceUser.lastname})`)
|
||||
logger.info(
|
||||
`EDIT :> Source user modify itself (${sourceUser.firstname} ${sourceUser.lastname})`,
|
||||
);
|
||||
}
|
||||
|
||||
//TODO Interface
|
||||
const modifiedData = {
|
||||
}
|
||||
const modifiedData = {};
|
||||
//@ts-ignore
|
||||
if (body.firstName) modifiedData.firstName = `${body.firstName}`;
|
||||
if (body.firstName)
|
||||
modifiedData.firstName = `${body.firstName}`;
|
||||
//@ts-ignore
|
||||
if (body.lastName) modifiedData.lastName = `${body.lastName}`;
|
||||
if (body.lastName)
|
||||
modifiedData.lastName = `${body.lastName}`;
|
||||
//@ts-ignore
|
||||
if (body.displayName) modifiedData.displayName = `${body.displayName}`;
|
||||
if (body.displayName)
|
||||
modifiedData.displayName = `${body.displayName}`;
|
||||
//TODO Case handled with hashing by the service.
|
||||
//if (body.password) modifiedData.password = `${body.password}`;
|
||||
|
||||
//Call service
|
||||
const EditUserServiceResult = await UserService.edit(`${targetUserId}`, modifiedData);
|
||||
if (EditUserServiceResult.error === 'userNotFound') {
|
||||
const EditUserServiceResult = await UserService.edit(
|
||||
`${targetUserId}`,
|
||||
modifiedData,
|
||||
);
|
||||
if (EditUserServiceResult.error === "userNotFound") {
|
||||
logger.warn(`User not found (${req.ip})`);
|
||||
return res
|
||||
.type('application/json')
|
||||
.status(404)
|
||||
.json({ error: 'User not found' });
|
||||
return res.type("application/json").status(404).json({
|
||||
error: "User not found",
|
||||
});
|
||||
}
|
||||
if (EditUserServiceResult.error !== 'none') {
|
||||
logger.error(`Error occurred during user edit (${req.ip})`);
|
||||
return res
|
||||
.type('application/json')
|
||||
.status(500)
|
||||
.json({ error: 'Internal server error' });
|
||||
if (EditUserServiceResult.error !== "none") {
|
||||
logger.error(
|
||||
`Error occurred during user edit (${req.ip})`,
|
||||
);
|
||||
return res.type("application/json").status(500).json({
|
||||
error: "Internal server error",
|
||||
});
|
||||
}
|
||||
return res
|
||||
.type('application/json')
|
||||
.type("application/json")
|
||||
.status(200)
|
||||
.json(EditUserServiceResult);
|
||||
}
|
||||
//Not itself or
|
||||
logger.warn(`Unauthorized access attempt, not self or admin (${req.ip})`);
|
||||
return res
|
||||
.type('application/json')
|
||||
.status(403)
|
||||
.json({ error: 'Unauthorized' });
|
||||
|
||||
|
||||
logger.warn(
|
||||
`Unauthorized access attempt, not self or admin (${req.ip})`,
|
||||
);
|
||||
return res.type("application/json").status(403).json({
|
||||
error: "Unauthorized",
|
||||
});
|
||||
}
|
||||
|
||||
async function deleteUser(req: Request, res: Response): Promise<Response> {
|
||||
async function deleteUser(
|
||||
req: Request,
|
||||
res: Response,
|
||||
): Promise<Response> {
|
||||
const authHeader = req.headers.authorization;
|
||||
const bearerToken = authHeader?.split(' ')[1];
|
||||
const bearerToken = authHeader?.split(" ")[1];
|
||||
if (!bearerToken) {
|
||||
logger.warn(`Bearer token not provided (${req.ip})`);
|
||||
return res
|
||||
.type('application/json')
|
||||
.status(401)
|
||||
.json({ error: 'Unauthorized' });
|
||||
return res.type("application/json").status(401).json({
|
||||
error: "Unauthorized",
|
||||
});
|
||||
}
|
||||
const payload = await JwtService.verify(bearerToken);
|
||||
|
||||
if (!payload) {
|
||||
logger.warn(`Invalid token (${req.ip})`);
|
||||
return res
|
||||
.type('application/json')
|
||||
.status(401)
|
||||
.json({ error: 'Invalid token' });
|
||||
return res.type("application/json").status(401).json({
|
||||
error: "Invalid token",
|
||||
});
|
||||
}
|
||||
const sourceUser = await UserService.getFromId(payload?.sub)
|
||||
const targetUserId = req.params["id"]
|
||||
const sourceUser = await UserService.getFromId(payload?.sub);
|
||||
const targetUserId = req.params["id"];
|
||||
if (!sourceUser) {
|
||||
logger.warn(`Unauthorized access attempt (${req.ip})`);
|
||||
return res
|
||||
.type('application/json')
|
||||
.status(404)
|
||||
.json({ error: 'You dont exist anymore' });
|
||||
return res.type("application/json").status(404).json({
|
||||
error: "You dont exist anymore",
|
||||
});
|
||||
}
|
||||
if (sourceUser.is_admin || sourceUser.id === payload.sub) {
|
||||
const deleteUserServiceResult = await UserService.delete(`${targetUserId}`);
|
||||
const deleteUserServiceResult = await UserService.delete(
|
||||
`${targetUserId}`,
|
||||
);
|
||||
if (!deleteUserServiceResult) {
|
||||
logger.error(`Error occurred during user delete (${req.ip})`);
|
||||
return res
|
||||
.type('application/json')
|
||||
.status(500)
|
||||
.json({ error: 'Internal server error' });
|
||||
logger.error(
|
||||
`Error occurred during user delete (${req.ip})`,
|
||||
);
|
||||
return res.type("application/json").status(500).json({
|
||||
error: "Internal server error",
|
||||
});
|
||||
}
|
||||
|
||||
return res
|
||||
.type('application/json')
|
||||
.status(200)
|
||||
.json({ message: 'User deleted successfully' });
|
||||
return res.type("application/json").status(200).json({
|
||||
message: "User deleted successfully",
|
||||
});
|
||||
}
|
||||
return res
|
||||
.type('application/json')
|
||||
.status(403)
|
||||
.json({ error: 'Unauthorized' });
|
||||
return res.type("application/json").status(403).json({
|
||||
error: "Unauthorized",
|
||||
});
|
||||
}
|
||||
|
||||
async function deleteSelf(req: Request, res: Response) {
|
||||
const authHeader = req.headers.authorization;
|
||||
const bearerToken = authHeader?.split(' ')[1];
|
||||
if (!bearerToken) {
|
||||
logger.warn(`Bearer token not provided (${req.ip})`);
|
||||
return res
|
||||
.type('application/json')
|
||||
.status(401)
|
||||
.json({ error: 'Unauthorized' });
|
||||
}
|
||||
const payload = await JwtService.verify(bearerToken);
|
||||
if (!payload) {
|
||||
logger.warn(`Unauthorized access attempt (${req.ip})`);
|
||||
return res
|
||||
.type('application/json')
|
||||
.status(401)
|
||||
.json({ error: 'Unauthorized' });
|
||||
}
|
||||
const sourceUser = await UserService.getFromId(payload.sub)
|
||||
if (!sourceUser) {
|
||||
return res
|
||||
.type('application/json')
|
||||
.status(404)
|
||||
.json({ error: 'You dont exist anymore' });
|
||||
}
|
||||
if (sourceUser.id !== req.params["id"]) {
|
||||
return res
|
||||
.type('application/json')
|
||||
.status(403)
|
||||
.json({ error: 'Unauthorized' });
|
||||
}
|
||||
const deleteResult = await UserService.delete(sourceUser.id);
|
||||
const bearerToken = authHeader?.split(" ")[1];
|
||||
if (!bearerToken) {
|
||||
logger.warn(`Bearer token not provided (${req.ip})`);
|
||||
return res.type("application/json").status(401).json({
|
||||
error: "Unauthorized",
|
||||
});
|
||||
}
|
||||
const payload = await JwtService.verify(bearerToken);
|
||||
if (!payload) {
|
||||
logger.warn(`Unauthorized access attempt (${req.ip})`);
|
||||
return res.type("application/json").status(401).json({
|
||||
error: "Unauthorized",
|
||||
});
|
||||
}
|
||||
const sourceUser = await UserService.getFromId(payload.sub);
|
||||
if (!sourceUser) {
|
||||
return res.type("application/json").status(404).json({
|
||||
error: "You dont exist anymore",
|
||||
});
|
||||
}
|
||||
if (sourceUser.id !== req.params["id"]) {
|
||||
return res.type("application/json").status(403).json({
|
||||
error: "Unauthorized",
|
||||
});
|
||||
}
|
||||
const deleteResult = await UserService.delete(sourceUser.id);
|
||||
if (!deleteResult) {
|
||||
logger.error(`Failed to delete user (${req.ip})`);
|
||||
return res
|
||||
.type('application/json')
|
||||
.status(500)
|
||||
.json({ error: 'Failed to delete user' });
|
||||
return res.type("application/json").status(500).json({
|
||||
error: "Failed to delete user",
|
||||
});
|
||||
}
|
||||
return res
|
||||
.type('application/json')
|
||||
.status(200)
|
||||
.json({ message: 'User deleted successfully' });
|
||||
return res.type("application/json").status(200).json({
|
||||
message: "User deleted successfully",
|
||||
});
|
||||
}
|
||||
|
||||
async function getSelf(req: Request, res: Response) {
|
||||
const authHeader = req.headers.authorization;
|
||||
const bearerToken = authHeader?.split(' ')[1];
|
||||
const bearerToken = authHeader?.split(" ")[1];
|
||||
if (!bearerToken) {
|
||||
return res
|
||||
.type('application/json')
|
||||
.status(401)
|
||||
.json({ error: 'Unauthorized' });
|
||||
return res.type("application/json").status(401).json({
|
||||
error: "Unauthorized",
|
||||
});
|
||||
}
|
||||
const payload = await JwtService.verify(bearerToken);
|
||||
if (!payload) {
|
||||
logger.warn(`Unauthorized access attempt (${req.ip})`);
|
||||
return res
|
||||
.type('application/json')
|
||||
.status(401)
|
||||
.json({ error: 'Unauthorized' });
|
||||
}
|
||||
const dbUser = await UserService.getFromId(payload.sub)
|
||||
if (!dbUser) {
|
||||
return res
|
||||
.type('application/json')
|
||||
.status(404)
|
||||
.json({ error: 'User not found' });
|
||||
}
|
||||
return res
|
||||
.type('application/json')
|
||||
.status(200)
|
||||
.json({
|
||||
id: dbUser.id,
|
||||
username: dbUser.username,
|
||||
firstName: dbUser.firstname,
|
||||
lastName: dbUser.firstname,
|
||||
isAdmin: dbUser.firstname
|
||||
logger.warn(`Unauthorized access attempt (${req.ip})`);
|
||||
return res.type("application/json").status(401).json({
|
||||
error: "Unauthorized",
|
||||
});
|
||||
}
|
||||
const dbUser = await UserService.getFromId(payload.sub);
|
||||
if (!dbUser) {
|
||||
return res.type("application/json").status(404).json({
|
||||
error: "User not found",
|
||||
});
|
||||
}
|
||||
return res.type("application/json").status(200).json({
|
||||
id: dbUser.id,
|
||||
username: dbUser.username,
|
||||
firstName: dbUser.firstname,
|
||||
lastName: dbUser.firstname,
|
||||
isAdmin: dbUser.firstname,
|
||||
});
|
||||
}
|
||||
|
||||
const AuthController = {
|
||||
register: registerUser,
|
||||
login: loginUser,
|
||||
getAllUsers,
|
||||
getUser,
|
||||
editUser,
|
||||
deleteUser,
|
||||
login: loginUser,
|
||||
getAllUsers,
|
||||
getUser,
|
||||
editUser,
|
||||
deleteUser,
|
||||
deleteSelf,
|
||||
getSelf
|
||||
}
|
||||
getSelf,
|
||||
};
|
||||
|
||||
export default AuthController;
|
||||
export default AuthController;
|
||||
|
@ -1,13 +1,13 @@
|
||||
import type {Request, Response} from "express";
|
||||
import {Logger} from "tslog";
|
||||
|
||||
import type { Request, Response } from "express";
|
||||
import { Logger } from "tslog";
|
||||
|
||||
import type IDbBrand from "@interfaces/database/IDbBrand";
|
||||
import BrandService from "@services/brand.service";
|
||||
//import {body} from "express-validator";
|
||||
|
||||
|
||||
const logger = new Logger({ name: "BrandController" });
|
||||
const logger = new Logger({
|
||||
name: "BrandController",
|
||||
});
|
||||
|
||||
/**
|
||||
* Creates a new brand.
|
||||
@ -17,24 +17,37 @@ const logger = new Logger({ name: "BrandController" });
|
||||
*
|
||||
* @returns A Promise that resolves to the response object with a status code and a JSON message indicating the success or failure of brand creation.
|
||||
*/
|
||||
async function createBrand(req: Request, res: Response): Promise<Response> {
|
||||
const body: IDbBrand = req.body
|
||||
const doesExist = await BrandService.getBySlug(`${body.slug_name}`)
|
||||
async function createBrand(
|
||||
req: Request,
|
||||
res: Response,
|
||||
): Promise<Response> {
|
||||
const body: IDbBrand = req.body;
|
||||
const doesExist = await BrandService.getBySlug(
|
||||
`${body.slug_name}`,
|
||||
);
|
||||
if (doesExist) {
|
||||
logger.error("Brand already exists");
|
||||
return res.status(400).json({ error: "Brand already exists" });
|
||||
return res.status(400).json({
|
||||
error: "Brand already exists",
|
||||
});
|
||||
}
|
||||
const createResult = await BrandService.create({
|
||||
slug_name: `${body.slug_name}`,
|
||||
display_name: `${body.display_name}`,
|
||||
image_blob: `${body.image_blob}`
|
||||
})
|
||||
image_blob: `${body.image_blob}`,
|
||||
});
|
||||
if (!createResult) {
|
||||
logger.error("Failed to create brand");
|
||||
return res.status(500).json({ error: "Failed to create brand" });
|
||||
return res.status(500).json({
|
||||
error: "Failed to create brand",
|
||||
});
|
||||
}
|
||||
logger.info(`Brand created successfully ! (${body.slug_name})`)
|
||||
return res.status(201).json({ message: "Brand created successfully" });
|
||||
logger.info(
|
||||
`Brand created successfully ! (${body.slug_name})`,
|
||||
);
|
||||
return res.status(201).json({
|
||||
message: "Brand created successfully",
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -44,29 +57,40 @@ async function createBrand(req: Request, res: Response): Promise<Response> {
|
||||
* @param {Response} res - The HTTP response object.
|
||||
* @return {Promise<Response>} A promise that resolves with the HTTP response.
|
||||
*/
|
||||
async function updateBrand(req: Request, res: Response): Promise<Response> {
|
||||
async function updateBrand(
|
||||
req: Request,
|
||||
res: Response,
|
||||
): Promise<Response> {
|
||||
const body: IDbBrand = req.body;
|
||||
const brandSlug = req.params["brandSlug"];
|
||||
const brandSlug = req.params["brandSlug"];
|
||||
if (!brandSlug) {
|
||||
logger.error("Brand slug is missing");
|
||||
return res.status(400).json({ error: "Brand slug is missing" });
|
||||
return res.status(400).json({
|
||||
error: "Brand slug is missing",
|
||||
});
|
||||
}
|
||||
const doesExist = await BrandService.getBySlug(brandSlug);
|
||||
if (!doesExist) {
|
||||
logger.error("Brand not found");
|
||||
return res.status(404).json({ error: "Brand not found" });
|
||||
}
|
||||
const updateResult = await BrandService.update({
|
||||
slug_name: `${body.slug_name}`,
|
||||
display_name: `${body.display_name}`,
|
||||
image_blob: `${body.image_blob}`
|
||||
});
|
||||
if (!updateResult) {
|
||||
logger.error("Failed to update brand");
|
||||
return res.status(500).json({ error: "Failed to update brand" });
|
||||
}
|
||||
logger.info(`Brand updated successfully ! (${brandSlug})`);
|
||||
return res.status(200).json({ message: "Brand updated successfully" });
|
||||
const doesExist = await BrandService.getBySlug(brandSlug);
|
||||
if (!doesExist) {
|
||||
logger.error("Brand not found");
|
||||
return res.status(404).json({
|
||||
error: "Brand not found",
|
||||
});
|
||||
}
|
||||
const updateResult = await BrandService.update({
|
||||
slug_name: `${body.slug_name}`,
|
||||
display_name: `${body.display_name}`,
|
||||
image_blob: `${body.image_blob}`,
|
||||
});
|
||||
if (!updateResult) {
|
||||
logger.error("Failed to update brand");
|
||||
return res.status(500).json({
|
||||
error: "Failed to update brand",
|
||||
});
|
||||
}
|
||||
logger.info(`Brand updated successfully ! (${brandSlug})`);
|
||||
return res.status(200).json({
|
||||
message: "Brand updated successfully",
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -76,19 +100,26 @@ async function updateBrand(req: Request, res: Response): Promise<Response> {
|
||||
* @param {Response} res - The response object to send the result.
|
||||
* @returns {Promise<Response>} - A promise that resolves to the response with the retrieved brand.
|
||||
*/
|
||||
async function getBySlugBrand(req: Request, res: Response): Promise<Response> {
|
||||
async function getBySlugBrand(
|
||||
req: Request,
|
||||
res: Response,
|
||||
): Promise<Response> {
|
||||
const brandSlug = req.params["brandSlug"];
|
||||
if (!brandSlug) {
|
||||
logger.error("Brand slug is missing");
|
||||
return res.status(400).json({ error: "Brand slug is missing" });
|
||||
}
|
||||
const brand = await BrandService.getBySlug(brandSlug);
|
||||
if (!brand) {
|
||||
logger.error("Brand not found");
|
||||
return res.status(404).json({ error: "Brand not found" });
|
||||
}
|
||||
logger.info(`Brand retrieved successfully ! (${brandSlug})`);
|
||||
return res.status(200).json(brand);
|
||||
if (!brandSlug) {
|
||||
logger.error("Brand slug is missing");
|
||||
return res.status(400).json({
|
||||
error: "Brand slug is missing",
|
||||
});
|
||||
}
|
||||
const brand = await BrandService.getBySlug(brandSlug);
|
||||
if (!brand) {
|
||||
logger.error("Brand not found");
|
||||
return res.status(404).json({
|
||||
error: "Brand not found",
|
||||
});
|
||||
}
|
||||
logger.info(`Brand retrieved successfully ! (${brandSlug})`);
|
||||
return res.status(200).json(brand);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -98,17 +129,22 @@ async function getBySlugBrand(req: Request, res: Response): Promise<Response> {
|
||||
* @param {Response} res - The response object.
|
||||
* @returns {Promise<Response>} - A promise with the response object.
|
||||
*/
|
||||
async function getAllBrand(_req: Request, res: Response): Promise<Response> {
|
||||
async function getAllBrand(
|
||||
_req: Request,
|
||||
res: Response,
|
||||
): Promise<Response> {
|
||||
const brands = await BrandService.getAll();
|
||||
if (!brands) {
|
||||
logger.error("Failed to retrieve brands");
|
||||
return res.status(500).json({ error: "Failed to retrieve brands" });
|
||||
}
|
||||
logger.info("Brands retrieved successfully !");
|
||||
return res.status(200).json({
|
||||
if (!brands) {
|
||||
logger.error("Failed to retrieve brands");
|
||||
return res.status(500).json({
|
||||
error: "Failed to retrieve brands",
|
||||
});
|
||||
}
|
||||
logger.info("Brands retrieved successfully !");
|
||||
return res.status(200).json({
|
||||
uat: Date.now(),
|
||||
brands: brands,
|
||||
total: brands.length
|
||||
total: brands.length,
|
||||
});
|
||||
}
|
||||
|
||||
@ -120,25 +156,36 @@ async function getAllBrand(_req: Request, res: Response): Promise<Response> {
|
||||
* @param {Response} res - The response object.
|
||||
* @returns {Promise<Response>} - The response object indicating the success or failure of the delete operation.
|
||||
*/
|
||||
async function deleteBrand(req: Request, res: Response): Promise<Response> {
|
||||
async function deleteBrand(
|
||||
req: Request,
|
||||
res: Response,
|
||||
): Promise<Response> {
|
||||
const brandSlug = req.params["brandSlug"];
|
||||
if (!brandSlug) {
|
||||
logger.error("Brand slug is missing");
|
||||
return res.status(400).json({ error: "Brand slug is missing" });
|
||||
}
|
||||
if (!brandSlug) {
|
||||
logger.error("Brand slug is missing");
|
||||
return res.status(400).json({
|
||||
error: "Brand slug is missing",
|
||||
});
|
||||
}
|
||||
//TODO verify if models linked to brand
|
||||
const doesExist = await BrandService.getBySlug(brandSlug);
|
||||
if (!doesExist) {
|
||||
logger.error("Brand not found");
|
||||
return res.status(404).json({ error: "Brand not found" });
|
||||
}
|
||||
const deleteResult = await BrandService.delete(brandSlug);
|
||||
if (!deleteResult) {
|
||||
logger.error("Failed to delete brand");
|
||||
return res.status(500).json({ error: "Failed to delete brand" });
|
||||
}
|
||||
logger.info(`Brand deleted successfully ! (${brandSlug})`);
|
||||
return res.status(200).json({ message: "Brand deleted successfully" });
|
||||
const doesExist = await BrandService.getBySlug(brandSlug);
|
||||
if (!doesExist) {
|
||||
logger.error("Brand not found");
|
||||
return res.status(404).json({
|
||||
error: "Brand not found",
|
||||
});
|
||||
}
|
||||
const deleteResult = await BrandService.delete(brandSlug);
|
||||
if (!deleteResult) {
|
||||
logger.error("Failed to delete brand");
|
||||
return res.status(500).json({
|
||||
error: "Failed to delete brand",
|
||||
});
|
||||
}
|
||||
logger.info(`Brand deleted successfully ! (${brandSlug})`);
|
||||
return res.status(200).json({
|
||||
message: "Brand deleted successfully",
|
||||
});
|
||||
}
|
||||
|
||||
//TODO get models of the brand
|
||||
@ -149,6 +196,6 @@ const BrandController = {
|
||||
getBySlug: getBySlugBrand,
|
||||
getAll: getAllBrand,
|
||||
delete: deleteBrand,
|
||||
}
|
||||
};
|
||||
|
||||
export default BrandController;
|
||||
export default BrandController;
|
||||
|
@ -1,12 +1,12 @@
|
||||
import type {Request, Response} from "express";
|
||||
import {Logger} from "tslog";
|
||||
import type IDbCategory from "@interfaces/database/IDbCategory";
|
||||
import CategoryService from "@services/category.service";
|
||||
import type { Request, Response } from "express";
|
||||
import { Logger } from "tslog";
|
||||
//import {validationResult} from "express-validator";
|
||||
|
||||
|
||||
const logger = new Logger({ name: "CategoryController" });
|
||||
|
||||
const logger = new Logger({
|
||||
name: "CategoryController",
|
||||
});
|
||||
|
||||
/**
|
||||
* Creates a new category.
|
||||
@ -15,23 +15,36 @@ const logger = new Logger({ name: "CategoryController" });
|
||||
* @param {Response} res - The response object to send back to the client.
|
||||
* @returns {Promise<Response>} The response object indicating the outcome of the category creation.
|
||||
*/
|
||||
async function createCategory(req: Request, res: Response): Promise<Response> {
|
||||
const body: IDbCategory = req.body
|
||||
const doesExist = await CategoryService.getBySlug(`${body.slug_name}`)
|
||||
async function createCategory(
|
||||
req: Request,
|
||||
res: Response,
|
||||
): Promise<Response> {
|
||||
const body: IDbCategory = req.body;
|
||||
const doesExist = await CategoryService.getBySlug(
|
||||
`${body.slug_name}`,
|
||||
);
|
||||
if (doesExist) {
|
||||
logger.error("Category already exists");
|
||||
return res.status(400).json({ error: "Category already exists" });
|
||||
}
|
||||
logger.error("Category already exists");
|
||||
return res.status(400).json({
|
||||
error: "Category already exists",
|
||||
});
|
||||
}
|
||||
const createResult = await CategoryService.create({
|
||||
display_name: `${body.display_name}`,
|
||||
slug_name: `${body.slug_name}`
|
||||
})
|
||||
slug_name: `${body.slug_name}`,
|
||||
});
|
||||
if (!createResult) {
|
||||
logger.error("Failed to create category");
|
||||
return res.status(500).json({ error: "Failed to create category" });
|
||||
return res.status(500).json({
|
||||
error: "Failed to create category",
|
||||
});
|
||||
}
|
||||
logger.info(`Category created successfully ! (${body.slug_name})`)
|
||||
return res.status(201).json({ message: "Category created successfully" });
|
||||
logger.info(
|
||||
`Category created successfully ! (${body.slug_name})`,
|
||||
);
|
||||
return res.status(201).json({
|
||||
message: "Category created successfully",
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -42,29 +55,42 @@ async function createCategory(req: Request, res: Response): Promise<Response> {
|
||||
*
|
||||
* @return {Promise<Response>} - A promise that will be resolved with the result of the update operation.
|
||||
*/
|
||||
async function updateCategory(req: Request, res:Response): Promise<Response> {
|
||||
async function updateCategory(
|
||||
req: Request,
|
||||
res: Response,
|
||||
): Promise<Response> {
|
||||
const body: IDbCategory = req.body;
|
||||
const categoryId = req.params["categorySlug"];
|
||||
const categoryId = req.params["categorySlug"];
|
||||
if (!categoryId) {
|
||||
logger.error("Category slug is missing");
|
||||
return res.status(400).json({ error: "Category slug is missing" });
|
||||
return res.status(400).json({
|
||||
error: "Category slug is missing",
|
||||
});
|
||||
}
|
||||
const doesExist = await CategoryService.getById(`${categoryId}`)
|
||||
if (!doesExist || !doesExist.id) {
|
||||
logger.error("Category not found");
|
||||
return res.status(404).json({ error: "Category not found" });
|
||||
}
|
||||
const updateResult = await CategoryService.update({
|
||||
const doesExist = await CategoryService.getById(
|
||||
`${categoryId}`,
|
||||
);
|
||||
if (!doesExist || !doesExist.id) {
|
||||
logger.error("Category not found");
|
||||
return res.status(404).json({
|
||||
error: "Category not found",
|
||||
});
|
||||
}
|
||||
const updateResult = await CategoryService.update({
|
||||
id: doesExist.id,
|
||||
slug_name: `${body.slug_name}`,
|
||||
display_name: `${body.display_name}`
|
||||
})
|
||||
if (!updateResult) {
|
||||
logger.error("Failed to update category");
|
||||
return res.status(500).json({ error: "Failed to update category" });
|
||||
}
|
||||
logger.info(`Category updated successfully! (${categoryId})`);
|
||||
return res.status(200).json({ message: "Category updated successfully" });
|
||||
display_name: `${body.display_name}`,
|
||||
});
|
||||
if (!updateResult) {
|
||||
logger.error("Failed to update category");
|
||||
return res.status(500).json({
|
||||
error: "Failed to update category",
|
||||
});
|
||||
}
|
||||
logger.info(`Category updated successfully! (${categoryId})`);
|
||||
return res.status(200).json({
|
||||
message: "Category updated successfully",
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -74,24 +100,41 @@ async function updateCategory(req: Request, res:Response): Promise<Response> {
|
||||
* @param {Response} res - The response object to send the result.
|
||||
* @returns {Promise<Response>} A Promise that resolves to the response object.
|
||||
*/
|
||||
async function deleteCategory(req: Request, res: Response): Promise<Response> {
|
||||
async function deleteCategory(
|
||||
req: Request,
|
||||
res: Response,
|
||||
): Promise<Response> {
|
||||
const categorySlug = req.params["categorySlug"];
|
||||
if (!categorySlug) {
|
||||
logger.error("Category slug is missing");
|
||||
return res.status(400).json({ error: "Category slug is missing" });
|
||||
}
|
||||
const doesExist = await CategoryService.getBySlug(`${categorySlug}`);
|
||||
if (!doesExist || !doesExist.id) {
|
||||
logger.error("Category not found");
|
||||
return res.status(404).json({ error: "Category not found" });
|
||||
}
|
||||
const deleteResult = await CategoryService.delete(`${doesExist.id}`);
|
||||
if (!deleteResult) {
|
||||
logger.error("Failed to delete category");
|
||||
return res.status(500).json({ error: "Failed to delete category" });
|
||||
}
|
||||
logger.info(`Category deleted successfully! (${categorySlug})`);
|
||||
return res.status(200).json({ message: "Category deleted successfully" });
|
||||
if (!categorySlug) {
|
||||
logger.error("Category slug is missing");
|
||||
return res.status(400).json({
|
||||
error: "Category slug is missing",
|
||||
});
|
||||
}
|
||||
const doesExist = await CategoryService.getBySlug(
|
||||
`${categorySlug}`,
|
||||
);
|
||||
if (!doesExist || !doesExist.id) {
|
||||
logger.error("Category not found");
|
||||
return res.status(404).json({
|
||||
error: "Category not found",
|
||||
});
|
||||
}
|
||||
const deleteResult = await CategoryService.delete(
|
||||
`${doesExist.id}`,
|
||||
);
|
||||
if (!deleteResult) {
|
||||
logger.error("Failed to delete category");
|
||||
return res.status(500).json({
|
||||
error: "Failed to delete category",
|
||||
});
|
||||
}
|
||||
logger.info(
|
||||
`Category deleted successfully! (${categorySlug})`,
|
||||
);
|
||||
return res.status(200).json({
|
||||
message: "Category deleted successfully",
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -101,23 +144,26 @@ async function deleteCategory(req: Request, res: Response): Promise<Response> {
|
||||
* @param {Response} res - The response object.
|
||||
* @return {Promise<Response>} - A promise that resolves to the response object.
|
||||
*/
|
||||
async function getAllCategory(_req: Request, res: Response): Promise<Response> {
|
||||
async function getAllCategory(
|
||||
_req: Request,
|
||||
res: Response,
|
||||
): Promise<Response> {
|
||||
const categories = await CategoryService.getAll();
|
||||
if (!categories) {
|
||||
logger.error("Failed to get categories");
|
||||
return res.status(500).json({ error: "Failed to get categories" });
|
||||
}
|
||||
logger.info("Categories retrieved successfully");
|
||||
return res
|
||||
.status(200)
|
||||
.json({
|
||||
if (!categories) {
|
||||
logger.error("Failed to get categories");
|
||||
return res.status(500).json({
|
||||
error: "Failed to get categories",
|
||||
});
|
||||
}
|
||||
logger.info("Categories retrieved successfully");
|
||||
return res.status(200).json({
|
||||
iat: Date.now(),
|
||||
categories: categories.map((category: IDbCategory) => ({
|
||||
id: category.id,
|
||||
display_name: category.display_name,
|
||||
slug_name: category.slug_name
|
||||
})),
|
||||
total: categories.length
|
||||
id: category.id,
|
||||
display_name: category.display_name,
|
||||
slug_name: category.slug_name,
|
||||
})),
|
||||
total: categories.length,
|
||||
});
|
||||
}
|
||||
|
||||
@ -129,23 +175,34 @@ async function getAllCategory(_req: Request, res: Response): Promise<Response> {
|
||||
*
|
||||
* @return {Promise<Response>} - The response with category data or error message
|
||||
*/
|
||||
async function getBySlugCategory(req: Request, res:Response): Promise<Response> {
|
||||
async function getBySlugCategory(
|
||||
req: Request,
|
||||
res: Response,
|
||||
): Promise<Response> {
|
||||
const categorySlug = req.params["categorySlug"];
|
||||
if (!categorySlug) {
|
||||
logger.error("Category slug is missing");
|
||||
return res.status(400).json({ error: "Category slug is missing" });
|
||||
}
|
||||
const category = await CategoryService.getBySlug(`${categorySlug}`);
|
||||
if (!category || !category.id) {
|
||||
logger.error("Category not found");
|
||||
return res.status(404).json({ error: "Category not found" });
|
||||
}
|
||||
logger.info(`Category retrieved successfully! (${categorySlug})`);
|
||||
return res.status(200).json({
|
||||
id: category.id,
|
||||
display_name: category.display_name,
|
||||
slug_name: category.slug_name
|
||||
});
|
||||
if (!categorySlug) {
|
||||
logger.error("Category slug is missing");
|
||||
return res.status(400).json({
|
||||
error: "Category slug is missing",
|
||||
});
|
||||
}
|
||||
const category = await CategoryService.getBySlug(
|
||||
`${categorySlug}`,
|
||||
);
|
||||
if (!category || !category.id) {
|
||||
logger.error("Category not found");
|
||||
return res.status(404).json({
|
||||
error: "Category not found",
|
||||
});
|
||||
}
|
||||
logger.info(
|
||||
`Category retrieved successfully! (${categorySlug})`,
|
||||
);
|
||||
return res.status(200).json({
|
||||
id: category.id,
|
||||
display_name: category.display_name,
|
||||
slug_name: category.slug_name,
|
||||
});
|
||||
}
|
||||
|
||||
const CategoryController = {
|
||||
@ -153,7 +210,7 @@ const CategoryController = {
|
||||
update: updateCategory,
|
||||
delete: deleteCategory,
|
||||
getAll: getAllCategory,
|
||||
getBySlug: getBySlugCategory
|
||||
}
|
||||
getBySlug: getBySlugCategory,
|
||||
};
|
||||
|
||||
export default CategoryController;
|
||||
export default CategoryController;
|
||||
|
@ -1,20 +1,27 @@
|
||||
import type {Request, Response} from "express";
|
||||
import {Logger} from "tslog";
|
||||
import CategoryService from "@services/category.service";
|
||||
import type IDbModel from "@interfaces/database/IDbModel";
|
||||
import CategoryService from "@services/category.service";
|
||||
import ModelService from "@services/model.service";
|
||||
import type { Request, Response } from "express";
|
||||
import { Logger } from "tslog";
|
||||
//import {validationResult} from "express-validator";
|
||||
|
||||
const logger = new Logger({
|
||||
name: "ModelController",
|
||||
});
|
||||
|
||||
const logger = new Logger({ name: "ModelController" });
|
||||
|
||||
|
||||
async function createModel(req: Request, res: Response): Promise<Response> {
|
||||
const body: IDbModel = req.body
|
||||
const doesExist = await CategoryService.getBySlug(`${body.slug_name}`)
|
||||
async function createModel(
|
||||
req: Request,
|
||||
res: Response,
|
||||
): Promise<Response> {
|
||||
const body: IDbModel = req.body;
|
||||
const doesExist = await CategoryService.getBySlug(
|
||||
`${body.slug_name}`,
|
||||
);
|
||||
if (doesExist) {
|
||||
logger.error("Category already exists");
|
||||
return res.status(400).json({ error: "Category already exists" });
|
||||
return res.status(400).json({
|
||||
error: "Category already exists",
|
||||
});
|
||||
}
|
||||
const createResult = await ModelService.create({
|
||||
display_name: `${body.display_name}`,
|
||||
@ -23,82 +30,123 @@ async function createModel(req: Request, res: Response): Promise<Response> {
|
||||
base_price: Number.parseFloat(`${body.base_price}`),
|
||||
brand_id: `${body.brand_id}`,
|
||||
image_blob: `${body.image_blob}`,
|
||||
is_trending: !!body.is_trending
|
||||
})
|
||||
is_trending: !!body.is_trending,
|
||||
});
|
||||
if (!createResult) {
|
||||
logger.error("Failed to create category");
|
||||
return res.status(500).json({ error: "Failed to create category" });
|
||||
return res.status(500).json({
|
||||
error: "Failed to create category",
|
||||
});
|
||||
}
|
||||
logger.info(`Category created successfully ! (${body.slug_name})`)
|
||||
return res.status(201).json({ message: "Category created successfully" });
|
||||
logger.info(
|
||||
`Category created successfully ! (${body.slug_name})`,
|
||||
);
|
||||
return res.status(201).json({
|
||||
message: "Category created successfully",
|
||||
});
|
||||
}
|
||||
|
||||
async function updateModel(req: Request, res: Response): Promise<Response> {
|
||||
async function updateModel(
|
||||
req: Request,
|
||||
res: Response,
|
||||
): Promise<Response> {
|
||||
const body: IDbModel = req.body;
|
||||
const doesExist = await ModelService.getBySlug(`${body.slug_name}`);
|
||||
if (!doesExist) {
|
||||
const doesExist = await ModelService.getBySlug(
|
||||
`${body.slug_name}`,
|
||||
);
|
||||
if (!doesExist) {
|
||||
logger.error("Model does not exist");
|
||||
return res.status(404).json({ error: "Model does not exist" });
|
||||
return res.status(404).json({
|
||||
error: "Model does not exist",
|
||||
});
|
||||
}
|
||||
const updateResult = await ModelService.update({
|
||||
id: `${body.id}`,
|
||||
display_name: `${body.display_name}`,
|
||||
slug_name: `${body.slug_name}`,
|
||||
category_id: `${body.category_id}`,
|
||||
base_price: Number.parseFloat(`${body.base_price}`),
|
||||
brand_id: `${body.brand_id}`,
|
||||
image_blob: `${body.image_blob}`,
|
||||
is_trending: !!body.is_trending
|
||||
});
|
||||
if (!updateResult) {
|
||||
logger.error("Failed to update model");
|
||||
return res.status(500).json({ error: "Failed to update model" });
|
||||
}
|
||||
logger.info(`Model updated successfully! (${body.slug_name})`);
|
||||
return res.status(200).json({ message: "Model updated successfully" });
|
||||
const updateResult = await ModelService.update({
|
||||
id: `${body.id}`,
|
||||
display_name: `${body.display_name}`,
|
||||
slug_name: `${body.slug_name}`,
|
||||
category_id: `${body.category_id}`,
|
||||
base_price: Number.parseFloat(`${body.base_price}`),
|
||||
brand_id: `${body.brand_id}`,
|
||||
image_blob: `${body.image_blob}`,
|
||||
is_trending: !!body.is_trending,
|
||||
});
|
||||
if (!updateResult) {
|
||||
logger.error("Failed to update model");
|
||||
return res.status(500).json({
|
||||
error: "Failed to update model",
|
||||
});
|
||||
}
|
||||
logger.info(
|
||||
`Model updated successfully! (${body.slug_name})`,
|
||||
);
|
||||
return res.status(200).json({
|
||||
message: "Model updated successfully",
|
||||
});
|
||||
}
|
||||
|
||||
async function getAllModel(res: Response): Promise<Response> {
|
||||
const models = await ModelService.getAll();
|
||||
if (!models) {
|
||||
logger.error("Failed to get all models");
|
||||
return res.status(500).json({ error: "Failed to get all models" });
|
||||
}
|
||||
return res.status(200).json({
|
||||
if (!models) {
|
||||
logger.error("Failed to get all models");
|
||||
return res.status(500).json({
|
||||
error: "Failed to get all models",
|
||||
});
|
||||
}
|
||||
return res.status(200).json({
|
||||
uat: Date.now(),
|
||||
models: models,
|
||||
total: models.length
|
||||
total: models.length,
|
||||
});
|
||||
}
|
||||
|
||||
async function getModelBySlug(req: Request, res: Response): Promise<Response> {
|
||||
async function getModelBySlug(
|
||||
req: Request,
|
||||
res: Response,
|
||||
): Promise<Response> {
|
||||
const slug = req.params["modelSlug"];
|
||||
if (!slug) {
|
||||
logger.error("Invalid slug");
|
||||
return res.status(400).json({ error: "Invalid slug" });
|
||||
return res.status(400).json({
|
||||
error: "Invalid slug",
|
||||
});
|
||||
}
|
||||
const model = await ModelService.getBySlug(slug);
|
||||
if (!model) {
|
||||
logger.error("Model not found");
|
||||
return res.status(404).json({ error: "Model not found" });
|
||||
}
|
||||
return res.status(200).json({ model });
|
||||
const model = await ModelService.getBySlug(slug);
|
||||
if (!model) {
|
||||
logger.error("Model not found");
|
||||
return res.status(404).json({
|
||||
error: "Model not found",
|
||||
});
|
||||
}
|
||||
return res.status(200).json({
|
||||
model,
|
||||
});
|
||||
}
|
||||
|
||||
async function deleteModel(req: Request, res: Response): Promise<Response> {
|
||||
async function deleteModel(
|
||||
req: Request,
|
||||
res: Response,
|
||||
): Promise<Response> {
|
||||
const modelSlug = req.params["modelSlug"];
|
||||
if (!modelSlug) {
|
||||
logger.error("Invalid model slug");
|
||||
return res.status(400).json({ error: "Invalid model slug" });
|
||||
}
|
||||
if (!modelSlug) {
|
||||
logger.error("Invalid model slug");
|
||||
return res.status(400).json({
|
||||
error: "Invalid model slug",
|
||||
});
|
||||
}
|
||||
//TODO Check if vehicle related to model
|
||||
const deleteResult = await ModelService.delete(modelSlug);
|
||||
if (!deleteResult) {
|
||||
logger.error("Failed to delete model");
|
||||
return res.status(500).json({ error: "Failed to delete model" });
|
||||
}
|
||||
logger.info(`Model deleted successfully! (SLUG: ${modelSlug})`);
|
||||
return res.status(200).json({ message: "Model deleted successfully" });
|
||||
const deleteResult = await ModelService.delete(modelSlug);
|
||||
if (!deleteResult) {
|
||||
logger.error("Failed to delete model");
|
||||
return res.status(500).json({
|
||||
error: "Failed to delete model",
|
||||
});
|
||||
}
|
||||
logger.info(
|
||||
`Model deleted successfully! (SLUG: ${modelSlug})`,
|
||||
);
|
||||
return res.status(200).json({
|
||||
message: "Model deleted successfully",
|
||||
});
|
||||
}
|
||||
|
||||
//TODO get all vehicles of an model by slug
|
||||
@ -108,9 +156,9 @@ async function deleteModel(req: Request, res: Response): Promise<Response> {
|
||||
const ModelController = {
|
||||
create: createModel,
|
||||
update: updateModel,
|
||||
getAll: getAllModel,
|
||||
getBySlug: getModelBySlug,
|
||||
delete: deleteModel,
|
||||
}
|
||||
getAll: getAllModel,
|
||||
getBySlug: getModelBySlug,
|
||||
delete: deleteModel,
|
||||
};
|
||||
|
||||
export default ModelController;
|
||||
export default ModelController;
|
||||
|
@ -3,4 +3,4 @@ export interface IReqEditUserData {
|
||||
lastName?: string;
|
||||
displayName?: string;
|
||||
password?: string;
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ interface DbUserData {
|
||||
isDisabled: boolean;
|
||||
|
||||
resetPasswordToken?: string;
|
||||
resetPasswordExpires?: Date;
|
||||
resetPasswordExpires?: Date;
|
||||
|
||||
dob: Date;
|
||||
gdpr: Date;
|
||||
@ -20,4 +20,4 @@ interface DbUserData {
|
||||
uat: Date;
|
||||
}
|
||||
|
||||
export default DbUserData
|
||||
export default DbUserData;
|
||||
|
@ -1,8 +1,8 @@
|
||||
export interface IDbBrand {
|
||||
id?: string;
|
||||
slug_name: string;
|
||||
display_name: string;
|
||||
image_blob: BinaryType;
|
||||
id?: string;
|
||||
slug_name: string;
|
||||
display_name: string;
|
||||
image_blob: BinaryType;
|
||||
}
|
||||
|
||||
export default IDbBrand;
|
||||
export default IDbBrand;
|
||||
|
@ -1,7 +1,7 @@
|
||||
export interface IDbCategory {
|
||||
id?: string;
|
||||
slug_name: string;
|
||||
display_name: string
|
||||
id?: string;
|
||||
slug_name: string;
|
||||
display_name: string;
|
||||
}
|
||||
|
||||
export default IDbCategory;
|
||||
export default IDbCategory;
|
||||
|
@ -1,12 +1,12 @@
|
||||
export interface IDbModel {
|
||||
id?: string;
|
||||
slug_name: string;
|
||||
display_name: string;
|
||||
brand_id: string;
|
||||
category_id: string;
|
||||
image_blob: BinaryType;
|
||||
is_trending: boolean;
|
||||
base_price: number;
|
||||
id?: string;
|
||||
slug_name: string;
|
||||
display_name: string;
|
||||
brand_id: string;
|
||||
category_id: string;
|
||||
image_blob: BinaryType;
|
||||
is_trending: boolean;
|
||||
base_price: number;
|
||||
}
|
||||
|
||||
export default IDbModel;
|
||||
export default IDbModel;
|
||||
|
@ -1,11 +1,11 @@
|
||||
export interface IDbRent {
|
||||
vehicle_id: string;
|
||||
user_id: string;
|
||||
active: boolean;
|
||||
iat: Date;
|
||||
eat: Date;
|
||||
need_survey: boolean;
|
||||
km_at_start: number
|
||||
vehicle_id: string;
|
||||
user_id: string;
|
||||
active: boolean;
|
||||
iat: Date;
|
||||
eat: Date;
|
||||
need_survey: boolean;
|
||||
km_at_start: number;
|
||||
}
|
||||
|
||||
export default IDbRent;
|
||||
export default IDbRent;
|
||||
|
@ -6,4 +6,4 @@ export interface IDbStatusResult {
|
||||
serverStatus: number;
|
||||
warningStatus: number;
|
||||
changedRows: number;
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
export interface IDbUser {
|
||||
id?: string;
|
||||
username: string;
|
||||
firstname: string;
|
||||
lastname: string;
|
||||
dob: Date;
|
||||
email: string;
|
||||
is_mail_verified: boolean;
|
||||
is_admin: boolean;
|
||||
gdpr: Date;
|
||||
hash: string
|
||||
}
|
||||
id?: string;
|
||||
username: string;
|
||||
firstname: string;
|
||||
lastname: string;
|
||||
dob: Date;
|
||||
email: string;
|
||||
is_mail_verified: boolean;
|
||||
is_admin: boolean;
|
||||
gdpr: Date;
|
||||
hash: string;
|
||||
}
|
||||
|
@ -4,4 +4,4 @@ export interface IDbVehicle {
|
||||
model_id: string;
|
||||
odometer: number;
|
||||
health_state: number;
|
||||
}
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
export * from './UserData'
|
||||
export * from "./UserData";
|
||||
|
@ -1,4 +1,4 @@
|
||||
export interface IReqLogin {
|
||||
username: string;
|
||||
password: string;
|
||||
}
|
||||
}
|
||||
|
@ -5,4 +5,4 @@ export interface IReqRegister {
|
||||
lastName: string;
|
||||
password: string;
|
||||
gdpr?: boolean;
|
||||
}
|
||||
}
|
||||
|
@ -1,38 +1,39 @@
|
||||
import express, {type Router} from "express";
|
||||
import UserGuard from "@validators/UserGuard";
|
||||
import AdminGuard from "@validators/AdminGuard";
|
||||
import AuthController from "@controllers/auth.controller";
|
||||
|
||||
import AdminGuard from "@validators/AdminGuard";
|
||||
import UserGuard from "@validators/UserGuard";
|
||||
import express, { type Router } from "express";
|
||||
|
||||
const AuthRouter: Router = express.Router();
|
||||
|
||||
AuthRouter.route('/login').post(AuthController.login)
|
||||
AuthRouter.route('/register').post(AuthController.register)
|
||||
AuthRouter.route("/login").post(AuthController.login);
|
||||
AuthRouter.route("/register").post(AuthController.register);
|
||||
|
||||
// PATCH
|
||||
//TODO - To test
|
||||
AuthRouter.route('/me')
|
||||
.patch(UserGuard, AuthController.editUser)
|
||||
AuthRouter.route("/me").patch(
|
||||
UserGuard,
|
||||
AuthController.editUser,
|
||||
);
|
||||
|
||||
// GET
|
||||
AuthRouter.route('/me')
|
||||
.get(UserGuard, AuthController.getSelf)
|
||||
AuthRouter.route("/me").get(UserGuard, AuthController.getSelf);
|
||||
|
||||
// DELETE
|
||||
AuthRouter.route('/me')
|
||||
.delete(UserGuard, AuthController.deleteSelf)
|
||||
|
||||
AuthRouter.route("/me").delete(
|
||||
UserGuard,
|
||||
AuthController.deleteSelf,
|
||||
);
|
||||
|
||||
// GET
|
||||
AuthRouter.route('/all')
|
||||
.get(AdminGuard, AuthController.getAllUsers)
|
||||
|
||||
AuthRouter.route("/all").get(
|
||||
AdminGuard,
|
||||
AuthController.getAllUsers,
|
||||
);
|
||||
|
||||
// GET
|
||||
AuthRouter.route('/user/:targetId')
|
||||
AuthRouter.route("/user/:targetId")
|
||||
.get(AdminGuard, AuthController.getUser)
|
||||
.patch(AdminGuard, AuthController.editUser)
|
||||
.delete(AdminGuard, AuthController.deleteUser)
|
||||
.delete(AdminGuard, AuthController.deleteUser);
|
||||
|
||||
|
||||
export default AuthRouter
|
||||
export default AuthRouter;
|
||||
|
@ -1,44 +1,52 @@
|
||||
import express, {type Router} from "express";
|
||||
import AdminGuard from "@validators/AdminGuard";
|
||||
import UserGuard from "@validators/UserGuard";
|
||||
import BrandController from "@controllers/brand.controller";
|
||||
import CategoryController from "@controllers/category.controller";
|
||||
import ModelController from "@controllers/model.controller";
|
||||
import BrandController from "@controllers/brand.controller";
|
||||
|
||||
import AdminGuard from "@validators/AdminGuard";
|
||||
import UserGuard from "@validators/UserGuard";
|
||||
import express, { type Router } from "express";
|
||||
|
||||
const CatalogRouter: Router = express.Router();
|
||||
|
||||
//-- MODELS >>
|
||||
|
||||
CatalogRouter.route('/model/new').get(AdminGuard, ModelController.create)
|
||||
CatalogRouter.route("/model/new").get(
|
||||
AdminGuard,
|
||||
ModelController.create,
|
||||
);
|
||||
|
||||
CatalogRouter.route('/model/all').get(ModelController.getAll)
|
||||
CatalogRouter.route("/model/all").get(ModelController.getAll);
|
||||
|
||||
CatalogRouter.route('/model/:modelSlug')
|
||||
CatalogRouter.route("/model/:modelSlug")
|
||||
.get(UserGuard, ModelController.getBySlug)
|
||||
.patch(AdminGuard, ModelController.update)
|
||||
.delete(AdminGuard, ModelController.delete)
|
||||
|
||||
.delete(AdminGuard, ModelController.delete);
|
||||
|
||||
//-- CATEGORY >>
|
||||
|
||||
CatalogRouter.route('/category/new').get(AdminGuard, CategoryController.create)
|
||||
CatalogRouter.route("/category/new").get(
|
||||
AdminGuard,
|
||||
CategoryController.create,
|
||||
);
|
||||
|
||||
CatalogRouter.route('/category/all').get(CategoryController.getAll)
|
||||
CatalogRouter.route("/category/all").get(
|
||||
CategoryController.getAll,
|
||||
);
|
||||
|
||||
CatalogRouter.route('/category/:categorySlug')
|
||||
CatalogRouter.route("/category/:categorySlug")
|
||||
.get(UserGuard, CategoryController.getBySlug)
|
||||
.patch(AdminGuard, CategoryController.update)
|
||||
.delete(AdminGuard, CategoryController.delete)
|
||||
|
||||
.delete(AdminGuard, CategoryController.delete);
|
||||
|
||||
//-- BRAND >>
|
||||
|
||||
CatalogRouter.route('/brand/new').post(AdminGuard, BrandController.create)
|
||||
CatalogRouter.route('/brand/all').get(BrandController.getAll)
|
||||
CatalogRouter.route('/brand/:brandSlug')
|
||||
CatalogRouter.route("/brand/new").post(
|
||||
AdminGuard,
|
||||
BrandController.create,
|
||||
);
|
||||
CatalogRouter.route("/brand/all").get(BrandController.getAll);
|
||||
CatalogRouter.route("/brand/:brandSlug")
|
||||
.get(UserGuard, BrandController.getBySlug)
|
||||
.patch(AdminGuard, BrandController.update)
|
||||
.delete(AdminGuard, BrandController.delete)
|
||||
.delete(AdminGuard, BrandController.delete);
|
||||
|
||||
export default CatalogRouter;
|
||||
export default CatalogRouter;
|
||||
|
@ -1,3 +1,3 @@
|
||||
export * from 'src/routes/auth/authRouter'
|
||||
export * from 'src/routes/catalog/catalogRouter'
|
||||
export * from 'src/routes/rent/rentRouter'
|
||||
export * from "src/routes/auth/authRouter";
|
||||
export * from "src/routes/catalog/catalogRouter";
|
||||
export * from "src/routes/rent/rentRouter";
|
||||
|
@ -1,34 +1,27 @@
|
||||
import express, {type Router} from "express";
|
||||
import AdminGuard from "@validators/AdminGuard";
|
||||
import UserGuard from "@validators/UserGuard";
|
||||
|
||||
import express, { type Router } from "express";
|
||||
|
||||
const RentRouter: Router = express.Router();
|
||||
|
||||
// Get rent affected to the user
|
||||
RentRouter.route('/affected')
|
||||
.get(UserGuard)
|
||||
RentRouter.route("/affected").get(UserGuard);
|
||||
|
||||
// Get all vehicle in rent (admin only)
|
||||
RentRouter.route('/affected/all')
|
||||
.get(AdminGuard)
|
||||
RentRouter.route("/affected/all").get(AdminGuard);
|
||||
|
||||
// Add a new vehicle (admin only)
|
||||
RentRouter.route('/veh/new')
|
||||
.post(AdminGuard)
|
||||
RentRouter.route("/veh/new").post(AdminGuard);
|
||||
|
||||
// Get all vehicles
|
||||
RentRouter.route('/veh/all')
|
||||
.get()
|
||||
RentRouter.route("/veh/all").get();
|
||||
|
||||
// Rent a specific vehicle
|
||||
RentRouter.route('/veh/rent/:vehicleId')
|
||||
.post(UserGuard)
|
||||
RentRouter.route("/veh/rent/:vehicleId").post(UserGuard);
|
||||
|
||||
|
||||
RentRouter.route('/veh/:vehicleId')
|
||||
RentRouter.route("/veh/:vehicleId")
|
||||
.get(UserGuard)
|
||||
.patch(AdminGuard)
|
||||
.delete(AdminGuard)
|
||||
.delete(AdminGuard);
|
||||
|
||||
export default RentRouter;
|
||||
export default RentRouter;
|
||||
|
@ -1,10 +1,12 @@
|
||||
import type IDbBrand from "@interfaces/database/IDbBrand";
|
||||
import MysqlService from "@services/mysql.service";
|
||||
import {Logger} from "tslog";
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { Logger } from "tslog";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
|
||||
const DbHandler = new MysqlService.Handler('BrandService')
|
||||
const logger = new Logger({name: 'BrandService'})
|
||||
const DbHandler = new MysqlService.Handler("BrandService");
|
||||
const logger = new Logger({
|
||||
name: "BrandService",
|
||||
});
|
||||
|
||||
//SEC todo Blob validation
|
||||
/**
|
||||
@ -14,24 +16,39 @@ const logger = new Logger({name: 'BrandService'})
|
||||
* @return {Promise<unknown>} A promise that resolves to the result of the operation.
|
||||
*/
|
||||
async function createBrand(data: IDbBrand): Promise<unknown> {
|
||||
const doesExist = await MysqlService.Brand.getBySlug(DbHandler, data.slug_name);
|
||||
const doesExist = await MysqlService.Brand.getBySlug(
|
||||
DbHandler,
|
||||
data.slug_name,
|
||||
);
|
||||
if (doesExist) {
|
||||
logger.error(`Brand already exists (${data.slug_name})`)
|
||||
return {error: 'exist'}
|
||||
logger.error(`Brand already exists (${data.slug_name})`);
|
||||
return {
|
||||
error: "exist",
|
||||
};
|
||||
}
|
||||
const brandId = uuidv4();
|
||||
const createdBrand = await MysqlService.Brand.insert(DbHandler, {
|
||||
id: brandId,
|
||||
slug_name: `${data.slug_name}`,
|
||||
display_name: `${data.display_name}`,
|
||||
image_blob: data.image_blob
|
||||
});
|
||||
if (createdBrand) {
|
||||
logger.info(`Brand created successfully (${data.slug_name})`);
|
||||
return { success: true, brand: createdBrand };
|
||||
}
|
||||
logger.error(`Failed to create brand (${data.slug_name})`);
|
||||
return { error: 'failed' };
|
||||
const createdBrand = await MysqlService.Brand.insert(
|
||||
DbHandler,
|
||||
{
|
||||
id: brandId,
|
||||
slug_name: `${data.slug_name}`,
|
||||
display_name: `${data.display_name}`,
|
||||
image_blob: data.image_blob,
|
||||
},
|
||||
);
|
||||
if (createdBrand) {
|
||||
logger.info(
|
||||
`Brand created successfully (${data.slug_name})`,
|
||||
);
|
||||
return {
|
||||
success: true,
|
||||
brand: createdBrand,
|
||||
};
|
||||
}
|
||||
logger.error(`Failed to create brand (${data.slug_name})`);
|
||||
return {
|
||||
error: "failed",
|
||||
};
|
||||
}
|
||||
|
||||
//SEC todo Blob validation
|
||||
@ -44,38 +61,48 @@ async function createBrand(data: IDbBrand): Promise<unknown> {
|
||||
async function updateBrand(data: IDbBrand): Promise<boolean> {
|
||||
if (!data.id) {
|
||||
logger.error("Brand ID is missing");
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
const doesExist = await MysqlService.Brand.getBySlug(DbHandler, data.slug_name);
|
||||
if (doesExist && doesExist.id !== data.id) {
|
||||
logger.error(`Brand already exists (${data.slug_name})`);
|
||||
return false;
|
||||
}
|
||||
const updatedBrand = await MysqlService.Brand.update(DbHandler, {
|
||||
id: data.id,
|
||||
slug_name: `${data.slug_name}`,
|
||||
display_name: `${data.display_name}`,
|
||||
image_blob: data.image_blob
|
||||
});
|
||||
if (updatedBrand) {
|
||||
logger.info(`Brand updated successfully (${data.slug_name})`);
|
||||
return true;
|
||||
}
|
||||
logger.error(`Failed to update brand (${data.slug_name})`);
|
||||
return false;
|
||||
const doesExist = await MysqlService.Brand.getBySlug(
|
||||
DbHandler,
|
||||
data.slug_name,
|
||||
);
|
||||
if (doesExist && doesExist.id !== data.id) {
|
||||
logger.error(`Brand already exists (${data.slug_name})`);
|
||||
return false;
|
||||
}
|
||||
const updatedBrand = await MysqlService.Brand.update(
|
||||
DbHandler,
|
||||
{
|
||||
id: data.id,
|
||||
slug_name: `${data.slug_name}`,
|
||||
display_name: `${data.display_name}`,
|
||||
image_blob: data.image_blob,
|
||||
},
|
||||
);
|
||||
if (updatedBrand) {
|
||||
logger.info(
|
||||
`Brand updated successfully (${data.slug_name})`,
|
||||
);
|
||||
return true;
|
||||
}
|
||||
logger.error(`Failed to update brand (${data.slug_name})`);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all brands from the database.
|
||||
* @returns {Promise<Array<IDbBrand>|false>} - An array of IDbBrand objects if successful, false otherwise.
|
||||
*/
|
||||
async function getAllBrand(): Promise<Array<IDbBrand>| false> {
|
||||
async function getAllBrand(): Promise<Array<IDbBrand> | false> {
|
||||
const brands = await MysqlService.Brand.getAll(DbHandler);
|
||||
if (!brands) {
|
||||
logger.error("Failed to retrieve brands");
|
||||
return false;
|
||||
}
|
||||
logger.info(`Retrieved all brands successfully (${brands.length})`);
|
||||
}
|
||||
logger.info(
|
||||
`Retrieved all brands successfully (${brands.length})`,
|
||||
);
|
||||
return brands;
|
||||
}
|
||||
|
||||
@ -85,18 +112,25 @@ async function getAllBrand(): Promise<Array<IDbBrand>| false> {
|
||||
* @param {string} brandSlug - The slug of the brand.
|
||||
* @returns {Promise<IDbBrand|false>} - A promise that resolves to the retrieved brand object or false if the brand is not found.
|
||||
*/
|
||||
async function getBySlugBrand(brandSlug: string): Promise<IDbBrand | false> {
|
||||
async function getBySlugBrand(
|
||||
brandSlug: string,
|
||||
): Promise<IDbBrand | false> {
|
||||
if (!brandSlug) {
|
||||
logger.error("Brand slug is missing");
|
||||
return false;
|
||||
}
|
||||
const brand = await MysqlService.Brand.getBySlug(DbHandler, brandSlug);
|
||||
if (!brand) {
|
||||
logger.error(`Brand not found (${brandSlug})`);
|
||||
return false;
|
||||
}
|
||||
logger.info(`Retrieved brand by slug successfully (${brandSlug})`);
|
||||
return brand;
|
||||
logger.error("Brand slug is missing");
|
||||
return false;
|
||||
}
|
||||
const brand = await MysqlService.Brand.getBySlug(
|
||||
DbHandler,
|
||||
brandSlug,
|
||||
);
|
||||
if (!brand) {
|
||||
logger.error(`Brand not found (${brandSlug})`);
|
||||
return false;
|
||||
}
|
||||
logger.info(
|
||||
`Retrieved brand by slug successfully (${brandSlug})`,
|
||||
);
|
||||
return brand;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -106,7 +140,9 @@ async function getBySlugBrand(brandSlug: string): Promise<IDbBrand | false> {
|
||||
*
|
||||
* @returns {Promise<IDbBrand | false>} A promise that resolves to the retrieved brand object, or false if the brand is not found or the ID is invalid.
|
||||
*/
|
||||
async function getByIdBrand(brandId: string): Promise<IDbBrand | false> {
|
||||
async function getByIdBrand(
|
||||
brandId: string,
|
||||
): Promise<IDbBrand | false> {
|
||||
if (!brandId) {
|
||||
logger.error("Brand ID is missing");
|
||||
return false;
|
||||
@ -115,12 +151,17 @@ async function getByIdBrand(brandId: string): Promise<IDbBrand | false> {
|
||||
logger.error("Invalid brand ID");
|
||||
return false;
|
||||
}
|
||||
const brand = await MysqlService.Brand.getById(DbHandler, brandId);
|
||||
const brand = await MysqlService.Brand.getById(
|
||||
DbHandler,
|
||||
brandId,
|
||||
);
|
||||
if (!brand) {
|
||||
logger.error(`Brand not found (${brandId})`);
|
||||
return false;
|
||||
}
|
||||
logger.info(`Retrieved brand by ID successfully (${brandId})`);
|
||||
logger.info(
|
||||
`Retrieved brand by ID successfully (${brandId})`,
|
||||
);
|
||||
return brand;
|
||||
}
|
||||
|
||||
@ -144,11 +185,14 @@ async function deleteBrand(brandId: string): Promise<boolean> {
|
||||
return false;
|
||||
}
|
||||
//TODO verify if as models linked
|
||||
const deletedBrand = await MysqlService.Brand.delete(DbHandler, brandId);
|
||||
if (!deletedBrand) {
|
||||
const deletedBrand = await MysqlService.Brand.delete(
|
||||
DbHandler,
|
||||
brandId,
|
||||
);
|
||||
if (!deletedBrand) {
|
||||
logger.error(`Failed to delete brand (${brandId})`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
logger.info(`Brand deleted successfully (${brandId})`);
|
||||
return true;
|
||||
}
|
||||
@ -160,6 +204,6 @@ const BrandService = {
|
||||
getBySlug: getBySlugBrand,
|
||||
getById: getByIdBrand,
|
||||
delete: deleteBrand,
|
||||
}
|
||||
};
|
||||
|
||||
export default BrandService;
|
||||
export default BrandService;
|
||||
|
@ -1,12 +1,12 @@
|
||||
import type { IDbCategory } from "@interfaces/database/IDbCategory";
|
||||
import MysqlService from "@services/mysql.service";
|
||||
import {Logger} from "tslog";
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
const DbHandler = new MysqlService.Handler('CategoryService')
|
||||
const logger = new Logger({name: 'CategoryService'})
|
||||
|
||||
import { Logger } from "tslog";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
|
||||
const DbHandler = new MysqlService.Handler("CategoryService");
|
||||
const logger = new Logger({
|
||||
name: "CategoryService",
|
||||
});
|
||||
|
||||
/**
|
||||
* Creates a new category with the given data.
|
||||
@ -15,19 +15,23 @@ const logger = new Logger({name: 'CategoryService'})
|
||||
* @returns {Promise<boolean>} A promise that resolves with the created category.
|
||||
* If an error occurs, the promise will reject with the error.
|
||||
*/
|
||||
async function createCategory(data: IDbCategory): Promise<boolean> {
|
||||
logger.info(`Creating a new category... (${data.display_name})`)
|
||||
async function createCategory(
|
||||
data: IDbCategory,
|
||||
): Promise<boolean> {
|
||||
logger.info(
|
||||
`Creating a new category... (${data.display_name})`,
|
||||
);
|
||||
try {
|
||||
await MysqlService.Category.insert(DbHandler, {
|
||||
id: uuidv4(),
|
||||
display_name: data.display_name,
|
||||
slug_name: data.slug_name
|
||||
})
|
||||
slug_name: data.slug_name,
|
||||
});
|
||||
//TODO Return the new id
|
||||
return true;
|
||||
} catch (error) {
|
||||
logger.error(`Error creating category: ${error}`);
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,19 +47,19 @@ async function createCategory(data: IDbCategory): Promise<boolean> {
|
||||
*/
|
||||
async function updateCategory(data: IDbCategory) {
|
||||
if (!data.id) {
|
||||
logger.error("Category id is missing.")
|
||||
return false
|
||||
logger.error("Category id is missing.");
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
await MysqlService.Category.update(DbHandler, {
|
||||
id: data.id,
|
||||
slug_name: data.slug_name,
|
||||
display_name: data.display_name
|
||||
display_name: data.display_name,
|
||||
});
|
||||
//TODO Return id
|
||||
return true;
|
||||
} catch (err) {
|
||||
logger.error(err)
|
||||
logger.error(err);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -65,31 +69,37 @@ async function updateCategory(data: IDbCategory) {
|
||||
*
|
||||
* @returns {Promise<Array<IDbCategory>> | null} Promise that resolves to an array of IDbCategory objects or null if an error occurred.
|
||||
*/
|
||||
async function getAll(): Promise<Promise<Array<IDbCategory>> | null> {
|
||||
async function getAll(): Promise<Promise<
|
||||
Array<IDbCategory>
|
||||
> | null> {
|
||||
try {
|
||||
logger.info("Getting all categories...");
|
||||
return await MysqlService.Category.getAll(DbHandler);
|
||||
} catch (error) {
|
||||
logger.error(`Error getting all categories: ${error}`);
|
||||
return null;
|
||||
}
|
||||
logger.info("Getting all categories...");
|
||||
return await MysqlService.Category.getAll(DbHandler);
|
||||
} catch (error) {
|
||||
logger.error(`Error getting all categories: ${error}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets a category by its slug
|
||||
*
|
||||
* @param {string} slug - The slug of the category
|
||||
* @return {Promise<IDbCategory|null>} - A promise that resolves to the category object or null if not found
|
||||
*/
|
||||
async function getBySlug(slug: string): Promise<IDbCategory | null> {
|
||||
async function getBySlug(
|
||||
slug: string,
|
||||
): Promise<IDbCategory | null> {
|
||||
try {
|
||||
logger.info(`Getting category by slug... (${slug})`);
|
||||
return await MysqlService.Category.getBySlug(DbHandler, slug);
|
||||
} catch (error) {
|
||||
logger.error(`Error getting category by slug: ${error}`);
|
||||
return null;
|
||||
}
|
||||
logger.info(`Getting category by slug... (${slug})`);
|
||||
return await MysqlService.Category.getBySlug(
|
||||
DbHandler,
|
||||
slug,
|
||||
);
|
||||
} catch (error) {
|
||||
logger.error(`Error getting category by slug: ${error}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -98,35 +108,36 @@ async function getBySlug(slug: string): Promise<IDbCategory | null> {
|
||||
* @param {string} id - The id of the category to retrieve.
|
||||
* @returns {Promise<IDbCategory | null>} - A Promise that resolves with the retrieved category object or null if not found.
|
||||
*/
|
||||
async function getById(id: string):Promise<IDbCategory | null> {
|
||||
async function getById(
|
||||
id: string,
|
||||
): Promise<IDbCategory | null> {
|
||||
try {
|
||||
logger.info(`Getting category by id... (${id})`);
|
||||
return await MysqlService.Category.getById(DbHandler, id);
|
||||
} catch (error) {
|
||||
logger.error(`Error getting category by id: ${error}`);
|
||||
return null;
|
||||
}
|
||||
logger.info(`Getting category by id... (${id})`);
|
||||
return await MysqlService.Category.getById(DbHandler, id);
|
||||
} catch (error) {
|
||||
logger.error(`Error getting category by id: ${error}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
//FEAT Get all models in category (slug)
|
||||
|
||||
|
||||
/**
|
||||
* Deletes a category with the given ID from the database.
|
||||
*
|
||||
* @param {string} id - The ID of the category to delete.
|
||||
* @return {Promise} - A Promise that resolves to the deleted category if successful, or null if an error occurs.
|
||||
*/
|
||||
async function deleteCategory(id:string): Promise<unknown> {
|
||||
async function deleteCategory(id: string): Promise<unknown> {
|
||||
//TODO Verify if exist
|
||||
//TODO Verify if element linked to category
|
||||
try {
|
||||
logger.info(`Deleting category... (${id})`);
|
||||
return await MysqlService.Category.delete(DbHandler, id);
|
||||
} catch (error) {
|
||||
logger.error(`Error deleting category: ${error}`);
|
||||
return null;
|
||||
}
|
||||
logger.info(`Deleting category... (${id})`);
|
||||
return await MysqlService.Category.delete(DbHandler, id);
|
||||
} catch (error) {
|
||||
logger.error(`Error deleting category: ${error}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
const CategoryService = {
|
||||
@ -135,7 +146,7 @@ const CategoryService = {
|
||||
update: updateCategory,
|
||||
getAll,
|
||||
getBySlug,
|
||||
getById
|
||||
}
|
||||
getById,
|
||||
};
|
||||
|
||||
export default CategoryService;
|
||||
export default CategoryService;
|
||||
|
@ -2,23 +2,26 @@ import Argon2id from "@node-rs/argon2";
|
||||
|
||||
//ToTest
|
||||
export async function getHashFromPassword(password: string) {
|
||||
return await Argon2id.hash(password,{
|
||||
return await Argon2id.hash(password, {
|
||||
secret: Buffer.from(`${process.env["HASH_SECRET"]}`),
|
||||
algorithm: 2
|
||||
})
|
||||
algorithm: 2,
|
||||
});
|
||||
}
|
||||
|
||||
//ToTest
|
||||
export async function comparePassword(password: string, hash: string) {
|
||||
export async function comparePassword(
|
||||
password: string,
|
||||
hash: string,
|
||||
) {
|
||||
return await Argon2id.verify(hash, password, {
|
||||
secret: Buffer.from(`${process.env["HASH_SECRET"]}`),
|
||||
algorithm: 2
|
||||
algorithm: 2,
|
||||
});
|
||||
}
|
||||
|
||||
const CredentialService = {
|
||||
compare: comparePassword,
|
||||
hash: getHashFromPassword,
|
||||
}
|
||||
};
|
||||
|
||||
export default CredentialService;
|
||||
export default CredentialService;
|
||||
|
@ -1,2 +1,2 @@
|
||||
export * from './jwt.service';
|
||||
export * as MySqlService from './mysql.service'
|
||||
export * from "./jwt.service";
|
||||
export * as MySqlService from "./mysql.service";
|
||||
|
@ -1,7 +1,14 @@
|
||||
import {type JWTHeaderParameters, type JWTPayload, jwtVerify, SignJWT} from "jose";
|
||||
import {Logger} from "tslog";
|
||||
import {
|
||||
type JWTHeaderParameters,
|
||||
type JWTPayload,
|
||||
SignJWT,
|
||||
jwtVerify,
|
||||
} from "jose";
|
||||
import { Logger } from "tslog";
|
||||
|
||||
const logger = new Logger({ name: "JwtService" });
|
||||
const logger = new Logger({
|
||||
name: "JwtService",
|
||||
});
|
||||
|
||||
/**
|
||||
* Verify a JWT token.
|
||||
@ -11,22 +18,22 @@ const logger = new Logger({ name: "JwtService" });
|
||||
* @returns {Promise<null | JWTPayload>}
|
||||
* - The payload of the verified JWT token or null if verification fails.
|
||||
*/
|
||||
async function JwtVerifyService(jwt: string | Uint8Array): Promise<null | JWTPayload> {
|
||||
try {
|
||||
const result = await jwtVerify(
|
||||
jwt,
|
||||
new TextEncoder()
|
||||
.encode(`${process.env["JWT_SECRET"]}`),
|
||||
{
|
||||
})
|
||||
return result.payload;
|
||||
} catch (error) {
|
||||
logger.error(error)
|
||||
return null
|
||||
}
|
||||
async function JwtVerifyService(
|
||||
jwt: string | Uint8Array,
|
||||
): Promise<null | JWTPayload> {
|
||||
try {
|
||||
const result = await jwtVerify(
|
||||
jwt,
|
||||
new TextEncoder().encode(`${process.env["JWT_SECRET"]}`),
|
||||
{},
|
||||
);
|
||||
return result.payload;
|
||||
} catch (error) {
|
||||
logger.error(error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Asynchronously signs a JWT token using the provided payload, header, expiration time, and audience.
|
||||
*
|
||||
@ -42,19 +49,26 @@ async function JwtVerifyService(jwt: string | Uint8Array): Promise<null | JWTPay
|
||||
* @returns {Promise<string>}
|
||||
* - A promise that resolves with the signed JWT token.
|
||||
*/
|
||||
async function JwtSignService(payload: JWTPayload, pHeader: JWTHeaderParameters, expTime: string | number | Date, audience: string | string[]): Promise<string> {
|
||||
return await new SignJWT(payload)
|
||||
.setProtectedHeader(pHeader)
|
||||
.setIssuedAt(new Date())
|
||||
.setIssuer(`${process.env["JWT_SECRET"]} - Mathis HERRIOT`)
|
||||
.setAudience(audience)
|
||||
.setExpirationTime(expTime)
|
||||
.sign(new TextEncoder().encode(`${process.env["JWT_SECRET"]}`))
|
||||
async function JwtSignService(
|
||||
payload: JWTPayload,
|
||||
pHeader: JWTHeaderParameters,
|
||||
expTime: string | number | Date,
|
||||
audience: string | string[],
|
||||
): Promise<string> {
|
||||
return await new SignJWT(payload)
|
||||
.setProtectedHeader(pHeader)
|
||||
.setIssuedAt(new Date())
|
||||
.setIssuer(`${process.env["JWT_SECRET"]} - Mathis HERRIOT`)
|
||||
.setAudience(audience)
|
||||
.setExpirationTime(expTime)
|
||||
.sign(
|
||||
new TextEncoder().encode(`${process.env["JWT_SECRET"]}`),
|
||||
);
|
||||
}
|
||||
|
||||
const JwtService = {
|
||||
verify: JwtVerifyService,
|
||||
sign: JwtSignService
|
||||
}
|
||||
verify: JwtVerifyService,
|
||||
sign: JwtSignService,
|
||||
};
|
||||
|
||||
export default JwtService
|
||||
export default JwtService;
|
||||
|
@ -1,10 +1,12 @@
|
||||
import type IDbModel from "@interfaces/database/IDbModel";
|
||||
import MysqlService from "@services/mysql.service";
|
||||
import {Logger} from "tslog";
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { Logger } from "tslog";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
|
||||
const DbHandler = new MysqlService.Handler('ModelService')
|
||||
const logger = new Logger({name: 'ModelService'})
|
||||
const DbHandler = new MysqlService.Handler("ModelService");
|
||||
const logger = new Logger({
|
||||
name: "ModelService",
|
||||
});
|
||||
|
||||
//SEC TODO validate blob
|
||||
/**
|
||||
@ -15,7 +17,7 @@ const logger = new Logger({name: 'ModelService'})
|
||||
* @return {Promise<boolean>} - Indicates whether the model was created successfully.
|
||||
*/
|
||||
async function createModel(data: IDbModel): Promise<boolean> {
|
||||
logger.info(`Creating a new model... (${data.display_name})`)
|
||||
logger.info(`Creating a new model... (${data.display_name})`);
|
||||
//TODO Validate IDbModel data
|
||||
try {
|
||||
await MysqlService.Model.insert(DbHandler, {
|
||||
@ -26,10 +28,10 @@ async function createModel(data: IDbModel): Promise<boolean> {
|
||||
brand_id: data.brand_id,
|
||||
category_id: data.category_id,
|
||||
base_price: data.base_price,
|
||||
is_trending: data.is_trending
|
||||
})
|
||||
is_trending: data.is_trending,
|
||||
});
|
||||
//TODO Return the new id
|
||||
logger.info('Success !')
|
||||
logger.info("Success !");
|
||||
return true;
|
||||
} catch (error) {
|
||||
logger.error(`Error creating category: ${error}`);
|
||||
@ -70,17 +72,22 @@ async function updateModel(data: IDbModel): Promise<boolean> {
|
||||
* @param {string} modelSlug - The slug of the model to be deleted.
|
||||
* @return {Promise<boolean>} - A promise that resolves to true if the deletion is successful, else false.
|
||||
*/
|
||||
async function deleteModel(modelSlug: string): Promise<boolean> {
|
||||
async function deleteModel(
|
||||
modelSlug: string,
|
||||
): Promise<boolean> {
|
||||
if (!modelSlug) {
|
||||
logger.error("Model slug is missing");
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
logger.info(`Deleting model with ID: ${modelSlug}`);
|
||||
const doesExist = await MysqlService.Model.getBySlug(DbHandler, modelSlug);
|
||||
const doesExist = await MysqlService.Model.getBySlug(
|
||||
DbHandler,
|
||||
modelSlug,
|
||||
);
|
||||
if (!doesExist || !doesExist.id) {
|
||||
logger.warn(`Model with slug ${modelSlug} not found`);
|
||||
return false;
|
||||
}
|
||||
logger.warn(`Model with slug ${modelSlug} not found`);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
await MysqlService.Model.delete(DbHandler, doesExist.id);
|
||||
logger.info("Deletion Successful !");
|
||||
@ -91,17 +98,21 @@ async function deleteModel(modelSlug: string): Promise<boolean> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetches a model by slug from the database.
|
||||
*
|
||||
* @param {string} modelSlug - The slug of the model to be fetched.
|
||||
* @return {Promise<IDbModel | null>} - A promise that resolves to the model if found, else null.
|
||||
*/
|
||||
async function getBySlugModel(modelSlug: string): Promise<IDbModel | null> {
|
||||
async function getBySlugModel(
|
||||
modelSlug: string,
|
||||
): Promise<IDbModel | null> {
|
||||
logger.info(`Fetching model with slug: ${modelSlug}`);
|
||||
try {
|
||||
const model = await MysqlService.Model.getBySlug(DbHandler, modelSlug);
|
||||
const model = await MysqlService.Model.getBySlug(
|
||||
DbHandler,
|
||||
modelSlug,
|
||||
);
|
||||
if (!model) {
|
||||
logger.warn(`Model with slug ${modelSlug} not found`);
|
||||
return null;
|
||||
@ -113,7 +124,6 @@ async function getBySlugModel(modelSlug: string): Promise<IDbModel | null> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetches all models from the database.
|
||||
*
|
||||
@ -127,7 +137,7 @@ async function getAllModels(): Promise<IDbModel[] | null> {
|
||||
logger.warn("No models found on the database");
|
||||
return null;
|
||||
}
|
||||
logger.info(`Found ${models.length} model(s)`)
|
||||
logger.info(`Found ${models.length} model(s)`);
|
||||
return models;
|
||||
} catch (error) {
|
||||
logger.error(`Error fetching all models: ${error}`);
|
||||
@ -135,8 +145,6 @@ async function getAllModels(): Promise<IDbModel[] | null> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* ModelService is responsible for managing models.
|
||||
* @namespace
|
||||
@ -149,6 +157,6 @@ const ModelService = {
|
||||
getAll: getAllModels,
|
||||
//getByCategory: getByCategoryModel,
|
||||
//getByBrand: getModelsByBrand,
|
||||
}
|
||||
};
|
||||
|
||||
export default ModelService;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,15 +1,16 @@
|
||||
import {Logger} from "tslog";
|
||||
import MySqlService from "@services/mysql.service";
|
||||
import type { IReqLogin } from "@interfaces/requests/IReqLogin";
|
||||
import type { IReqRegister } from "@interfaces/requests/IReqRegister";
|
||||
import CredentialService from "@services/credential.service";
|
||||
import JwtService from "@services/jwt.service";
|
||||
import MySqlService from "@services/mysql.service";
|
||||
import MysqlService from "@services/mysql.service";
|
||||
import type {IReqRegister} from "@interfaces/requests/IReqRegister";
|
||||
import {IReqLogin} from "@interfaces/requests/IReqLogin";
|
||||
import { Logger } from "tslog";
|
||||
|
||||
const logger = new Logger({
|
||||
name: "UserService",
|
||||
});
|
||||
|
||||
const logger = new Logger({ name: "UserService" });
|
||||
|
||||
const DbHandler = new MySqlService.Handler('UserService')
|
||||
const DbHandler = new MySqlService.Handler("UserService");
|
||||
|
||||
/**
|
||||
* Retrieves a user object from the database based on the given username.
|
||||
@ -17,55 +18,84 @@ const DbHandler = new MySqlService.Handler('UserService')
|
||||
* @param {string} username - The username of the user to retrieve.
|
||||
* @returns {Promise<Object | null>} - The user object if found, or null if not found.
|
||||
*/
|
||||
async function getUserFromUsername(username: string): Promise<object | null> {
|
||||
const dbUser = await MySqlService.User.getByUsername(DbHandler, username)
|
||||
async function getUserFromUsername(
|
||||
username: string,
|
||||
): Promise<object | null> {
|
||||
const dbUser = await MySqlService.User.getByUsername(
|
||||
DbHandler,
|
||||
username,
|
||||
);
|
||||
if (dbUser === undefined) return null;
|
||||
return dbUser;
|
||||
}
|
||||
|
||||
async function getUserFromIdService(id: string | undefined) {
|
||||
const dbUser = await MySqlService.User.getById(DbHandler, id);
|
||||
if (dbUser === undefined) return null;
|
||||
return dbUser;
|
||||
if (dbUser === undefined) return null;
|
||||
return dbUser;
|
||||
}
|
||||
|
||||
async function register(ReqData: IReqRegister) {
|
||||
if (ReqData.password.length < 6) {
|
||||
logger.info(`REGISTER :> Invalid password (${ReqData.username})`)
|
||||
return { error: "invalidPassword" };
|
||||
logger.info(
|
||||
`REGISTER :> Invalid password (${ReqData.username})`,
|
||||
);
|
||||
return {
|
||||
error: "invalidPassword",
|
||||
};
|
||||
}
|
||||
const passwordHash = await CredentialService.hash(ReqData.password)
|
||||
const passwordHash = await CredentialService.hash(
|
||||
ReqData.password,
|
||||
);
|
||||
|
||||
// Does the new user has accepted GDPR ?
|
||||
if (ReqData.gdpr !== true) {
|
||||
logger.info(`REGISTER :> GDPR not validated (${ReqData.username})`)
|
||||
return { error: "gdprNotApproved" }
|
||||
logger.info(
|
||||
`REGISTER :> GDPR not validated (${ReqData.username})`,
|
||||
);
|
||||
return {
|
||||
error: "gdprNotApproved",
|
||||
};
|
||||
}
|
||||
|
||||
// Check if exist and return
|
||||
|
||||
const dbUserIfExist = await getUserFromUsername(ReqData.username)
|
||||
const dbUserIfExist = await getUserFromUsername(
|
||||
ReqData.username,
|
||||
);
|
||||
if (dbUserIfExist) {
|
||||
logger.info(`REGISTER :> User exist (${dbUserIfExist.username})\n ID:${dbUserIfExist.id}`)
|
||||
return { error: "exist" }
|
||||
logger.info(
|
||||
`REGISTER :> User exist (${dbUserIfExist.username})\n ID:${dbUserIfExist.id}`,
|
||||
);
|
||||
return {
|
||||
error: "exist",
|
||||
};
|
||||
}
|
||||
|
||||
const currentDate = new Date();
|
||||
|
||||
// New UserService (class)
|
||||
|
||||
const NewUser = new User(ReqData.username, ReqData.displayName, passwordHash, currentDate);
|
||||
const NewUser = new User(
|
||||
ReqData.username,
|
||||
ReqData.displayName,
|
||||
passwordHash,
|
||||
currentDate,
|
||||
);
|
||||
NewUser.setFirstName(ReqData.firstName);
|
||||
NewUser.setLastName(ReqData.lastName);
|
||||
|
||||
// JWT
|
||||
|
||||
const alg = 'HS512'
|
||||
const token = await JwtService.sign({
|
||||
sub: NewUser.id
|
||||
}, alg,
|
||||
'1d',
|
||||
'user')
|
||||
const alg = "HS512";
|
||||
const token = await JwtService.sign(
|
||||
{
|
||||
sub: NewUser.id,
|
||||
},
|
||||
alg,
|
||||
"1d",
|
||||
"user",
|
||||
);
|
||||
|
||||
const userData = {
|
||||
error: "none",
|
||||
@ -75,45 +105,74 @@ async function register(ReqData: IReqRegister) {
|
||||
username: NewUser.username,
|
||||
displayName: NewUser.displayName,
|
||||
firstName: NewUser.firstName,
|
||||
lastName: NewUser.lastName
|
||||
}};
|
||||
logger.info(userData)
|
||||
lastName: NewUser.lastName,
|
||||
},
|
||||
};
|
||||
logger.info(userData);
|
||||
await Db.collection("users").insertOne(NewUser);
|
||||
logger.info(`REGISTER :> Inserted new user (${NewUser.username})`)
|
||||
return userData
|
||||
logger.info(
|
||||
`REGISTER :> Inserted new user (${NewUser.username})`,
|
||||
);
|
||||
return userData;
|
||||
}
|
||||
|
||||
async function login(ReqData: IReqLogin) {
|
||||
//const passwordHash = await getHashFromPassword(sanitizedData.password);
|
||||
const dbUser = await MysqlService.User.getByUsername(DbHandler, ReqData.username);
|
||||
const dbUser = await MysqlService.User.getByUsername(
|
||||
DbHandler,
|
||||
ReqData.username,
|
||||
);
|
||||
if (!dbUser) {
|
||||
console.log(`LoginService :> User does not exist (${ReqData.username})`);
|
||||
return { error: "userNotFound" };
|
||||
console.log(
|
||||
`LoginService :> User does not exist (${ReqData.username})`,
|
||||
);
|
||||
return {
|
||||
error: "userNotFound",
|
||||
};
|
||||
}
|
||||
if (ReqData.password.length < 6) {
|
||||
console.log('X')
|
||||
console.log(`LoginService :> Invalid password (${ReqData.username})`);
|
||||
return { error: "invalidPassword" };
|
||||
console.log("X");
|
||||
console.log(
|
||||
`LoginService :> Invalid password (${ReqData.username})`,
|
||||
);
|
||||
return {
|
||||
error: "invalidPassword",
|
||||
};
|
||||
}
|
||||
const isPasswordValid = await CredentialService.compare(ReqData.password, dbUser.hash)
|
||||
const isPasswordValid = await CredentialService.compare(
|
||||
ReqData.password,
|
||||
dbUser.hash,
|
||||
);
|
||||
if (!isPasswordValid) {
|
||||
console.log(isPasswordValid)
|
||||
console.log(`LoginService :> Invalid password (${ReqData.username})`);
|
||||
return { error: "invalidPassword" };
|
||||
console.log(isPasswordValid);
|
||||
console.log(
|
||||
`LoginService :> Invalid password (${ReqData.username})`,
|
||||
);
|
||||
return {
|
||||
error: "invalidPassword",
|
||||
};
|
||||
}
|
||||
// biome-ignore lint/style/useConst: <explanation>
|
||||
let userData = {
|
||||
error: "none",
|
||||
jwt: '',
|
||||
jwt: "",
|
||||
user: {
|
||||
id: dbUser.id,
|
||||
username: dbUser.username,
|
||||
displayName: dbUser.displayName,
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
userData.jwt = await JwtService.sign({sub: dbUser.id}, {alg: 'HS512'}, '7d', 'user')
|
||||
|
||||
userData.jwt = await JwtService.sign(
|
||||
{
|
||||
sub: dbUser.id,
|
||||
},
|
||||
{
|
||||
alg: "HS512",
|
||||
},
|
||||
"7d",
|
||||
"user",
|
||||
);
|
||||
|
||||
console.log("USERDATA :>");
|
||||
console.log(userData);
|
||||
@ -130,17 +189,17 @@ async function login(ReqData: IReqLogin) {
|
||||
async function getAllUsersService() {
|
||||
const users = await Db.collection("users").find().toArray();
|
||||
// biome-ignore lint/complexity/noForEach: <explanation>
|
||||
users.forEach(user => {
|
||||
delete user.passwordHash
|
||||
delete user._id
|
||||
delete user.gdpr
|
||||
users.forEach((user) => {
|
||||
delete user.passwordHash;
|
||||
delete user._id;
|
||||
delete user.gdpr;
|
||||
});
|
||||
logger.info(`Query ${users.length} user(s)`)
|
||||
logger.info(`Query ${users.length} user(s)`);
|
||||
return {
|
||||
iat: Date.now(),
|
||||
users: users,
|
||||
length: users.length
|
||||
}
|
||||
length: users.length,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@ -154,19 +213,34 @@ async function getAllUsersService() {
|
||||
*/
|
||||
async function editUserService(targetId, sanitizedData) {
|
||||
if (sanitizedData.password) {
|
||||
const passwordHash = await getHashFromPassword(sanitizedData.password)
|
||||
delete sanitizedData.password
|
||||
logger.info(`Changing password for user "${targetId}"`)
|
||||
sanitizedData.passwordHash = passwordHash
|
||||
const passwordHash = await getHashFromPassword(
|
||||
sanitizedData.password,
|
||||
);
|
||||
delete sanitizedData.password;
|
||||
logger.info(`Changing password for user "${targetId}"`);
|
||||
sanitizedData.passwordHash = passwordHash;
|
||||
}
|
||||
const updatedUserResult = await Db.collection("users").updateOne({id: targetId}, {$set: sanitizedData});
|
||||
const updatedUserResult = await Db.collection(
|
||||
"users",
|
||||
).updateOne(
|
||||
{
|
||||
id: targetId,
|
||||
},
|
||||
{
|
||||
$set: sanitizedData,
|
||||
},
|
||||
);
|
||||
if (updatedUserResult.modifiedCount === 0) {
|
||||
logger.info(`EDIT :> User not found (${targetId})`);
|
||||
return { error: "userNotFound" };
|
||||
return {
|
||||
error: "userNotFound",
|
||||
};
|
||||
}
|
||||
|
||||
logger.info(`EDIT :> User updated (${targetId})`);
|
||||
return { error: "none" };
|
||||
return {
|
||||
error: "none",
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@ -176,13 +250,15 @@ async function editUserService(targetId, sanitizedData) {
|
||||
* @return {Promise<boolean>} - A promise that resolves to true if the user is successfully deleted, or false if an error occurs.
|
||||
*/
|
||||
async function deleteUserService(targetId) {
|
||||
logger.info(`Deleting user ${targetId}`)
|
||||
logger.info(`Deleting user ${targetId}`);
|
||||
try {
|
||||
await Db.collection("users").deleteOne({id: targetId});
|
||||
return true
|
||||
await Db.collection("users").deleteOne({
|
||||
id: targetId,
|
||||
});
|
||||
return true;
|
||||
} catch (e) {
|
||||
logger.warn(e)
|
||||
return false
|
||||
logger.warn(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -192,7 +268,7 @@ const UserService = {
|
||||
getAll: getAllUsersService,
|
||||
getFromId: getUserFromIdService,
|
||||
edit: editUserService,
|
||||
delete: deleteUserService
|
||||
}
|
||||
delete: deleteUserService,
|
||||
};
|
||||
|
||||
export default UserService;
|
||||
export default UserService;
|
||||
|
@ -1,39 +1,58 @@
|
||||
import JwtService from "@services/jwt.service";
|
||||
import type {NextFunction, Request, Response} from "express";
|
||||
import MySqlService from "@services/mysql.service";
|
||||
import MysqlService from "@services/mysql.service";
|
||||
import {Logger} from "tslog";
|
||||
import type { NextFunction, Request, Response } from "express";
|
||||
import { Logger } from "tslog";
|
||||
|
||||
const DbHandler = new MySqlService.Handler('AdminGuard')
|
||||
const logger = new Logger({name: 'AdminGuard'})
|
||||
const DbHandler = new MySqlService.Handler("AdminGuard");
|
||||
const logger = new Logger({
|
||||
name: "AdminGuard",
|
||||
});
|
||||
|
||||
const UNAUTHORIZED = 401;
|
||||
const FORBIDDEN = 403;
|
||||
const UNAUTH_MESSAGE = 'Missing Authorization Header';
|
||||
const INVALID_TOKEN_MESSAGE = 'Invalid or expired token.';
|
||||
const PERMISSON_NOT_VALID = 'You are missing the required permission.'
|
||||
const UNAUTH_MESSAGE = "Missing Authorization Header";
|
||||
const INVALID_TOKEN_MESSAGE = "Invalid or expired token.";
|
||||
const PERMISSON_NOT_VALID =
|
||||
"You are missing the required permission.";
|
||||
|
||||
async function AdminGuard(req: Request, res: Response, next: NextFunction) {
|
||||
async function AdminGuard(
|
||||
req: Request,
|
||||
res: Response,
|
||||
next: NextFunction,
|
||||
) {
|
||||
const authHeader = req.headers.authorization;
|
||||
if (!authHeader) {
|
||||
logger.warn(`Invalid header (${req.ip})`)
|
||||
return res.status(UNAUTHORIZED).json({message: UNAUTH_MESSAGE});
|
||||
logger.warn(`Invalid header (${req.ip})`);
|
||||
return res.status(UNAUTHORIZED).json({
|
||||
message: UNAUTH_MESSAGE,
|
||||
});
|
||||
}
|
||||
|
||||
const bearerToken = authHeader.split(' ')[1];
|
||||
const bearerToken = authHeader.split(" ")[1];
|
||||
|
||||
if (!bearerToken) return res.status(FORBIDDEN).json({message: INVALID_TOKEN_MESSAGE});
|
||||
if (!bearerToken)
|
||||
return res.status(FORBIDDEN).json({
|
||||
message: INVALID_TOKEN_MESSAGE,
|
||||
});
|
||||
|
||||
const token = await JwtService.verify(bearerToken);
|
||||
|
||||
if (token) {
|
||||
// @ts-ignore
|
||||
const isSourceAdmin = await MysqlService.User.getAdminStateForId(DbHandler, token.sub)
|
||||
const isSourceAdmin =
|
||||
await MysqlService.User.getAdminStateForId(
|
||||
DbHandler,
|
||||
token.sub,
|
||||
);
|
||||
if (isSourceAdmin === true) next();
|
||||
return res.status(FORBIDDEN).json({message: PERMISSON_NOT_VALID});
|
||||
|
||||
return res.status(FORBIDDEN).json({
|
||||
message: PERMISSON_NOT_VALID,
|
||||
});
|
||||
}
|
||||
return res.status(FORBIDDEN).json({message: INVALID_TOKEN_MESSAGE});
|
||||
return res.status(FORBIDDEN).json({
|
||||
message: INVALID_TOKEN_MESSAGE,
|
||||
});
|
||||
}
|
||||
|
||||
export default AdminGuard
|
||||
export default AdminGuard;
|
||||
|
@ -1,26 +1,37 @@
|
||||
import JwtService from "@services/jwt.service";
|
||||
import type {NextFunction, Request, Response} from "express";
|
||||
import MySqlService from "@services/mysql.service";
|
||||
import {Logger} from "tslog";
|
||||
import type { NextFunction, Request, Response } from "express";
|
||||
import { Logger } from "tslog";
|
||||
|
||||
const DbHandler = new MySqlService.Handler('UserGuard')
|
||||
const logger = new Logger({name: 'UserGuard'})
|
||||
const DbHandler = new MySqlService.Handler("UserGuard");
|
||||
const logger = new Logger({
|
||||
name: "UserGuard",
|
||||
});
|
||||
|
||||
const UNAUTHORIZED = 401;
|
||||
const FORBIDDEN = 403;
|
||||
const UNAUTH_MESSAGE = 'Missing Authorization Header';
|
||||
const INVALID_TOKEN_MESSAGE = 'Invalid or expired token.';
|
||||
const USER_NOT_EXIST = 'You dont exist anymore'
|
||||
const UNAUTH_MESSAGE = "Missing Authorization Header";
|
||||
const INVALID_TOKEN_MESSAGE = "Invalid or expired token.";
|
||||
const USER_NOT_EXIST = "You dont exist anymore";
|
||||
|
||||
async function UserGuard(req: Request, res: Response, next: NextFunction) {
|
||||
async function UserGuard(
|
||||
req: Request,
|
||||
res: Response,
|
||||
next: NextFunction,
|
||||
) {
|
||||
const authHeader = req.headers.authorization;
|
||||
if (!authHeader) {
|
||||
return res.status(UNAUTHORIZED).json({message: UNAUTH_MESSAGE});
|
||||
return res.status(UNAUTHORIZED).json({
|
||||
message: UNAUTH_MESSAGE,
|
||||
});
|
||||
}
|
||||
|
||||
const bearerToken = authHeader.split(' ')[1];
|
||||
const bearerToken = authHeader.split(" ")[1];
|
||||
|
||||
if (!bearerToken) return res.status(FORBIDDEN).json({message: INVALID_TOKEN_MESSAGE});
|
||||
if (!bearerToken)
|
||||
return res.status(FORBIDDEN).json({
|
||||
message: INVALID_TOKEN_MESSAGE,
|
||||
});
|
||||
|
||||
const token = await JwtService.verify(bearerToken);
|
||||
|
||||
@ -29,16 +40,25 @@ async function UserGuard(req: Request, res: Response, next: NextFunction) {
|
||||
const userId = token.sub;
|
||||
if (!userId) {
|
||||
logger.error(USER_NOT_EXIST);
|
||||
return res.status(UNAUTHORIZED).json({message: USER_NOT_EXIST});
|
||||
return res.status(UNAUTHORIZED).json({
|
||||
message: USER_NOT_EXIST,
|
||||
});
|
||||
}
|
||||
const user= await MySqlService.User.getById(DbHandler, userId);
|
||||
if (user) {
|
||||
logger.info(`An user do a request. (${user?.username})`)
|
||||
next()
|
||||
const user = await MySqlService.User.getById(
|
||||
DbHandler,
|
||||
userId,
|
||||
);
|
||||
if (user) {
|
||||
logger.info(`An user do a request. (${user?.username})`);
|
||||
next();
|
||||
}
|
||||
return res.status(UNAUTHORIZED).json({message: USER_NOT_EXIST});
|
||||
return res.status(UNAUTHORIZED).json({
|
||||
message: USER_NOT_EXIST,
|
||||
});
|
||||
}
|
||||
return res.status(FORBIDDEN).json({message: INVALID_TOKEN_MESSAGE});
|
||||
return res.status(FORBIDDEN).json({
|
||||
message: INVALID_TOKEN_MESSAGE,
|
||||
});
|
||||
}
|
||||
|
||||
export default UserGuard
|
||||
export default UserGuard;
|
||||
|
Loading…
x
Reference in New Issue
Block a user