Compare commits
60 Commits
3232e5fac1
...
deadline
| Author | SHA1 | Date | |
|---|---|---|---|
|
7fead5486b
|
|||
|
5cc214a29b
|
|||
|
65a6ae2e3c
|
|||
|
83d07a2812
|
|||
|
e8acfd7b30
|
|||
|
438ae4b5d0
|
|||
|
6ccc899320
|
|||
|
5afb6e22bf
|
|||
|
bdba2f6e29
|
|||
|
30c6f2e3f1
|
|||
|
b47ec6c440
|
|||
|
b4f200cb32
|
|||
|
ec53fcb247
|
|||
|
371d960cf3
|
|||
|
3525fb12e6
|
|||
|
82afff9878
|
|||
|
fef2bda082
|
|||
|
f87aecaf75
|
|||
|
170b9a5693
|
|||
|
c9ca39ddfa
|
|||
|
da028ea2c4
|
|||
|
1c643b3625
|
|||
|
33d6793758
|
|||
|
c95ac03680
|
|||
|
03fc5307e6
|
|||
|
b6a2a74ba0
|
|||
|
f310bedeff
|
|||
|
838ea4ad22
|
|||
|
00064fd054
|
|||
|
70a6e5df54
|
|||
|
7f52a9d75e
|
|||
|
62742e6afe
|
|||
|
bdfc598218
|
|||
|
1cbc771251
|
|||
|
8644b5add6
|
|||
|
b66a5aff6d
|
|||
|
3d3da77df0
|
|||
|
abaeafea8a
|
|||
|
cb41c68f77
|
|||
|
e98729c9e5
|
|||
|
cd09a0c61b
|
|||
|
1723a8588a
|
|||
|
3fe6453b0c
|
|||
|
98477c5f27
|
|||
|
3472c59ac2
|
|||
|
3b6726113d
|
|||
|
d78b0aec4c
|
|||
|
ae6b25fbd6
|
|||
|
d7f9cb0b37
|
|||
|
cb1c2ee87c
|
|||
|
23ce32cb6f
|
|||
|
f6d18fc58d
|
|||
|
5163d79056
|
|||
|
ea3b7aa68b
|
|||
|
bc12f94e41
|
|||
|
df28d3aa52
|
|||
|
3d5ea6ac30
|
|||
|
2fb6cd6e83
|
|||
|
34f028ef9f
|
|||
|
0635c512cc
|
@@ -1036,7 +1036,7 @@ brief\\_05|schema||user_brief05||UPDATE|G</Grants>
|
|||||||
</schema>
|
</schema>
|
||||||
<schema id="325" parent="1" name="brief_05">
|
<schema id="325" parent="1" name="brief_05">
|
||||||
<Current>1</Current>
|
<Current>1</Current>
|
||||||
<LastIntrospectionLocalTimestamp>2024-04-29.12:54:42</LastIntrospectionLocalTimestamp>
|
<LastIntrospectionLocalTimestamp>2024-05-03.07:39:06</LastIntrospectionLocalTimestamp>
|
||||||
<CollationName>latin1_swedish_ci</CollationName>
|
<CollationName>latin1_swedish_ci</CollationName>
|
||||||
</schema>
|
</schema>
|
||||||
<user id="326" parent="1" name="user_brief05"/>
|
<user id="326" parent="1" name="user_brief05"/>
|
||||||
@@ -1063,7 +1063,7 @@ brief\\_05|schema||user_brief05||UPDATE|G</Grants>
|
|||||||
<Engine>InnoDB</Engine>
|
<Engine>InnoDB</Engine>
|
||||||
<CollationName>latin1_swedish_ci</CollationName>
|
<CollationName>latin1_swedish_ci</CollationName>
|
||||||
</table>
|
</table>
|
||||||
<table id="332" parent="325" name="rent">
|
<table id="332" parent="325" name="rents">
|
||||||
<Engine>InnoDB</Engine>
|
<Engine>InnoDB</Engine>
|
||||||
<CollationName>latin1_swedish_ci</CollationName>
|
<CollationName>latin1_swedish_ci</CollationName>
|
||||||
</table>
|
</table>
|
||||||
@@ -1270,7 +1270,7 @@ brief\\_05|schema||user_brief05||UPDATE|G</Grants>
|
|||||||
<Position>7</Position>
|
<Position>7</Position>
|
||||||
</column>
|
</column>
|
||||||
<column id="376" parent="332" name="id">
|
<column id="376" parent="332" name="id">
|
||||||
<DasType>tinyint(1)|0s</DasType>
|
<DasType>varchar(36)|0s</DasType>
|
||||||
<NotNull>1</NotNull>
|
<NotNull>1</NotNull>
|
||||||
<Position>8</Position>
|
<Position>8</Position>
|
||||||
</column>
|
</column>
|
||||||
|
|||||||
2
.idea/inspectionProfiles/Project_Default.xml
generated
2
.idea/inspectionProfiles/Project_Default.xml
generated
@@ -3,7 +3,7 @@
|
|||||||
<option name="myName" value="Project Default" />
|
<option name="myName" value="Project Default" />
|
||||||
<inspection_tool class="DuplicatedCode" enabled="true" level="WEAK WARNING" enabled_by_default="true">
|
<inspection_tool class="DuplicatedCode" enabled="true" level="WEAK WARNING" enabled_by_default="true">
|
||||||
<Languages>
|
<Languages>
|
||||||
<language minSize="114" name="TypeScript" />
|
<language minSize="174" name="TypeScript" />
|
||||||
</Languages>
|
</Languages>
|
||||||
</inspection_tool>
|
</inspection_tool>
|
||||||
</profile>
|
</profile>
|
||||||
|
|||||||
10
db.sql
10
db.sql
@@ -74,13 +74,13 @@ CREATE TABLE `models` (
|
|||||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Table structure for table `rent`
|
-- Table structure for table `rents`
|
||||||
--
|
--
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `rent`;
|
DROP TABLE IF EXISTS `rents`;
|
||||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||||
/*!40101 SET character_set_client = utf8 */;
|
/*!40101 SET character_set_client = utf8 */;
|
||||||
CREATE TABLE `rent` (
|
CREATE TABLE `rents` (
|
||||||
`vehicle_id` varchar(36) NOT NULL,
|
`vehicle_id` varchar(36) NOT NULL,
|
||||||
`user_id` varchar(36) NOT NULL,
|
`user_id` varchar(36) NOT NULL,
|
||||||
`active` tinyint(1) NOT NULL,
|
`active` tinyint(1) NOT NULL,
|
||||||
@@ -88,7 +88,7 @@ CREATE TABLE `rent` (
|
|||||||
`eat` date NOT NULL,
|
`eat` date NOT NULL,
|
||||||
`need_survey` tinyint(1) DEFAULT NULL,
|
`need_survey` tinyint(1) DEFAULT NULL,
|
||||||
`km_at_start` int(11) DEFAULT NULL,
|
`km_at_start` int(11) DEFAULT NULL,
|
||||||
`id` tinyint(1) NOT NULL,
|
`id` varchar(36) NOT NULL,
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
KEY `rent_vehicles_id_fk` (`vehicle_id`),
|
KEY `rent_vehicles_id_fk` (`vehicle_id`),
|
||||||
KEY `rent_users_id_fk` (`user_id`),
|
KEY `rent_users_id_fk` (`user_id`),
|
||||||
@@ -152,4 +152,4 @@ CREATE TABLE `vehicles` (
|
|||||||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
||||||
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
||||||
|
|
||||||
-- Dump completed on 2024-04-29 14:54:00
|
-- Dump completed on 2024-05-03 14:56:07
|
||||||
|
|||||||
BIN
schema-db.png
BIN
schema-db.png
Binary file not shown.
|
Before Width: | Height: | Size: 176 KiB After Width: | Height: | Size: 198 KiB |
@@ -51,7 +51,13 @@ try {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
app.listen(process.env["APP_PORT"]);
|
app.listen(process.env["APP_PORT"]);
|
||||||
logger.info("Server is running !");
|
logger.info(
|
||||||
|
`Server is running !\n >> Memory total: ${Math.round(
|
||||||
|
process.memoryUsage().rss / 1_000_000,
|
||||||
|
)} Mio\n >> Memory heap: ${Math.round(
|
||||||
|
process.memoryUsage().heapUsed / 1_000_000,
|
||||||
|
)} Mio\n`,
|
||||||
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(`Server failed to start: ${error}`);
|
logger.error(`Server failed to start: ${error}`);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
import JwtService from "@services/jwt.service";
|
import JwtService from "@services/jwt.service";
|
||||||
|
|
||||||
import type { IReqEditUserData } from "@interfaces/IReqEditUserData";
|
import type { IReqEditUserData } from "@interfaces/IReqEditUserData";
|
||||||
|
import { HttpStatusCode } from "@interfaces/requests/HttpStatusCode";
|
||||||
|
import type { IReqRegister } from "@interfaces/requests/IReqRegister";
|
||||||
import UserService from "@services/user.service";
|
import UserService from "@services/user.service";
|
||||||
|
import { isDebugMode } from "@utils/debugState";
|
||||||
|
import { isEmail } from "@utils/validators/email";
|
||||||
import type { Request, Response } from "express";
|
import type { Request, Response } from "express";
|
||||||
import { Logger } from "tslog";
|
import { Logger } from "tslog";
|
||||||
|
|
||||||
@@ -9,24 +13,19 @@ const logger = new Logger({
|
|||||||
name: "AuthController",
|
name: "AuthController",
|
||||||
});
|
});
|
||||||
|
|
||||||
//FIX Better return object interface
|
|
||||||
/**
|
/**
|
||||||
* Registers a user with the given request data.
|
* Registers a user.
|
||||||
*
|
*
|
||||||
* @param {Request} req - The request object containing user data.
|
* @param {Request} req - The request object.
|
||||||
* @param {Response} res - The response object to send the registration result.
|
* @param {Response} res - The response object.
|
||||||
*
|
*
|
||||||
* @return {Promise} A promise that resolves to the registration result.
|
* @return {Promise} - A promise that resolves with the registration result or rejects with an error.
|
||||||
* It can have the following properties:
|
|
||||||
* - error: "gdprNotApproved" if GDPR is not approved
|
|
||||||
* - 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<Response> {
|
||||||
const body = req.body;
|
const body: IReqRegister = req.body;
|
||||||
if (!body) {
|
if (!body) {
|
||||||
logger.warn(`Invalid input data (${req.ip})`);
|
logger.warn(`Invalid input data (${req.ip})`);
|
||||||
return res.type("application/json").status(400).json({
|
return res.type("application/json").status(HttpStatusCode.BadRequest).json({
|
||||||
error: "Invalid input data",
|
error: "Invalid input data",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -35,21 +34,28 @@ async function registerUser(req: Request, res: Response): Promise<unknown> {
|
|||||||
!body.username ||
|
!body.username ||
|
||||||
!body.firstName ||
|
!body.firstName ||
|
||||||
!body.lastName ||
|
!body.lastName ||
|
||||||
!body.displayName
|
!body.email
|
||||||
) {
|
) {
|
||||||
logger.warn(`Field(s) missing (${req.ip})`);
|
logger.warn(`Field(s) missing (${req.ip})`);
|
||||||
return res.type("application/json").status(400).json({
|
return res.type("application/json").status(HttpStatusCode.BadRequest).json({
|
||||||
error: "Field(s) missing",
|
error: "Field(s) missing",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!isEmail(body.email)) {
|
||||||
|
logger.warn(`Invalid email format (${req.ip})`);
|
||||||
|
return res.type("application/json").status(HttpStatusCode.BadRequest).json({
|
||||||
|
error: "Invalid email format",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
let gdpr = false;
|
let gdpr = false;
|
||||||
if (body.gdpr === true) {
|
if (body.gdpr === true) {
|
||||||
gdpr = true;
|
gdpr = true;
|
||||||
}
|
}
|
||||||
const sanitizeData = {
|
const sanitizeData: IReqRegister = {
|
||||||
username: `${body.username}`,
|
username: `${body.username}`,
|
||||||
displayName: `${body.displayName}`,
|
email: `${body.email.toLowerCase()}`,
|
||||||
gdpr: gdpr,
|
gdpr: gdpr,
|
||||||
password: `${body.password}`,
|
password: `${body.password}`,
|
||||||
firstName: `${body.firstName}`,
|
firstName: `${body.firstName}`,
|
||||||
@@ -58,24 +64,33 @@ async function registerUser(req: Request, res: Response): Promise<unknown> {
|
|||||||
|
|
||||||
const RegisterServiceResult = await UserService.register(sanitizeData);
|
const RegisterServiceResult = await UserService.register(sanitizeData);
|
||||||
|
|
||||||
if (RegisterServiceResult.error === "gdprNotApproved") {
|
if (
|
||||||
|
typeof RegisterServiceResult !== "string" &&
|
||||||
|
RegisterServiceResult.message === "GDPR acceptance is required."
|
||||||
|
) {
|
||||||
logger.warn(`GDPR not approved (${req.ip})`);
|
logger.warn(`GDPR not approved (${req.ip})`);
|
||||||
return res.status(400).json({
|
return res.status(HttpStatusCode.BadRequest).json({
|
||||||
error: RegisterServiceResult.error,
|
error: RegisterServiceResult.error,
|
||||||
message: "GDPR not accepted.",
|
message: "GDPR not accepted.",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (RegisterServiceResult.error === "exist") {
|
if (
|
||||||
logger.warn(`The user already exists (${req.ip})`);
|
typeof RegisterServiceResult !== "string" &&
|
||||||
return res.type("application/json").status(400).json({
|
RegisterServiceResult.error === 5
|
||||||
|
) {
|
||||||
|
logger.warn(`The user already exists (${sanitizeData.email})`);
|
||||||
|
return res.type("application/json").status(HttpStatusCode.Conflict).json({
|
||||||
error: RegisterServiceResult.error,
|
error: RegisterServiceResult.error,
|
||||||
message: "The user already exists.",
|
message: "The user already exists.",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// SUCCESS
|
// SUCCESS
|
||||||
logger.info(`User registered successfully (${req.ip})`);
|
//logger.info(`User registered successfully (${sanitizeData.username})`);
|
||||||
return res.type("application/json").status(201).json(RegisterServiceResult);
|
return res
|
||||||
|
.type("application/json")
|
||||||
|
.status(HttpStatusCode.Ok)
|
||||||
|
.json({ token: RegisterServiceResult });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -89,34 +104,39 @@ async function registerUser(req: Request, res: Response): Promise<unknown> {
|
|||||||
async function loginUser(req: Request, res: Response): Promise<void> {
|
async function loginUser(req: Request, res: Response): Promise<void> {
|
||||||
const body = req.body;
|
const body = req.body;
|
||||||
if (!body) {
|
if (!body) {
|
||||||
res.type("application/json").status(400).json({
|
res.type("application/json").status(HttpStatusCode.BadRequest).json({
|
||||||
error: "Invalid input data",
|
error: "Invalid input data",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (!body.password || !body.username) {
|
if (!body.password || !body.email) {
|
||||||
logger.warn(`Field(s) missing (${req.ip})`);
|
logger.warn(`Field(s) missing (${req.ip})`);
|
||||||
res.type("application/json").status(400).json({
|
res.type("application/json").status(HttpStatusCode.BadRequest).json({
|
||||||
error: "Field(s) missing",
|
error: "Field(s) missing",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const loginData = {
|
const loginData = {
|
||||||
username: `${body.username}`,
|
email: `${body.email}`,
|
||||||
password: `${body.password}`,
|
password: `${body.password}`,
|
||||||
};
|
};
|
||||||
console.log(body);
|
console.log(body);
|
||||||
const LoginServiceResult = await UserService.login(loginData);
|
const LoginServiceResult = await UserService.login(loginData);
|
||||||
console.log(LoginServiceResult);
|
console.log(LoginServiceResult);
|
||||||
|
|
||||||
if (LoginServiceResult.error === "userNotFound") {
|
if (
|
||||||
console.log("POOL");
|
typeof LoginServiceResult !== "string" &&
|
||||||
res.type("application/json").status(404).json({
|
LoginServiceResult.error === 3
|
||||||
|
) {
|
||||||
|
res.type("application/json").status(HttpStatusCode.NotFound).json({
|
||||||
error: LoginServiceResult.error,
|
error: LoginServiceResult.error,
|
||||||
message: "User not found.",
|
message: "User not found.",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (LoginServiceResult.error === "invalidPassword") {
|
if (
|
||||||
res.type("application/json").status(401).json({
|
typeof LoginServiceResult !== "string" &&
|
||||||
|
LoginServiceResult.error === 5
|
||||||
|
) {
|
||||||
|
res.type("application/json").status(HttpStatusCode.NotAcceptable).json({
|
||||||
error: LoginServiceResult.error,
|
error: LoginServiceResult.error,
|
||||||
message: "Invalid password.",
|
message: "Invalid password.",
|
||||||
});
|
});
|
||||||
@@ -124,74 +144,97 @@ async function loginUser(req: Request, res: Response): Promise<void> {
|
|||||||
res.type("application/json").status(200).json(LoginServiceResult);
|
res.type("application/json").status(200).json(LoginServiceResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//ToTest
|
||||||
async function getAllUsers(req: Request, res: Response) {
|
async function getAllUsers(req: Request, res: Response) {
|
||||||
const authHeader = req.headers.authorization;
|
const authHeader = req.headers.authorization;
|
||||||
const bearerToken = authHeader?.split(" ")[1];
|
const bearerToken = authHeader?.split(" ")[1];
|
||||||
if (!bearerToken) {
|
if (!bearerToken) {
|
||||||
logger.warn(`Bearer token not provided (${req.ip})`);
|
logger.warn(`Bearer token not provided (${req.ip})`);
|
||||||
return res.type("application/json").status(401).json({
|
return res.type("application/json").status(HttpStatusCode.Forbidden).json({
|
||||||
error: "Unauthorized",
|
error: "Invalid token",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const payload = await JwtService.verify(bearerToken);
|
const payload = await JwtService.verify(bearerToken);
|
||||||
if (!payload) {
|
if (!payload || !payload.sub) {
|
||||||
logger.warn(`Unauthorized access attempt (${req.ip})`);
|
logger.warn(`Unauthorized access attempt (${req.ip})`);
|
||||||
return res.type("application/json").status(401).json({
|
return res.type("application/json").status(HttpStatusCode.Forbidden).json({
|
||||||
error: "Unauthorized",
|
error: "Invalid token",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const sourceUser = await UserService.getFromId(payload.sub);
|
const sourceUser = await UserService.getFromId(payload.sub);
|
||||||
if (!sourceUser) {
|
if (!sourceUser) {
|
||||||
return res.type("application/json").status(404).json({
|
return res.type("application/json").status(HttpStatusCode.ImATeapot).json({
|
||||||
error: "You dont exist anymore",
|
error: "You dont exist anymore",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (!sourceUser.is_admin) {
|
if ("id" in sourceUser && !sourceUser.is_admin) {
|
||||||
return res.type("application/json").status(403).json({
|
return res.type("application/json").status(HttpStatusCode.Forbidden).json({
|
||||||
error: "Unauthorized",
|
error: "Unauthorized",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const AllUserResponse = await UserService.getAll();
|
const AllUserResponse = await UserService.getAll();
|
||||||
if (!AllUserResponse.users) {
|
if (typeof AllUserResponse === "object") {
|
||||||
return res.type("application/json").status(500).json({
|
return res
|
||||||
error: "Internal server error",
|
.type("application/json")
|
||||||
});
|
.status(HttpStatusCode.InternalServerError)
|
||||||
|
.json({
|
||||||
|
error: "Internal server error",
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return res.type("application/json").status(200).json(AllUserResponse);
|
return res
|
||||||
|
.type("application/json")
|
||||||
|
.status(HttpStatusCode.Found)
|
||||||
|
.json(AllUserResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//ToTest
|
||||||
async function getUser(req: Request, res: Response) {
|
async function getUser(req: Request, res: Response) {
|
||||||
const authHeader = req.headers.authorization;
|
const authHeader = req.headers.authorization;
|
||||||
const bearerToken = authHeader?.split(" ")[1];
|
const bearerToken = authHeader?.split(" ")[1];
|
||||||
if (!bearerToken) {
|
if (!bearerToken) {
|
||||||
logger.warn(`Bearer token not provided (${req.ip})`);
|
logger.warn(`Bearer token not provided (${req.ip})`);
|
||||||
return res.type("application/json").status(401).json({
|
return res
|
||||||
error: "Unauthorized",
|
.type("application/json")
|
||||||
});
|
.status(HttpStatusCode.Unauthorized)
|
||||||
|
.json({
|
||||||
|
error: "Unauthorized",
|
||||||
|
});
|
||||||
}
|
}
|
||||||
const payload = await JwtService.verify(bearerToken);
|
const payload = await JwtService.verify(bearerToken);
|
||||||
if (!payload) {
|
if (!payload || !payload.sub) {
|
||||||
logger.warn(`Unauthorized access attempt (${req.ip})`);
|
logger.warn(`Unauthorized access attempt (${req.ip})`);
|
||||||
return res.type("application/json").status(401).json({
|
return res
|
||||||
error: "Unauthorized",
|
.type("application/json")
|
||||||
});
|
.status(HttpStatusCode.Unauthorized)
|
||||||
|
.json({
|
||||||
|
error: "Unauthorized",
|
||||||
|
});
|
||||||
}
|
}
|
||||||
const sourceUser = await UserService.getFromId(payload.sub);
|
const sourceUser = await UserService.getFromId(payload.sub);
|
||||||
if (!sourceUser) {
|
if (!sourceUser) {
|
||||||
return res.type("application/json").status(404).json({
|
return res.type("application/json").status(HttpStatusCode.ImATeapot).json({
|
||||||
error: "You dont exist anymore",
|
error: "You dont exist anymore",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (!sourceUser.is_admin) {
|
if ("username" in sourceUser && !sourceUser.is_admin) {
|
||||||
return res.type("application/json").status(403).json({
|
return res
|
||||||
error: "Unauthorized",
|
.type("application/json")
|
||||||
});
|
.status(HttpStatusCode.Unauthorized)
|
||||||
|
.json({
|
||||||
|
error: "Unauthorized",
|
||||||
|
});
|
||||||
}
|
}
|
||||||
const userId = req.params["id"];
|
const userId = req.params["id"];
|
||||||
|
if (!userId) {
|
||||||
|
logger.warn(`User ID not provided (${req.ip})`);
|
||||||
|
return res.type("application/json").status(HttpStatusCode.BadRequest).json({
|
||||||
|
error: "User ID not provided",
|
||||||
|
});
|
||||||
|
}
|
||||||
const dbUser = await UserService.getFromId(userId);
|
const dbUser = await UserService.getFromId(userId);
|
||||||
if (!dbUser) {
|
if (!dbUser) {
|
||||||
logger.warn(`User not found (${req.ip})`);
|
logger.warn(`User not found (${req.ip})`);
|
||||||
return res.type("application/json").status(404).json({
|
return res.type("application/json").status(HttpStatusCode.NotFound).json({
|
||||||
error: "User not found",
|
error: "User not found",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -199,10 +242,11 @@ async function getUser(req: Request, res: Response) {
|
|||||||
delete dbUser.passwordHash;
|
delete dbUser.passwordHash;
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
delete dbUser._id;
|
delete dbUser._id;
|
||||||
return res.type("application/json").status(200).json(dbUser);
|
return res.type("application/json").status(HttpStatusCode.Found).json(dbUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
//FEAT - Implement re-auth by current password in case of password change
|
//FEAT - Implement re-auth by current password in case of password change
|
||||||
|
//ToTest
|
||||||
async function editUser(req: Request, res: Response) {
|
async function editUser(req: Request, res: Response) {
|
||||||
const body: IReqEditUserData | null = req.body;
|
const body: IReqEditUserData | null = req.body;
|
||||||
if (!body) {
|
if (!body) {
|
||||||
@@ -219,7 +263,7 @@ async function editUser(req: Request, res: Response) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
const payload = await JwtService.verify(bearerToken);
|
const payload = await JwtService.verify(bearerToken);
|
||||||
if (!payload) {
|
if (!payload || !payload.sub) {
|
||||||
logger.warn(`Unauthorized access attempt (${req.ip})`);
|
logger.warn(`Unauthorized access attempt (${req.ip})`);
|
||||||
return res.type("application/json").status(401).json({
|
return res.type("application/json").status(401).json({
|
||||||
error: "Unauthorized",
|
error: "Unauthorized",
|
||||||
@@ -237,7 +281,10 @@ async function editUser(req: Request, res: Response) {
|
|||||||
error: "You dont exist anymore",
|
error: "You dont exist anymore",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (sourceUser.is_admin || sourceUser.id === payload.sub) {
|
if (
|
||||||
|
("id" in sourceUser && sourceUser.is_admin) ||
|
||||||
|
("id" in sourceUser && sourceUser.id === payload.sub)
|
||||||
|
) {
|
||||||
if (sourceUser.is_admin) {
|
if (sourceUser.is_admin) {
|
||||||
logger.info(
|
logger.info(
|
||||||
`EDIT :> Source user is an admin (${sourceUser.firstname} ${sourceUser.lastname})`,
|
`EDIT :> Source user is an admin (${sourceUser.firstname} ${sourceUser.lastname})`,
|
||||||
@@ -264,13 +311,19 @@ async function editUser(req: Request, res: Response) {
|
|||||||
`${targetUserId}`,
|
`${targetUserId}`,
|
||||||
modifiedData,
|
modifiedData,
|
||||||
);
|
);
|
||||||
if (EditUserServiceResult.error === "userNotFound") {
|
if (
|
||||||
|
typeof EditUserServiceResult !== "boolean" &&
|
||||||
|
EditUserServiceResult.error === 3
|
||||||
|
) {
|
||||||
logger.warn(`User not found (${req.ip})`);
|
logger.warn(`User not found (${req.ip})`);
|
||||||
return res.type("application/json").status(404).json({
|
return res.type("application/json").status(404).json({
|
||||||
error: "User not found",
|
error: "User not found",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (EditUserServiceResult.error !== "none") {
|
if (
|
||||||
|
typeof EditUserServiceResult !== "boolean" &&
|
||||||
|
EditUserServiceResult.error
|
||||||
|
) {
|
||||||
logger.error(`Error occurred during user edit (${req.ip})`);
|
logger.error(`Error occurred during user edit (${req.ip})`);
|
||||||
return res.type("application/json").status(500).json({
|
return res.type("application/json").status(500).json({
|
||||||
error: "Internal server error",
|
error: "Internal server error",
|
||||||
@@ -285,6 +338,7 @@ async function editUser(req: Request, res: Response) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//ToTest
|
||||||
async function deleteUser(req: Request, res: Response): Promise<Response> {
|
async function deleteUser(req: Request, res: Response): Promise<Response> {
|
||||||
const authHeader = req.headers.authorization;
|
const authHeader = req.headers.authorization;
|
||||||
const bearerToken = authHeader?.split(" ")[1];
|
const bearerToken = authHeader?.split(" ")[1];
|
||||||
@@ -296,7 +350,7 @@ async function deleteUser(req: Request, res: Response): Promise<Response> {
|
|||||||
}
|
}
|
||||||
const payload = await JwtService.verify(bearerToken);
|
const payload = await JwtService.verify(bearerToken);
|
||||||
|
|
||||||
if (!payload) {
|
if (!payload || !payload.sub) {
|
||||||
logger.warn(`Invalid token (${req.ip})`);
|
logger.warn(`Invalid token (${req.ip})`);
|
||||||
return res.type("application/json").status(401).json({
|
return res.type("application/json").status(401).json({
|
||||||
error: "Invalid token",
|
error: "Invalid token",
|
||||||
@@ -310,7 +364,10 @@ async function deleteUser(req: Request, res: Response): Promise<Response> {
|
|||||||
error: "You dont exist anymore",
|
error: "You dont exist anymore",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (sourceUser.is_admin || sourceUser.id === payload.sub) {
|
if (
|
||||||
|
("id" in sourceUser && sourceUser.is_admin) ||
|
||||||
|
("id" in sourceUser && sourceUser.id === payload.sub)
|
||||||
|
) {
|
||||||
const deleteUserServiceResult = await UserService.delete(`${targetUserId}`);
|
const deleteUserServiceResult = await UserService.delete(`${targetUserId}`);
|
||||||
if (!deleteUserServiceResult) {
|
if (!deleteUserServiceResult) {
|
||||||
logger.error(`Error occurred during user delete (${req.ip})`);
|
logger.error(`Error occurred during user delete (${req.ip})`);
|
||||||
@@ -328,6 +385,7 @@ async function deleteUser(req: Request, res: Response): Promise<Response> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//ToTest
|
||||||
async function deleteSelf(req: Request, res: Response) {
|
async function deleteSelf(req: Request, res: Response) {
|
||||||
const authHeader = req.headers.authorization;
|
const authHeader = req.headers.authorization;
|
||||||
const bearerToken = authHeader?.split(" ")[1];
|
const bearerToken = authHeader?.split(" ")[1];
|
||||||
@@ -338,7 +396,7 @@ async function deleteSelf(req: Request, res: Response) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
const payload = await JwtService.verify(bearerToken);
|
const payload = await JwtService.verify(bearerToken);
|
||||||
if (!payload) {
|
if (!payload || !payload.sub) {
|
||||||
logger.warn(`Unauthorized access attempt (${req.ip})`);
|
logger.warn(`Unauthorized access attempt (${req.ip})`);
|
||||||
return res.type("application/json").status(401).json({
|
return res.type("application/json").status(401).json({
|
||||||
error: "Unauthorized",
|
error: "Unauthorized",
|
||||||
@@ -350,23 +408,27 @@ async function deleteSelf(req: Request, res: Response) {
|
|||||||
error: "You dont exist anymore",
|
error: "You dont exist anymore",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (sourceUser.id !== req.params["id"]) {
|
if ("id" in sourceUser && sourceUser.id !== req.params["id"]) {
|
||||||
return res.type("application/json").status(403).json({
|
return res.type("application/json").status(403).json({
|
||||||
error: "Unauthorized",
|
error: "Unauthorized",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const deleteResult = await UserService.delete(sourceUser.id);
|
if ("id" in sourceUser) {
|
||||||
if (!deleteResult) {
|
const deleteResult = await UserService.delete(sourceUser.id);
|
||||||
logger.error(`Failed to delete user (${req.ip})`);
|
|
||||||
return res.type("application/json").status(500).json({
|
if (!deleteResult) {
|
||||||
error: "Failed to delete user",
|
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(200).json({
|
return res.type("application/json").status(200).json({
|
||||||
message: "User deleted successfully",
|
message: "User deleted successfully",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//ToTest
|
||||||
async function getSelf(req: Request, res: Response) {
|
async function getSelf(req: Request, res: Response) {
|
||||||
const authHeader = req.headers.authorization;
|
const authHeader = req.headers.authorization;
|
||||||
const bearerToken = authHeader?.split(" ")[1];
|
const bearerToken = authHeader?.split(" ")[1];
|
||||||
@@ -376,27 +438,29 @@ async function getSelf(req: Request, res: Response) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
const payload = await JwtService.verify(bearerToken);
|
const payload = await JwtService.verify(bearerToken);
|
||||||
if (!payload) {
|
if (!payload || !payload.sub) {
|
||||||
logger.warn(`Unauthorized access attempt (${req.ip})`);
|
logger.warn(`Unauthorized access attempt (${req.ip})`);
|
||||||
return res.type("application/json").status(401).json({
|
return res.type("application/json").status(401).json({
|
||||||
error: "Unauthorized",
|
error: "Unauthorized",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const dbUser = await UserService.getFromId(payload.sub);
|
const GetUserResult = await UserService.getFromId(payload.sub);
|
||||||
if (!dbUser) {
|
if ("id" in GetUserResult) {
|
||||||
return res.type("application/json").status(404).json({
|
return res.type("application/json").status(200).json({
|
||||||
error: "User not found",
|
id: GetUserResult.id,
|
||||||
|
username: GetUserResult.username,
|
||||||
|
firstName: GetUserResult.firstname,
|
||||||
|
lastName: GetUserResult.lastname,
|
||||||
|
isAdmin: GetUserResult.is_admin,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return res.type("application/json").status(200).json({
|
return res.type("application/json").status(404).json({
|
||||||
id: dbUser.id,
|
error: "User not found",
|
||||||
username: dbUser.username,
|
|
||||||
firstName: dbUser.firstname,
|
|
||||||
lastName: dbUser.firstname,
|
|
||||||
isAdmin: dbUser.firstname,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isDebugMode()) logger.debug("\nController loaded.");
|
||||||
|
|
||||||
const AuthController = {
|
const AuthController = {
|
||||||
register: registerUser,
|
register: registerUser,
|
||||||
login: loginUser,
|
login: loginUser,
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { Logger } from "tslog";
|
|||||||
|
|
||||||
import type IDbBrand from "@interfaces/database/IDbBrand";
|
import type IDbBrand from "@interfaces/database/IDbBrand";
|
||||||
import BrandService from "@services/brand.service";
|
import BrandService from "@services/brand.service";
|
||||||
|
import { isDebugMode } from "@utils/debugState";
|
||||||
//import {body} from "express-validator";
|
//import {body} from "express-validator";
|
||||||
|
|
||||||
const logger = new Logger({
|
const logger = new Logger({
|
||||||
@@ -171,6 +172,8 @@ async function deleteBrand(req: Request, res: Response): Promise<Response> {
|
|||||||
|
|
||||||
//TODO get models of the brand
|
//TODO get models of the brand
|
||||||
|
|
||||||
|
if (isDebugMode()) logger.debug("\nController loaded.");
|
||||||
|
|
||||||
const BrandController = {
|
const BrandController = {
|
||||||
create: createBrand,
|
create: createBrand,
|
||||||
update: updateBrand,
|
update: updateBrand,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import type IDbCategory from "@interfaces/database/IDbCategory";
|
import type IDbCategory from "@interfaces/database/IDbCategory";
|
||||||
import CategoryService from "@services/category.service";
|
import CategoryService from "@services/category.service";
|
||||||
|
import { isDebugMode } from "@utils/debugState";
|
||||||
import type { Request, Response } from "express";
|
import type { Request, Response } from "express";
|
||||||
import { Logger } from "tslog";
|
import { Logger } from "tslog";
|
||||||
//import {validationResult} from "express-validator";
|
//import {validationResult} from "express-validator";
|
||||||
@@ -177,6 +178,8 @@ async function getBySlugCategory(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isDebugMode()) logger.debug("\nController loaded.");
|
||||||
|
|
||||||
const CategoryController = {
|
const CategoryController = {
|
||||||
create: createCategory,
|
create: createCategory,
|
||||||
update: updateCategory,
|
update: updateCategory,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import type IDbModel from "@interfaces/database/IDbModel";
|
import type IDbModel from "@interfaces/database/IDbModel";
|
||||||
import CategoryService from "@services/category.service";
|
import CategoryService from "@services/category.service";
|
||||||
import ModelService from "@services/model.service";
|
import ModelService from "@services/model.service";
|
||||||
|
import { isDebugMode } from "@utils/debugState";
|
||||||
import type { Request, Response } from "express";
|
import type { Request, Response } from "express";
|
||||||
import { Logger } from "tslog";
|
import { Logger } from "tslog";
|
||||||
//import {validationResult} from "express-validator";
|
//import {validationResult} from "express-validator";
|
||||||
@@ -41,7 +42,7 @@ async function createModel(req: Request, res: Response): Promise<Response> {
|
|||||||
|
|
||||||
async function updateModel(req: Request, res: Response): Promise<Response> {
|
async function updateModel(req: Request, res: Response): Promise<Response> {
|
||||||
const body: IDbModel = req.body;
|
const body: IDbModel = req.body;
|
||||||
const doesExist = await ModelService.getBySlug(`${body.slug_name}`);
|
const doesExist = await ModelService.getBySlug(`${req.params["modelSlug"]}`);
|
||||||
if (!doesExist) {
|
if (!doesExist) {
|
||||||
logger.error("Model does not exist");
|
logger.error("Model does not exist");
|
||||||
return res.status(404).json({
|
return res.status(404).json({
|
||||||
@@ -131,6 +132,8 @@ async function deleteModel(req: Request, res: Response): Promise<Response> {
|
|||||||
|
|
||||||
//TODO get model with vehicle available.
|
//TODO get model with vehicle available.
|
||||||
|
|
||||||
|
if (isDebugMode()) logger.debug("\nController loaded.");
|
||||||
|
|
||||||
const ModelController = {
|
const ModelController = {
|
||||||
create: createModel,
|
create: createModel,
|
||||||
update: updateModel,
|
update: updateModel,
|
||||||
|
|||||||
150
src/controllers/rent.controller.ts
Normal file
150
src/controllers/rent.controller.ts
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
import { isDebugMode } from "@utils/debugState";
|
||||||
|
import type { Request, Response } from "express";
|
||||||
|
import { Logger } from "tslog";
|
||||||
|
import RentService from "@services/rent.service";
|
||||||
|
import {HttpStatusCode} from "@interfaces/requests/HttpStatusCode";
|
||||||
|
import type IDbRent from "@interfaces/database/IDbRent";
|
||||||
|
import JwtService from "@services/jwt.service";
|
||||||
|
import UserService from "@services/user.service";
|
||||||
|
|
||||||
|
|
||||||
|
const logger = new Logger({
|
||||||
|
name: "RentController",
|
||||||
|
});
|
||||||
|
|
||||||
|
async function createRent(req: Request, res: Response): Promise<Response> {
|
||||||
|
try {
|
||||||
|
const rentData: IDbRent = req.body;
|
||||||
|
if (!rentData.active || !rentData.need_survey || !rentData.eat || !rentData.iat || !rentData.user_id || !rentData.vehicle_id || !rentData.km_at_start || !rentData.active) {
|
||||||
|
logger.error("Invalid rent data");
|
||||||
|
return res.status(HttpStatusCode.BadRequest).json({
|
||||||
|
error: "Invalid rent data",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const rent = await RentService.create(rentData);
|
||||||
|
logger.info(`\n\n> Rent created successfully! (ID: ${rentData.vehicle_id})\n`);
|
||||||
|
return res.status(201).json({
|
||||||
|
message: "Rent created successfully",
|
||||||
|
rent,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(`\n\n> Failed to create rent !\n${error}\n`);
|
||||||
|
return res.status(500).json({
|
||||||
|
error: "Failed to create rent",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateRent(req: Request, res: Response): Promise<Response> {
|
||||||
|
const body: IDbRent = req.body;
|
||||||
|
if (!body.vehicle_id || !body.user_id || !body.active || !body.need_survey || !body.eat || !body.iat || !body.km_at_start) {
|
||||||
|
logger.error("Invalid rent data");
|
||||||
|
return res.status(HttpStatusCode.BadRequest).json({
|
||||||
|
error: "Invalid rent data",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const rentId = req.params["rentId"];
|
||||||
|
if (!rentId || rentId.length !== 36) {
|
||||||
|
logger.error("Invalid rent ID");
|
||||||
|
return res.status(HttpStatusCode.BadRequest).json({
|
||||||
|
error: "Invalid rent ID",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const result = await RentService.update({
|
||||||
|
id: rentId,
|
||||||
|
vehicle_id: ``,
|
||||||
|
user_id: ``,
|
||||||
|
active: !!body.active,
|
||||||
|
need_survey: !!body.need_survey,
|
||||||
|
eat: body.eat,
|
||||||
|
iat: body.iat,
|
||||||
|
km_at_start: body.km_at_start,
|
||||||
|
})
|
||||||
|
if (!result) {
|
||||||
|
logger.error(`Failed to update rent with ID: ${rentId}`);
|
||||||
|
return res.status(HttpStatusCode.InternalServerError).json({
|
||||||
|
error: `Failed to update rent with ID: ${rentId}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
logger.info(`Rent with ID: ${rentId} updated successfully`);
|
||||||
|
return res.status(HttpStatusCode.Ok).json({
|
||||||
|
message: `Rent with ID: ${rentId} updated successfully`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getAllAssigned(res: Response): Promise<Response> {
|
||||||
|
const rents = await RentService.getAll();
|
||||||
|
if (rents.length === 0) {
|
||||||
|
return res.status(HttpStatusCode.NotFound).json({
|
||||||
|
error: "No assigned rents found",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return res.status(HttpStatusCode.Ok).json({
|
||||||
|
iat: Date.now(),
|
||||||
|
rents: rents,
|
||||||
|
total: rents.length
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getAssignedToUser(req: Request, res: Response): Promise<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(HttpStatusCode.Unauthorized)
|
||||||
|
.json({
|
||||||
|
error: "Unauthorized",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const payload = await JwtService.verify(bearerToken);
|
||||||
|
if (!payload || !payload.sub) {
|
||||||
|
logger.warn(`Unauthorized access attempt (${req.ip})`);
|
||||||
|
return res
|
||||||
|
.type("application/json")
|
||||||
|
.status(HttpStatusCode.Unauthorized)
|
||||||
|
.json({
|
||||||
|
error: "Unauthorized",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const sourceUser = await UserService.getFromId(payload.sub);
|
||||||
|
if (!sourceUser) {
|
||||||
|
return res.type("application/json").status(HttpStatusCode.ImATeapot).json({
|
||||||
|
error: "You dont exist anymore",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const userId: string = payload.sub;
|
||||||
|
if (!userId || userId.length !== 36) {
|
||||||
|
logger.error("Invalid user ID");
|
||||||
|
return res.status(HttpStatusCode.BadRequest).json({
|
||||||
|
error: "Invalid user ID",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let targetId = userId
|
||||||
|
if ("is_admin" in sourceUser && sourceUser.is_admin) {
|
||||||
|
targetId = req.body.targetId || userId
|
||||||
|
}
|
||||||
|
const rents = await RentService.getUserRent(targetId);
|
||||||
|
if (!rents) {
|
||||||
|
return res.status(HttpStatusCode.NotFound).json({
|
||||||
|
error: "No assigned rents found for the user",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return res.status(HttpStatusCode.Ok).json({
|
||||||
|
iat: Date.now(),
|
||||||
|
rents: rents,
|
||||||
|
total: rents.length,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isDebugMode()) logger.debug("\nController loaded.");
|
||||||
|
|
||||||
|
const RentController = {
|
||||||
|
create: createRent,
|
||||||
|
update: updateRent,
|
||||||
|
getAll: getAllAssigned,
|
||||||
|
getAssignedToUser,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default RentController;
|
||||||
174
src/controllers/vehicle.controller.ts
Normal file
174
src/controllers/vehicle.controller.ts
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
import type { IDbVehicle } from "@interfaces/database/IDbVehicle";
|
||||||
|
import VehicleService from "@services/vehicle.service";
|
||||||
|
import { isDebugMode } from "@utils/debugState";
|
||||||
|
import type { Request, Response } from "express";
|
||||||
|
import { Logger } from "tslog";
|
||||||
|
//import {validationResult} from "express-validator";
|
||||||
|
|
||||||
|
const logger = new Logger({
|
||||||
|
name: "VehicleController",
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new vehicle in the database.
|
||||||
|
*
|
||||||
|
* @param {Request} req - The request object containing the vehicle details in the body.
|
||||||
|
* @param {Response} res - The response object used to send the result of the operation.
|
||||||
|
* @returns {Promise<Response>} The response with the result of the operation.
|
||||||
|
*/
|
||||||
|
async function createVehicle(req: Request, res: Response): Promise<Response> {
|
||||||
|
const body: IDbVehicle = req.body;
|
||||||
|
const createResult = await VehicleService.create({
|
||||||
|
plate_number: `${body.plate_number}`,
|
||||||
|
model_id: `${body.plate_number}`,
|
||||||
|
odometer: Number.parseInt(`${body.odometer}`),
|
||||||
|
health_state: Number.parseInt(`${body.health_state}`),
|
||||||
|
});
|
||||||
|
if (!createResult) {
|
||||||
|
logger.error("Failed to create vehicle");
|
||||||
|
return res.status(500).json({
|
||||||
|
error: "Failed to create vehicle",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
logger.info(`Vehicle created successfully ! (${body.plate_number})`);
|
||||||
|
return res.status(201).json({
|
||||||
|
message: "Vehicle created successfully",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates a vehicle in the database.
|
||||||
|
*
|
||||||
|
* @param {Request} req - The request object containing the vehicle data in the request body and the vehicle ID in the request parameters.
|
||||||
|
* @param {Response} res - The response object used to send the result of the update operation.
|
||||||
|
*
|
||||||
|
* @return {Promise<Response>} A promise that resolves to the response object with a status and a JSON body indicating the result of the update operation.
|
||||||
|
*/
|
||||||
|
async function updateVehicle(req: Request, res: Response): Promise<Response> {
|
||||||
|
const body: IDbVehicle = req.body;
|
||||||
|
const vehicleId = req.params["vehicleId"];
|
||||||
|
if (!vehicleId || vehicleId.length !== 36) {
|
||||||
|
if (isDebugMode()) logger.error("Vehicle ID is missing");
|
||||||
|
return res.status(400).json({
|
||||||
|
error: "Vehicle ID is missing or not valid",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const updateResult = await VehicleService.update({
|
||||||
|
plate_number: `${body.plate_number}`,
|
||||||
|
model_id: `${body.plate_number}`,
|
||||||
|
odometer: Number.parseInt(`${body.odometer}`),
|
||||||
|
health_state: Number.parseInt(`${body.health_state}`),
|
||||||
|
});
|
||||||
|
if (!updateResult) {
|
||||||
|
logger.error("Failed to update vehicle");
|
||||||
|
return res.status(500).json({
|
||||||
|
error: "Failed to update vehicle",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
logger.info(`Vehicle updated successfully ! (${body.plate_number})`);
|
||||||
|
return res.status(200).json({
|
||||||
|
message: "Vehicle updated successfully",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves all vehicles from the vehicle service.
|
||||||
|
*
|
||||||
|
* @param {Response} res - The response object from the client.
|
||||||
|
* @returns {Promise<Response>} A promise that resolves to a response object containing the result of the operation. The result is a JSON object containing all vehicles.
|
||||||
|
*/
|
||||||
|
async function getAllVehicle(res: Response): Promise<Response> {
|
||||||
|
const getAllVehicleResult = await VehicleService.getAll();
|
||||||
|
if (!getAllVehicleResult) {
|
||||||
|
logger.error("Failed to get all vehicles");
|
||||||
|
return res.status(500).json({
|
||||||
|
error: "Failed to get all vehicles",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return res.status(200).json(getAllVehicleResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the available vehicles from the VehicleService
|
||||||
|
*
|
||||||
|
* @param {Response} res - The Response object to send the result to
|
||||||
|
* @returns {Promise<Response<any, Record<string, any>>>} - A promise that resolves to a Response object containing the available vehicles or an error message
|
||||||
|
*/
|
||||||
|
async function getAvailableVehicle(res: Response): Promise<Response<any, Record<string, any>>> {
|
||||||
|
const getAvailableVehicleResult = await VehicleService.getAvailable();
|
||||||
|
if (!getAvailableVehicleResult) {
|
||||||
|
logger.error("Failed to get available vehicles");
|
||||||
|
return res.status(500).json({
|
||||||
|
error: "Failed to get available vehicles",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return res.status(200).json(getAvailableVehicleResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a vehicle by its ID.
|
||||||
|
*
|
||||||
|
* @param {Request} req - The request object containing the vehicle ID.
|
||||||
|
* @param {Response} res - The response object used to send the result.
|
||||||
|
*
|
||||||
|
* @return {Promise<Response>} A promise that resolves to the result of the retrieval operation.
|
||||||
|
*/
|
||||||
|
async function getVehicleById(req: Request, res: Response): Promise<Response> {
|
||||||
|
const vehicleId = req.params["vehicleId"];
|
||||||
|
if (!vehicleId || vehicleId.length !== 36) {
|
||||||
|
if (isDebugMode()) logger.error("Vehicle ID is missing or not valid");
|
||||||
|
return res.status(400).json({
|
||||||
|
error: "Vehicle ID is missing or not valid",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const getVehicleResult = await VehicleService.getById(vehicleId);
|
||||||
|
if (!getVehicleResult) {
|
||||||
|
logger.error(`Failed to get vehicle by ID: ${vehicleId}`);
|
||||||
|
return res.status(500).json({
|
||||||
|
error: `Failed to get vehicle by ID: ${vehicleId}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return res.status(200).json(getVehicleResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes a vehicle.
|
||||||
|
*
|
||||||
|
* @param {Object} req - The request object.
|
||||||
|
* @param {Object} res - The response object.
|
||||||
|
*
|
||||||
|
* @return {Promise<Response>} A promise that resolves to the response JSON object.
|
||||||
|
*/
|
||||||
|
async function deleteVehicle(req: Request, res: Response): Promise<Response> {
|
||||||
|
const vehicleId = req.params["vehicleId"];
|
||||||
|
if (!vehicleId || vehicleId.length !== 36) {
|
||||||
|
if (isDebugMode()) logger.error("Vehicle ID is missing or not valid");
|
||||||
|
return res.status(400).json({
|
||||||
|
error: "Vehicle ID is missing or not valid",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const deleteResult = await VehicleService.delete(vehicleId);
|
||||||
|
if (!deleteResult) {
|
||||||
|
logger.error(`Failed to delete vehicle with ID: ${vehicleId}`);
|
||||||
|
return res.status(500).json({
|
||||||
|
error: `Failed to delete vehicle with ID: ${vehicleId}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
logger.info(`Vehicle deleted successfully ! (ID: ${vehicleId})`);
|
||||||
|
return res.status(200).json({
|
||||||
|
message: "Vehicle deleted successfully",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isDebugMode()) logger.debug("\nController loaded.");
|
||||||
|
|
||||||
|
const VehicleController = {
|
||||||
|
create: createVehicle,
|
||||||
|
update: updateVehicle,
|
||||||
|
getAll: getAllVehicle,
|
||||||
|
delete: deleteVehicle,
|
||||||
|
getById: getVehicleById,
|
||||||
|
getAvailable: getAvailableVehicle,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default VehicleController;
|
||||||
54
src/interfaces/database/IDbFactorize.ts
Normal file
54
src/interfaces/database/IDbFactorize.ts
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
/**
|
||||||
|
* Represents the output of the factorization function.
|
||||||
|
*/
|
||||||
|
export interface IDbFactorizeOutput {
|
||||||
|
/**
|
||||||
|
* Description: The variable `_valuesArray` is an array that can contain values of type `string`, `boolean`, `number`, or `Date`.
|
||||||
|
* (The value associated with the keys of `_keysTemplate`)
|
||||||
|
*
|
||||||
|
* @type {Array<string | boolean | number | Date>}
|
||||||
|
*/
|
||||||
|
_valuesArray: Array<string | boolean | number | Date>;
|
||||||
|
/**
|
||||||
|
* Represents the SQL Query template for the keys.
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
_keysTemplate: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The list of ? for the "VALUE" section
|
||||||
|
*/
|
||||||
|
_questionMarksFields: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The total number of fields.
|
||||||
|
*
|
||||||
|
* @type {number}
|
||||||
|
*/
|
||||||
|
totalFields: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface IDbFactorizeInput represents the input required to factorize a SQL query.
|
||||||
|
*/
|
||||||
|
export interface IDbFactorizeInput {
|
||||||
|
/**
|
||||||
|
* An object containing values that will be in a SQL Query.
|
||||||
|
*
|
||||||
|
* @type {Array<string | boolean | number | Date>}
|
||||||
|
*/
|
||||||
|
values: object;
|
||||||
|
/**
|
||||||
|
* Represents the name of the action that will result of the prepared SQL Query.
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
actionName: string;
|
||||||
|
/**
|
||||||
|
* Indicates whether an error should be thrown when encountering an error.
|
||||||
|
* If set to true, an error will be thrown. If set to false or not provided, the error will not be thrown.
|
||||||
|
*
|
||||||
|
* @type {boolean}
|
||||||
|
*/
|
||||||
|
throwOnError?: true;
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
export interface IDbRent {
|
export interface IDbRent {
|
||||||
|
id?: string;
|
||||||
vehicle_id: string;
|
vehicle_id: string;
|
||||||
user_id: string;
|
user_id: string;
|
||||||
active: boolean;
|
active: boolean;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ export interface IDbUser {
|
|||||||
lastname: string;
|
lastname: string;
|
||||||
dob: Date;
|
dob: Date;
|
||||||
email: string;
|
email: string;
|
||||||
is_mail_verified: boolean;
|
is_email_verified: boolean;
|
||||||
is_admin: boolean;
|
is_admin: boolean;
|
||||||
gdpr: Date;
|
gdpr: Date;
|
||||||
hash: string;
|
hash: string;
|
||||||
|
|||||||
@@ -4,4 +4,5 @@ export interface IDbVehicle {
|
|||||||
model_id: string;
|
model_id: string;
|
||||||
odometer: number;
|
odometer: number;
|
||||||
health_state: number;
|
health_state: number;
|
||||||
|
isAvailable?: boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
269
src/interfaces/requests/HttpStatusCode.ts
Normal file
269
src/interfaces/requests/HttpStatusCode.ts
Normal file
@@ -0,0 +1,269 @@
|
|||||||
|
export enum HttpStatusCode {
|
||||||
|
/**
|
||||||
|
* Status code for a request indicating that the server received the request headers
|
||||||
|
* and the client should proceed to send the request body.
|
||||||
|
* @enum {number}
|
||||||
|
*/
|
||||||
|
Continue = 100,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Status code for a request indicating that the requester has asked the server to switch protocols.
|
||||||
|
* @enum {number}
|
||||||
|
*/
|
||||||
|
SwitchingProtocols = 101,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Status code for a request indicating that the server has received and is processing the request,
|
||||||
|
* but no response is available yet.
|
||||||
|
* @enum {number}
|
||||||
|
*/
|
||||||
|
Processing = 102,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Successful HTTP response
|
||||||
|
* @enum {number}
|
||||||
|
*/
|
||||||
|
Ok = 200,
|
||||||
|
/**
|
||||||
|
* Request has been fulfilled; new resource created as a result.
|
||||||
|
* @enum {number}
|
||||||
|
*/
|
||||||
|
Created = 201,
|
||||||
|
/**
|
||||||
|
* Request accepted, but not yet processed.
|
||||||
|
* @enum {number}
|
||||||
|
*/
|
||||||
|
Accepted = 202,
|
||||||
|
/**
|
||||||
|
* Request successful. Meta-information returned is from original server, not local.
|
||||||
|
* @enum {number}
|
||||||
|
*/
|
||||||
|
NonAuthoritativeInformation = 203,
|
||||||
|
/**
|
||||||
|
* Request processed. No content returned.
|
||||||
|
* @enum {number}
|
||||||
|
*/
|
||||||
|
NoContent = 204,
|
||||||
|
/**
|
||||||
|
* Server specifies part of document should be reset.
|
||||||
|
* @enum {number}
|
||||||
|
*/
|
||||||
|
ResetContent = 205,
|
||||||
|
/**
|
||||||
|
* Partial content returned due to GET.
|
||||||
|
* @enum {number}
|
||||||
|
*/
|
||||||
|
PartialContent = 206,
|
||||||
|
/**
|
||||||
|
* Multiple Resource Meta-Data: Could be used for collection instances.
|
||||||
|
* @enum {number}
|
||||||
|
*/
|
||||||
|
MultiStatus = 207,
|
||||||
|
/**
|
||||||
|
* Status code used to indicate that a certain request has been already reported.
|
||||||
|
* @enum {number}
|
||||||
|
*/
|
||||||
|
AlreadyReported = 208,
|
||||||
|
/**
|
||||||
|
* The server has fulfilled the request for the content, and the content is being conveyed in a manner described by the Content-Encoding, Content-Range, and Content-Type headers.
|
||||||
|
* @enum {number}
|
||||||
|
*/
|
||||||
|
ImUsed = 226,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @enum {number}
|
||||||
|
* @description HTTP status code for multiple choices
|
||||||
|
*/
|
||||||
|
MultipleChoices = 300,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @enum {number}
|
||||||
|
* @description HTTP status code for moved permanently
|
||||||
|
*/
|
||||||
|
MovedPermanently = 301,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @enum {number}
|
||||||
|
* @description HTTP status code for found
|
||||||
|
*/
|
||||||
|
Found = 302,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @enum {number}
|
||||||
|
* @description HTTP status code for see other
|
||||||
|
*/
|
||||||
|
SeeOther = 303,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @enum {number}
|
||||||
|
* @description HTTP status code for not modified
|
||||||
|
*/
|
||||||
|
NotModified = 304,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @enum {number}
|
||||||
|
* @description HTTP status code for use proxy
|
||||||
|
*/
|
||||||
|
UseProxy = 305,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @enum {number}
|
||||||
|
* @description HTTP status code for temporary redirect
|
||||||
|
*/
|
||||||
|
TemporaryRedirect = 307,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @enum {number}
|
||||||
|
* @description HTTP status code for permanent redirect
|
||||||
|
*/
|
||||||
|
PermanentRedirect = 308,
|
||||||
|
|
||||||
|
/** @description Client error: The server could not understand the request due to invalid syntax. */
|
||||||
|
BadRequest = 400,
|
||||||
|
|
||||||
|
/** @description Client error: The client must authenticate itself to get the requested response. */
|
||||||
|
Unauthorized = 401,
|
||||||
|
|
||||||
|
/** @description Client error: This response code is reserved for future use. */
|
||||||
|
PaymentRequired = 402,
|
||||||
|
|
||||||
|
/** @description Client error: The client does not have access rights to the content; that is, it is unauthorized, so the server is refusing to give the requested resource. */
|
||||||
|
Forbidden = 403,
|
||||||
|
|
||||||
|
/** @description Client error: The server cannot find requested resource. */
|
||||||
|
NotFound = 404,
|
||||||
|
|
||||||
|
/** @description Client error: The request method is not supported by the server and cannot be handled. */
|
||||||
|
MethodNotAllowed = 405,
|
||||||
|
|
||||||
|
/** @description Client error: This response is sent when the web server, after performing server-driven content negotiation, doesn't find any content following the criteria given by the user agent. */
|
||||||
|
NotAcceptable = 406,
|
||||||
|
|
||||||
|
/** @description Client error: This is similar to 401 (Unauthorised), but indicates that the client must authenticate itself to get the requested response. */
|
||||||
|
ProxyAuthenticationRequired = 407,
|
||||||
|
|
||||||
|
/** @description Client error: This response is sent on an idle connection by some servers, even without any previous request by the client. */
|
||||||
|
RequestTimeout = 408,
|
||||||
|
|
||||||
|
/** @description Client error: This response is sent when a request conflicts with the current state of the server. */
|
||||||
|
Conflict = 409,
|
||||||
|
|
||||||
|
/** @description Client error: This response is sent when the requested content has been permanently deleted from server, with no forwarding address. */
|
||||||
|
Gone = 410,
|
||||||
|
|
||||||
|
/** @description Client error: The server refuses to accept the request without a defined Content- Length. */
|
||||||
|
LengthRequired = 411,
|
||||||
|
|
||||||
|
/** @description Client error: The precondition given in the request evaluated to false by the server. */
|
||||||
|
PreconditionFailed = 412,
|
||||||
|
|
||||||
|
/** @description Client error: Request entity is larger than limits defined by server. */
|
||||||
|
PayloadTooLarge = 413,
|
||||||
|
|
||||||
|
/** @description Client error: The URI requested by the client is longer than the server is willing to interpret. */
|
||||||
|
UriTooLong = 414,
|
||||||
|
|
||||||
|
/** @description Client error: The media format of the requested data is not supported by the server, so the server is rejecting the request. */
|
||||||
|
UnsupportedMediaType = 415,
|
||||||
|
|
||||||
|
/** @description Client error: The range specified by the Range header field in the request can't be fulfilled. */
|
||||||
|
RangeNotSatisfiable = 416,
|
||||||
|
|
||||||
|
/** @description Client error: This response code means the expectation indicated by the Expect request header field can't be met by the server. */
|
||||||
|
ExpectationFailed = 417,
|
||||||
|
|
||||||
|
/** @description Client error: The server refuses to brew coffee because it is, permanently, a teapot. */
|
||||||
|
ImATeapot = 418,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @enum
|
||||||
|
* @name MisdirectedRequest
|
||||||
|
* @description Represents HTTP status code 421: Misdirected Request.
|
||||||
|
* The client should switch to a different protocol such as TLS/1.0.
|
||||||
|
*/
|
||||||
|
MisdirectedRequest = 421,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @enum
|
||||||
|
* @name UnprocessableEntity
|
||||||
|
* @description Represents HTTP status code 422: Unprocessable Entity.
|
||||||
|
* The request was well-formed but was unable to be followed due to semantic errors.
|
||||||
|
*/
|
||||||
|
UnprocessableEntity = 422,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @enum
|
||||||
|
* @name Locked
|
||||||
|
* @description Represents HTTP status code 423: Locked.
|
||||||
|
* The resource that is being accessed is locked.
|
||||||
|
*/
|
||||||
|
Locked = 423,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @enum
|
||||||
|
* @name FailedDependency
|
||||||
|
* @description Represents HTTP status code 424: Failed Dependency.
|
||||||
|
* The request failed because it depended on another request and that request failed.
|
||||||
|
*/
|
||||||
|
FailedDependency = 424,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @enum
|
||||||
|
* @name TooEarly
|
||||||
|
* @description Represents HTTP status code 425: Too Early.
|
||||||
|
* Indicates that the server is unwilling to risk processing a request that might be replayed.
|
||||||
|
*/
|
||||||
|
TooEarly = 425,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @enum
|
||||||
|
* @name UpgradeRequired
|
||||||
|
* @description Represents HTTP status code 426: Upgrade Required.
|
||||||
|
* The client should switch to a different protocol.
|
||||||
|
*/
|
||||||
|
UpgradeRequired = 426,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @enum
|
||||||
|
* @name PreconditionRequired
|
||||||
|
* @description Represents HTTP status code 428: Precondition Required.
|
||||||
|
* The client must first fulfill certain precondition.
|
||||||
|
*/
|
||||||
|
PreconditionRequired = 428,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @enum
|
||||||
|
* @name TooManyRequests
|
||||||
|
* @description Represents HTTP status code 429: Too Many Requests.
|
||||||
|
* The user has sent too many requests in a certain amount of time.
|
||||||
|
*/
|
||||||
|
TooManyRequests = 429,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @enum
|
||||||
|
* @name RequestHeaderFieldsTooLarge
|
||||||
|
* @description Represents HTTP status code 431: Request Header Fields Too Large.
|
||||||
|
* The server is unwilling to process the request because its header fields are too large.
|
||||||
|
*/
|
||||||
|
RequestHeaderFieldsTooLarge = 431,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @enum
|
||||||
|
* @name UnavailableForLegalReasons
|
||||||
|
* @description Represents HTTP status code 451: Unavailable For Legal Reasons.
|
||||||
|
* The server is denying access for legal reasons.
|
||||||
|
*/
|
||||||
|
UnavailableForLegalReasons = 451,
|
||||||
|
|
||||||
|
InternalServerError = 500,
|
||||||
|
NotImplemented = 501,
|
||||||
|
BadGateway = 502,
|
||||||
|
ServiceUnavailable = 503,
|
||||||
|
GatewayTimeout = 504,
|
||||||
|
HttpVersionNotSupported = 505,
|
||||||
|
VariantAlsoNegotiates = 506,
|
||||||
|
InsufficientStorage = 507,
|
||||||
|
LoopDetected = 508,
|
||||||
|
NotExtended = 510,
|
||||||
|
NetworkAuthenticationRequired = 511,
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
export interface IReqLogin {
|
export interface IReqLogin {
|
||||||
username: string;
|
email: string;
|
||||||
password: string;
|
password: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ export interface IReqRegister {
|
|||||||
username: string;
|
username: string;
|
||||||
firstName: string;
|
firstName: string;
|
||||||
lastName: string;
|
lastName: string;
|
||||||
dob: Date;
|
/*dob: Date;*/
|
||||||
email: string;
|
email: string;
|
||||||
gdpr?: boolean;
|
gdpr?: boolean;
|
||||||
password: string;
|
password: string;
|
||||||
|
|||||||
8
src/interfaces/services/IUserUpdate.ts
Normal file
8
src/interfaces/services/IUserUpdate.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
export interface IUserUpdate {
|
||||||
|
id?: string;
|
||||||
|
username?: string;
|
||||||
|
firstname?: string;
|
||||||
|
lastname?: string;
|
||||||
|
dob?: Date;
|
||||||
|
gdpr?: Date;
|
||||||
|
}
|
||||||
@@ -1,27 +1,29 @@
|
|||||||
import AdminGuard from "@validators/AdminGuard";
|
import AdminGuard from "@validators/AdminGuard";
|
||||||
import UserGuard from "@validators/UserGuard";
|
import UserGuard from "@validators/UserGuard";
|
||||||
import express, { type Router } from "express";
|
import express, { type Router } from "express";
|
||||||
|
import VehicleController from "@controllers/vehicle.controller";
|
||||||
|
import RentController from "@controllers/rent.controller";
|
||||||
|
|
||||||
const RentRouter: Router = express.Router();
|
const RentRouter: Router = express.Router();
|
||||||
|
|
||||||
// Get rent affected to the user
|
// Get rent affected to the user
|
||||||
RentRouter.route("/affected").get(UserGuard);
|
RentRouter.route("/affected").get(UserGuard, RentController.getAssignedToUser);
|
||||||
|
|
||||||
// Get all vehicle in rent (admin only)
|
// Get all vehicle in rent (admin only)
|
||||||
RentRouter.route("/affected/all").get(AdminGuard);
|
RentRouter.route("/affected/all").get(AdminGuard, RentController.getAll);
|
||||||
|
|
||||||
// Add a new vehicle (admin only)
|
// Add a new vehicle (admin only)
|
||||||
RentRouter.route("/veh/new").post(AdminGuard);
|
RentRouter.route("/veh/new").post(AdminGuard, VehicleController.create);
|
||||||
|
|
||||||
// Get all vehicles
|
// Get all vehicles
|
||||||
RentRouter.route("/veh/all").get();
|
RentRouter.route("/veh/all").get(VehicleController.getAll);
|
||||||
|
|
||||||
// Rent a specific vehicle
|
// 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)
|
.get(UserGuard, VehicleController.getById)
|
||||||
.patch(AdminGuard)
|
.patch(AdminGuard, VehicleController.update)
|
||||||
.delete(AdminGuard);
|
.delete(AdminGuard, VehicleController.delete);
|
||||||
|
|
||||||
export default RentRouter;
|
export default RentRouter;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import type IDbBrand from "@interfaces/database/IDbBrand";
|
import type IDbBrand from "@interfaces/database/IDbBrand";
|
||||||
import MysqlService from "@services/mysql.service";
|
import MysqlService from "@services/mysql.service";
|
||||||
|
import { isDebugMode } from "@utils/debugState";
|
||||||
import { Logger } from "tslog";
|
import { Logger } from "tslog";
|
||||||
import { v4 as uuidv4 } from "uuid";
|
import { v4 as uuidv4 } from "uuid";
|
||||||
|
|
||||||
@@ -168,6 +169,8 @@ async function deleteBrand(brandId: string): Promise<boolean> {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isDebugMode()) logger.debug("\nService loaded.");
|
||||||
|
|
||||||
const BrandService = {
|
const BrandService = {
|
||||||
create: createBrand,
|
create: createBrand,
|
||||||
update: updateBrand,
|
update: updateBrand,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import type { IDbCategory } from "@interfaces/database/IDbCategory";
|
import type { IDbCategory } from "@interfaces/database/IDbCategory";
|
||||||
import MysqlService from "@services/mysql.service";
|
import MysqlService from "@services/mysql.service";
|
||||||
|
import { isDebugMode } from "@utils/debugState";
|
||||||
import { Logger } from "tslog";
|
import { Logger } from "tslog";
|
||||||
import { v4 as uuidv4 } from "uuid";
|
import { v4 as uuidv4 } from "uuid";
|
||||||
|
|
||||||
@@ -127,6 +128,8 @@ async function deleteCategory(id: string): Promise<unknown> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isDebugMode()) logger.debug("\nService loaded.");
|
||||||
|
|
||||||
const CategoryService = {
|
const CategoryService = {
|
||||||
create: createCategory,
|
create: createCategory,
|
||||||
delete: deleteCategory,
|
delete: deleteCategory,
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { isDebugMode } from "@utils/debugState";
|
||||||
import {
|
import {
|
||||||
type JWTHeaderParameters,
|
type JWTHeaderParameters,
|
||||||
type JWTPayload,
|
type JWTPayload,
|
||||||
@@ -64,6 +65,8 @@ async function JwtSignService(
|
|||||||
.sign(new TextEncoder().encode(`${process.env["JWT_SECRET"]}`));
|
.sign(new TextEncoder().encode(`${process.env["JWT_SECRET"]}`));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isDebugMode()) logger.debug("\nService loaded.");
|
||||||
|
|
||||||
const JwtService = {
|
const JwtService = {
|
||||||
verify: JwtVerifyService,
|
verify: JwtVerifyService,
|
||||||
sign: JwtSignService,
|
sign: JwtSignService,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import type IDbModel from "@interfaces/database/IDbModel";
|
import type IDbModel from "@interfaces/database/IDbModel";
|
||||||
import MysqlService from "@services/mysql.service";
|
import MysqlService from "@services/mysql.service";
|
||||||
|
import { isDebugMode } from "@utils/debugState";
|
||||||
import { Logger } from "tslog";
|
import { Logger } from "tslog";
|
||||||
import { v4 as uuidv4 } from "uuid";
|
import { v4 as uuidv4 } from "uuid";
|
||||||
|
|
||||||
@@ -79,12 +80,14 @@ async function deleteModel(modelSlug: string): Promise<boolean> {
|
|||||||
}
|
}
|
||||||
logger.info(`Deleting model with ID: ${modelSlug}`);
|
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) {
|
if (!doesExist[0]) {
|
||||||
logger.warn(`Model with slug ${modelSlug} not found`);
|
logger.warn(`Model with slug ${modelSlug} not found`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
const target = doesExist[0]
|
||||||
|
if (!target.id) return false;
|
||||||
try {
|
try {
|
||||||
await MysqlService.Model.delete(DbHandler, doesExist.id);
|
await MysqlService.Model.delete(DbHandler, target.id);
|
||||||
logger.info("Deletion Successful !");
|
logger.info("Deletion Successful !");
|
||||||
return true;
|
return true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -103,11 +106,11 @@ async function getBySlugModel(modelSlug: string): Promise<IDbModel | null> {
|
|||||||
logger.info(`Fetching model with slug: ${modelSlug}`);
|
logger.info(`Fetching model with slug: ${modelSlug}`);
|
||||||
try {
|
try {
|
||||||
const model = await MysqlService.Model.getBySlug(DbHandler, modelSlug);
|
const model = await MysqlService.Model.getBySlug(DbHandler, modelSlug);
|
||||||
if (!model) {
|
if (!model[0]) {
|
||||||
logger.warn(`Model with slug ${modelSlug} not found`);
|
logger.warn(`Model with slug ${modelSlug} not found`);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return model;
|
return model[0];
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(`Error fetching model by slug: ${error}`);
|
logger.error(`Error fetching model by slug: ${error}`);
|
||||||
return null;
|
return null;
|
||||||
@@ -135,6 +138,8 @@ async function getAllModels(): Promise<IDbModel[] | null> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isDebugMode()) logger.debug("\nService loaded.");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ModelService is responsible for managing models.
|
* ModelService is responsible for managing models.
|
||||||
* @namespace
|
* @namespace
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
182
src/services/rent.service.ts
Normal file
182
src/services/rent.service.ts
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
//import { ErrorType, type ISError } from "@interfaces/services/ISError";
|
||||||
|
import MySqlService from "@services/mysql.service";
|
||||||
|
import { isDebugMode } from "@utils/debugState";
|
||||||
|
import { Logger } from "tslog";
|
||||||
|
import { v4 } from "uuid";
|
||||||
|
import IDbRent from "@interfaces/database/IDbRent";
|
||||||
|
|
||||||
|
const logger = new Logger({
|
||||||
|
name: "RentService",
|
||||||
|
});
|
||||||
|
|
||||||
|
const DbHandler = new MySqlService.Handler("RentService");
|
||||||
|
|
||||||
|
async function createRentService(data: IDbRent): Promise<boolean> {
|
||||||
|
if (isDebugMode()) logger.debug(`\n\n> Creating a new rent...\n`);
|
||||||
|
const wantedVehicleId = data.id;
|
||||||
|
const targetUserId = data.user_id;
|
||||||
|
if (!targetUserId || !wantedVehicleId) {
|
||||||
|
logger.error(`Missing targetUserId or targetVehicleId`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const userIfExist = await MySqlService.User.getById(DbHandler, targetUserId);
|
||||||
|
if (!userIfExist[0]) {
|
||||||
|
logger.error(`User does not exist`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const targetUser = userIfExist[0]
|
||||||
|
if (!targetUser.id) return false;
|
||||||
|
const vehicleIfExist = await MySqlService.Vehicle.getById(DbHandler, wantedVehicleId);
|
||||||
|
if (!vehicleIfExist[0] || !vehicleIfExist[0].id) {
|
||||||
|
logger.error(`Vehicle does not exist`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const vehicleId = vehicleIfExist[0].id
|
||||||
|
if (!vehicleIfExist[0].isAvailable) {
|
||||||
|
logger.error(`Vehicle is not available`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const result = await MySqlService.Rent.insert(DbHandler, {
|
||||||
|
id: v4(),
|
||||||
|
vehicle_id: vehicleId,
|
||||||
|
user_id: targetUser.id,
|
||||||
|
active: data.active,
|
||||||
|
iat: new Date(Date.parse(`${data.iat}`)),
|
||||||
|
eat: new Date(Date.parse(`${data.eat}`)),
|
||||||
|
need_survey: data.need_survey,
|
||||||
|
km_at_start: Number.parseInt(`${data.km_at_start}`)
|
||||||
|
});
|
||||||
|
if (result.affectedRows !== 0) {
|
||||||
|
logger.info("\n\n> Success !");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(`\n\n> Error creating category: \n${error}\n`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateRentService(data: IDbRent) {
|
||||||
|
if (isDebugMode()) logger.debug(`\n\n> Updating a rent...\n`);
|
||||||
|
const wantedVehicleId = data.id;
|
||||||
|
const targetUserId = data.user_id;
|
||||||
|
if (!targetUserId || !wantedVehicleId || !data.id) {
|
||||||
|
logger.error(`Missing targetUserId or targetVehicleId`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const rentIfExist = await MySqlService.Rent.getById(DbHandler, data.id);
|
||||||
|
if (!rentIfExist[0]) {
|
||||||
|
logger.error(`Rent does not exist`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const rentId = rentIfExist[0].id;
|
||||||
|
if (!rentId) {
|
||||||
|
logger.error(`RentId does not exist`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const userIfExist = await MySqlService.User.getById(DbHandler, targetUserId);
|
||||||
|
if (!userIfExist[0]) {
|
||||||
|
logger.error(`User does not exist`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const targetUser = userIfExist[0]
|
||||||
|
if (!targetUser.id) return false;
|
||||||
|
const vehicleIfExist = await MySqlService.Vehicle.getById(DbHandler, wantedVehicleId);
|
||||||
|
if (!vehicleIfExist[0] || !vehicleIfExist[0].id) {
|
||||||
|
logger.error(`Vehicle does not exist`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const vehicleId = vehicleIfExist[0].id
|
||||||
|
try {
|
||||||
|
const result = await MySqlService.Rent.update(DbHandler, {
|
||||||
|
id: rentId,
|
||||||
|
vehicle_id: vehicleId,
|
||||||
|
user_id: targetUser.id,
|
||||||
|
active: data.active,
|
||||||
|
iat: new Date(Date.parse(`${data.iat}`)),
|
||||||
|
eat: new Date(Date.parse(`${data.eat}`)),
|
||||||
|
need_survey: data.need_survey,
|
||||||
|
km_at_start: Number.parseInt(`${data.km_at_start}`)
|
||||||
|
});
|
||||||
|
if (result.affectedRows !== 0) {
|
||||||
|
logger.info("\n\n> Success !");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(`\n\n> Error updating category: \n${error}\n`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getAllAssignedRentService() {
|
||||||
|
const result = await MySqlService.Rent.getAllAssigned(DbHandler);
|
||||||
|
if (result.length > 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
logger.warn(`No assigned rents found`);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getRentByIdService(rentId: string) {
|
||||||
|
if (!rentId || rentId.length !== 36) {
|
||||||
|
logger.warn(`Id missing or not conform`)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const rent = await MySqlService.Rent.getById(DbHandler, rentId);
|
||||||
|
if (rent.length > 0) {
|
||||||
|
return rent[0];
|
||||||
|
}
|
||||||
|
logger.warn(`Rent not found`);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function deleteRentService(rentId: string) {
|
||||||
|
const rentIfExist = await MySqlService.Rent.getById(DbHandler, rentId);
|
||||||
|
if (!rentIfExist[0]) {
|
||||||
|
logger.error(`Rent does not exist`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const target = rentIfExist[0]
|
||||||
|
if (!target.id) return false;
|
||||||
|
try {
|
||||||
|
const result = await MySqlService.Rent.delete(DbHandler, target.id);
|
||||||
|
if (result.affectedRows !== 0) {
|
||||||
|
logger.info("\n\n> Success !");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(`\n\n> Error deleting rent: \n${error}\n`);
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getUserRentService(userId: string) {
|
||||||
|
if (!userId) {
|
||||||
|
logger.warn(`Missing userId`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const rents = await MySqlService.Rent.getAssignedToUser(DbHandler, userId);
|
||||||
|
if (rents.length > 0) {
|
||||||
|
return rents;
|
||||||
|
}
|
||||||
|
logger.warn(`No rents found for user`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isDebugMode()) logger.debug("\nService loaded.");
|
||||||
|
|
||||||
|
const VehicleService = {
|
||||||
|
create: createRentService,
|
||||||
|
update: updateRentService,
|
||||||
|
getAll: getAllAssignedRentService,
|
||||||
|
getById: getRentByIdService,
|
||||||
|
delete: deleteRentService,
|
||||||
|
getUserRent: getUserRentService,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default VehicleService;
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
import type {IDbUser} from "@interfaces/database/IDbUser";
|
import type { IDbUser } from "@interfaces/database/IDbUser";
|
||||||
import type {IReqLogin} from "@interfaces/requests/IReqLogin";
|
import type { IReqLogin } from "@interfaces/requests/IReqLogin";
|
||||||
import type {IReqRegister} from "@interfaces/requests/IReqRegister";
|
import type { IReqRegister } from "@interfaces/requests/IReqRegister";
|
||||||
import {ErrorType, type ISError} from "@interfaces/services/ISError";
|
import { ErrorType, type ISError } from "@interfaces/services/ISError";
|
||||||
|
import type { IUserUpdate } from "@interfaces/services/IUserUpdate";
|
||||||
import CredentialService from "@services/credential.service";
|
import CredentialService from "@services/credential.service";
|
||||||
import JwtService from "@services/jwt.service";
|
import JwtService from "@services/jwt.service";
|
||||||
import MySqlService from "@services/mysql.service";
|
import MySqlService from "@services/mysql.service";
|
||||||
import MysqlService from "@services/mysql.service";
|
import { isDebugMode } from "@utils/debugState";
|
||||||
import {Logger} from "tslog";
|
import { Logger } from "tslog";
|
||||||
import {v4} from "uuid";
|
import { v4 } from "uuid";
|
||||||
|
|
||||||
|
|
||||||
const logger = new Logger({
|
const logger = new Logger({
|
||||||
name: "UserService",
|
name: "UserService",
|
||||||
@@ -28,14 +28,18 @@ const DbHandler = new MySqlService.Handler("UserService");
|
|||||||
async function getUserByEmail(targetEmail: string): Promise<IDbUser | ISError> {
|
async function getUserByEmail(targetEmail: string): Promise<IDbUser | ISError> {
|
||||||
try {
|
try {
|
||||||
const dbUser = await MySqlService.User.getByEmail(DbHandler, targetEmail);
|
const dbUser = await MySqlService.User.getByEmail(DbHandler, targetEmail);
|
||||||
if (dbUser === undefined) {
|
if (dbUser.length === 0) {
|
||||||
logger.info(`User not found (${targetEmail})`);
|
logger.info(`\n\n> User not found (${targetEmail})\n`);
|
||||||
return {
|
return {
|
||||||
error: ErrorType.NotFound,
|
error: ErrorType.NotFound,
|
||||||
message: "The user was not fund.",
|
message: "The user was not fund.",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return dbUser;
|
if (dbUser.length === 1 && dbUser[0]) return dbUser[0];
|
||||||
|
return {
|
||||||
|
error: ErrorType.ServiceError,
|
||||||
|
message: "To many user found, suspicious.",
|
||||||
|
};
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error(err);
|
logger.error(err);
|
||||||
return {
|
return {
|
||||||
@@ -54,21 +58,26 @@ async function getUserByEmail(targetEmail: string): Promise<IDbUser | ISError> {
|
|||||||
async function getUserFromIdService(id: string): Promise<IDbUser | ISError> {
|
async function getUserFromIdService(id: string): Promise<IDbUser | ISError> {
|
||||||
try {
|
try {
|
||||||
if (!id || id.length !== 36) {
|
if (!id || id.length !== 36) {
|
||||||
logger.info(`Invalid ID (${id})`);
|
logger.info(`\n\n> Invalid ID (${id})\n`);
|
||||||
return {
|
return {
|
||||||
error: ErrorType.InvalidData,
|
error: ErrorType.InvalidData,
|
||||||
message: "Invalid ID length.",
|
message: "Invalid ID length.",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
const dbUser = await MySqlService.User.getById(DbHandler, id);
|
const dbUser = await MySqlService.User.getById(DbHandler, id);
|
||||||
if (dbUser === undefined) {
|
if (dbUser.length === 0) {
|
||||||
logger.info(`User not found (${id})`);
|
logger.info(`User not found (${id})`);
|
||||||
return {
|
return {
|
||||||
error: ErrorType.NotFound,
|
error: ErrorType.NotFound,
|
||||||
message: "The user was not found.",
|
message: "The user was not found.",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return dbUser;
|
const firstUser = dbUser[0];
|
||||||
|
if (firstUser) return firstUser;
|
||||||
|
return {
|
||||||
|
error: ErrorType.ServiceError,
|
||||||
|
message: "No user found.",
|
||||||
|
};
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return {
|
return {
|
||||||
error: ErrorType.DatabaseError,
|
error: ErrorType.DatabaseError,
|
||||||
@@ -77,181 +86,237 @@ async function getUserFromIdService(id: string): Promise<IDbUser | ISError> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function register(ReqData: IReqRegister): Promise<ISError | string> {
|
/*
|
||||||
if (ReqData.password.length < 6) {
|
DbHandler.factorize({
|
||||||
|
values: {
|
||||||
|
id: '011010101',
|
||||||
|
username: 'avnyr',
|
||||||
|
age: 42,
|
||||||
|
is_admin: true
|
||||||
|
},
|
||||||
|
actionName: "Testing"
|
||||||
|
}).then((result)=>{
|
||||||
|
logger.trace(`\n\n> ${result._valuesArray.join(', ')}\n\n> ${result.totalFields}\n\n> ${result._keysTemplate}\n`)
|
||||||
|
})*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a new user.
|
||||||
|
*
|
||||||
|
* @param {IReqRegister} inputData - The input data for registration.
|
||||||
|
* @return {Promise<ISError | string>} - A Promise that resolves to either an error or a token.
|
||||||
|
*/
|
||||||
|
async function register(inputData: IReqRegister): Promise<ISError | string> {
|
||||||
|
try {
|
||||||
|
if (inputData.password.length < 6) {
|
||||||
|
return {
|
||||||
|
error: ErrorType.InvalidData,
|
||||||
|
message: "Password must be at least 6 characters long.",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const passwordHash = await CredentialService.hash(`${inputData.password}`);
|
||||||
|
|
||||||
|
// Does the new user has accepted GDPR ?
|
||||||
|
if (inputData.gdpr !== true) {
|
||||||
|
return {
|
||||||
|
error: ErrorType.InvalidData,
|
||||||
|
message: "GDPR acceptance is required.",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const currentDate = new Date();
|
||||||
|
|
||||||
|
// Check if exist and return
|
||||||
|
const dbUserIfExist: IDbUser | ISError = await getUserByEmail(
|
||||||
|
inputData.email,
|
||||||
|
);
|
||||||
|
if ("username" in dbUserIfExist) {
|
||||||
|
logger.info(
|
||||||
|
`\n\n> User already exist for email "${inputData.email}".\n(${dbUserIfExist.username}::${dbUserIfExist.id})\n`,
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
error: ErrorType.UnAuthorized,
|
||||||
|
message: "User already exists.",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const currentId = v4();
|
||||||
|
logger.info(`\n\n> Trying to insert a new user... (${currentId})\n`);
|
||||||
|
const NewUser = await MySqlService.User.insert(DbHandler, {
|
||||||
|
id: currentId,
|
||||||
|
email: inputData.email,
|
||||||
|
username: inputData.username,
|
||||||
|
firstname: inputData.firstName,
|
||||||
|
lastname: inputData.lastName,
|
||||||
|
dob: new Date(),
|
||||||
|
hash: passwordHash,
|
||||||
|
gdpr: currentDate,
|
||||||
|
is_admin: false,
|
||||||
|
is_email_verified: false,
|
||||||
|
});
|
||||||
|
if ("error" in NewUser && NewUser.affectedRows === 0) {
|
||||||
|
return {
|
||||||
|
error: ErrorType.DatabaseError,
|
||||||
|
message: "Error when inserting user in database.",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
logger.info(
|
||||||
|
`\n\n> New user created ! (${inputData.username}::${currentId})\n`,
|
||||||
|
);
|
||||||
|
|
||||||
|
// JWT
|
||||||
|
return await JwtService.sign(
|
||||||
|
{
|
||||||
|
sub: currentId,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alg: "HS512",
|
||||||
|
},
|
||||||
|
"1d",
|
||||||
|
"user",
|
||||||
|
);
|
||||||
|
} catch (err) {
|
||||||
|
logger.error(`\n\n${err}\n`);
|
||||||
return {
|
return {
|
||||||
error: ErrorType.InvalidData,
|
error: ErrorType.DatabaseError,
|
||||||
message: "Password must be at least 6 characters long.",
|
message: "An unknown error occurred.",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
const passwordHash = await CredentialService.hash(`${ReqData.password}`);
|
|
||||||
|
|
||||||
// Does the new user has accepted GDPR ?
|
|
||||||
if (ReqData.gdpr !== true) {
|
|
||||||
return {
|
|
||||||
error: ErrorType.InvalidData,
|
|
||||||
message: "GDPR acceptance is required.",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
const currentDate = new Date();
|
|
||||||
|
|
||||||
// Check if exist and return
|
|
||||||
const dbUserIfExist: IDbUser | ISError = await getUserByEmail(ReqData.email);
|
|
||||||
if ("error" in dbUserIfExist) {
|
|
||||||
return {
|
|
||||||
error: dbUserIfExist.error,
|
|
||||||
message: dbUserIfExist.message,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const NewUser = await MySqlService.User.insert(DbHandler, {
|
|
||||||
id: v4(),
|
|
||||||
email: ReqData.email,
|
|
||||||
username: ReqData.username,
|
|
||||||
firstname: ReqData.firstName,
|
|
||||||
lastname: ReqData.lastName,
|
|
||||||
dob: ReqData.dob,
|
|
||||||
hash: passwordHash,
|
|
||||||
gdpr: currentDate,
|
|
||||||
is_admin: false,
|
|
||||||
is_mail_verified: false,
|
|
||||||
});
|
|
||||||
if ("error" in NewUser || !NewUser.id) {
|
|
||||||
return {
|
|
||||||
error: ErrorType.DatabaseError,
|
|
||||||
message: 'Error when inserting user in database.'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// JWT
|
|
||||||
const token = await JwtService.sign(
|
|
||||||
{
|
|
||||||
sub: NewUser.id,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
alg: "HS512",
|
|
||||||
},
|
|
||||||
"1d",
|
|
||||||
"user",
|
|
||||||
);
|
|
||||||
return token;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function login(ReqData: IReqLogin) {
|
/**
|
||||||
//const passwordHash = await getHashFromPassword(sanitizedData.password);
|
* Logs in a user with the provided input data.
|
||||||
const dbUser = await MysqlService.User.getByUsername(
|
*
|
||||||
DbHandler,
|
* @param inputData - The input data for the login operation.
|
||||||
ReqData.username,
|
* @property email - The email of the user.
|
||||||
);
|
* @property password - The password of the user.
|
||||||
if (!dbUser) {
|
* @returns A promise that resolves to either an error or a token string.
|
||||||
console.log(`LoginService :> User does not exist (${ReqData.username})`);
|
* @throws {ISError} - If an error occurs in the login process.
|
||||||
|
* @throws {string} - If the login was successful, returns a token string.
|
||||||
|
*/
|
||||||
|
async function login(inputData: IReqLogin): Promise<ISError | string> {
|
||||||
|
try {
|
||||||
|
const dbUser = await getUserByEmail(inputData.email);
|
||||||
|
if ("error" in dbUser) {
|
||||||
|
return {
|
||||||
|
error: dbUser.error,
|
||||||
|
message: dbUser.message,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (!dbUser?.id) {
|
||||||
|
return {
|
||||||
|
error: ErrorType.NotFound,
|
||||||
|
message: "User not found.",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const isPasswordValid = await CredentialService.compare(
|
||||||
|
inputData.password,
|
||||||
|
dbUser.hash,
|
||||||
|
);
|
||||||
|
if (!isPasswordValid) {
|
||||||
|
return {
|
||||||
|
error: ErrorType.UnAuthorized,
|
||||||
|
message: "Invalid password.",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// Generate the JSDoc definition for those html status code
|
||||||
|
const token = await JwtService.sign(
|
||||||
|
{
|
||||||
|
sub: dbUser.id,
|
||||||
|
p: [
|
||||||
|
{
|
||||||
|
isAdmin: dbUser.is_admin,
|
||||||
|
gdpr: dbUser.gdpr,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alg: "HS512",
|
||||||
|
},
|
||||||
|
"1d",
|
||||||
|
"user",
|
||||||
|
);
|
||||||
|
if (isDebugMode())
|
||||||
|
logger.trace(
|
||||||
|
`\n\n> New token for login of "${dbUser.username}".\n${token}`,
|
||||||
|
);
|
||||||
|
return token;
|
||||||
|
} catch (err) {
|
||||||
|
logger.error(`\n\n${err}\n`);
|
||||||
return {
|
return {
|
||||||
error: "userNotFound",
|
error: ErrorType.DatabaseError,
|
||||||
|
message: "An unknown error occurred.",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (ReqData.password.length < 6) {
|
|
||||||
console.log("X");
|
|
||||||
console.log(`LoginService :> Invalid password (${ReqData.username})`);
|
|
||||||
return {
|
|
||||||
error: "invalidPassword",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
const isPasswordValid = await CredentialService.compare(
|
|
||||||
ReqData.password,
|
|
||||||
dbUser.hash,
|
|
||||||
);
|
|
||||||
if (!isPasswordValid) {
|
|
||||||
console.log(isPasswordValid);
|
|
||||||
console.log(`LoginService :> Invalid password (${ReqData.username})`);
|
|
||||||
return {
|
|
||||||
error: "invalidPassword",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
// biome-ignore lint/style/useConst: <explanation>
|
|
||||||
let userData = {
|
|
||||||
error: "none",
|
|
||||||
jwt: "",
|
|
||||||
user: {
|
|
||||||
id: dbUser.id,
|
|
||||||
username: dbUser.username,
|
|
||||||
displayName: dbUser.displayName,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
userData.jwt = await JwtService.sign(
|
|
||||||
{
|
|
||||||
sub: dbUser.id,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
alg: "HS512",
|
|
||||||
},
|
|
||||||
"7d",
|
|
||||||
"user",
|
|
||||||
);
|
|
||||||
|
|
||||||
console.log("USERDATA :>");
|
|
||||||
console.log(userData);
|
|
||||||
return userData;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a user from the database by email.
|
||||||
|
*
|
||||||
|
* @param {string} email - The email associated with the user.
|
||||||
|
* @return {Promise<IDbUser | false>} - A Promise that resolves to the user (if found) or false (if not found).
|
||||||
|
*/
|
||||||
|
async function getByEmailService(email: string): Promise<IDbUser | false> {
|
||||||
|
const dbUser = await MySqlService.User.getByEmail(DbHandler, email);
|
||||||
|
if (dbUser.length === 0) {
|
||||||
|
if (isDebugMode()) logger.trace(`\n\n> User not found in DB (${email})\n`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (isDebugMode()) logger.trace(dbUser);
|
||||||
|
if (dbUser.length > 1 && dbUser[0]) return dbUser[0];
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TOTest
|
||||||
/**
|
/**
|
||||||
* Retrieves all users from the database.
|
* Retrieves all users from the database.
|
||||||
*
|
*
|
||||||
* @async
|
* @returns {Promise<Array<IDbUser> | ISError>} The list of users, or an error object if an error occurred.
|
||||||
* @function getAllUsersService
|
|
||||||
* @returns {Promise<{iat: number, users: Array<user>, length: number}>} - The response object containing the users array and its length.
|
|
||||||
*/
|
*/
|
||||||
async function getAllUsersService() {
|
async function getAllUsersService(): Promise<Array<IDbUser> | ISError> {
|
||||||
const users = await Db.collection("users").find().toArray();
|
try {
|
||||||
// biome-ignore lint/complexity/noForEach: <explanation>
|
const allUsers = await MySqlService.User.getAll(DbHandler);
|
||||||
users.forEach((user) => {
|
if (allUsers === undefined) {
|
||||||
delete user.passwordHash;
|
logger.error(`Error retrieving all users.`);
|
||||||
delete user._id;
|
return {
|
||||||
delete user.gdpr;
|
error: ErrorType.DatabaseError,
|
||||||
});
|
message: "An unknown error occurred.",
|
||||||
logger.info(`Query ${users.length} user(s)`);
|
};
|
||||||
return {
|
}
|
||||||
iat: Date.now(),
|
return allUsers;
|
||||||
users: users,
|
} catch (err) {
|
||||||
length: users.length,
|
logger.error(`\n\n${err}\n`);
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Edits a user in the database.
|
|
||||||
*
|
|
||||||
* @param {string} targetId - The ID of the user to be edited.
|
|
||||||
* @param {object} sanitizedData - The sanitized data to update the user with.
|
|
||||||
* @returns {object} - An object indicating the result of the operation.
|
|
||||||
* If the user is not found, the error property will be a string "userNotFound".
|
|
||||||
* Otherwise, the error property will be a string "none".
|
|
||||||
*/
|
|
||||||
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 updatedUserResult = await Db.collection("users").updateOne(
|
|
||||||
{
|
|
||||||
id: targetId,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
$set: sanitizedData,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
if (updatedUserResult.modifiedCount === 0) {
|
|
||||||
logger.info(`EDIT :> User not found (${targetId})`);
|
|
||||||
return {
|
return {
|
||||||
error: "userNotFound",
|
error: ErrorType.DatabaseError,
|
||||||
|
message: "An unknown error occurred.",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
logger.info(`EDIT :> User updated (${targetId})`);
|
async function editUserService(
|
||||||
return {
|
targetId: string,
|
||||||
error: "none",
|
inputData: IUserUpdate,
|
||||||
};
|
): Promise<ISError | boolean> {
|
||||||
|
if (!targetId || targetId.length !== 36) {
|
||||||
|
logger.info(`\n\n> Invalid ID (${targetId})\n`);
|
||||||
|
return {
|
||||||
|
error: ErrorType.InvalidData,
|
||||||
|
message: "Invalid ID length.",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const dbUser = await MySqlService.User.getById(DbHandler, targetId);
|
||||||
|
if (!dbUser[0] || !dbUser[0].id) {
|
||||||
|
return {
|
||||||
|
error: ErrorType.NotFound,
|
||||||
|
message: "User not found.",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const result = await MySqlService.User.update(DbHandler, inputData);
|
||||||
|
if (result.affectedRows === 0) {
|
||||||
|
return {
|
||||||
|
error: ErrorType.DatabaseError,
|
||||||
|
message: "An unknown error occurred.",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -260,24 +325,25 @@ async function editUserService(targetId, sanitizedData) {
|
|||||||
* @param {string} targetId - The ID of the user to be deleted.
|
* @param {string} targetId - The ID of the user to be deleted.
|
||||||
* @return {Promise<boolean>} - A promise that resolves to true if the user is successfully deleted, or false if an error occurs.
|
* @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) {
|
async function deleteUserService(targetId: string): Promise<boolean> {
|
||||||
logger.info(`Deleting user ${targetId}`);
|
logger.info(`Deleting user ${targetId}`);
|
||||||
try {
|
try {
|
||||||
await Db.collection("users").deleteOne({
|
const DeleteResult = await MySqlService.User.delete(DbHandler, targetId);
|
||||||
id: targetId,
|
return DeleteResult.affectedRows !== 0;
|
||||||
});
|
|
||||||
return true;
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.warn(e);
|
logger.warn(e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isDebugMode()) logger.debug("\nService loaded.");
|
||||||
|
|
||||||
const UserService = {
|
const UserService = {
|
||||||
register: register,
|
register: register,
|
||||||
login: login,
|
login: login,
|
||||||
getAll: getAllUsersService,
|
getAll: getAllUsersService,
|
||||||
getFromId: getUserFromIdService,
|
getFromId: getUserFromIdService,
|
||||||
|
getByEmail: getByEmailService,
|
||||||
edit: editUserService,
|
edit: editUserService,
|
||||||
delete: deleteUserService,
|
delete: deleteUserService,
|
||||||
};
|
};
|
||||||
|
|||||||
125
src/services/vehicle.service.ts
Normal file
125
src/services/vehicle.service.ts
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
import type { IDbVehicle } from "@interfaces/database/IDbVehicle";
|
||||||
|
//import { ErrorType, type ISError } from "@interfaces/services/ISError";
|
||||||
|
import MySqlService from "@services/mysql.service";
|
||||||
|
import { isDebugMode } from "@utils/debugState";
|
||||||
|
import { Logger } from "tslog";
|
||||||
|
import { v4 } from "uuid";
|
||||||
|
|
||||||
|
const logger = new Logger({
|
||||||
|
name: "VehicleService",
|
||||||
|
});
|
||||||
|
|
||||||
|
const DbHandler = new MySqlService.Handler("VehicleService");
|
||||||
|
|
||||||
|
async function createVehicleService(data: IDbVehicle) {
|
||||||
|
if (isDebugMode()) logger.debug(`\n\n> Creating a new vehicle...\n`);
|
||||||
|
try {
|
||||||
|
const result = await MySqlService.Vehicle.insert(DbHandler, {
|
||||||
|
id: v4(),
|
||||||
|
plate_number: data.plate_number,
|
||||||
|
model_id: data.model_id,
|
||||||
|
odometer: data.odometer | 0,
|
||||||
|
health_state: data.health_state,
|
||||||
|
});
|
||||||
|
if (result.affectedRows !== 0) {
|
||||||
|
logger.info("\n\n> Success !");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(`\n\n> Error creating category: \n${error}\n`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateVehicleService(data: IDbVehicle) {
|
||||||
|
if (isDebugMode()) logger.debug(`\n\n> Updating vehicle...\n`);
|
||||||
|
try {
|
||||||
|
if (!data.id) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const result = await MySqlService.Vehicle.update(DbHandler, {
|
||||||
|
id: data.id,
|
||||||
|
plate_number: data.plate_number,
|
||||||
|
model_id: data.model_id,
|
||||||
|
odometer: data.odometer | 0,
|
||||||
|
health_state: data.health_state,
|
||||||
|
});
|
||||||
|
if (result.affectedRows !== 0) {
|
||||||
|
logger.info("\n\n> Success !");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(`\n\n> Error updating vehicle: \n${error}\n`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getAllVehiclesService() {
|
||||||
|
try {
|
||||||
|
const result = await MySqlService.Vehicle.getAll(DbHandler);
|
||||||
|
return {
|
||||||
|
iat: Date.now(),
|
||||||
|
vehicles: result,
|
||||||
|
total: result.length,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(`\n\n> Error getting vehicles: \n${error}\n`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getVehicleByIdService(vehicleId: string) {
|
||||||
|
try {
|
||||||
|
const result = await MySqlService.Vehicle.getById(DbHandler, vehicleId);
|
||||||
|
return {
|
||||||
|
iat: Date.now(),
|
||||||
|
vehicle: result,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(`\n\n> Error getting vehicle by id: \n${error}\n`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getAvailableVehicleService() {
|
||||||
|
try {
|
||||||
|
const result = await MySqlService.Vehicle.getAvailable(DbHandler);
|
||||||
|
return {
|
||||||
|
iat: Date.now(),
|
||||||
|
vehicles: result,
|
||||||
|
total: result.length,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(`\n\n> Error getting available vehicles: \n${error}\n`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function deleteVehicleService(vehicleId: string) {
|
||||||
|
try {
|
||||||
|
const result = await MySqlService.Vehicle.delete(DbHandler, vehicleId);
|
||||||
|
if (result.affectedRows !== 0) {
|
||||||
|
logger.info("\n\n> Success !");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(`\n\n> Error deleting vehicle: \n${error}\n`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isDebugMode()) logger.debug("\nService loaded.");
|
||||||
|
|
||||||
|
const VehicleService = {
|
||||||
|
create: createVehicleService,
|
||||||
|
update: updateVehicleService,
|
||||||
|
getAll: getAllVehiclesService,
|
||||||
|
getById: getVehicleByIdService,
|
||||||
|
delete: deleteVehicleService,
|
||||||
|
getAvailable: getAvailableVehicleService,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default VehicleService;
|
||||||
8
src/utils/debugState.ts
Normal file
8
src/utils/debugState.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import process from "node:process";
|
||||||
|
|
||||||
|
export function isDebugMode() {
|
||||||
|
if (process.env["DEBUG"] === "true") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
5
src/utils/validators/email.ts
Normal file
5
src/utils/validators/email.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
export function isEmail(email: string) {
|
||||||
|
const re =
|
||||||
|
/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
||||||
|
return re.test(String(email).toLowerCase());
|
||||||
|
}
|
||||||
@@ -33,7 +33,7 @@ async function AdminGuard(req: Request, res: Response, next: NextFunction) {
|
|||||||
|
|
||||||
const token = await JwtService.verify(bearerToken);
|
const token = await JwtService.verify(bearerToken);
|
||||||
|
|
||||||
if (token) {
|
if (token && token.sub) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const isSourceAdmin = await MysqlService.User.getAdminStateForId(
|
const isSourceAdmin = await MysqlService.User.getAdminStateForId(
|
||||||
DbHandler,
|
DbHandler,
|
||||||
|
|||||||
@@ -1,10 +1,22 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "es2017",
|
"module": "commonjs",
|
||||||
"module": "es6",
|
"declaration": true,
|
||||||
"rootDir": "./src",
|
"removeComments": true,
|
||||||
"moduleResolution": "node",
|
"emitDecoratorMetadata": true,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"target": "ES2021",
|
||||||
|
"sourceMap": true,
|
||||||
|
"outDir": "./dist",
|
||||||
"baseUrl": "./",
|
"baseUrl": "./",
|
||||||
|
"incremental": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"strictNullChecks": true,
|
||||||
|
"noImplicitAny": true,
|
||||||
|
"strictBindCallApply": true,
|
||||||
|
"forceConsistentCasingInFileNames": false,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
"paths": {
|
"paths": {
|
||||||
"@services/*": [
|
"@services/*": [
|
||||||
"src/services/*"
|
"src/services/*"
|
||||||
@@ -26,19 +38,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"declaration": true,
|
|
||||||
"declarationMap": true,
|
"declarationMap": true,
|
||||||
"sourceMap": true,
|
|
||||||
"outDir": "./dist",
|
|
||||||
"removeComments": false,
|
|
||||||
"noEmitOnError": true,
|
"noEmitOnError": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"forceConsistentCasingInFileNames": true,
|
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"noImplicitAny": true,
|
|
||||||
"strictNullChecks": true,
|
|
||||||
"strictFunctionTypes": true,
|
"strictFunctionTypes": true,
|
||||||
"strictBindCallApply": true,
|
|
||||||
"strictPropertyInitialization": true,
|
"strictPropertyInitialization": true,
|
||||||
"noImplicitThis": true,
|
"noImplicitThis": true,
|
||||||
"useUnknownInCatchVariables": true,
|
"useUnknownInCatchVariables": true,
|
||||||
@@ -47,12 +51,10 @@
|
|||||||
"noUnusedParameters": true,
|
"noUnusedParameters": true,
|
||||||
"exactOptionalPropertyTypes": true,
|
"exactOptionalPropertyTypes": true,
|
||||||
"noImplicitReturns": true,
|
"noImplicitReturns": true,
|
||||||
"noFallthroughCasesInSwitch": true,
|
|
||||||
"noUncheckedIndexedAccess": true,
|
"noUncheckedIndexedAccess": true,
|
||||||
"noImplicitOverride": true,
|
"noImplicitOverride": true,
|
||||||
"noPropertyAccessFromIndexSignature": true,
|
"noPropertyAccessFromIndexSignature": true,
|
||||||
"allowUnusedLabels": true,
|
"allowUnusedLabels": true,
|
||||||
"allowUnreachableCode": true,
|
"allowUnreachableCode": true
|
||||||
"skipLibCheck": true
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user