From 59f1fe275839c569327347c0694794d7d3ae19d0 Mon Sep 17 00:00:00 2001 From: OxSaitama Date: Thu, 13 Jul 2023 13:31:15 +0200 Subject: [PATCH 01/49] add vote service --- package.json | 2 +- .../api/super-admin/AppointmentsController.ts | 103 ++++++++++++ src/app/api/super-admin/UsersController.ts | 8 +- src/app/api/super-admin/VotesController.ts | 147 ++++++++++++++++++ src/app/index.ts | 4 + .../20230713145026_v12/migration.sql | 38 +++++ .../20230725084826_v12/migration.sql | 45 ++++++ .../20230725151748_v13/migration.sql | 11 ++ src/common/databases/schema.prisma | 33 ++++ .../repositories/AppointmentsRepository.ts | 95 +++++++++++ src/common/repositories/UsersRepository.ts | 12 ++ src/common/repositories/VotesRepository.ts | 71 +++++++++ .../AppointmentsService.ts | 67 ++++++++ .../super-admin/UsersService/UsersService.ts | 8 + .../super-admin/VotesService/VotesService.ts | 73 +++++++++ 15 files changed, 714 insertions(+), 3 deletions(-) create mode 100644 src/app/api/super-admin/AppointmentsController.ts create mode 100644 src/app/api/super-admin/VotesController.ts create mode 100644 src/common/databases/migrations/20230713145026_v12/migration.sql create mode 100644 src/common/databases/migrations/20230725084826_v12/migration.sql create mode 100644 src/common/databases/migrations/20230725151748_v13/migration.sql create mode 100644 src/common/repositories/AppointmentsRepository.ts create mode 100644 src/common/repositories/VotesRepository.ts create mode 100644 src/services/super-admin/AppointmentsService/AppointmentsService.ts create mode 100644 src/services/super-admin/VotesService/VotesService.ts diff --git a/package.json b/package.json index fe9c92be..7372ff24 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "cron": "^2.3.1", "express": "^4.18.2", "jsonwebtoken": "^9.0.0", - "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.63", + "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.64", "module-alias": "^2.2.2", "multer": "^1.4.5-lts.1", "next": "^13.1.5", diff --git a/src/app/api/super-admin/AppointmentsController.ts b/src/app/api/super-admin/AppointmentsController.ts new file mode 100644 index 00000000..936774c2 --- /dev/null +++ b/src/app/api/super-admin/AppointmentsController.ts @@ -0,0 +1,103 @@ +import { Response, Request } from "express"; +import { Controller, Get, Post } from "@ControllerPattern/index"; +import ApiController from "@Common/system/controller-pattern/ApiController"; +import AppointmentsService from "@Services/super-admin/AppointmentsService/AppointmentsService"; +import { Service } from "typedi"; +import { Appointment } from "le-coffre-resources/dist/SuperAdmin"; +import { validateOrReject } from "class-validator"; +import authHandler from "@App/middlewares/AuthHandler"; + +@Controller() +@Service() +export default class AppointmentsController extends ApiController { + constructor(private appointmentsService: AppointmentsService) { + super(); + } + + /** + * @description Get all appointments + */ + @Get("/api/v1/super-admin/appointments", [authHandler]) + protected async get(req: Request, response: Response) { + try { + //get query + let query; + if (req.query["q"]) { + query = JSON.parse(req.query["q"] as string); + } + + //call service to get prisma entity + const appointmentsEntities = await this.appointmentsService.get(query); + + //Hydrate ressource with prisma entity + const appointments = Appointment.hydrateArray(appointmentsEntities, { strategy: "excludeAll" }); + + //success + this.httpSuccess(response, appointments); + } catch (error) { + this.httpInternalError(response, error); + return; + } + } + + /** + * @description Create a new appointment + */ + @Post("/api/v1/super-admin/appointments", [authHandler]) + protected async post(req: Request, response: Response) { + try { + //init IUser resource with request body values + const appointmentEntity = Appointment.hydrate(req.body); + //validate user + await validateOrReject(appointmentEntity, { groups: ["createAppointment"]}); + + //call service to get prisma entity + const appointmentEntityCreated = await this.appointmentsService.create(appointmentEntity); + //Hydrate ressource with prisma entity + const appointment = Appointment.hydrate(appointmentEntityCreated, { + strategy: "excludeAll", + }); + + //success + this.httpCreated(response, appointment); + } catch (error) { + this.httpInternalError(response, error); + return; + } + } + + /** + * @description Get a specific appointment by uid + */ + @Get("/api/v1/super-admin/appointments/:uid", [authHandler]) + protected async getOneByUid(req: Request, response: Response) { + try { + const uid = req.params["uid"]; + if (!uid) { + this.httpBadRequest(response, "No uid provided"); + return; + } + + let query; + if (req.query["q"]) { + query = JSON.parse(req.query["q"] as string); + } + + const appointmentEntity = await this.appointmentsService.getByUid(uid, query); + + if (!appointmentEntity) { + this.httpNotFoundRequest(response, "appointment not found"); + return; + } + + //Hydrate ressource with prisma entity + const appointment = Appointment.hydrate(appointmentEntity, { strategy: "excludeAll" }); + + //success + this.httpSuccess(response, appointment); + } catch (error) { + this.httpInternalError(response, error); + return; + } + } +} diff --git a/src/app/api/super-admin/UsersController.ts b/src/app/api/super-admin/UsersController.ts index a96b3f5a..87d46cad 100644 --- a/src/app/api/super-admin/UsersController.ts +++ b/src/app/api/super-admin/UsersController.ts @@ -90,12 +90,13 @@ export default class UsersController extends ApiController { protected async put(req: Request, response: Response) { try { const uid = req.params["uid"]; + if (!uid) { this.httpBadRequest(response, "No uid provided"); return; } - const userFound = await this.usersService.getByUid(uid); + const userFound = await this.usersService.getByUid(uid, {role: true, votes: true}); if (!userFound) { this.httpNotFoundRequest(response, "user not found"); @@ -104,12 +105,15 @@ export default class UsersController extends ApiController { //init IUser resource with request body values const userEntity = User.hydrate(req.body); + const userFoundEntity = User.hydrate(userFound, { strategy: "excludeAll" }); //validate user await validateOrReject(userEntity, { groups: ["updateUser"] }); + const userEntityToUpdate = this.voteService.vote(userEntity, userFoundEntity, userId); + //call service to get prisma entity - const userEntityUpdated = await this.usersService.update(uid, userEntity); + const userEntityUpdated = await this.usersService.update(uid, userFoundEntity); //Hydrate ressource with prisma entity const user = User.hydrate(userEntityUpdated, { diff --git a/src/app/api/super-admin/VotesController.ts b/src/app/api/super-admin/VotesController.ts new file mode 100644 index 00000000..eac8b6a9 --- /dev/null +++ b/src/app/api/super-admin/VotesController.ts @@ -0,0 +1,147 @@ +import { Response, Request } from "express"; +import { Controller, Delete, Get, Post } from "@ControllerPattern/index"; +import ApiController from "@Common/system/controller-pattern/ApiController"; +import VotesService from "@Services/super-admin/VotesService/VotesService"; +import { Service } from "typedi"; +import { Vote } from "le-coffre-resources/dist/SuperAdmin"; +import { validateOrReject } from "class-validator"; +import authHandler from "@App/middlewares/AuthHandler"; +import UsersService from "@Services/super-admin/UsersService/UsersService"; +import { Votes } from "@prisma/client"; + +@Controller() +@Service() +export default class VotesController extends ApiController { + constructor(private votesService: VotesService, private usersService: UsersService) { + super(); + } + + /** + * @description Get all votes + */ + @Get("/api/v1/super-admin/votes", [authHandler]) + protected async get(req: Request, response: Response) { + try { + //get query + let query; + if (req.query["q"]) { + query = JSON.parse(req.query["q"] as string); + } + + //call service to get prisma entity + const votesEntities = await this.votesService.get(query); + + //Hydrate ressource with prisma entity + const votes = Vote.hydrateArray(votesEntities, { strategy: "excludeAll" }); + + //success + this.httpSuccess(response, votes); + } catch (error) { + this.httpInternalError(response, error); + return; + } + } + + /** + * @description Create a new vote + */ + @Post("/api/v1/super-admin/votes", [authHandler]) + protected async post(req: Request, response: Response) { + try { + const userId = req.body.user.userId; + //init IUser resource with request body values + const voteEntity = Vote.hydrate(req.body); + //validate user + await validateOrReject(voteEntity, { groups: ["createVote"]}); + + const votes = await this.votesService.get({ where: { AND: [{ appointment: {uid: voteEntity.uid } }, {voter: {uid: userId}}]}}); + console.log(votes) + if (votes.length) throw new Error("Voter already voted for this appointment"); + + const voter = await this.usersService.getByUid(userId); + + voteEntity.voter = voter!; + //call service to get prisma entity + const voteEntityCreated = await this.votesService.create(voteEntity); + //Hydrate ressource with prisma entity + const vote = Vote.hydrate(voteEntityCreated, { + strategy: "excludeAll", + }); + + //success + this.httpCreated(response, vote); + } catch (error) { + this.httpInternalError(response, error); + return; + } + } + + /** + * @description Get a specific vote by uid + */ + @Get("/api/v1/super-admin/votes/:uid", [authHandler]) + protected async getOneByUid(req: Request, response: Response) { + try { + const uid = req.params["uid"]; + if (!uid) { + this.httpBadRequest(response, "No uid provided"); + return; + } + + let query; + if (req.query["q"]) { + query = JSON.parse(req.query["q"] as string); + } + + const voteEntity = await this.votesService.getByUid(uid, query); + + if (!voteEntity) { + this.httpNotFoundRequest(response, "vote not found"); + return; + } + + //Hydrate ressource with prisma entity + const vote = Vote.hydrate(voteEntity, { strategy: "excludeAll" }); + + //success + this.httpSuccess(response, vote); + } catch (error) { + this.httpInternalError(response, error); + return; + } + } + + /** + * @description Delete a specific folder + */ + @Delete("/api/v1/super-admin/votes/:uid", [authHandler]) + protected async delete(req: Request, response: Response) { + try { + const uid = req.params["uid"]; + if (!uid) { + this.httpBadRequest(response, "No uid provided"); + return; + } + + const voteFound = await this.votesService.getByUid(uid); + + if (!voteFound) { + this.httpNotFoundRequest(response, "vote not found"); + return; + } + + //call service to get prisma entity + const votetEntity: Votes = await this.votesService.delete(uid); + + //Hydrate ressource with prisma entity + const vote = Vote.hydrate(votetEntity, { strategy: "excludeAll" }); + + //success + this.httpSuccess(response, vote); + } catch (error) { + this.httpInternalError(response, error); + return; + } + } + +} diff --git a/src/app/index.ts b/src/app/index.ts index 22f4d1f3..a4b4d9a2 100644 --- a/src/app/index.ts +++ b/src/app/index.ts @@ -40,6 +40,8 @@ import RolesControllerNotary from "./api/notary/RolesController"; import OfficeRolesControllerNotary from "./api/notary/OfficeRolesController"; import FilesControllerCustomer from "./api/customer/FilesController"; import DocumentsControllerCustomer from "./api/customer/DocumentsController"; +import AppointmentsController from "./api/super-admin/AppointmentsController"; +import VotesController from "./api/super-admin/VotesController"; /** @@ -56,6 +58,8 @@ export default { Container.get(DeedTypesControllerSuperAdmin); Container.get(DocumentsControllerSuperAdmin); Container.get(DocumentTypesControllerSuperAdmin); + Container.get(AppointmentsController); + Container.get(VotesController); Container.get(IdNotUserController); Container.get(FranceConnectCustomerController); Container.get(FilesControllerSuperAdmin); diff --git a/src/common/databases/migrations/20230713145026_v12/migration.sql b/src/common/databases/migrations/20230713145026_v12/migration.sql new file mode 100644 index 00000000..c5dac8d4 --- /dev/null +++ b/src/common/databases/migrations/20230713145026_v12/migration.sql @@ -0,0 +1,38 @@ +-- DropForeignKey +ALTER TABLE "users" DROP CONSTRAINT "users_contact_uid_fkey"; + +-- DropForeignKey +ALTER TABLE "users" DROP CONSTRAINT "users_office_role_uid_fkey"; + +-- DropForeignKey +ALTER TABLE "users" DROP CONSTRAINT "users_office_uid_fkey"; + +-- DropForeignKey +ALTER TABLE "users" DROP CONSTRAINT "users_roles_uid_fkey"; + +-- CreateTable +CREATE TABLE "votes" ( + "uid" TEXT NOT NULL, + "user_uid" VARCHAR(255) NOT NULL, + "voters" TEXT[], + + CONSTRAINT "votes_pkey" PRIMARY KEY ("uid") +); + +-- CreateIndex +CREATE UNIQUE INDEX "votes_uid_key" ON "votes"("uid"); + +-- AddForeignKey +ALTER TABLE "users" ADD CONSTRAINT "users_contact_uid_fkey" FOREIGN KEY ("contact_uid") REFERENCES "contacts"("uid") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "users" ADD CONSTRAINT "users_roles_uid_fkey" FOREIGN KEY ("roles_uid") REFERENCES "roles"("uid") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "users" ADD CONSTRAINT "users_office_role_uid_fkey" FOREIGN KEY ("office_role_uid") REFERENCES "office_roles"("uid") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "users" ADD CONSTRAINT "users_office_uid_fkey" FOREIGN KEY ("office_uid") REFERENCES "offices"("uid") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "votes" ADD CONSTRAINT "votes_user_uid_fkey" FOREIGN KEY ("user_uid") REFERENCES "users"("uid") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/src/common/databases/migrations/20230725084826_v12/migration.sql b/src/common/databases/migrations/20230725084826_v12/migration.sql new file mode 100644 index 00000000..0b7f1455 --- /dev/null +++ b/src/common/databases/migrations/20230725084826_v12/migration.sql @@ -0,0 +1,45 @@ +/* + Warnings: + + - You are about to drop the column `user_uid` on the `votes` table. All the data in the column will be lost. + - You are about to drop the column `voters` on the `votes` table. All the data in the column will be lost. + - Added the required column `appointment_uid` to the `votes` table without a default value. This is not possible if the table is not empty. + - Added the required column `voter_uid` to the `votes` table without a default value. This is not possible if the table is not empty. + +*/ +-- CreateEnum +CREATE TYPE "EVote" AS ENUM ('NOMINATE', 'DISMISS'); + +-- CreateEnum +CREATE TYPE "EAppointmentStatus" AS ENUM ('OPEN', 'CLOSED'); + +-- DropForeignKey +ALTER TABLE "votes" DROP CONSTRAINT "votes_user_uid_fkey"; + +-- AlterTable +ALTER TABLE "votes" DROP COLUMN "user_uid", +DROP COLUMN "voters", +ADD COLUMN "appointment_uid" VARCHAR(255) NOT NULL, +ADD COLUMN "choice" "EVote" NOT NULL DEFAULT 'NOMINATE', +ADD COLUMN "voter_uid" VARCHAR(255) NOT NULL; + +-- CreateTable +CREATE TABLE "appointments" ( + "uid" TEXT NOT NULL, + "user_uid" VARCHAR(255) NOT NULL, + "status" "EAppointmentStatus" NOT NULL DEFAULT 'OPEN', + + CONSTRAINT "appointments_pkey" PRIMARY KEY ("uid") +); + +-- CreateIndex +CREATE UNIQUE INDEX "appointments_uid_key" ON "appointments"("uid"); + +-- AddForeignKey +ALTER TABLE "appointments" ADD CONSTRAINT "appointments_user_uid_fkey" FOREIGN KEY ("user_uid") REFERENCES "users"("uid") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "votes" ADD CONSTRAINT "votes_appointment_uid_fkey" FOREIGN KEY ("appointment_uid") REFERENCES "appointments"("uid") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "votes" ADD CONSTRAINT "votes_voter_uid_fkey" FOREIGN KEY ("voter_uid") REFERENCES "users"("uid") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/src/common/databases/migrations/20230725151748_v13/migration.sql b/src/common/databases/migrations/20230725151748_v13/migration.sql new file mode 100644 index 00000000..b8c667d7 --- /dev/null +++ b/src/common/databases/migrations/20230725151748_v13/migration.sql @@ -0,0 +1,11 @@ +/* + Warnings: + + - You are about to drop the column `choice` on the `votes` table. All the data in the column will be lost. + +*/ +-- AlterTable +ALTER TABLE "appointments" ADD COLUMN "choice" "EVote" NOT NULL DEFAULT 'NOMINATE'; + +-- AlterTable +ALTER TABLE "votes" DROP COLUMN "choice"; diff --git a/src/common/databases/schema.prisma b/src/common/databases/schema.prisma index 53eae7d8..ae182a9d 100644 --- a/src/common/databases/schema.prisma +++ b/src/common/databases/schema.prisma @@ -65,6 +65,8 @@ model Users { office_uid String @db.VarChar(255) notifications Notifications[] @relation("UserHasNotifications") office_folders OfficeFolders[] @relation("OfficeFolderHasStakeholders") + appointment Appointments[] + votes Votes[] @@map("users") } @@ -287,6 +289,27 @@ model Emails { @@map("email") } +model Appointments { + uid String @id @unique @default(uuid()) + user Users @relation(fields: [user_uid], references: [uid], onDelete: Cascade) + user_uid String @db.VarChar(255) + choice EVote @default(NOMINATE) + status EAppointmentStatus @default(OPEN) + votes Votes[] + + @@map("appointments") +} + +model Votes { + uid String @id @unique @default(uuid()) + appointment Appointments @relation(fields: [appointment_uid], references: [uid], onDelete: Cascade) + appointment_uid String @db.VarChar(255) + voter Users @relation(fields: [voter_uid], references: [uid]) + voter_uid String @db.VarChar(255) + + @@map("votes") +} + enum ECivility { MALE FEMALE @@ -321,3 +344,13 @@ enum EDocumentStatus { ANCHORED REFUSED } + +enum EVote { + NOMINATE + DISMISS +} + +enum EAppointmentStatus { + OPEN + CLOSED +} diff --git a/src/common/repositories/AppointmentsRepository.ts b/src/common/repositories/AppointmentsRepository.ts new file mode 100644 index 00000000..9d5102bc --- /dev/null +++ b/src/common/repositories/AppointmentsRepository.ts @@ -0,0 +1,95 @@ +import Database from "@Common/databases/database"; +import BaseRepository from "@Repositories/BaseRepository"; +import { Service } from "typedi"; +import { Appointments, EAppointmentStatus, EVote, Prisma } from "@prisma/client"; +import { Appointment } from "le-coffre-resources/dist/SuperAdmin"; + +@Service() +export default class AppointmentsRepository extends BaseRepository { + constructor(private database: Database) { + super(); + } + protected get model() { + return this.database.getClient().appointments; + } + protected get instanceDb() { + return this.database.getClient(); + } + + /** + * @description : Find many appointments + */ + public async findMany(query: Prisma.AppointmentsFindManyArgs) { + query.take = Math.min(query.take || this.defaultFetchRows, this.maxFetchRows); + return this.model.findMany(query); + } + + /** + * @description : Create new appointment + */ + public async create(appointment: Appointment): Promise { + const createArgs: Prisma.AppointmentsCreateArgs = { + data: { + user: { + connect: { + uid: appointment.targeted_user!.uid, + }, + }, + choice: EVote[appointment.choice as keyof typeof EVote], + }, + }; + + return this.model.create(createArgs); + } + + /** + * @description : Update data of a appointment + */ + public async update(uid: string, status: EAppointmentStatus): Promise { + const updateArgs: Prisma.AppointmentsUpdateArgs = { + where: { + uid: uid, + }, + data: { + status: status, + }, + }; + + return this.model.update(updateArgs); + } + + /** + * @description : Find one appointment + */ + public async findOneByUid(uid: string, query?: Prisma.AppointmentsInclude) { + return this.model.findUnique({ + where: { + uid: uid, + }, + include: query, + }); + } + + /** + * @description : Find one appointment with votes + */ + public async findOneByUidWithVotes(uid: string) { + return this.model.findUnique({ + where: { + uid: uid, + }, + include: {votes: true}, + }); + } + + /** + * @description : delete a appointment + */ + public async delete(uid: string): Promise { + return this.model.delete({ + where: { + uid: uid, + }, + }); + } +} diff --git a/src/common/repositories/UsersRepository.ts b/src/common/repositories/UsersRepository.ts index b472a8ec..8545627c 100644 --- a/src/common/repositories/UsersRepository.ts +++ b/src/common/repositories/UsersRepository.ts @@ -196,6 +196,18 @@ export default class UsersRepository extends BaseRepository { }); } + /** + * @description : Find one user with office + */ + public async findOneByUidWithRole(uid: string) { + return this.model.findUnique({ + where: { + uid: uid, + }, + include: { role: true }, + }); + } + /** * @description : Find one user */ diff --git a/src/common/repositories/VotesRepository.ts b/src/common/repositories/VotesRepository.ts new file mode 100644 index 00000000..2283ca94 --- /dev/null +++ b/src/common/repositories/VotesRepository.ts @@ -0,0 +1,71 @@ +import Database from "@Common/databases/database"; +import BaseRepository from "@Repositories/BaseRepository"; +import { Service } from "typedi"; +import { Votes, Prisma } from "@prisma/client"; +import { Vote } from "le-coffre-resources/dist/SuperAdmin"; + +@Service() +export default class VotesRepository extends BaseRepository { + constructor(private database: Database) { + super(); + } + protected get model() { + return this.database.getClient().votes; + } + protected get instanceDb() { + return this.database.getClient(); + } + + /** + * @description : Find many votes + */ + public async findMany(query: Prisma.VotesFindManyArgs) { + query.take = Math.min(query.take || this.defaultFetchRows, this.maxFetchRows); + return this.model.findMany(query); + } + + /** + * @description : Create new vote + */ + public async create(vote: Vote): Promise { + const createArgs: Prisma.VotesCreateArgs = { + data: { + appointment: { + connect: { + uid: vote.appointment.uid, + }, + }, + voter: { + connect: { + uid: vote.voter.uid, + }, + }, + }, + }; + + return this.model.create(createArgs); + } + + /** + * @description : Find one vote + */ + public async findOneByUid(uid: string, query?: Prisma.VotesInclude): Promise { + return this.model.findUnique({ + where: { + uid: uid, + }, + include: query, + }); + } + + /** + * @description : delete a vote + */ + public async delete(uid: string): Promise { + return this.model.delete({ + where: { + uid: uid, + }, + }); + } +} diff --git a/src/services/super-admin/AppointmentsService/AppointmentsService.ts b/src/services/super-admin/AppointmentsService/AppointmentsService.ts new file mode 100644 index 00000000..9a47953e --- /dev/null +++ b/src/services/super-admin/AppointmentsService/AppointmentsService.ts @@ -0,0 +1,67 @@ +import BaseService from "@Services/BaseService"; +import { Service } from "typedi"; +import { Appointment } from "le-coffre-resources/dist/SuperAdmin"; +import AppointmentsRepository from "@Repositories/AppointmentsRepository"; +import { Prisma, Appointments, EAppointmentStatus } from "@prisma/client"; +import UsersService from "../UsersService/UsersService"; +import { EVote } from "le-coffre-resources/dist/SuperAdmin/Appointment"; + +@Service() +export default class AppointmentService extends BaseService { + constructor(private appointmentRepository: AppointmentsRepository, private userService: UsersService) { + super(); + } + + /** + * @description : Get all appointments + * @throws {Error} If appointments cannot be get + */ + public get(query: Prisma.AppointmentsFindManyArgs) { + return this.appointmentRepository.findMany(query); + } + + /** + * @description : Create a appointment + * @throws {Error} If appointment couldn't be created + */ + public async create(appointment: Appointment): Promise { + const user = await this.userService.getByUidWithRole(appointment.targeted_user!.uid!) + if(!user) throw new Error("User not found"); + user.role.name === "super-admin" ? appointment.choice = EVote.DISMISS : appointment.choice = EVote.NOMINATE; + return this.appointmentRepository.create(appointment); + } + + /** + * @description : Modify a appointment + * @throws {Error} If appointment cannot be modified + */ + public async update(uid: string, status: EAppointmentStatus): Promise { + return this.appointmentRepository.update(uid, status); + } + + /** + * @description : Get a appointment by uid + * @throws {Error} If appointment cannot be get by uid + */ + public getByUid(uid: string, query?: Prisma.AppointmentsInclude): Promise { + return this.appointmentRepository.findOneByUid(uid, query); + } + + /** + * @description : Get a appointment by uid + * @throws {Error} If appointment cannot be get by uid + */ + public getByUidWithVotes(uid: string) { + return this.appointmentRepository.findOneByUidWithVotes(uid); + } + + /** + * @description : delete a appointment by uid + * @throws {Error} If appointment cannot be get by uid + */ + public delete(uid: string) { + return this.appointmentRepository.delete(uid); + } + + +} diff --git a/src/services/super-admin/UsersService/UsersService.ts b/src/services/super-admin/UsersService/UsersService.ts index da350fea..241cb1e4 100644 --- a/src/services/super-admin/UsersService/UsersService.ts +++ b/src/services/super-admin/UsersService/UsersService.ts @@ -51,6 +51,14 @@ export default class UsersService extends BaseService { return this.userRepository.findOneByUidWithOffice(uid); } + /** + * @description : Get a user by uid with role + * @throws {Error} If user cannot be get by uid + */ + public getByUidWithRole(uid: string) { + return this.userRepository.findOneByUidWithRole(uid); + } + /** * @description : Get a user by uid * @throws {Error} If user cannot be get by uid diff --git a/src/services/super-admin/VotesService/VotesService.ts b/src/services/super-admin/VotesService/VotesService.ts new file mode 100644 index 00000000..bdd95fe4 --- /dev/null +++ b/src/services/super-admin/VotesService/VotesService.ts @@ -0,0 +1,73 @@ +import BaseService from "@Services/BaseService"; +import { Service } from "typedi"; +import { Vote } from "le-coffre-resources/dist/SuperAdmin"; +import VotesRepository from "@Repositories/VotesRepository"; +import { EAppointmentStatus, EVote, Prisma, Votes } from "@prisma/client"; +import AppointmentService from "../AppointmentsService/AppointmentsService"; +import UsersService from "../UsersService/UsersService"; +import RolesService from "../RolesService/RolesService"; + +@Service() +export default class VoteService extends BaseService { + constructor( + private voteRepository: VotesRepository, + private appointmentService: AppointmentService, + private userService: UsersService, + private roleService: RolesService, + ) { + super(); + } + + /** + * @description : Get all votes + * @throws {Error} If votes cannot be get + */ + public get(query: Prisma.VotesFindManyArgs) { + return this.voteRepository.findMany(query); + } + + /** + * @description : Create a vote + * @throws {Error} If vote couldn't be created + */ + public async create(vote: Vote): Promise { + const appointment = await this.appointmentService.getByUidWithVotes(vote.appointment.uid!); + if (!appointment) throw new Error("Appointment not found"); + if (appointment.status === EAppointmentStatus.CLOSED) throw new Error("Appointment is closed"); + + if (appointment.votes.length >= 2) { + const voteCreated = await this.voteRepository.create(vote); + await this.appointmentService.update(appointment.uid!, EAppointmentStatus.CLOSED); + const user = await this.userService.getByUid(appointment.user_uid); + + if (appointment.choice === EVote.DISMISS) { + const roles = await this.roleService.get({ where: { name: "default" } }); + user!.roles_uid = roles[0]!.uid; + await this.userService.update(appointment.user_uid, user!); + return voteCreated; + } else if (appointment.choice === EVote.NOMINATE) { + const roles = await this.roleService.get({ where: { name: "super-admin" } }); + user!.roles_uid = roles[0]!.uid; + await this.userService.update(appointment.user_uid, user!); + return voteCreated; + } + } + return this.voteRepository.create(vote); + } + + /** + * @description : Get a vote by uid + * @throws {Error} If vote cannot be get by uid + */ + public getByUid(uid: string, query?: Prisma.VotesInclude) { + return this.voteRepository.findOneByUid(uid, query); + } + + /** + * @description : delete a vote by uid + * @throws {Error} If vote cannot be get by uid + */ + public delete(uid: string) { + return this.voteRepository.delete(uid); + } +} From 0a675027ca03b749419dfa31e7a90a067e755bf0 Mon Sep 17 00:00:00 2001 From: OxSaitama Date: Tue, 25 Jul 2023 18:56:47 +0200 Subject: [PATCH 02/49] fix merge issue --- src/app/api/super-admin/UsersController.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/app/api/super-admin/UsersController.ts b/src/app/api/super-admin/UsersController.ts index 87d46cad..71d97022 100644 --- a/src/app/api/super-admin/UsersController.ts +++ b/src/app/api/super-admin/UsersController.ts @@ -109,8 +109,6 @@ export default class UsersController extends ApiController { //validate user await validateOrReject(userEntity, { groups: ["updateUser"] }); - - const userEntityToUpdate = this.voteService.vote(userEntity, userFoundEntity, userId); //call service to get prisma entity const userEntityUpdated = await this.usersService.update(uid, userFoundEntity); From e9f3fb7e9c475ae216ff4843e775640ad57b4bac Mon Sep 17 00:00:00 2001 From: OxSaitama Date: Wed, 26 Jul 2023 11:49:32 +0200 Subject: [PATCH 03/49] add error handling --- .../api/super-admin/AppointmentsController.ts | 9 ++++- src/app/api/super-admin/VotesController.ts | 35 +++++++++++++------ .../super-admin/VotesService/VotesService.ts | 25 ++++++------- 3 files changed, 46 insertions(+), 23 deletions(-) diff --git a/src/app/api/super-admin/AppointmentsController.ts b/src/app/api/super-admin/AppointmentsController.ts index 936774c2..fa143534 100644 --- a/src/app/api/super-admin/AppointmentsController.ts +++ b/src/app/api/super-admin/AppointmentsController.ts @@ -6,11 +6,12 @@ import { Service } from "typedi"; import { Appointment } from "le-coffre-resources/dist/SuperAdmin"; import { validateOrReject } from "class-validator"; import authHandler from "@App/middlewares/AuthHandler"; +import UsersService from "@Services/super-admin/UsersService/UsersService"; @Controller() @Service() export default class AppointmentsController extends ApiController { - constructor(private appointmentsService: AppointmentsService) { + constructor(private appointmentsService: AppointmentsService, private usersService: UsersService) { super(); } @@ -51,6 +52,12 @@ export default class AppointmentsController extends ApiController { //validate user await validateOrReject(appointmentEntity, { groups: ["createAppointment"]}); + const targetedUser = await this.usersService.getByUid(appointmentEntity.targeted_user.uid!); + if(!targetedUser) { + this.httpNotFoundRequest(response, "targeted user not found"); + return; + } + //call service to get prisma entity const appointmentEntityCreated = await this.appointmentsService.create(appointmentEntity); //Hydrate ressource with prisma entity diff --git a/src/app/api/super-admin/VotesController.ts b/src/app/api/super-admin/VotesController.ts index eac8b6a9..71057e82 100644 --- a/src/app/api/super-admin/VotesController.ts +++ b/src/app/api/super-admin/VotesController.ts @@ -7,12 +7,13 @@ import { Vote } from "le-coffre-resources/dist/SuperAdmin"; import { validateOrReject } from "class-validator"; import authHandler from "@App/middlewares/AuthHandler"; import UsersService from "@Services/super-admin/UsersService/UsersService"; -import { Votes } from "@prisma/client"; +import { EAppointmentStatus, Votes } from "@prisma/client"; +import AppointmentService from "@Services/super-admin/AppointmentsService/AppointmentsService"; @Controller() @Service() export default class VotesController extends ApiController { - constructor(private votesService: VotesService, private usersService: UsersService) { + constructor(private votesService: VotesService, private usersService: UsersService, private appointmentService: AppointmentService) { super(); } @@ -52,14 +53,29 @@ export default class VotesController extends ApiController { //init IUser resource with request body values const voteEntity = Vote.hydrate(req.body); //validate user - await validateOrReject(voteEntity, { groups: ["createVote"]}); + await validateOrReject(voteEntity, { groups: ["createVote"] }); + + const appointment = await this.appointmentService.getByUid(voteEntity.appointment.uid!); + if (!appointment) { + this.httpNotFoundRequest(response, "Appointment not found"); + return; + } + if (appointment.status === EAppointmentStatus.CLOSED) { + this.httpBadRequest(response, "Appointment is closed"); + return; + } + + const votes = await this.votesService.get({ + where: { AND: [{ appointment: { uid: voteEntity.appointment.uid } }, { voter: { uid: userId } }] }, + }); + console.log(votes); + if (votes.length) { + this.httpBadRequest(response, "Voter already voted for this appointment"); + return; + } - const votes = await this.votesService.get({ where: { AND: [{ appointment: {uid: voteEntity.uid } }, {voter: {uid: userId}}]}}); - console.log(votes) - if (votes.length) throw new Error("Voter already voted for this appointment"); - const voter = await this.usersService.getByUid(userId); - + voteEntity.voter = voter!; //call service to get prisma entity const voteEntityCreated = await this.votesService.create(voteEntity); @@ -92,7 +108,7 @@ export default class VotesController extends ApiController { if (req.query["q"]) { query = JSON.parse(req.query["q"] as string); } - + const voteEntity = await this.votesService.getByUid(uid, query); if (!voteEntity) { @@ -143,5 +159,4 @@ export default class VotesController extends ApiController { return; } } - } diff --git a/src/services/super-admin/VotesService/VotesService.ts b/src/services/super-admin/VotesService/VotesService.ts index bdd95fe4..663058ef 100644 --- a/src/services/super-admin/VotesService/VotesService.ts +++ b/src/services/super-admin/VotesService/VotesService.ts @@ -1,6 +1,6 @@ import BaseService from "@Services/BaseService"; import { Service } from "typedi"; -import { Vote } from "le-coffre-resources/dist/SuperAdmin"; +import User, { Role, Vote } from "le-coffre-resources/dist/SuperAdmin"; import VotesRepository from "@Repositories/VotesRepository"; import { EAppointmentStatus, EVote, Prisma, Votes } from "@prisma/client"; import AppointmentService from "../AppointmentsService/AppointmentsService"; @@ -32,23 +32,24 @@ export default class VoteService extends BaseService { */ public async create(vote: Vote): Promise { const appointment = await this.appointmentService.getByUidWithVotes(vote.appointment.uid!); - if (!appointment) throw new Error("Appointment not found"); - if (appointment.status === EAppointmentStatus.CLOSED) throw new Error("Appointment is closed"); - if (appointment.votes.length >= 2) { + if (appointment!.votes.length >= 2) { const voteCreated = await this.voteRepository.create(vote); - await this.appointmentService.update(appointment.uid!, EAppointmentStatus.CLOSED); - const user = await this.userService.getByUid(appointment.user_uid); + await this.appointmentService.update(appointment!.uid!, EAppointmentStatus.CLOSED); + const user = await this.userService.getByUid(appointment!.user_uid, { role: true }); + const userEntity = User.hydrate(user!, { strategy: "excludeAll" }); - if (appointment.choice === EVote.DISMISS) { + if (appointment!.choice === EVote.DISMISS) { const roles = await this.roleService.get({ where: { name: "default" } }); - user!.roles_uid = roles[0]!.uid; - await this.userService.update(appointment.user_uid, user!); + const roleEntity = Role.hydrate(roles[0]!, { strategy: "excludeAll" }); + userEntity.role = roleEntity; + await this.userService.update(appointment!.user_uid, userEntity); return voteCreated; - } else if (appointment.choice === EVote.NOMINATE) { + } else if (appointment!.choice === EVote.NOMINATE) { const roles = await this.roleService.get({ where: { name: "super-admin" } }); - user!.roles_uid = roles[0]!.uid; - await this.userService.update(appointment.user_uid, user!); + const roleEntity = Role.hydrate(roles[0]!, { strategy: "excludeAll" }); + userEntity!.role = roleEntity; + await this.userService.update(appointment!.user_uid, userEntity); return voteCreated; } } From d244158c4ec31a3bae9ea6b10dbf7ff60a3b5683 Mon Sep 17 00:00:00 2001 From: OxSaitama Date: Wed, 26 Jul 2023 11:53:20 +0200 Subject: [PATCH 04/49] add unique constraint on appointments --- .../databases/migrations/20230726095252_v25/migration.sql | 8 ++++++++ src/common/databases/schema.prisma | 1 + 2 files changed, 9 insertions(+) create mode 100644 src/common/databases/migrations/20230726095252_v25/migration.sql diff --git a/src/common/databases/migrations/20230726095252_v25/migration.sql b/src/common/databases/migrations/20230726095252_v25/migration.sql new file mode 100644 index 00000000..389c4749 --- /dev/null +++ b/src/common/databases/migrations/20230726095252_v25/migration.sql @@ -0,0 +1,8 @@ +/* + Warnings: + + - A unique constraint covering the columns `[user_uid,choice,status]` on the table `appointments` will be added. If there are existing duplicate values, this will fail. + +*/ +-- CreateIndex +CREATE UNIQUE INDEX "appointments_user_uid_choice_status_key" ON "appointments"("user_uid", "choice", "status"); diff --git a/src/common/databases/schema.prisma b/src/common/databases/schema.prisma index ae182a9d..98ff92ea 100644 --- a/src/common/databases/schema.prisma +++ b/src/common/databases/schema.prisma @@ -297,6 +297,7 @@ model Appointments { status EAppointmentStatus @default(OPEN) votes Votes[] + @@unique([user_uid, choice, status]) @@map("appointments") } From fffcd17944892fd89dde3098c0a0dab130477239 Mon Sep 17 00:00:00 2001 From: OxSaitama Date: Wed, 26 Jul 2023 17:11:32 +0200 Subject: [PATCH 05/49] refacto vote creation in live-votes --- package.json | 2 +- .../api/super-admin/AppointmentsController.ts | 38 +------- src/app/api/super-admin/LiveVoteController.ts | 90 +++++++++++++++++ src/app/api/super-admin/VotesController.ts | 58 +---------- src/app/index.ts | 2 + .../repositories/AppointmentsRepository.ts | 21 +--- src/common/repositories/UsersRepository.ts | 4 +- src/common/repositories/VotesRepository.ts | 29 ++++-- .../AppointmentsService.ts | 16 +-- .../LiveVoteService/LiveVoteService.ts | 97 +++++++++++++++++++ .../super-admin/VotesService/VotesService.ts | 43 +------- 11 files changed, 224 insertions(+), 176 deletions(-) create mode 100644 src/app/api/super-admin/LiveVoteController.ts create mode 100644 src/services/super-admin/LiveVoteService/LiveVoteService.ts diff --git a/package.json b/package.json index 7372ff24..31b23e12 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "cron": "^2.3.1", "express": "^4.18.2", "jsonwebtoken": "^9.0.0", - "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.64", + "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.65", "module-alias": "^2.2.2", "multer": "^1.4.5-lts.1", "next": "^13.1.5", diff --git a/src/app/api/super-admin/AppointmentsController.ts b/src/app/api/super-admin/AppointmentsController.ts index fa143534..f2790755 100644 --- a/src/app/api/super-admin/AppointmentsController.ts +++ b/src/app/api/super-admin/AppointmentsController.ts @@ -1,17 +1,15 @@ import { Response, Request } from "express"; -import { Controller, Get, Post } from "@ControllerPattern/index"; +import { Controller, Get } from "@ControllerPattern/index"; import ApiController from "@Common/system/controller-pattern/ApiController"; import AppointmentsService from "@Services/super-admin/AppointmentsService/AppointmentsService"; import { Service } from "typedi"; import { Appointment } from "le-coffre-resources/dist/SuperAdmin"; -import { validateOrReject } from "class-validator"; import authHandler from "@App/middlewares/AuthHandler"; -import UsersService from "@Services/super-admin/UsersService/UsersService"; @Controller() @Service() export default class AppointmentsController extends ApiController { - constructor(private appointmentsService: AppointmentsService, private usersService: UsersService) { + constructor(private appointmentsService: AppointmentsService) { super(); } @@ -41,38 +39,6 @@ export default class AppointmentsController extends ApiController { } } - /** - * @description Create a new appointment - */ - @Post("/api/v1/super-admin/appointments", [authHandler]) - protected async post(req: Request, response: Response) { - try { - //init IUser resource with request body values - const appointmentEntity = Appointment.hydrate(req.body); - //validate user - await validateOrReject(appointmentEntity, { groups: ["createAppointment"]}); - - const targetedUser = await this.usersService.getByUid(appointmentEntity.targeted_user.uid!); - if(!targetedUser) { - this.httpNotFoundRequest(response, "targeted user not found"); - return; - } - - //call service to get prisma entity - const appointmentEntityCreated = await this.appointmentsService.create(appointmentEntity); - //Hydrate ressource with prisma entity - const appointment = Appointment.hydrate(appointmentEntityCreated, { - strategy: "excludeAll", - }); - - //success - this.httpCreated(response, appointment); - } catch (error) { - this.httpInternalError(response, error); - return; - } - } - /** * @description Get a specific appointment by uid */ diff --git a/src/app/api/super-admin/LiveVoteController.ts b/src/app/api/super-admin/LiveVoteController.ts new file mode 100644 index 00000000..e07b6eab --- /dev/null +++ b/src/app/api/super-admin/LiveVoteController.ts @@ -0,0 +1,90 @@ +import { Response, Request } from "express"; +import { Controller, Post } from "@ControllerPattern/index"; +import ApiController from "@Common/system/controller-pattern/ApiController"; +import VotesService from "@Services/super-admin/VotesService/VotesService"; +import { Service } from "typedi"; +import { Vote } from "le-coffre-resources/dist/SuperAdmin"; +import { validateOrReject } from "class-validator"; +import authHandler from "@App/middlewares/AuthHandler"; +import UsersService from "@Services/super-admin/UsersService/UsersService"; +import { EAppointmentStatus } from "@prisma/client"; +import AppointmentService from "@Services/super-admin/AppointmentsService/AppointmentsService"; +import LiveVoteService from "@Services/super-admin/LiveVoteService/LiveVoteService"; + +@Controller() +@Service() +export default class LiveVoteController extends ApiController { + constructor(private liveVoteService: LiveVoteService, private votesService: VotesService, private usersService: UsersService, private appointmentService: AppointmentService) { + super(); + } + + /** + * @description Create a new vote + */ + @Post("/api/v1/super-admin/live-votes", [authHandler]) + protected async post(req: Request, response: Response) { + try { + const userId = req.body.user.userId; + //init IUser resource with request body values + const voteEntity = Vote.hydrate(req.body); + //validate user + await validateOrReject(voteEntity, { groups: ["createVote"] }); + + if (voteEntity.appointment.uid) { + const appointment = await this.appointmentService.getByUid(voteEntity.appointment.uid); + if (!appointment) { + this.httpNotFoundRequest(response, "Appointment not found"); + return; + } + if (appointment.status === EAppointmentStatus.CLOSED) { + this.httpBadRequest(response, "Appointment is closed"); + return; + } + } + + const votes = await this.votesService.get({ + where: { + OR: [ + { AND: [{ appointment: { uid: voteEntity.appointment.uid } }, { voter: { uid: userId } }] }, + { + AND: [ + { + appointment: { + AND: [{ user_uid: voteEntity.appointment.targeted_user.uid }, { status: EAppointmentStatus.OPEN }], + }, + }, + { voter: { uid: userId } }, + ], + }, + ], + }, + }); + + if (votes.length) { + this.httpBadRequest(response, "Voter already voted for this appointment"); + return; + } + + const voter = await this.usersService.getByUid(userId); + + voteEntity.voter = voter!; + //call service to get prisma entity + const voteEntityCreated = await this.liveVoteService.create(voteEntity); + + if(!voteEntityCreated) { + this.httpBadRequest(response, "Appointment choice is not valid"); + return; + } + //Hydrate ressource with prisma entity + const vote = Vote.hydrate(voteEntityCreated, { + strategy: "excludeAll", + }); + + //success + this.httpCreated(response, vote); + } catch (error) { + this.httpInternalError(response, error); + return; + } + } +} diff --git a/src/app/api/super-admin/VotesController.ts b/src/app/api/super-admin/VotesController.ts index 71057e82..4f08ccf8 100644 --- a/src/app/api/super-admin/VotesController.ts +++ b/src/app/api/super-admin/VotesController.ts @@ -1,19 +1,16 @@ import { Response, Request } from "express"; -import { Controller, Delete, Get, Post } from "@ControllerPattern/index"; +import { Controller, Delete, Get } from "@ControllerPattern/index"; import ApiController from "@Common/system/controller-pattern/ApiController"; import VotesService from "@Services/super-admin/VotesService/VotesService"; import { Service } from "typedi"; import { Vote } from "le-coffre-resources/dist/SuperAdmin"; -import { validateOrReject } from "class-validator"; import authHandler from "@App/middlewares/AuthHandler"; -import UsersService from "@Services/super-admin/UsersService/UsersService"; -import { EAppointmentStatus, Votes } from "@prisma/client"; -import AppointmentService from "@Services/super-admin/AppointmentsService/AppointmentsService"; +import { Votes } from "@prisma/client"; @Controller() @Service() export default class VotesController extends ApiController { - constructor(private votesService: VotesService, private usersService: UsersService, private appointmentService: AppointmentService) { + constructor(private votesService: VotesService) { super(); } @@ -43,55 +40,6 @@ export default class VotesController extends ApiController { } } - /** - * @description Create a new vote - */ - @Post("/api/v1/super-admin/votes", [authHandler]) - protected async post(req: Request, response: Response) { - try { - const userId = req.body.user.userId; - //init IUser resource with request body values - const voteEntity = Vote.hydrate(req.body); - //validate user - await validateOrReject(voteEntity, { groups: ["createVote"] }); - - const appointment = await this.appointmentService.getByUid(voteEntity.appointment.uid!); - if (!appointment) { - this.httpNotFoundRequest(response, "Appointment not found"); - return; - } - if (appointment.status === EAppointmentStatus.CLOSED) { - this.httpBadRequest(response, "Appointment is closed"); - return; - } - - const votes = await this.votesService.get({ - where: { AND: [{ appointment: { uid: voteEntity.appointment.uid } }, { voter: { uid: userId } }] }, - }); - console.log(votes); - if (votes.length) { - this.httpBadRequest(response, "Voter already voted for this appointment"); - return; - } - - const voter = await this.usersService.getByUid(userId); - - voteEntity.voter = voter!; - //call service to get prisma entity - const voteEntityCreated = await this.votesService.create(voteEntity); - //Hydrate ressource with prisma entity - const vote = Vote.hydrate(voteEntityCreated, { - strategy: "excludeAll", - }); - - //success - this.httpCreated(response, vote); - } catch (error) { - this.httpInternalError(response, error); - return; - } - } - /** * @description Get a specific vote by uid */ diff --git a/src/app/index.ts b/src/app/index.ts index a4b4d9a2..f550461c 100644 --- a/src/app/index.ts +++ b/src/app/index.ts @@ -42,6 +42,7 @@ import FilesControllerCustomer from "./api/customer/FilesController"; import DocumentsControllerCustomer from "./api/customer/DocumentsController"; import AppointmentsController from "./api/super-admin/AppointmentsController"; import VotesController from "./api/super-admin/VotesController"; +import LiveVoteController from "./api/super-admin/LiveVoteController"; /** @@ -60,6 +61,7 @@ export default { Container.get(DocumentTypesControllerSuperAdmin); Container.get(AppointmentsController); Container.get(VotesController); + Container.get(LiveVoteController); Container.get(IdNotUserController); Container.get(FranceConnectCustomerController); Container.get(FilesControllerSuperAdmin); diff --git a/src/common/repositories/AppointmentsRepository.ts b/src/common/repositories/AppointmentsRepository.ts index 9d5102bc..62b74d34 100644 --- a/src/common/repositories/AppointmentsRepository.ts +++ b/src/common/repositories/AppointmentsRepository.ts @@ -1,8 +1,7 @@ import Database from "@Common/databases/database"; import BaseRepository from "@Repositories/BaseRepository"; import { Service } from "typedi"; -import { Appointments, EAppointmentStatus, EVote, Prisma } from "@prisma/client"; -import { Appointment } from "le-coffre-resources/dist/SuperAdmin"; +import { Appointments, EAppointmentStatus, Prisma } from "@prisma/client"; @Service() export default class AppointmentsRepository extends BaseRepository { @@ -24,24 +23,6 @@ export default class AppointmentsRepository extends BaseRepository { return this.model.findMany(query); } - /** - * @description : Create new appointment - */ - public async create(appointment: Appointment): Promise { - const createArgs: Prisma.AppointmentsCreateArgs = { - data: { - user: { - connect: { - uid: appointment.targeted_user!.uid, - }, - }, - choice: EVote[appointment.choice as keyof typeof EVote], - }, - }; - - return this.model.create(createArgs); - } - /** * @description : Update data of a appointment */ diff --git a/src/common/repositories/UsersRepository.ts b/src/common/repositories/UsersRepository.ts index 8545627c..49673146 100644 --- a/src/common/repositories/UsersRepository.ts +++ b/src/common/repositories/UsersRepository.ts @@ -2,7 +2,7 @@ import Database from "@Common/databases/database"; import BaseRepository from "@Repositories/BaseRepository"; import { Service } from "typedi"; import { ECivility, Prisma, Users } from "@prisma/client"; -import User from "le-coffre-resources/dist/SuperAdmin"; +import User, { Role } from "le-coffre-resources/dist/SuperAdmin"; @Service() export default class UsersRepository extends BaseRepository { @@ -199,7 +199,7 @@ export default class UsersRepository extends BaseRepository { /** * @description : Find one user with office */ - public async findOneByUidWithRole(uid: string) { + public async findOneByUidWithRole(uid: string): Promise<((Users & {role: Role} )| null)> { return this.model.findUnique({ where: { uid: uid, diff --git a/src/common/repositories/VotesRepository.ts b/src/common/repositories/VotesRepository.ts index 2283ca94..0450760a 100644 --- a/src/common/repositories/VotesRepository.ts +++ b/src/common/repositories/VotesRepository.ts @@ -1,7 +1,7 @@ import Database from "@Common/databases/database"; import BaseRepository from "@Repositories/BaseRepository"; import { Service } from "typedi"; -import { Votes, Prisma } from "@prisma/client"; +import { Votes, Prisma, EVote, EAppointmentStatus } from "@prisma/client"; import { Vote } from "le-coffre-resources/dist/SuperAdmin"; @Service() @@ -27,12 +27,29 @@ export default class VotesRepository extends BaseRepository { /** * @description : Create new vote */ - public async create(vote: Vote): Promise { + public async create(vote: Vote): Promise { + let whereArg: Prisma.AppointmentsWhereUniqueInput; + if(vote.appointment.targeted_user.uid) { + whereArg = { + user_uid_choice_status: { + user_uid: vote.appointment.targeted_user.uid, + choice: EVote[vote.appointment.choice as keyof typeof EVote], + status: EAppointmentStatus.OPEN, + } + }; + } else { + whereArg = { + uid: vote.appointment.uid, + }; + } const createArgs: Prisma.VotesCreateArgs = { data: { appointment: { - connect: { - uid: vote.appointment.uid, + connectOrCreate: { + where: whereArg, + create: { + user_uid: vote.appointment.targeted_user.uid!, + } }, }, voter: { @@ -40,10 +57,10 @@ export default class VotesRepository extends BaseRepository { uid: vote.voter.uid, }, }, - }, + } }; - return this.model.create(createArgs); + return this.model.create({...createArgs, include: {appointment: {include: {votes: true}}}}); } /** diff --git a/src/services/super-admin/AppointmentsService/AppointmentsService.ts b/src/services/super-admin/AppointmentsService/AppointmentsService.ts index 9a47953e..45d8b481 100644 --- a/src/services/super-admin/AppointmentsService/AppointmentsService.ts +++ b/src/services/super-admin/AppointmentsService/AppointmentsService.ts @@ -1,14 +1,11 @@ import BaseService from "@Services/BaseService"; import { Service } from "typedi"; -import { Appointment } from "le-coffre-resources/dist/SuperAdmin"; import AppointmentsRepository from "@Repositories/AppointmentsRepository"; import { Prisma, Appointments, EAppointmentStatus } from "@prisma/client"; -import UsersService from "../UsersService/UsersService"; -import { EVote } from "le-coffre-resources/dist/SuperAdmin/Appointment"; @Service() export default class AppointmentService extends BaseService { - constructor(private appointmentRepository: AppointmentsRepository, private userService: UsersService) { + constructor(private appointmentRepository: AppointmentsRepository) { super(); } @@ -20,17 +17,6 @@ export default class AppointmentService extends BaseService { return this.appointmentRepository.findMany(query); } - /** - * @description : Create a appointment - * @throws {Error} If appointment couldn't be created - */ - public async create(appointment: Appointment): Promise { - const user = await this.userService.getByUidWithRole(appointment.targeted_user!.uid!) - if(!user) throw new Error("User not found"); - user.role.name === "super-admin" ? appointment.choice = EVote.DISMISS : appointment.choice = EVote.NOMINATE; - return this.appointmentRepository.create(appointment); - } - /** * @description : Modify a appointment * @throws {Error} If appointment cannot be modified diff --git a/src/services/super-admin/LiveVoteService/LiveVoteService.ts b/src/services/super-admin/LiveVoteService/LiveVoteService.ts new file mode 100644 index 00000000..5576bb28 --- /dev/null +++ b/src/services/super-admin/LiveVoteService/LiveVoteService.ts @@ -0,0 +1,97 @@ +import BaseService from "@Services/BaseService"; +import { Service } from "typedi"; +import User, { Appointment, Role, Vote } from "le-coffre-resources/dist/SuperAdmin"; +import VotesRepository from "@Repositories/VotesRepository"; +import { Appointments, EAppointmentStatus, EVote, Votes } from "@prisma/client"; +import AppointmentService from "../AppointmentsService/AppointmentsService"; +import UsersService from "../UsersService/UsersService"; +import RolesService from "../RolesService/RolesService"; + +@Service() +export default class LiveVoteService extends BaseService { + constructor( + private voteRepository: VotesRepository, + private appointmentService: AppointmentService, + private userService: UsersService, + private roleService: RolesService, + ) { + super(); + } + + public async verifyVoterChoice(vote: Vote): Promise { + const userWithRole = await this.userService.getByUidWithRole(vote.appointment.targeted_user.uid!); + if (userWithRole!.role.name === "super-admin" && vote.appointment.choice === EVote.DISMISS) { + return true; + } + if (userWithRole!.role.name !== "super-admin" && vote.appointment.choice === EVote.NOMINATE) { + return true; + } + return false; + } + + public async getAppointmentWithVotes(vote: Vote): Promise { + if (vote.appointment.uid) { + return this.appointmentService.getByUidWithVotes(vote.appointment.uid); + } + const appointmentByUser = await this.appointmentService.get({ + where: { + AND: [ + { user_uid: vote.appointment.targeted_user.uid }, + { status: EAppointmentStatus.OPEN }, + { choice: EVote[vote.appointment.choice as keyof typeof EVote] }, + ], + }, + include: { votes: true }, + }); + if (appointmentByUser.length >= 1) { + return this.appointmentService.getByUidWithVotes(appointmentByUser[0]!.uid); + } + return null; + } + + private async closeVote(appointment: Appointments, vote: Votes) { + await this.appointmentService.update(vote.appointment_uid, EAppointmentStatus.CLOSED); + const user = await this.userService.getByUid(appointment.user_uid, { role: true }); + const userEntity = User.hydrate(user!, { strategy: "excludeAll" }); + + return await this.updateRole(appointment, userEntity, vote); + } + + private async updateRole(appointment: Appointments, userEntity: User, vote: Votes) { + if (appointment.choice === EVote.DISMISS) { + const roles = await this.roleService.get({ where: { name: "default" } }); + const roleEntity = Role.hydrate(roles[0]!, { strategy: "excludeAll" }); + userEntity.role = roleEntity; + await this.userService.update(appointment!.user_uid, userEntity); + return vote; + } else if (appointment.choice === EVote.NOMINATE) { + const roles = await this.roleService.get({ where: { name: "super-admin" } }); + const roleEntity = Role.hydrate(roles[0]!, { strategy: "excludeAll" }); + userEntity!.role = roleEntity; + await this.userService.update(appointment!.user_uid, userEntity); + return vote; + } + return vote; + } + + /** + * @description : Create a vote + * @throws {Error} If vote couldn't be created + */ + public async create(vote: Vote): Promise { + const appointment = await this.getAppointmentWithVotes(vote); + + if (appointment) { + const appointmentEntity = Appointment.hydrate(appointment, { strategy: "excludeAll" }); + if (appointmentEntity?.votes && appointmentEntity.votes.length >= 2) { + const voteCreated = await this.voteRepository.create(vote); + return this.closeVote(appointment, voteCreated); + } + } + + const approvedChoice = await this.verifyVoterChoice(vote); + if(!approvedChoice) return null; + + return this.voteRepository.create(vote); + } +} diff --git a/src/services/super-admin/VotesService/VotesService.ts b/src/services/super-admin/VotesService/VotesService.ts index 663058ef..fa32fb4d 100644 --- a/src/services/super-admin/VotesService/VotesService.ts +++ b/src/services/super-admin/VotesService/VotesService.ts @@ -1,20 +1,11 @@ import BaseService from "@Services/BaseService"; import { Service } from "typedi"; -import User, { Role, Vote } from "le-coffre-resources/dist/SuperAdmin"; import VotesRepository from "@Repositories/VotesRepository"; -import { EAppointmentStatus, EVote, Prisma, Votes } from "@prisma/client"; -import AppointmentService from "../AppointmentsService/AppointmentsService"; -import UsersService from "../UsersService/UsersService"; -import RolesService from "../RolesService/RolesService"; +import { Prisma } from "@prisma/client"; @Service() export default class VoteService extends BaseService { - constructor( - private voteRepository: VotesRepository, - private appointmentService: AppointmentService, - private userService: UsersService, - private roleService: RolesService, - ) { + constructor(private voteRepository: VotesRepository) { super(); } @@ -26,36 +17,6 @@ export default class VoteService extends BaseService { return this.voteRepository.findMany(query); } - /** - * @description : Create a vote - * @throws {Error} If vote couldn't be created - */ - public async create(vote: Vote): Promise { - const appointment = await this.appointmentService.getByUidWithVotes(vote.appointment.uid!); - - if (appointment!.votes.length >= 2) { - const voteCreated = await this.voteRepository.create(vote); - await this.appointmentService.update(appointment!.uid!, EAppointmentStatus.CLOSED); - const user = await this.userService.getByUid(appointment!.user_uid, { role: true }); - const userEntity = User.hydrate(user!, { strategy: "excludeAll" }); - - if (appointment!.choice === EVote.DISMISS) { - const roles = await this.roleService.get({ where: { name: "default" } }); - const roleEntity = Role.hydrate(roles[0]!, { strategy: "excludeAll" }); - userEntity.role = roleEntity; - await this.userService.update(appointment!.user_uid, userEntity); - return voteCreated; - } else if (appointment!.choice === EVote.NOMINATE) { - const roles = await this.roleService.get({ where: { name: "super-admin" } }); - const roleEntity = Role.hydrate(roles[0]!, { strategy: "excludeAll" }); - userEntity!.role = roleEntity; - await this.userService.update(appointment!.user_uid, userEntity); - return voteCreated; - } - } - return this.voteRepository.create(vote); - } - /** * @description : Get a vote by uid * @throws {Error} If vote cannot be get by uid From 3b7b9288bc6c285458bc748d30a8511406eba03a Mon Sep 17 00:00:00 2001 From: Maxime Lalo Date: Thu, 27 Jul 2023 13:20:13 +0200 Subject: [PATCH 06/49] :bug: Fixing you already voted for this appointment --- package-lock.json | 185 +++++++++++------- package.json | 2 +- src/app/api/super-admin/LiveVoteController.ts | 62 +++--- src/common/repositories/VotesRepository.ts | 5 +- 4 files changed, 146 insertions(+), 108 deletions(-) diff --git a/package-lock.json b/package-lock.json index a6b784ab..0290f4ae 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,7 @@ "cron": "^2.3.1", "express": "^4.18.2", "jsonwebtoken": "^9.0.0", - "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.57", + "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.66", "module-alias": "^2.2.2", "multer": "^1.4.5-lts.1", "next": "^13.1.5", @@ -1061,14 +1061,14 @@ } }, "node_modules/@next/env": { - "version": "13.4.10", - "resolved": "https://registry.npmjs.org/@next/env/-/env-13.4.10.tgz", - "integrity": "sha512-3G1yD/XKTSLdihyDSa8JEsaWOELY+OWe08o0LUYzfuHp1zHDA8SObQlzKt+v+wrkkPcnPweoLH1ImZeUa0A1NQ==" + "version": "13.4.12", + "resolved": "https://registry.npmjs.org/@next/env/-/env-13.4.12.tgz", + "integrity": "sha512-RmHanbV21saP/6OEPBJ7yJMuys68cIf8OBBWd7+uj40LdpmswVAwe1uzeuFyUsd6SfeITWT3XnQfn6wULeKwDQ==" }, "node_modules/@next/swc-darwin-arm64": { - "version": "13.4.10", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.10.tgz", - "integrity": "sha512-4bsdfKmmg7mgFGph0UorD1xWfZ5jZEw4kKRHYEeTK9bT1QnMbPVPlVXQRIiFPrhoDQnZUoa6duuPUJIEGLV1Jg==", + "version": "13.4.12", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.12.tgz", + "integrity": "sha512-deUrbCXTMZ6ZhbOoloqecnUeNpUOupi8SE2tx4jPfNS9uyUR9zK4iXBvH65opVcA/9F5I/p8vDXSYbUlbmBjZg==", "cpu": [ "arm64" ], @@ -1081,9 +1081,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "13.4.10", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.10.tgz", - "integrity": "sha512-ngXhUBbcZIWZWqNbQSNxQrB9T1V+wgfCzAor2olYuo/YpaL6mUYNUEgeBMhr8qwV0ARSgKaOp35lRvB7EmCRBg==", + "version": "13.4.12", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.12.tgz", + "integrity": "sha512-WRvH7RxgRHlC1yb5oG0ZLx8F7uci9AivM5/HGGv9ZyG2Als8Ij64GC3d+mQ5sJhWjusyU6T6V1WKTUoTmOB0zQ==", "cpu": [ "x64" ], @@ -1096,9 +1096,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "13.4.10", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.10.tgz", - "integrity": "sha512-SjCZZCOmHD4uyM75MVArSAmF5Y+IJSGroPRj2v9/jnBT36SYFTORN8Ag/lhw81W9EeexKY/CUg2e9mdebZOwsg==", + "version": "13.4.12", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.12.tgz", + "integrity": "sha512-YEKracAWuxp54tKiAvvq73PUs9lok57cc8meYRibTWe/VdPB2vLgkTVWFcw31YDuRXdEhdX0fWS6Q+ESBhnEig==", "cpu": [ "arm64" ], @@ -1111,9 +1111,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "13.4.10", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.10.tgz", - "integrity": "sha512-F+VlcWijX5qteoYIOxNiBbNE8ruaWuRlcYyIRK10CugqI/BIeCDzEDyrHIHY8AWwbkTwe6GRHabMdE688Rqq4Q==", + "version": "13.4.12", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.12.tgz", + "integrity": "sha512-LhJR7/RAjdHJ2Isl2pgc/JaoxNk0KtBgkVpiDJPVExVWA1c6gzY57+3zWuxuyWzTG+fhLZo2Y80pLXgIJv7g3g==", "cpu": [ "arm64" ], @@ -1126,9 +1126,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "13.4.10", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.10.tgz", - "integrity": "sha512-WDv1YtAV07nhfy3i1visr5p/tjiH6CeXp4wX78lzP1jI07t4PnHHG1WEDFOduXh3WT4hG6yN82EQBQHDi7hBrQ==", + "version": "13.4.12", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.12.tgz", + "integrity": "sha512-1DWLL/B9nBNiQRng+1aqs3OaZcxC16Nf+mOnpcrZZSdyKHek3WQh6j/fkbukObgNGwmCoVevLUa/p3UFTTqgqg==", "cpu": [ "x64" ], @@ -1141,9 +1141,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "13.4.10", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.10.tgz", - "integrity": "sha512-zFkzqc737xr6qoBgDa3AwC7jPQzGLjDlkNmt/ljvQJ/Veri5ECdHjZCUuiTUfVjshNIIpki6FuP0RaQYK9iCRg==", + "version": "13.4.12", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.12.tgz", + "integrity": "sha512-kEAJmgYFhp0VL+eRWmUkVxLVunn7oL9Mdue/FS8yzRBVj7Z0AnIrHpTIeIUl1bbdQq1VaoOztnKicAjfkLTRCQ==", "cpu": [ "x64" ], @@ -1156,9 +1156,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "13.4.10", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.10.tgz", - "integrity": "sha512-IboRS8IWz5mWfnjAdCekkl8s0B7ijpWeDwK2O8CdgZkoCDY0ZQHBSGiJ2KViAG6+BJVfLvcP+a2fh6cdyBr9QQ==", + "version": "13.4.12", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.12.tgz", + "integrity": "sha512-GMLuL/loR6yIIRTnPRY6UGbLL9MBdw2anxkOnANxvLvsml4F0HNIgvnU3Ej4BjbqMTNjD4hcPFdlEow4XHPdZA==", "cpu": [ "arm64" ], @@ -1171,9 +1171,9 @@ } }, "node_modules/@next/swc-win32-ia32-msvc": { - "version": "13.4.10", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.10.tgz", - "integrity": "sha512-bSA+4j8jY4EEiwD/M2bol4uVEu1lBlgsGdvM+mmBm/BbqofNBfaZ2qwSbwE2OwbAmzNdVJRFRXQZ0dkjopTRaQ==", + "version": "13.4.12", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.12.tgz", + "integrity": "sha512-PhgNqN2Vnkm7XaMdRmmX0ZSwZXQAtamBVSa9A/V1dfKQCV1rjIZeiy/dbBnVYGdj63ANfsOR/30XpxP71W0eww==", "cpu": [ "ia32" ], @@ -1186,9 +1186,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "13.4.10", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.10.tgz", - "integrity": "sha512-g2+tU63yTWmcVQKDGY0MV1PjjqgZtwM4rB1oVVi/v0brdZAcrcTV+04agKzWtvWroyFz6IqtT0MoZJA7PNyLVw==", + "version": "13.4.12", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.12.tgz", + "integrity": "sha512-Z+56e/Ljt0bUs+T+jPjhFyxYBcdY2RIq9ELFU+qAMQMteHo7ymbV7CKmlcX59RI9C4YzN8PgMgLyAoi916b5HA==", "cpu": [ "x64" ], @@ -1493,9 +1493,9 @@ } }, "node_modules/@types/node": { - "version": "18.17.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.0.tgz", - "integrity": "sha512-GXZxEtOxYGFchyUzxvKI14iff9KZ2DI+A6a37o6EQevtg6uO9t+aUZKcaC1Te5Ng1OnLM7K9NVVj+FbecD9cJg==" + "version": "18.17.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.1.tgz", + "integrity": "sha512-xlR1jahfizdplZYRU59JlUx9uzF1ARa8jbhM11ccpCJya8kvos5jwdm2ZAgxSCwOl0fq21svP18EVwPBXMQudw==" }, "node_modules/@types/node-fetch": { "version": "2.6.4", @@ -2049,9 +2049,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001516", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001516.tgz", - "integrity": "sha512-Wmec9pCBY8CWbmI4HsjBeQLqDTqV91nFVR83DnZpYyRnPI1wePDsTg0bGLPC5VU/3OIZV1fmxEea1b+tFKe86g==", + "version": "1.0.30001517", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001517.tgz", + "integrity": "sha512-Vdhm5S11DaFVLlyiKu4hiUTkpZu+y1KA/rZZqVQfOD5YdDT/eQKlkt7NaE0WGOFgX32diqt9MiP9CAiFeRklaA==", "funding": [ { "type": "opencollective", @@ -2335,9 +2335,9 @@ "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" }, "node_modules/cron": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/cron/-/cron-2.3.1.tgz", - "integrity": "sha512-1eRRlIT0UfIqauwbG9pkg3J6CX9A6My2ytJWqAXoK0T9oJnUZTzGBNPxao0zjodIbPgf8UQWjE62BMb9eVllSQ==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/cron/-/cron-2.4.0.tgz", + "integrity": "sha512-Cx77ic1TyIAtUggr0oAhtS8MLzPBUqGNIvdDM7jE3oFIxfe8LXWI9q3iQN/H2CebAiMir53LQKWOhEKnzkJTAQ==", "dependencies": { "luxon": "^3.2.1" } @@ -2467,9 +2467,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron-to-chromium": { - "version": "1.4.461", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.461.tgz", - "integrity": "sha512-1JkvV2sgEGTDXjdsaQCeSwYYuhLRphRpc+g6EHTFELJXEiznLt3/0pZ9JuAOQ5p2rI3YxKTbivtvajirIfhrEQ==", + "version": "1.4.473", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.473.tgz", + "integrity": "sha512-aVfC8+440vGfl06l8HKKn8/PD5jRfSnLkTTD65EFvU46igbpQRri1gxSzW9/+TeUlwYzrXk1sw867T96zlyECA==", "dev": true }, "node_modules/emittery": { @@ -3193,17 +3193,17 @@ } }, "node_modules/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, "dependencies": { "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", + "make-dir": "^4.0.0", "supports-color": "^7.1.0" }, "engines": { - "node": ">=8" + "node": ">=10" } }, "node_modules/istanbul-lib-source-maps": { @@ -3244,9 +3244,9 @@ "dev": true }, "node_modules/istanbul-reports": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", - "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", + "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", "dev": true, "dependencies": { "html-escaper": "^2.0.0", @@ -3972,7 +3972,7 @@ } }, "node_modules/le-coffre-resources": { - "resolved": "git+ssh://git@github.com/smart-chain-fr/leCoffre-resources.git#dffc2429ba6ceb4129deb56e308962799b9b572c", + "resolved": "git+ssh://git@github.com/smart-chain-fr/leCoffre-resources.git#e7916d516fe434c93ef13e765d8d63a7ce3c56b2", "license": "MIT", "dependencies": { "class-transformer": "^0.5.1", @@ -3990,9 +3990,9 @@ } }, "node_modules/libphonenumber-js": { - "version": "1.10.37", - "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.37.tgz", - "integrity": "sha512-Z10PCaOCiAxbUxLyR31DNeeNugSVP6iv/m7UrSKS5JHziEMApJtgku4e9Q69pzzSC9LnQiM09sqsGf2ticZnMw==" + "version": "1.10.38", + "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.38.tgz", + "integrity": "sha512-4NjVXVUmpZ9Zsqq6FXa2+MKI+KAI3tOqA0pxXgXGluhpj4ge5didmbWJpMBqGB3AVGv1SnEtKdGTbxjSEG1kCQ==" }, "node_modules/lines-and-columns": { "version": "1.2.4", @@ -4066,20 +4066,53 @@ } }, "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", "dev": true, "dependencies": { - "semver": "^6.0.0" + "semver": "^7.5.3" }, "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/make-dir/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-dir/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", @@ -4386,11 +4419,11 @@ } }, "node_modules/next": { - "version": "13.4.10", - "resolved": "https://registry.npmjs.org/next/-/next-13.4.10.tgz", - "integrity": "sha512-4ep6aKxVTQ7rkUW2fBLhpBr/5oceCuf4KmlUpvG/aXuDTIf9mexNSpabUD6RWPspu6wiJJvozZREhXhueYO36A==", + "version": "13.4.12", + "resolved": "https://registry.npmjs.org/next/-/next-13.4.12.tgz", + "integrity": "sha512-eHfnru9x6NRmTMcjQp6Nz0J4XH9OubmzOa7CkWL+AUrUxpibub3vWwttjduu9No16dug1kq04hiUUpo7J3m3Xw==", "dependencies": { - "@next/env": "13.4.10", + "@next/env": "13.4.12", "@swc/helpers": "0.5.1", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001406", @@ -4406,15 +4439,15 @@ "node": ">=16.8.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "13.4.10", - "@next/swc-darwin-x64": "13.4.10", - "@next/swc-linux-arm64-gnu": "13.4.10", - "@next/swc-linux-arm64-musl": "13.4.10", - "@next/swc-linux-x64-gnu": "13.4.10", - "@next/swc-linux-x64-musl": "13.4.10", - "@next/swc-win32-arm64-msvc": "13.4.10", - "@next/swc-win32-ia32-msvc": "13.4.10", - "@next/swc-win32-x64-msvc": "13.4.10" + "@next/swc-darwin-arm64": "13.4.12", + "@next/swc-darwin-x64": "13.4.12", + "@next/swc-linux-arm64-gnu": "13.4.12", + "@next/swc-linux-arm64-musl": "13.4.12", + "@next/swc-linux-x64-gnu": "13.4.12", + "@next/swc-linux-x64-musl": "13.4.12", + "@next/swc-win32-arm64-msvc": "13.4.12", + "@next/swc-win32-ia32-msvc": "13.4.12", + "@next/swc-win32-x64-msvc": "13.4.12" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", @@ -5661,9 +5694,9 @@ } }, "node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==" + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", + "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==" }, "node_modules/type-detect": { "version": "4.0.8", diff --git a/package.json b/package.json index 31b23e12..17bcb5c6 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "cron": "^2.3.1", "express": "^4.18.2", "jsonwebtoken": "^9.0.0", - "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.65", + "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.66", "module-alias": "^2.2.2", "multer": "^1.4.5-lts.1", "next": "^13.1.5", diff --git a/src/app/api/super-admin/LiveVoteController.ts b/src/app/api/super-admin/LiveVoteController.ts index e07b6eab..0e3307f4 100644 --- a/src/app/api/super-admin/LiveVoteController.ts +++ b/src/app/api/super-admin/LiveVoteController.ts @@ -1,20 +1,25 @@ -import { Response, Request } from "express"; -import { Controller, Post } from "@ControllerPattern/index"; -import ApiController from "@Common/system/controller-pattern/ApiController"; -import VotesService from "@Services/super-admin/VotesService/VotesService"; -import { Service } from "typedi"; -import { Vote } from "le-coffre-resources/dist/SuperAdmin"; -import { validateOrReject } from "class-validator"; import authHandler from "@App/middlewares/AuthHandler"; -import UsersService from "@Services/super-admin/UsersService/UsersService"; +import ApiController from "@Common/system/controller-pattern/ApiController"; +import { Controller, Post } from "@ControllerPattern/index"; import { EAppointmentStatus } from "@prisma/client"; import AppointmentService from "@Services/super-admin/AppointmentsService/AppointmentsService"; import LiveVoteService from "@Services/super-admin/LiveVoteService/LiveVoteService"; +import UsersService from "@Services/super-admin/UsersService/UsersService"; +import VotesService from "@Services/super-admin/VotesService/VotesService"; +import { validateOrReject } from "class-validator"; +import { Request, Response } from "express"; +import { Vote } from "le-coffre-resources/dist/SuperAdmin"; +import { Service } from "typedi"; @Controller() @Service() export default class LiveVoteController extends ApiController { - constructor(private liveVoteService: LiveVoteService, private votesService: VotesService, private usersService: UsersService, private appointmentService: AppointmentService) { + constructor( + private liveVoteService: LiveVoteService, + private votesService: VotesService, + private usersService: UsersService, + private appointmentService: AppointmentService, + ) { super(); } @@ -30,6 +35,7 @@ export default class LiveVoteController extends ApiController { //validate user await validateOrReject(voteEntity, { groups: ["createVote"] }); + let voteFound = []; if (voteEntity.appointment.uid) { const appointment = await this.appointmentService.getByUid(voteEntity.appointment.uid); if (!appointment) { @@ -40,27 +46,25 @@ export default class LiveVoteController extends ApiController { this.httpBadRequest(response, "Appointment is closed"); return; } + voteFound = await this.votesService.get({ + where: { AND: [{ appointment: { uid: voteEntity.appointment.uid } }, { voter: { uid: userId } }] }, + }); + } else { + voteFound = await this.votesService.get({ + where: { + AND: [ + { + appointment: { + AND: [{ user_uid: voteEntity.appointment.targeted_user.uid }, { status: EAppointmentStatus.OPEN }], + }, + }, + { voter: { uid: userId } }, + ], + }, + }); } - const votes = await this.votesService.get({ - where: { - OR: [ - { AND: [{ appointment: { uid: voteEntity.appointment.uid } }, { voter: { uid: userId } }] }, - { - AND: [ - { - appointment: { - AND: [{ user_uid: voteEntity.appointment.targeted_user.uid }, { status: EAppointmentStatus.OPEN }], - }, - }, - { voter: { uid: userId } }, - ], - }, - ], - }, - }); - - if (votes.length) { + if (voteFound.length) { this.httpBadRequest(response, "Voter already voted for this appointment"); return; } @@ -71,7 +75,7 @@ export default class LiveVoteController extends ApiController { //call service to get prisma entity const voteEntityCreated = await this.liveVoteService.create(voteEntity); - if(!voteEntityCreated) { + if (!voteEntityCreated) { this.httpBadRequest(response, "Appointment choice is not valid"); return; } diff --git a/src/common/repositories/VotesRepository.ts b/src/common/repositories/VotesRepository.ts index 0450760a..a9bf7746 100644 --- a/src/common/repositories/VotesRepository.ts +++ b/src/common/repositories/VotesRepository.ts @@ -1,8 +1,8 @@ import Database from "@Common/databases/database"; +import { EAppointmentStatus, EVote, Prisma, Votes } from "@prisma/client"; import BaseRepository from "@Repositories/BaseRepository"; -import { Service } from "typedi"; -import { Votes, Prisma, EVote, EAppointmentStatus } from "@prisma/client"; import { Vote } from "le-coffre-resources/dist/SuperAdmin"; +import { Service } from "typedi"; @Service() export default class VotesRepository extends BaseRepository { @@ -48,6 +48,7 @@ export default class VotesRepository extends BaseRepository { connectOrCreate: { where: whereArg, create: { + choice: EVote[vote.appointment.choice as keyof typeof EVote], user_uid: vote.appointment.targeted_user.uid!, } }, From 69afd66d2ea015ea18dea379d3e5bdb6e7806d96 Mon Sep 17 00:00:00 2001 From: Maxime Lalo Date: Thu, 27 Jul 2023 15:26:41 +0200 Subject: [PATCH 07/49] :sparkles: Modify seeder --- src/common/databases/seeders/seeder.ts | 34 ++++++-------------------- 1 file changed, 8 insertions(+), 26 deletions(-) diff --git a/src/common/databases/seeders/seeder.ts b/src/common/databases/seeders/seeder.ts index cf0129f4..941942db 100644 --- a/src/common/databases/seeders/seeder.ts +++ b/src/common/databases/seeders/seeder.ts @@ -1,18 +1,7 @@ +import { ECivility, ECustomerStatus, EFolderStatus, EOfficeStatus, Prisma, PrismaClient } from "@prisma/client"; +import User, { Address, Contact, Customer, Deed, DeedType, DocumentType, Office, OfficeFolder, OfficeRole, Role, Rule } from "le-coffre-resources/dist/SuperAdmin"; + import "module-alias/register"; -import { EFolderStatus, EOfficeStatus, ECivility, ECustomerStatus, PrismaClient, Prisma } from "@prisma/client"; -import User, { - Address, - Contact, - Customer, - Deed, - DeedType, - Office, - OfficeFolder, - OfficeRole, - Role, - Rule, - DocumentType, -} from "le-coffre-resources/dist/SuperAdmin"; export default async function main() { try{ @@ -605,7 +594,7 @@ export default async function main() { updated_at: new Date(), }, { - name: "PUT deedtypes", + name: "PUT deed-types", created_at: new Date(), updated_at: new Date(), }, @@ -665,7 +654,7 @@ export default async function main() { updated_at: new Date(), }, { - name: "POST deedtypes", + name: "POST deed-types", created_at: new Date(), updated_at: new Date(), }, @@ -862,26 +851,19 @@ export default async function main() { rules: rules.slice(0, 40), }, { - name: "notary", + name: "Notaire", created_at: new Date(), updated_at: new Date(), office: offices[0]!, rules: rules.slice(0, 33), }, { - name: "deputy", + name: "Collaborateur", created_at: new Date(), updated_at: new Date(), office: offices[0]!, rules: rules.slice(0, 22), - }, - { - name: "listener", - created_at: new Date(), - updated_at: new Date(), - office: offices[0]!, - rules: rules.slice(0, 11), - }, + } ]; const users: User[] = [ From 246e8d4394bf62a72ead8ff49047bbe6a6da2262 Mon Sep 17 00:00:00 2001 From: Vins Date: Tue, 1 Aug 2023 11:56:00 +0200 Subject: [PATCH 08/49] Super-admin role override every rules --- src/app/middlewares/RulesHandler.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/middlewares/RulesHandler.ts b/src/app/middlewares/RulesHandler.ts index 83baab87..59ac1c0a 100644 --- a/src/app/middlewares/RulesHandler.ts +++ b/src/app/middlewares/RulesHandler.ts @@ -18,7 +18,7 @@ export default async function ruleHandler(req: Request, response: Response, next return; } - if (!rules.includes(req.method + " " + service)) { + if (!rules.includes(req.method + " " + service) && role != "super-admin") { response.status(HttpCodes.UNAUTHORIZED).send("Unauthorized with those rules"); return; } From 7777bc6e91d1b06cc8fe7e7ee075e263d276df28 Mon Sep 17 00:00:00 2001 From: Maxime Lalo Date: Tue, 1 Aug 2023 15:35:40 +0200 Subject: [PATCH 09/49] :bug: Fixing documents get --- .../api/super-admin/DocumentsController.ts | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/app/api/super-admin/DocumentsController.ts b/src/app/api/super-admin/DocumentsController.ts index 7ccdb18c..03621ba8 100644 --- a/src/app/api/super-admin/DocumentsController.ts +++ b/src/app/api/super-admin/DocumentsController.ts @@ -1,14 +1,14 @@ -import { Response, Request } from "express"; -import { Controller, Delete, Get, Post, Put } from "@ControllerPattern/index"; -import ApiController from "@Common/system/controller-pattern/ApiController"; -import { Service } from "typedi"; -import DocumentsService from "@Services/super-admin/DocumentsService/DocumentsService"; -import { Documents, Prisma } from "@prisma/client"; -import { Document } from "le-coffre-resources/dist/SuperAdmin"; -import { validateOrReject } from "class-validator"; import authHandler from "@App/middlewares/AuthHandler"; -import ruleHandler from "@App/middlewares/RulesHandler"; import documentHandler from "@App/middlewares/OfficeMembershipHandlers/DocumentHandler"; +import ruleHandler from "@App/middlewares/RulesHandler"; +import ApiController from "@Common/system/controller-pattern/ApiController"; +import { Controller, Delete, Get, Post, Put } from "@ControllerPattern/index"; +import { Documents, Prisma } from "@prisma/client"; +import DocumentsService from "@Services/super-admin/DocumentsService/DocumentsService"; +import { validateOrReject } from "class-validator"; +import { Request, Response } from "express"; +import { Document } from "le-coffre-resources/dist/SuperAdmin"; +import { Service } from "typedi"; @Controller() @Service() @@ -30,12 +30,18 @@ export default class DocumentsController extends ApiController { query = JSON.parse(req.query["q"] as string); } const officeId: string = req.body.user.office_Id; + const officeWhereInput: Prisma.OfficesWhereInput = { uid: officeId } ; + if(!query.where) query.where = { document_type : {office: officeWhereInput}}; - query.where.document_type!.office = officeWhereInput; + + // query.where.document_type!.office = officeWhereInput; //call service to get prisma entity + const documentEntities = await this.documentsService.get(query); + console.log(documentEntities); + //Hydrate ressource with prisma entity const documents = Document.hydrateArray(documentEntities, { strategy: "excludeAll" }); From a05be05b72efafc4eb7e53f79ca4a51c03114240 Mon Sep 17 00:00:00 2001 From: Vins Date: Wed, 2 Aug 2023 10:53:39 +0200 Subject: [PATCH 10/49] Error when deed types name already exists --- src/app/api/admin/DeedTypesController.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/app/api/admin/DeedTypesController.ts b/src/app/api/admin/DeedTypesController.ts index bb42d6de..852b11cf 100644 --- a/src/app/api/admin/DeedTypesController.ts +++ b/src/app/api/admin/DeedTypesController.ts @@ -71,8 +71,13 @@ export default class DeedTypesController extends ApiController { //init DeedType resource with request body values const deedTypeEntity = DeedType.hydrate(req.body); - //validate deed type + //validate deed type await validateOrReject(deedTypeEntity, { groups: ["createDeedType"], forbidUnknownValues: false }); + const doesExist = await this.deedTypesService.get({ where: { name: deedTypeEntity.name } }); + if (doesExist.length > 0) { + this.httpBadRequest(response, "Deed type name already used"); + return; + } //call service to get prisma entity const deedTypeEntityCreated = await this.deedTypesService.create(deedTypeEntity); @@ -84,7 +89,7 @@ export default class DeedTypesController extends ApiController { //success this.httpCreated(response, deedType); - } catch (error) { + } catch (error) { this.httpInternalError(response, error); return; } From 609a099d0ba6de5711649e5c0c1eed0b0ba1147e Mon Sep 17 00:00:00 2001 From: Vins Date: Wed, 2 Aug 2023 11:04:33 +0200 Subject: [PATCH 11/49] Fixed Document type name unique constraints --- src/app/api/super-admin/DocumentTypesController.ts | 5 +++++ src/app/api/super-admin/OfficeFoldersController.ts | 1 - 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/app/api/super-admin/DocumentTypesController.ts b/src/app/api/super-admin/DocumentTypesController.ts index baceb4db..577086d5 100644 --- a/src/app/api/super-admin/DocumentTypesController.ts +++ b/src/app/api/super-admin/DocumentTypesController.ts @@ -58,6 +58,11 @@ export default class DocumentTypesController extends ApiController { try { //init DocumentType resource with request body values const documentTypeEntity = DocumentType.hydrate(req.body); + const doesExist = await this.documentTypesService.get({ where: { name: documentTypeEntity.name } }); + if (doesExist.length > 0) { + this.httpBadRequest(response, "Document type name already used"); + return; + } //validate user await validateOrReject(documentTypeEntity, { groups: ["createDocumentType"], forbidUnknownValues: false }); //call service to get prisma entity diff --git a/src/app/api/super-admin/OfficeFoldersController.ts b/src/app/api/super-admin/OfficeFoldersController.ts index dcd1b29c..de9d6586 100644 --- a/src/app/api/super-admin/OfficeFoldersController.ts +++ b/src/app/api/super-admin/OfficeFoldersController.ts @@ -175,7 +175,6 @@ export default class OfficeFoldersController extends ApiController { this.httpInternalError(response, error); return; } - this.httpSuccess(response, await this.officeFoldersService.getByUid("uid")); } /** From 5328313004123763f3a90eff873d244e00c5394d Mon Sep 17 00:00:00 2001 From: Vins Date: Wed, 2 Aug 2023 14:06:40 +0200 Subject: [PATCH 12/49] Fix users --- src/app/api/super-admin/UsersController.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/app/api/super-admin/UsersController.ts b/src/app/api/super-admin/UsersController.ts index 71d97022..a9815f14 100644 --- a/src/app/api/super-admin/UsersController.ts +++ b/src/app/api/super-admin/UsersController.ts @@ -105,13 +105,12 @@ export default class UsersController extends ApiController { //init IUser resource with request body values const userEntity = User.hydrate(req.body); - const userFoundEntity = User.hydrate(userFound, { strategy: "excludeAll" }); //validate user await validateOrReject(userEntity, { groups: ["updateUser"] }); //call service to get prisma entity - const userEntityUpdated = await this.usersService.update(uid, userFoundEntity); + const userEntityUpdated = await this.usersService.update(uid, userEntity); //Hydrate ressource with prisma entity const user = User.hydrate(userEntityUpdated, { From c3317c8cd851e433416d3f2159c96a81be18953f Mon Sep 17 00:00:00 2001 From: pida123 Date: Thu, 3 Aug 2023 10:19:37 +0200 Subject: [PATCH 13/49] fix circleci --- .circleci/config.yml | 51 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 28182707..3f7eb00f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -30,6 +30,10 @@ jobs: - image: cimg/base:stable environment: TAG: << pipeline.git.tag >> + parameters: + env: + type: string + default: stg steps: - checkout - kubernetes/install-kubeconfig: @@ -40,7 +44,7 @@ jobs: command: > helm upgrade lecoffre-back devops/ -i -f devops/values.yaml - -n lecoffre + -n lecoffre-<> --create-namespace --set lecoffreBack.image.repository='rg.fr-par.scw.cloud/lecoffre/back' --set lecoffreBack.image.tag=$TAG @@ -48,7 +52,7 @@ jobs: workflows: version: 2 - build-and-register: + build-and-register-stg: jobs: - build-push-docker-image: filters: @@ -57,10 +61,51 @@ workflows: branches: ignore: /.*/ - deploy-docker-image: + env: stg requires: - build-push-docker-image context: - - staging + - sc-shared-prd + filters: + tags: + only: /^v.*/ + branches: + ignore: /.*/ + + build-and-register-ppd: + jobs: + - build-push-docker-image: + filters: + tags: + only: /^v.*/ + branches: + ignore: /.*/ + - deploy-docker-image: + env: ppd + requires: + - build-push-docker-image + context: + - sc-shared-prd + filters: + tags: + only: /^v.*/ + branches: + ignore: /.*/ + + build-and-register-prd: + jobs: + - build-push-docker-image: + filters: + tags: + only: /^v.*/ + branches: + ignore: /.*/ + - deploy-docker-image: + env: prd + requires: + - build-push-docker-image + context: + - sc-shared-prd filters: tags: only: /^v.*/ From a6c5219620d78b2d32a9eac5e46f0aadec7e69c2 Mon Sep 17 00:00:00 2001 From: pida123 Date: Thu, 3 Aug 2023 10:22:26 +0200 Subject: [PATCH 14/49] fix circleci concurrent build --- .circleci/config.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 3f7eb00f..29889f30 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -59,7 +59,7 @@ workflows: tags: only: /^v.*/ branches: - ignore: /.*/ + only: staging - deploy-docker-image: env: stg requires: @@ -79,7 +79,7 @@ workflows: tags: only: /^v.*/ branches: - ignore: /.*/ + only: preprod - deploy-docker-image: env: ppd requires: @@ -99,7 +99,7 @@ workflows: tags: only: /^v.*/ branches: - ignore: /.*/ + only: main - deploy-docker-image: env: prd requires: From 9360cd012cf3cdd423bee5a533cc69d561619631 Mon Sep 17 00:00:00 2001 From: pida123 Date: Thu, 3 Aug 2023 10:27:18 +0200 Subject: [PATCH 15/49] add logic statement to circleci jobs --- .circleci/config.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 29889f30..9a4ed714 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -53,6 +53,10 @@ jobs: workflows: version: 2 build-and-register-stg: + when: + and: + - equal: [ staging, << pipeline.git.branch >> ] + - << pipeline.git.tag >> jobs: - build-push-docker-image: filters: @@ -73,6 +77,10 @@ workflows: ignore: /.*/ build-and-register-ppd: + when: + and: + - equal: [ preprod, << pipeline.git.branch >> ] + - << pipeline.git.tag >> jobs: - build-push-docker-image: filters: @@ -93,6 +101,10 @@ workflows: ignore: /.*/ build-and-register-prd: + when: + and: + - equal: [ main, << pipeline.git.branch >> ] + - << pipeline.git.tag >> jobs: - build-push-docker-image: filters: From 62952bc9f91df70a665a83c7709e751e00ec1178 Mon Sep 17 00:00:00 2001 From: pida123 Date: Thu, 3 Aug 2023 12:10:07 +0200 Subject: [PATCH 16/49] update devops flow --- .circleci/config.yml | 2 +- devops/ppd.values.yaml | 31 +++++++++++++++++++ devops/prd.values.yaml | 31 +++++++++++++++++++ devops/stg.values.yaml | 38 ++++++++++++++++++++++++ devops/templates/docker-pull-secret.yaml | 6 ++-- devops/templates/lecoffre-back.yaml | 11 ++++--- devops/templates/sealed-secret.yaml | 12 ++++++++ devops/templates/secret-store.yaml | 15 ++++++++++ devops/templates/secrets.yaml | 16 ++++++++++ devops/values.yaml | 26 ++++++---------- 10 files changed, 161 insertions(+), 27 deletions(-) create mode 100644 devops/ppd.values.yaml create mode 100644 devops/prd.values.yaml create mode 100644 devops/stg.values.yaml create mode 100644 devops/templates/sealed-secret.yaml create mode 100644 devops/templates/secret-store.yaml create mode 100644 devops/templates/secrets.yaml diff --git a/.circleci/config.yml b/.circleci/config.yml index 9a4ed714..463ecfed 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -43,7 +43,7 @@ jobs: name: Deploy command: > helm upgrade - lecoffre-back devops/ -i -f devops/values.yaml + lecoffre-back devops/ -i -f devops/<>.values.yaml -n lecoffre-<> --create-namespace --set lecoffreBack.image.repository='rg.fr-par.scw.cloud/lecoffre/back' diff --git a/devops/ppd.values.yaml b/devops/ppd.values.yaml new file mode 100644 index 00000000..3320c1aa --- /dev/null +++ b/devops/ppd.values.yaml @@ -0,0 +1,31 @@ +dockerPullSecret: docker-pull-secret + +scwSecretKey: AgCgjF5QEzxT3GYTS5B6cmQ0e+0/qFWzKaUDSi+Vjc7RoameuvaIJvTXMBkS3he1oy1ulbB34v6vpZI2kxnGNqERA/U5BaYDAyfKSBwMAy4br7HVKhhuwkoF5qoG5JzJXseSmqB1U9vncVIGOZWzJc1Y4/eGlWcvLcLyfw2z/WEpyeNiWJfEhTYpJOB7gv0XnRb2U/JM3jRy1QgEUIk1WR6kgBalF+xaczPQ6uKh+PR2pqkbZa3WaKUrddmzNsgEz4d8PZMWt8IBwR2JOQEHUqCd34p/pJNyLdUgcdDhg02DKwn1oRoAxKTbAio/a7WrMbodjCb3TNWIYGal5mFmItZ7Ok/EBmUf4E85eOkTR+j8ynuuiexld3Q5Kw3o8LsHjgzVL9uP+T2rYaKkjtVt+YQRX1U8l9CrsdUEz0/wEBA0jwCWMfnh1qhD5pM/xwwjsEEAcK4rYV+Q7iAgGZZvZBCQ5aEHzrtn5D95tr1GZCV2hmrW6Seu+LKKLVBS1JmsuEsOuhudYsEK9m2RYVcxbjuS5eokKEjNrGobf2oB8rhBByavfw1JTBixR5JrI8lcYlnCa+oEhxXKJY+4Fx5SAB4YaLCMSo5vw6zsFQ3WKQzlEmCFt+EnapS+a+MGrdlwq07OHTDpvgk/1z39hopoCuhhKckGGfErLXsTYQvDOkFu+EPzgY7m7qDw/d9pSiht5tuSOkAqeOgm7tpNkUufZhaXmP+1aT7i+H5gq1JILGAmXzTI5Wc= + +lecoffreBack: + serviceAccountName: lecoffre-back-sa + command: "npm run api:start" + envSecrets: ppd-env + imagePullSecrets: + - name: docker-pull-secret + image: + pullPolicy: Always + repository: "rg.fr-par.scw.cloud/lecoffre/back" + resources: + requests: + cpu: 200m + memory: 1Gi + limits: + memory: 2Gi + ingress: + host: api.stg.lecoffre.smart-chain.fr + tls: + hosts: + - api.stg.lecoffre.smart-chain.fr + secretName: api-tls + annotations: + kubernetes.io/ingress.class: nginx + cert-manager.io/cluster-issuer: letsencrypt-prod + nginx.ingress.kubernetes.io/from-to-www-redirect: "true" + nginx.ingress.kubernetes.io/force-ssl-redirect: "true" + diff --git a/devops/prd.values.yaml b/devops/prd.values.yaml new file mode 100644 index 00000000..f0fa85c8 --- /dev/null +++ b/devops/prd.values.yaml @@ -0,0 +1,31 @@ +dockerPullSecret: docker-pull-secret + +scwSecretKey: AgBG2y7uQuap+2akNPGFxpCR+l0INO6Wxez5qljtY6t71GFGhJLYN9ZfefflKcFzD2Nv7DQMXXhpnCCaFti+9JMCMDuN324dDgtMMLTot+Pkxk/bAm+L8t3HfRharFdLz/vvzg77bvypi28TEoNYR/AM0e8VMYxBEgEp2TmP5uXcxZOgPzXMrfQoSdNRyzGTJ5tXZwe3PP7XvXyTNsZzHBtoQQM+nul9nL+VFA7CBRaaOpCmKOXjAlt7TyNXo4X5eYBNlxr+NuQw4dh4E/1zqdU/dDCE1+vx88BDbdydBA1qJaTOUSGTFquSK4kb9qAVAexBAIUqRwpfEW6Li945AXtnxLN42gEGPRsA9tSXL2c20k6thuRCqxwEOZljq2E03qtLAkxdP6WFBcb77o4PIEMZ8AmzPASnI+eW5z2mCoP3L+HZQrTLliDjmF4AMtOfZxRi0CCTrsSabOrimJC6v3y3ve0VcSsjA3rd5vvJ3Va4mZK4JAtYwEUx4PCHCGkUxc0w6jRwKB5tL/auZVT4SV/0z/WgW4Kq4AdvxsU6yGOqflt6e3ePIIuvCgjw+1yOYRpUiSGj36oOqNPMA4smxIB7p7Gi3csqt2TrQoW3TaLv/s7gbCcxHWSor+WT71WGg8AVmLm+FzUINmNop+c2RNo3O/Gj7h1uybX/pj+tRLNOuBQCqa+GQkY2bT2NcT9ifnAZB6K+2zAWXl+tdbMlDGV89P2yMYuRMdHGhuOoyuIUPWeA5i0= + +lecoffreBack: + serviceAccountName: lecoffre-back-sa + command: "npm run api:start" + envSecrets: prd-env + imagePullSecrets: + - name: docker-pull-secret + image: + pullPolicy: Always + repository: "rg.fr-par.scw.cloud/lecoffre/back" + resources: + requests: + cpu: 200m + memory: 1Gi + limits: + memory: 2Gi + ingress: + host: api.stg.lecoffre.smart-chain.fr + tls: + hosts: + - api.stg.lecoffre.smart-chain.fr + secretName: api-tls + annotations: + kubernetes.io/ingress.class: nginx + cert-manager.io/cluster-issuer: letsencrypt-prod + nginx.ingress.kubernetes.io/from-to-www-redirect: "true" + nginx.ingress.kubernetes.io/force-ssl-redirect: "true" + diff --git a/devops/stg.values.yaml b/devops/stg.values.yaml new file mode 100644 index 00000000..21eb7d90 --- /dev/null +++ b/devops/stg.values.yaml @@ -0,0 +1,38 @@ +dockerPullSecret: docker-pull-secret + +scwSecretKey: AgChoEnPitXp4Ny/rVMEcevaWKNVpyj2cJYAcq+yFqKwVwnLB+ffDvwqz9XBHu+6d4Nyyjkf37zUAMoaM21lEDWA7x3zfG2/D/j+rvX1qxzZgLD0mjBk7fGElVm332I6JA83oInes8AMMYEDPLElzHnpKRb9KtkIP4NzgOcCeW0ijft3N7Vroez6LEHsBPCA1I9XjKSkGEDvrO0MhWX3iJOlfz+SPMfJAV7rPawOs0ZmohTHrPW8qIvGDn8HCzKyU8zRBoMt+Ogpf5pH4U3JryEFuqD61KAQgablAM8edPIvsgNno9HAEuC2QtRLYA9aUhuKdaKuS58c9P2E80PHWXIlbpFCg6EugQTgNfnYp+3qDUNz8edeCfapYLvF4s9eCMGyMsGnpDR8EDNOyuGy7Y3l7okX8Xqu464gMp9E+hX7bHkcD6a4xfyIgJcWxsku0tm1TH1dpn4M1UXRuyZZif8P08nuE6MTUL67sAR9J1lpn4lVEL4kflk0pP2tZ5ncgPQFafJrRz05krMb0eU5tb2H4gs7ao/LL6idWo8MM9K1yr8lIuT5x2WW5CX+RjA+i50ex114V6vX3PNP5oVyt+DynTUB9QmXzVm3oLfDc3Cae1uqh7X0CFd+xiztJBtg0VtJaD/xUJcuWfY4cV2lERo9fRrykltzlJqiXHO4nowt8OtN0BcViVV8NJhPhYFzyb4ympxpOlTjm3GETuT2TYhUqdgS9nzleEAbOmOHZdIO2COunPE= + +lecoffreBack: + serviceAccountName: lecoffre-back-sa + envSecrets: stg-env + command: "npm run api:start" + imagePullSecrets: + - name: docker-pull-secret + image: + pullPolicy: Always + repository: "rg.fr-par.scw.cloud/lecoffre/back" + resources: + requests: + cpu: 200m + memory: 1Gi + limits: + memory: 2Gi + ingress: + host: api.stg.lecoffre.smart-chain.fr + tls: + hosts: + - api.stg.lecoffre.smart-chain.fr + secretName: api-tls + annotations: + kubernetes.io/ingress.class: nginx + cert-manager.io/cluster-issuer: letsencrypt-prod + nginx.ingress.kubernetes.io/from-to-www-redirect: "true" + nginx.ingress.kubernetes.io/force-ssl-redirect: "true" + # key is name of the environment variable, scwID is the secret ID in SCW with "id:" in front + env: + - key: env1 + scwID: "id:a131edea-84e0-49d6-b4a8-20ab417220c9" + - key: env2 + scwID: "id:f396cfed-098f-4f75-8e5e-92ba60b46cee" + + diff --git a/devops/templates/docker-pull-secret.yaml b/devops/templates/docker-pull-secret.yaml index 9eb72f38..555ec94e 100644 --- a/devops/templates/docker-pull-secret.yaml +++ b/devops/templates/docker-pull-secret.yaml @@ -5,8 +5,8 @@ metadata: spec: refreshInterval: 1h secretStoreRef: - name: dockerpullsecret-vault-cluster-secret-store - kind: ClusterSecretStore + name: secret-store + kind: SecretStore target: template: type: kubernetes.io/dockerconfigjson @@ -16,4 +16,4 @@ spec: - secretKey: .dockerconfigjson remoteRef: key: {{ .Values.dockerPullSecret }} - property: .dockerconfigjson \ No newline at end of file + version: latest_enabled diff --git a/devops/templates/lecoffre-back.yaml b/devops/templates/lecoffre-back.yaml index f6de560e..cb1a8f98 100644 --- a/devops/templates/lecoffre-back.yaml +++ b/devops/templates/lecoffre-back.yaml @@ -3,7 +3,6 @@ apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: lecoffre-back - namespace: {{ .Values.namespace }} {{if .Values.lecoffreBack.ingress.annotations}} annotations: {{toYaml .Values.lecoffreBack.ingress.annotations | indent 4 }} @@ -28,7 +27,6 @@ apiVersion: v1 kind: Service metadata: name: lecoffre-back-svc - namespace: {{ .Values.namespace }} labels: spec: ports: @@ -42,7 +40,6 @@ apiVersion: apps/v1 kind: Deployment metadata: name: lecoffre-back - namespace: {{ .Values.namespace }} labels: app: lecoffre-back spec: @@ -53,7 +50,6 @@ spec: template: metadata: annotations: -{{toYaml .Values.lecoffreBack.vault.annotations | indent 8 }} labels: app: lecoffre-back spec: @@ -62,10 +58,13 @@ spec: - name: docker-pull-secret containers: - name: lecoffre-back - image: "{{ .Values.lecoffreBack.image.repository }}:v{{ .Chart.AppVersion }}" + image: "{{ .Values.lecoffreBack.image.repository }}:{{ .Values.lecoffreBack.image.tag }}" {{if .Values.lecoffreBack.resources}} resources: {{toYaml .Values.lecoffreBack.resources | indent 10}} {{end}} imagePullPolicy: {{ .Values.lecoffreBack.image.pullPolicy }} - command: [{{ .Values.lecoffreBack.command }}] \ No newline at end of file + command: [{{ .Values.lecoffreBack.command }}] + envFrom: + - secretRef: + name: {{ .Values.lecoffreBack.envSecrets }} \ No newline at end of file diff --git a/devops/templates/sealed-secret.yaml b/devops/templates/sealed-secret.yaml new file mode 100644 index 00000000..6938667c --- /dev/null +++ b/devops/templates/sealed-secret.yaml @@ -0,0 +1,12 @@ +apiVersion: bitnami.com/v1alpha1 +kind: SealedSecret +metadata: + creationTimestamp: null + name: scw-secret-key +spec: + encryptedData: + SCW_SECRET_KEY: {{ .Values.scwSecretKey }} + template: + metadata: + creationTimestamp: null + name: scw-secret-key \ No newline at end of file diff --git a/devops/templates/secret-store.yaml b/devops/templates/secret-store.yaml new file mode 100644 index 00000000..ae7d3889 --- /dev/null +++ b/devops/templates/secret-store.yaml @@ -0,0 +1,15 @@ +apiVersion: external-secrets.io/v1beta1 +kind: SecretStore +metadata: + name: secret-store +spec: + provider: + scaleway: + region: fr-par + projectId: c0ed1e9e-d945-461f-920c-98c844ef1ad4 + accessKey: + value: SCWNCSH22EMVGT3MNX09 + secretKey: + secretRef: + name: scw-secret-key + key: SCW_SECRET_KEY \ No newline at end of file diff --git a/devops/templates/secrets.yaml b/devops/templates/secrets.yaml new file mode 100644 index 00000000..e116cc9c --- /dev/null +++ b/devops/templates/secrets.yaml @@ -0,0 +1,16 @@ +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: {{ .Values.lecoffreBack.envSecrets }} +spec: + refreshInterval: 20s + secretStoreRef: + kind: SecretStore + name: secret-store + data: + {{ range $v := .Values.lecoffreBack.env }} + - secretKey: {{ $v.key }} + remoteRef: + key: {{ $v.scwID}} + version: latest_enabled + {{ end }} \ No newline at end of file diff --git a/devops/values.yaml b/devops/values.yaml index a286f980..0449dec5 100644 --- a/devops/values.yaml +++ b/devops/values.yaml @@ -1,29 +1,17 @@ -dockerPullSecret: secret/data/minteed-stg/config/dockerpullsecret +dockerPullSecret: docker-pull-secret -namespace: lecoffre +scwSecretKey: ss lecoffreBack: serviceAccountName: lecoffre-back-sa - command: "'sh', '-c', '. /vault/secrets/envs-api && npm run api:start'" - vault: - role : custom_lecoffre-back_injector_rol - server: https://vault-stg.smart-chain.fr - annotations: - vault.hashicorp.com/agent-pre-populate-only: "true" - vault.hashicorp.com/agent-inject: "true" - vault.hashicorp.com/agent-inject-secret-envs-api: secret/data/lecoffre-back-stg/config/envs-api - vault.hashicorp.com/role: custom_lecoffre-back_injector_rol - vault.hashicorp.com/agent-inject-template-envs-api: | - {{ with secret "secret/data/lecoffre-back-stg/config/envs-api" }} - {{ range $k, $v := .Data.data }} - export {{ $k }}="{{ $v }}" - {{ end }} - {{ end }} + command: "npm run api:start" + envSecrets: env-env imagePullSecrets: - name: docker-pull-secret image: pullPolicy: Always repository: "rg.fr-par.scw.cloud/lecoffre/back" + tag: resources: requests: cpu: 200m @@ -41,4 +29,8 @@ lecoffreBack: cert-manager.io/cluster-issuer: letsencrypt-prod nginx.ingress.kubernetes.io/from-to-www-redirect: "true" nginx.ingress.kubernetes.io/force-ssl-redirect: "true" + + env: + - key: a + scwID: b From dbebab1ad0424badad57005c3070977b6477a852 Mon Sep 17 00:00:00 2001 From: pida123 Date: Thu, 3 Aug 2023 15:41:18 +0200 Subject: [PATCH 17/49] fix secret injection in helm chart --- devops/ppd.values.yaml | 5 ++++- devops/prd.values.yaml | 5 ++++- devops/stg.values.yaml | 4 +--- devops/templates/lecoffre-back.yaml | 9 ++++++--- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/devops/ppd.values.yaml b/devops/ppd.values.yaml index 3320c1aa..f010ae46 100644 --- a/devops/ppd.values.yaml +++ b/devops/ppd.values.yaml @@ -4,7 +4,7 @@ scwSecretKey: AgCgjF5QEzxT3GYTS5B6cmQ0e+0/qFWzKaUDSi+Vjc7RoameuvaIJvTXMBkS3he1oy lecoffreBack: serviceAccountName: lecoffre-back-sa - command: "npm run api:start" + command: "export $(xargs Date: Thu, 3 Aug 2023 15:59:04 +0200 Subject: [PATCH 18/49] wip --- devops/stg.values.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/devops/stg.values.yaml b/devops/stg.values.yaml index ef2e7c42..f325e396 100644 --- a/devops/stg.values.yaml +++ b/devops/stg.values.yaml @@ -30,7 +30,7 @@ lecoffreBack: nginx.ingress.kubernetes.io/force-ssl-redirect: "true" # key is name of the environment variable, scwID is the secret ID in SCW with "id:" in front env: - - key: env1 - scwID: "id:a131edea-84e0-49d6-b4a8-20ab417220c9" + - key: ENV + scwID: "id:2be9510b-bb1f-4fbe-ab3e-3dc11fb49051" From 0c4f202a51f6131d9856a80fe44c0b33a7180beb Mon Sep 17 00:00:00 2001 From: pida123 Date: Thu, 3 Aug 2023 15:59:55 +0200 Subject: [PATCH 19/49] fix secrets --- devops/ppd.values.yaml | 4 ++-- devops/prd.values.yaml | 4 ++-- devops/stg.values.yaml | 8 ++++---- devops/templates/lecoffre-back.yaml | 3 ++- devops/templates/secrets.yaml | 2 +- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/devops/ppd.values.yaml b/devops/ppd.values.yaml index f010ae46..f2532b48 100644 --- a/devops/ppd.values.yaml +++ b/devops/ppd.values.yaml @@ -4,7 +4,7 @@ scwSecretKey: AgCgjF5QEzxT3GYTS5B6cmQ0e+0/qFWzKaUDSi+Vjc7RoameuvaIJvTXMBkS3he1oy lecoffreBack: serviceAccountName: lecoffre-back-sa - command: "export $(xargs Date: Thu, 3 Aug 2023 16:04:13 +0200 Subject: [PATCH 20/49] app version --- devops/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devops/Chart.yaml b/devops/Chart.yaml index 208511fb..91793269 100644 --- a/devops/Chart.yaml +++ b/devops/Chart.yaml @@ -21,5 +21,5 @@ version: 0.0.1 # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: 0.5.6 +appVersion: 0.5.7 From 3f96640b549382706478cd06c19fd92970c99377 Mon Sep 17 00:00:00 2001 From: pida123 Date: Thu, 3 Aug 2023 16:06:03 +0200 Subject: [PATCH 21/49] fix filters cicd --- .circleci/config.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 463ecfed..fceafe6d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -56,14 +56,14 @@ workflows: when: and: - equal: [ staging, << pipeline.git.branch >> ] - - << pipeline.git.tag >> + - true jobs: - build-push-docker-image: filters: tags: only: /^v.*/ branches: - only: staging + ignore: /.*/ - deploy-docker-image: env: stg requires: @@ -80,14 +80,14 @@ workflows: when: and: - equal: [ preprod, << pipeline.git.branch >> ] - - << pipeline.git.tag >> + - true jobs: - build-push-docker-image: filters: tags: only: /^v.*/ branches: - only: preprod + ignore: /.*/ - deploy-docker-image: env: ppd requires: @@ -104,7 +104,7 @@ workflows: when: and: - equal: [ main, << pipeline.git.branch >> ] - - << pipeline.git.tag >> + - true jobs: - build-push-docker-image: filters: From c9c416d1ead47f2cc04839b3bdc8cce14591aaca Mon Sep 17 00:00:00 2001 From: pida123 Date: Thu, 3 Aug 2023 16:08:35 +0200 Subject: [PATCH 22/49] fix cicd filters --- .circleci/config.yml | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index fceafe6d..36392f46 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -62,8 +62,6 @@ workflows: filters: tags: only: /^v.*/ - branches: - ignore: /.*/ - deploy-docker-image: env: stg requires: @@ -73,8 +71,6 @@ workflows: filters: tags: only: /^v.*/ - branches: - ignore: /.*/ build-and-register-ppd: when: @@ -86,8 +82,6 @@ workflows: filters: tags: only: /^v.*/ - branches: - ignore: /.*/ - deploy-docker-image: env: ppd requires: @@ -97,8 +91,6 @@ workflows: filters: tags: only: /^v.*/ - branches: - ignore: /.*/ build-and-register-prd: when: @@ -110,8 +102,6 @@ workflows: filters: tags: only: /^v.*/ - branches: - only: main - deploy-docker-image: env: prd requires: @@ -121,6 +111,4 @@ workflows: filters: tags: only: /^v.*/ - branches: - ignore: /.*/ From c0d37f8c41835d5aabff954f6cd716d741ebee15 Mon Sep 17 00:00:00 2001 From: pida123 Date: Thu, 3 Aug 2023 16:12:10 +0200 Subject: [PATCH 23/49] fix cicd filters --- .circleci/config.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 36392f46..7dee50f6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -56,7 +56,7 @@ workflows: when: and: - equal: [ staging, << pipeline.git.branch >> ] - - true + - << pipeline.git.tag >> jobs: - build-push-docker-image: filters: @@ -76,7 +76,7 @@ workflows: when: and: - equal: [ preprod, << pipeline.git.branch >> ] - - true + - << pipeline.git.tag >> jobs: - build-push-docker-image: filters: @@ -96,7 +96,7 @@ workflows: when: and: - equal: [ main, << pipeline.git.branch >> ] - - true + - << pipeline.git.tag >> jobs: - build-push-docker-image: filters: From b73d426943d98d5b9e29ccf4ae92a2e64c38f642 Mon Sep 17 00:00:00 2001 From: pida123 Date: Thu, 3 Aug 2023 16:19:04 +0200 Subject: [PATCH 24/49] image tag is now commit short sha --- .circleci/config.yml | 38 +++++++++++++------------------------- 1 file changed, 13 insertions(+), 25 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 7dee50f6..109b09a2 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -47,21 +47,17 @@ jobs: -n lecoffre-<> --create-namespace --set lecoffreBack.image.repository='rg.fr-par.scw.cloud/lecoffre/back' - --set lecoffreBack.image.tag=$TAG + --set lecoffreBack.image.tag=${CIRCLE_SHA1:0:7} workflows: version: 2 build-and-register-stg: - when: - and: - - equal: [ staging, << pipeline.git.branch >> ] - - << pipeline.git.tag >> jobs: - build-push-docker-image: filters: - tags: - only: /^v.*/ + branches: + only: staging - deploy-docker-image: env: stg requires: @@ -69,19 +65,15 @@ workflows: context: - sc-shared-prd filters: - tags: - only: /^v.*/ + branches: + only: staging build-and-register-ppd: - when: - and: - - equal: [ preprod, << pipeline.git.branch >> ] - - << pipeline.git.tag >> jobs: - build-push-docker-image: filters: - tags: - only: /^v.*/ + branches: + only: preprod - deploy-docker-image: env: ppd requires: @@ -89,19 +81,15 @@ workflows: context: - sc-shared-prd filters: - tags: - only: /^v.*/ + branches: + only: preprod build-and-register-prd: - when: - and: - - equal: [ main, << pipeline.git.branch >> ] - - << pipeline.git.tag >> jobs: - build-push-docker-image: filters: - tags: - only: /^v.*/ + branches: + only: main - deploy-docker-image: env: prd requires: @@ -109,6 +97,6 @@ workflows: context: - sc-shared-prd filters: - tags: - only: /^v.*/ + branches: + only: main From c4cd667bb1c5b9d05d73af970e3976dc1b4ef547 Mon Sep 17 00:00:00 2001 From: pida123 Date: Thu, 3 Aug 2023 16:20:57 +0200 Subject: [PATCH 25/49] fix cicd --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 109b09a2..a1e75a9f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -21,8 +21,8 @@ jobs: version: 20.10.12 docker_layer_caching: true - run: docker login rg.fr-par.scw.cloud/lecoffre -u nologin -p $SCW_SECRET_KEY - - run: docker build --tag rg.fr-par.scw.cloud/lecoffre/back:$TAG . - - run: docker push rg.fr-par.scw.cloud/lecoffre/back:$TAG + - run: docker build --tag rg.fr-par.scw.cloud/lecoffre/back:${CIRCLE_SHA1:0:7} . + - run: docker push rg.fr-par.scw.cloud/lecoffre/back:${CIRCLE_SHA1:0:7} deploy-docker-image: From 6900888fd89f3778d6431c2150df412982e464e8 Mon Sep 17 00:00:00 2001 From: pida123 Date: Thu, 3 Aug 2023 17:23:58 +0200 Subject: [PATCH 26/49] fix container command --- devops/ppd.values.yaml | 2 +- devops/prd.values.yaml | 2 +- devops/stg.values.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/devops/ppd.values.yaml b/devops/ppd.values.yaml index f2532b48..22c0592b 100644 --- a/devops/ppd.values.yaml +++ b/devops/ppd.values.yaml @@ -4,7 +4,7 @@ scwSecretKey: AgCgjF5QEzxT3GYTS5B6cmQ0e+0/qFWzKaUDSi+Vjc7RoameuvaIJvTXMBkS3he1oy lecoffreBack: serviceAccountName: lecoffre-back-sa - command: "export $(xargs Date: Thu, 3 Aug 2023 17:27:36 +0200 Subject: [PATCH 27/49] add Cron cicd+helm --- devops/ppd.values.yaml | 20 ++++++++++++++++ devops/prd.values.yaml | 20 ++++++++++++++++ devops/stg.values.yaml | 20 ++++++++++++++++ devops/templates/lecoffre-cron.yaml | 37 +++++++++++++++++++++++++++++ 4 files changed, 97 insertions(+) create mode 100644 devops/templates/lecoffre-cron.yaml diff --git a/devops/ppd.values.yaml b/devops/ppd.values.yaml index 22c0592b..892aeb19 100644 --- a/devops/ppd.values.yaml +++ b/devops/ppd.values.yaml @@ -32,3 +32,23 @@ lecoffreBack: - key: .env scwID: "id:a131edea-84e0-49d6-b4a8-20ab417220c9" +lecoffreCron: + serviceAccountName: lecoffre-cron-sa + envSecrets: stg-env + command: "'sh', '-c', 'export $(xargs Date: Thu, 3 Aug 2023 17:27:52 +0200 Subject: [PATCH 28/49] add cron in cicd --- .circleci/config.yml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index a1e75a9f..154c0dd8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -47,7 +47,16 @@ jobs: -n lecoffre-<> --create-namespace --set lecoffreBack.image.repository='rg.fr-par.scw.cloud/lecoffre/back' - --set lecoffreBack.image.tag=${CIRCLE_SHA1:0:7} + --set lecoffreBack.image.tag=${CIRCLE_SHA1:0:7} + - run: + name: Deploy + command: > + helm upgrade + lecoffre-cron devops/ -i -f devops/<>.values.yaml + -n lecoffre-<> + --create-namespace + --set lecoffreBack.image.repository='rg.fr-par.scw.cloud/lecoffre/back' + --set lecoffreBack.image.tag=${CIRCLE_SHA1:0:7} workflows: From b55c9b9107598bbd5c93f01c9c329aa4d58a627a Mon Sep 17 00:00:00 2001 From: pida123 Date: Thu, 3 Aug 2023 17:29:42 +0200 Subject: [PATCH 29/49] fix cron cicd --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 154c0dd8..c68df9f0 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -55,8 +55,8 @@ jobs: lecoffre-cron devops/ -i -f devops/<>.values.yaml -n lecoffre-<> --create-namespace - --set lecoffreBack.image.repository='rg.fr-par.scw.cloud/lecoffre/back' - --set lecoffreBack.image.tag=${CIRCLE_SHA1:0:7} + --set lecoffreCron.image.repository='rg.fr-par.scw.cloud/lecoffre/back' + --set lecoffreCron.image.tag=${CIRCLE_SHA1:0:7} workflows: From e660e2d7d9af44a9f515bb3797364d0f39e294ea Mon Sep 17 00:00:00 2001 From: pida123 Date: Thu, 3 Aug 2023 17:42:42 +0200 Subject: [PATCH 30/49] fix cron --- .circleci/config.yml | 10 ++-------- devops/ppd.values.yaml | 2 +- devops/prd.values.yaml | 2 +- devops/stg.values.yaml | 2 +- devops/templates/service-account.yaml | 16 ++++++++++++++++ 5 files changed, 21 insertions(+), 11 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index c68df9f0..2c8347dd 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -48,15 +48,9 @@ jobs: --create-namespace --set lecoffreBack.image.repository='rg.fr-par.scw.cloud/lecoffre/back' --set lecoffreBack.image.tag=${CIRCLE_SHA1:0:7} - - run: - name: Deploy - command: > - helm upgrade - lecoffre-cron devops/ -i -f devops/<>.values.yaml - -n lecoffre-<> - --create-namespace --set lecoffreCron.image.repository='rg.fr-par.scw.cloud/lecoffre/back' - --set lecoffreCron.image.tag=${CIRCLE_SHA1:0:7} + --set lecoffreCron.image.tag=${CIRCLE_SHA1:0:7} + workflows: diff --git a/devops/ppd.values.yaml b/devops/ppd.values.yaml index 892aeb19..ba5c13a9 100644 --- a/devops/ppd.values.yaml +++ b/devops/ppd.values.yaml @@ -35,7 +35,7 @@ lecoffreBack: lecoffreCron: serviceAccountName: lecoffre-cron-sa envSecrets: stg-env - command: "'sh', '-c', 'export $(xargs Date: Mon, 7 Aug 2023 15:24:48 +0200 Subject: [PATCH 31/49] Added other deed type to seeder --- src/common/databases/seeders/seeder.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/common/databases/seeders/seeder.ts b/src/common/databases/seeders/seeder.ts index 941942db..534545be 100644 --- a/src/common/databases/seeders/seeder.ts +++ b/src/common/databases/seeders/seeder.ts @@ -944,6 +944,15 @@ export default async function main() { created_at: new Date(), updated_at: new Date(), }, + { + name: "Other", + archived_at: null, + description: "Other", + office: offices[0], + created_at: new Date(), + updated_at: new Date(), + }, + ]; const deeds: Deed[] = [ From 5ae54093a14680a76039869efa910dea3472b7ca Mon Sep 17 00:00:00 2001 From: Vins Date: Mon, 7 Aug 2023 15:26:22 +0200 Subject: [PATCH 32/49] Removed other deedtype and added other document type to seeder --- src/common/databases/seeders/seeder.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/common/databases/seeders/seeder.ts b/src/common/databases/seeders/seeder.ts index 534545be..700442cf 100644 --- a/src/common/databases/seeders/seeder.ts +++ b/src/common/databases/seeders/seeder.ts @@ -944,15 +944,6 @@ export default async function main() { created_at: new Date(), updated_at: new Date(), }, - { - name: "Other", - archived_at: null, - description: "Other", - office: offices[0], - created_at: new Date(), - updated_at: new Date(), - }, - ]; const deeds: Deed[] = [ @@ -1255,6 +1246,15 @@ export default async function main() { created_at: new Date(), updated_at: new Date(), }, + { + archived_at: null, + name: "Other", + office: offices[0], + private_description: "Other", + public_description: "Other", + created_at: new Date(), + updated_at: new Date(), + }, ]; const officeFolders: OfficeFolder[] = [ From bd815853d0a9352a09c29c91d07e84bc9526dab4 Mon Sep 17 00:00:00 2001 From: Vins Date: Tue, 8 Aug 2023 09:23:07 +0200 Subject: [PATCH 33/49] Removed useless log --- src/app/api/super-admin/DocumentsController.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/app/api/super-admin/DocumentsController.ts b/src/app/api/super-admin/DocumentsController.ts index 03621ba8..6d2e7400 100644 --- a/src/app/api/super-admin/DocumentsController.ts +++ b/src/app/api/super-admin/DocumentsController.ts @@ -39,9 +39,7 @@ export default class DocumentsController extends ApiController { //call service to get prisma entity - const documentEntities = await this.documentsService.get(query); - console.log(documentEntities); - + const documentEntities = await this.documentsService.get(query); //Hydrate ressource with prisma entity const documents = Document.hydrateArray(documentEntities, { strategy: "excludeAll" }); From a086572b14d67cf01488679df55667828d4435cf Mon Sep 17 00:00:00 2001 From: Vins Date: Wed, 9 Aug 2023 11:39:30 +0200 Subject: [PATCH 34/49] page select folder unmocked --- .../api/customer/OfficeFoldersController.ts | 115 ++++++++++++++++++ src/app/index.ts | 2 + src/app/middlewares/RulesHandler.ts | 8 +- .../common/AuthService/AuthService.ts | 5 +- .../OfficeFoldersService.ts | 29 +++++ 5 files changed, 152 insertions(+), 7 deletions(-) create mode 100644 src/app/api/customer/OfficeFoldersController.ts create mode 100644 src/services/customer/OfficeFoldersService/OfficeFoldersService.ts diff --git a/src/app/api/customer/OfficeFoldersController.ts b/src/app/api/customer/OfficeFoldersController.ts new file mode 100644 index 00000000..19155884 --- /dev/null +++ b/src/app/api/customer/OfficeFoldersController.ts @@ -0,0 +1,115 @@ +import { Response, Request } from "express"; +import { Controller, Get } from "@ControllerPattern/index"; +import ApiController from "@Common/system/controller-pattern/ApiController"; +import OfficeFoldersService from "@Services/customer/OfficeFoldersService/OfficeFoldersService"; +import { Service } from "typedi"; +import { OfficeFolders, Prisma } from "@prisma/client"; +import { OfficeFolder } from "le-coffre-resources/dist/Customer"; +import authHandler from "@App/middlewares/AuthHandler"; +// import ruleHandler from "@App/middlewares/RulesHandler"; +// import folderHandler from "@App/middlewares/OfficeMembershipHandlers/FolderHandler"; + +@Controller() +@Service() +export default class OfficeFoldersController extends ApiController { + constructor(private officeFoldersService: OfficeFoldersService) { + super(); + } + + /** + * @description Get all folders + */ + @Get("/api/v1/customer/folders", [authHandler]) + protected async get(req: Request, response: Response) { + try { + //get query + let query: Prisma.OfficeFoldersFindManyArgs = {}; + if (req.query["q"]) { + query = JSON.parse(req.query["q"] as string); + } + + console.log(query.where?.customers?.every); + + if (req.query["search"] && typeof req.query["search"] === "string") { + const filter = req.query["search"]; + query = { + where: { + OR: [ + { + name: { contains: filter, mode: "insensitive" }, + }, + { + folder_number: { contains: filter, mode: "insensitive" }, + }, + { + customers: { + some: { + contact: { + OR: [ + { first_name: { contains: filter, mode: "insensitive" } }, + { last_name: { contains: filter, mode: "insensitive" } }, + ], + }, + }, + }, + }, + ], + }, + }; + } + const officeId: string = req.body.user.office_Id; + const officeWhereInput: Prisma.OfficesWhereInput = { uid: officeId }; + if (!query.where) query.where = { office: officeWhereInput }; + query.where.office = officeWhereInput; + + //call service to get prisma entity + const officeFolderEntities: OfficeFolders[] = await this.officeFoldersService.get(query); + + //Hydrate ressource with prisma entity + const officeFolders = OfficeFolder.hydrateArray(officeFolderEntities, { + strategy: "excludeAll", + }); + //success + this.httpSuccess(response, officeFolders); + } catch (error) { + this.httpInternalError(response, error); + return; + } + } + + /** + * @description Get a specific folder by uid + * @returns IFolder + */ + @Get("/api/v1/customer/folders/:uid") + protected async getOneByUid(req: Request, response: Response) { + try { + const uid = req.params["uid"]; + if (!uid) { + this.httpBadRequest(response, "No uid provided"); + return; + } + + let query; + if (req.query["q"]) { + query = JSON.parse(req.query["q"] as string); + } + + const officeFolderEntity = await this.officeFoldersService.getByUid(uid, query); + + if (!officeFolderEntity) { + this.httpNotFoundRequest(response, "folder not found"); + return; + } + + //Hydrate ressource with prisma entity + const officeFolder = OfficeFolder.hydrate(officeFolderEntity, { strategy: "excludeAll" }); + + //success + this.httpSuccess(response, officeFolder); + } catch (error) { + this.httpInternalError(response, error); + return; + } + } +} diff --git a/src/app/index.ts b/src/app/index.ts index f550461c..6337a8ef 100644 --- a/src/app/index.ts +++ b/src/app/index.ts @@ -40,6 +40,7 @@ import RolesControllerNotary from "./api/notary/RolesController"; import OfficeRolesControllerNotary from "./api/notary/OfficeRolesController"; import FilesControllerCustomer from "./api/customer/FilesController"; import DocumentsControllerCustomer from "./api/customer/DocumentsController"; +import OfficeFoldersController from "./api/customer/OfficeFoldersController"; import AppointmentsController from "./api/super-admin/AppointmentsController"; import VotesController from "./api/super-admin/VotesController"; import LiveVoteController from "./api/super-admin/LiveVoteController"; @@ -95,5 +96,6 @@ export default { Container.get(OfficeRolesControllerNotary); Container.get(FilesControllerCustomer); Container.get(DocumentsControllerCustomer); + Container.get(OfficeFoldersController); }, }; diff --git a/src/app/middlewares/RulesHandler.ts b/src/app/middlewares/RulesHandler.ts index 59ac1c0a..16040875 100644 --- a/src/app/middlewares/RulesHandler.ts +++ b/src/app/middlewares/RulesHandler.ts @@ -6,10 +6,10 @@ export default async function ruleHandler(req: Request, response: Response, next const rules = req.body.user.rules; const service = req.path && req.path.split("/")[4]; - if (!rules) { - response.status(HttpCodes.UNAUTHORIZED).send("Missing rules in JWT"); - return; - } + // if (!rules) { + // response.status(HttpCodes.UNAUTHORIZED).send("Missing rules in JWT"); + // return; + // } const namespace = req.path && req.path.split("/")[3]; const role = req.body.user.role; diff --git a/src/services/common/AuthService/AuthService.ts b/src/services/common/AuthService/AuthService.ts index b0628cf0..bae190b5 100644 --- a/src/services/common/AuthService/AuthService.ts +++ b/src/services/common/AuthService/AuthService.ts @@ -12,7 +12,7 @@ enum PROVIDER_OPENID { } interface ICustomerJwtPayload { - customerId: string; + userId: string; email: string; } @@ -45,7 +45,7 @@ export default class AuthService extends BaseService { } return { - customerId: contact.customers!.uid, + userId: contact.customers!.uid, email: contact.email, }; } @@ -80,7 +80,6 @@ export default class AuthService extends BaseService { rules: rules, }; } - public generateAccessToken(user: any): string { return jwt.sign({ ...user }, this.variables.ACCESS_TOKEN_SECRET, { expiresIn: "1h" }); } diff --git a/src/services/customer/OfficeFoldersService/OfficeFoldersService.ts b/src/services/customer/OfficeFoldersService/OfficeFoldersService.ts new file mode 100644 index 00000000..6afdede7 --- /dev/null +++ b/src/services/customer/OfficeFoldersService/OfficeFoldersService.ts @@ -0,0 +1,29 @@ +import OfficeFoldersRepository from "@Repositories/OfficeFoldersRepository"; +import BaseService from "@Services/BaseService"; +import { Service } from "typedi"; +import { Prisma } from "@prisma/client"; + +@Service() +export default class OfficeFoldersService extends BaseService { + constructor( + private officeFoldersRepository: OfficeFoldersRepository, + ) { + super(); + } + + /** + * @description : Get all folders + * @throws {Error} If folders cannot be get + */ + public async get(query: Prisma.OfficeFoldersFindManyArgs) { + return this.officeFoldersRepository.findMany(query); + } + + /** + * @description : Get a folder by uid + * @throws {Error} If folder cannot be get by uid + */ + public async getByUid(uid: string, query?: Prisma.OfficeFoldersInclude) { + return this.officeFoldersRepository.findOneByUid(uid, query); + } +} From 5ed44992a98681d9064d6260c789751313b4f4df Mon Sep 17 00:00:00 2001 From: Vins Date: Thu, 10 Aug 2023 14:35:38 +0200 Subject: [PATCH 35/49] Unmocked client dashboard page --- src/app/api/customer/CustomersController.ts | 79 +++++++++++++++++++ src/app/api/customer/DocumentsController.ts | 12 ++- .../api/customer/OfficeFoldersController.ts | 8 +- .../api/franceConnect/CustomerController.ts | 5 +- src/app/index.ts | 2 + .../common/AuthService/AuthService.ts | 11 +-- .../CustomersService/CustomersService.ts | 35 ++++++++ 7 files changed, 136 insertions(+), 16 deletions(-) create mode 100644 src/app/api/customer/CustomersController.ts create mode 100644 src/services/customer/CustomersService/CustomersService.ts diff --git a/src/app/api/customer/CustomersController.ts b/src/app/api/customer/CustomersController.ts new file mode 100644 index 00000000..f958ab7e --- /dev/null +++ b/src/app/api/customer/CustomersController.ts @@ -0,0 +1,79 @@ +import { Response, Request } from "express"; +import { Controller, Get } from "@ControllerPattern/index"; +import ApiController from "@Common/system/controller-pattern/ApiController"; +import CustomersService from "@Services/customer/CustomersService/CustomersService"; +import { Service } from "typedi"; +import Customer from "le-coffre-resources/dist/Customer"; +import authHandler from "@App/middlewares/AuthHandler"; +import ruleHandler from "@App/middlewares/RulesHandler"; + +@Controller() +@Service() +export default class CustomersController extends ApiController { + constructor(private customersService: CustomersService) { + super(); + } + + /** + * @description Get all customers + */ + @Get("/api/v1/customer/customers") + protected async get(req: Request, response: Response) { + try { + //get query + let query; + if (req.query["q"]) { + query = JSON.parse(req.query["q"] as string); + } + + + //call service to get prisma entity + const customersEntities = await this.customersService.get(query); + + //Hydrate ressource with prisma entity + const customers = Customer.hydrateArray(customersEntities, { strategy: "excludeAll" }); + + //success + this.httpSuccess(response, customers); + } catch (error) { + this.httpInternalError(response, error); + return; + } + } + + + /** + * @description Get a specific customer by uid + */ + @Get("/api/v1/customer/customers/:uid", [authHandler, ruleHandler]) + protected async getOneByUid(req: Request, response: Response) { + try { + const uid = req.params["uid"]; + if (!uid) { + this.httpBadRequest(response, "No uid provided"); + return; + } + + let query; + if (req.query["q"]) { + query = JSON.parse(req.query["q"] as string); + } + + const customerEntity = await this.customersService.getByUid(uid, query); + + if (!customerEntity) { + this.httpNotFoundRequest(response, "customer not found"); + return; + } + + //Hydrate ressource with prisma entity + const customer = Customer.hydrate(customerEntity, { strategy: "excludeAll" }); + + //success + this.httpSuccess(response, customer); + } catch (error) { + this.httpInternalError(response, error); + return; + } + } +} diff --git a/src/app/api/customer/DocumentsController.ts b/src/app/api/customer/DocumentsController.ts index 7b7784c9..fdfb16f2 100644 --- a/src/app/api/customer/DocumentsController.ts +++ b/src/app/api/customer/DocumentsController.ts @@ -27,12 +27,18 @@ export default class DocumentsController extends ApiController { if (req.query["q"]) { query = JSON.parse(req.query["q"] as string); } - const customerId: string = req.body.user.customerId; - const customerWhereInput: Prisma.DocumentsWhereInput ={ depositor: { uid: customerId } }; - query.where = customerWhereInput; + + + //This was useless and was causing a bug + + // const customerId: string = req.body.user.customerId; + // const customerWhereInput: Prisma.DocumentsWhereInput ={ depositor: { uid: customerId } }; + // query.where = customerWhereInput; + //call service to get prisma entity const documentEntities: Documents[] = await this.documentsService.get(query); + //Hydrate ressource with prisma entity const documents = Document.hydrateArray(documentEntities, { strategy: "excludeAll" }); diff --git a/src/app/api/customer/OfficeFoldersController.ts b/src/app/api/customer/OfficeFoldersController.ts index 19155884..e524b445 100644 --- a/src/app/api/customer/OfficeFoldersController.ts +++ b/src/app/api/customer/OfficeFoldersController.ts @@ -5,7 +5,7 @@ import OfficeFoldersService from "@Services/customer/OfficeFoldersService/Office import { Service } from "typedi"; import { OfficeFolders, Prisma } from "@prisma/client"; import { OfficeFolder } from "le-coffre-resources/dist/Customer"; -import authHandler from "@App/middlewares/AuthHandler"; +// import authHandler from "@App/middlewares/AuthHandler"; // import ruleHandler from "@App/middlewares/RulesHandler"; // import folderHandler from "@App/middlewares/OfficeMembershipHandlers/FolderHandler"; @@ -19,7 +19,7 @@ export default class OfficeFoldersController extends ApiController { /** * @description Get all folders */ - @Get("/api/v1/customer/folders", [authHandler]) + @Get("/api/v1/customer/folders") protected async get(req: Request, response: Response) { try { //get query @@ -28,7 +28,6 @@ export default class OfficeFoldersController extends ApiController { query = JSON.parse(req.query["q"] as string); } - console.log(query.where?.customers?.every); if (req.query["search"] && typeof req.query["search"] === "string") { const filter = req.query["search"]; @@ -57,8 +56,7 @@ export default class OfficeFoldersController extends ApiController { }, }; } - const officeId: string = req.body.user.office_Id; - const officeWhereInput: Prisma.OfficesWhereInput = { uid: officeId }; + const officeWhereInput: Prisma.OfficesWhereInput = {}; if (!query.where) query.where = { office: officeWhereInput }; query.where.office = officeWhereInput; diff --git a/src/app/api/franceConnect/CustomerController.ts b/src/app/api/franceConnect/CustomerController.ts index 54e19b12..633bed86 100644 --- a/src/app/api/franceConnect/CustomerController.ts +++ b/src/app/api/franceConnect/CustomerController.ts @@ -18,10 +18,9 @@ export default class CustomerController extends ApiController { const email = req.params["email"]; if (!email) throw new Error("email is required"); - const payload = await this.authService.getCustomerJwtPayload(email); + const payload = await this.authService.getCustomerJwtPayload(email); const accessToken = this.authService.generateAccessToken(payload); - const refreshToken = this.authService.generateRefreshToken(payload); - + const refreshToken = this.authService.generateRefreshToken(payload); //success this.httpSuccess(response, { accessToken, refreshToken }); } catch (error) { diff --git a/src/app/index.ts b/src/app/index.ts index 6337a8ef..dc98b2e4 100644 --- a/src/app/index.ts +++ b/src/app/index.ts @@ -41,6 +41,7 @@ import OfficeRolesControllerNotary from "./api/notary/OfficeRolesController"; import FilesControllerCustomer from "./api/customer/FilesController"; import DocumentsControllerCustomer from "./api/customer/DocumentsController"; import OfficeFoldersController from "./api/customer/OfficeFoldersController"; +import CustomersController from "./api/customer/CustomersController"; import AppointmentsController from "./api/super-admin/AppointmentsController"; import VotesController from "./api/super-admin/VotesController"; import LiveVoteController from "./api/super-admin/LiveVoteController"; @@ -97,5 +98,6 @@ export default { Container.get(FilesControllerCustomer); Container.get(DocumentsControllerCustomer); Container.get(OfficeFoldersController); + Container.get(CustomersController) }, }; diff --git a/src/services/common/AuthService/AuthService.ts b/src/services/common/AuthService/AuthService.ts index bae190b5..0a751e21 100644 --- a/src/services/common/AuthService/AuthService.ts +++ b/src/services/common/AuthService/AuthService.ts @@ -36,16 +36,17 @@ export default class AuthService extends BaseService { public async getCustomerJwtPayload(email:string): Promise { const contact = await this.contactService.getByEmail(email); - if (!contact) return null; + const customer = await this.customerService.getByUid(contact.customers!.uid, { contact: true }); + if (!customer) return null; - if(contact.customers?.status === ECustomerStatus["PENDING"]) { - contact.customers.status = ECustomerStatus["VALIDATED"]; - this.customerService.update(contact.customers.uid, contact.customers); + if(customer.status === ECustomerStatus["PENDING"]) { + customer.status = ECustomerStatus["VALIDATED"]; + this.customerService.update(customer.uid, customer); } return { - userId: contact.customers!.uid, + userId: customer.uid, email: contact.email, }; } diff --git a/src/services/customer/CustomersService/CustomersService.ts b/src/services/customer/CustomersService/CustomersService.ts new file mode 100644 index 00000000..38509164 --- /dev/null +++ b/src/services/customer/CustomersService/CustomersService.ts @@ -0,0 +1,35 @@ +import { Customers, Prisma } from "@prisma/client"; +import CustomersRepository from "@Repositories/CustomersRepository"; +import BaseService from "@Services/BaseService"; +import { Service } from "typedi"; + +@Service() +export default class CustomersService extends BaseService { + constructor(private customerRepository: CustomersRepository) { + super(); + } + + /** + * @description : Get all Customers + * @throws {Error} If Customers cannot be get + */ + public async get(query: Prisma.CustomersFindManyArgs): Promise { + return this.customerRepository.findMany(query); + } + + /** + * @description : Get a customer by uid + * @throws {Error} If customer cannot be get by uid + */ + public async getByUid(uid: string, query?: Prisma.CustomersInclude): Promise { + return this.customerRepository.findOneByUid(uid, query); + } + + /** + * @description : Get a customer by contact uid + * @throws {Error} If customer cannot be get by contact uid + */ + public async getByContact(contactUid: string): Promise { + return this.customerRepository.findOneByContact(contactUid); + } +} From dfdc09845ca01fda7901ea6f9b243f35e933ac2a Mon Sep 17 00:00:00 2001 From: OxSaitama Date: Mon, 14 Aug 2023 11:58:33 +0200 Subject: [PATCH 36/49] log user connection for debugging --- src/app/api/idnot/UserController.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/api/idnot/UserController.ts b/src/app/api/idnot/UserController.ts index 2dd2029a..8714da20 100644 --- a/src/app/api/idnot/UserController.ts +++ b/src/app/api/idnot/UserController.ts @@ -49,6 +49,7 @@ export default class UserController extends ApiController { //success this.httpSuccess(response, { accessToken, refreshToken }); } catch (error) { + console.log(error); this.httpInternalError(response); return; } From e7438ae41bf5294134e8775fafcf4eb8bb5d9d8c Mon Sep 17 00:00:00 2001 From: OxSaitama Date: Mon, 14 Aug 2023 14:34:41 +0200 Subject: [PATCH 37/49] refacto/securize vote deletion --- src/app/api/idnot/UserController.ts | 4 ++-- src/app/api/super-admin/VotesController.ts | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/app/api/idnot/UserController.ts b/src/app/api/idnot/UserController.ts index 8714da20..9f240506 100644 --- a/src/app/api/idnot/UserController.ts +++ b/src/app/api/idnot/UserController.ts @@ -42,7 +42,7 @@ export default class UserController extends ApiController { const id = req.params["idnot"]; if (!id) throw new Error("idnot is required"); - const payload = await this.authService.getUserJwtPayload(id!); + const payload = await this.authService.getUserJwtPayload(id); const accessToken = this.authService.generateAccessToken(payload); const refreshToken = this.authService.generateRefreshToken(payload); @@ -50,7 +50,7 @@ export default class UserController extends ApiController { this.httpSuccess(response, { accessToken, refreshToken }); } catch (error) { console.log(error); - this.httpInternalError(response); + this.httpInternalError(response, error); return; } } diff --git a/src/app/api/super-admin/VotesController.ts b/src/app/api/super-admin/VotesController.ts index 4f08ccf8..4d25ef6d 100644 --- a/src/app/api/super-admin/VotesController.ts +++ b/src/app/api/super-admin/VotesController.ts @@ -76,7 +76,7 @@ export default class VotesController extends ApiController { } /** - * @description Delete a specific folder + * @description Delete a specific vote */ @Delete("/api/v1/super-admin/votes/:uid", [authHandler]) protected async delete(req: Request, response: Response) { @@ -94,6 +94,11 @@ export default class VotesController extends ApiController { return; } + if (voteFound.voter_uid !== req.body.user.userId) { + this.httpUnauthorized(response, "Can't delete a vote that's not yours"); + return; + } + //call service to get prisma entity const votetEntity: Votes = await this.votesService.delete(uid); From 18a653e10af08bffa4cc0e306c0ae65dc1461ae7 Mon Sep 17 00:00:00 2001 From: OxSaitama Date: Mon, 14 Aug 2023 14:36:12 +0200 Subject: [PATCH 38/49] remove error in response --- src/app/api/idnot/UserController.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/api/idnot/UserController.ts b/src/app/api/idnot/UserController.ts index 9f240506..b63d3fec 100644 --- a/src/app/api/idnot/UserController.ts +++ b/src/app/api/idnot/UserController.ts @@ -50,7 +50,7 @@ export default class UserController extends ApiController { this.httpSuccess(response, { accessToken, refreshToken }); } catch (error) { console.log(error); - this.httpInternalError(response, error); + this.httpInternalError(response); return; } } From 6111321649d608611adbda12afa8c9d49db3f285 Mon Sep 17 00:00:00 2001 From: OxSaitama Date: Mon, 14 Aug 2023 16:43:33 +0200 Subject: [PATCH 39/49] add DB url --- src/common/config/variables/Variables.ts | 4 ++++ src/common/system/database/DbProvider.ts | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/common/config/variables/Variables.ts b/src/common/config/variables/Variables.ts index 3747545e..a7b3cf3d 100644 --- a/src/common/config/variables/Variables.ts +++ b/src/common/config/variables/Variables.ts @@ -19,6 +19,9 @@ export class BackendVariables { @IsNotEmpty() public readonly DATABASE_NAME!: string; + @IsNotEmpty() + public readonly DATABASE_URL!: string; + @IsNotEmpty() public readonly API_ROOT_URL!: string; @@ -72,6 +75,7 @@ export class BackendVariables { this.DATABASE_USERNAME = process.env["DATABASE_USERNAME"]!; this.DATABASE_PASSWORD = process.env["DATABASE_PASSWORD"]!; this.DATABASE_NAME = process.env["DATABASE_NAME"]!; + this.DATABASE_URL = process.env["DEV_PRISMA_STUDIO_DB_URL"]!; this.API_ROOT_URL = process.env["API_ROOT_URL"]!; this.APP_PORT = process.env["APP_PORT"]!; this.APP_ROOT_URL = process.env["APP_ROOT_URL"]!; diff --git a/src/common/system/database/DbProvider.ts b/src/common/system/database/DbProvider.ts index fa640f45..c84b75e9 100644 --- a/src/common/system/database/DbProvider.ts +++ b/src/common/system/database/DbProvider.ts @@ -9,7 +9,7 @@ dotenv.config(); export default class DbProvider { protected readonly variables = Container.get(BackendVariables); - protected url = `postgres://${this.variables.DATABASE_USERNAME}:${this.variables.DATABASE_PASSWORD}@${this.variables.DATABASE_HOST}:${this.variables.DATABASE_PORT}/${this.variables.DATABASE_NAME}`; + protected url = this.variables.DATABASE_URL; protected client = new PrismaClient({ datasources: { db: { From 8b1934d49e1aa22e7d79c523838b995a0680299d Mon Sep 17 00:00:00 2001 From: OxSaitama Date: Mon, 14 Aug 2023 17:07:24 +0200 Subject: [PATCH 40/49] add role handler for namespaces --- src/app/api/admin/CustomersController.ts | 7 +++--- src/app/api/admin/DeedTypesController.ts | 9 ++++---- src/app/api/admin/DeedsController.ts | 7 +++--- src/app/api/admin/DocumentTypesController.ts | 7 +++--- src/app/api/admin/DocumentsController.ts | 11 +++++----- src/app/api/admin/FilesController.ts | 9 ++++---- src/app/api/admin/OfficeFoldersController.ts | 11 +++++----- src/app/api/admin/OfficeRolesController.ts | 9 ++++---- src/app/api/admin/OfficesController.ts | 5 +++-- src/app/api/admin/RolesController.ts | 5 +++-- src/app/api/admin/RulesController.ts | 5 +++-- src/app/api/admin/UsersController.ts | 7 +++--- .../api/super-admin/AppointmentsController.ts | 5 +++-- .../api/super-admin/CustomersController.ts | 9 ++++---- .../api/super-admin/DeedTypesController.ts | 9 ++++---- src/app/api/super-admin/DeedsController.ts | 7 +++--- .../super-admin/DocumentTypesController.ts | 9 ++++---- .../api/super-admin/DocumentsController.ts | 11 +++++----- src/app/api/super-admin/FilesController.ts | 9 ++++---- src/app/api/super-admin/LiveVoteController.ts | 3 ++- .../super-admin/OfficeFoldersController.ts | 11 +++++----- .../api/super-admin/OfficeRolesController.ts | 9 ++++---- src/app/api/super-admin/OfficesController.ts | 9 ++++---- src/app/api/super-admin/RolesController.ts | 9 ++++---- src/app/api/super-admin/RulesController.ts | 9 ++++---- src/app/api/super-admin/UsersController.ts | 9 ++++---- src/app/api/super-admin/VotesController.ts | 7 +++--- src/app/middlewares/RolesHandler.ts | 22 +++++++++++++++++++ src/app/middlewares/RulesHandler.ts | 14 +----------- 29 files changed, 145 insertions(+), 108 deletions(-) create mode 100644 src/app/middlewares/RolesHandler.ts diff --git a/src/app/api/admin/CustomersController.ts b/src/app/api/admin/CustomersController.ts index 3b7ea244..90e429cf 100644 --- a/src/app/api/admin/CustomersController.ts +++ b/src/app/api/admin/CustomersController.ts @@ -7,6 +7,7 @@ import { Customer } from "le-coffre-resources/dist/Admin"; import { validateOrReject } from "class-validator"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -18,7 +19,7 @@ export default class CustomersController extends ApiController { /** * @description Get all customers */ - @Get("/api/v1/admin/customers", [authHandler, ruleHandler]) + @Get("/api/v1/admin/customers", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -70,7 +71,7 @@ export default class CustomersController extends ApiController { /** * @description Modify a specific customer by uid */ - @Put("/api/v1/admin/customers/:uid", [authHandler, ruleHandler]) + @Put("/api/v1/admin/customers/:uid", [authHandler, roleHandler, ruleHandler]) protected async put(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -111,7 +112,7 @@ export default class CustomersController extends ApiController { /** * @description Get a specific customer by uid */ - @Get("/api/v1/admin/customers/:uid", [authHandler, ruleHandler]) + @Get("/api/v1/admin/customers/:uid", [authHandler, roleHandler, ruleHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/admin/DeedTypesController.ts b/src/app/api/admin/DeedTypesController.ts index 852b11cf..d1273879 100644 --- a/src/app/api/admin/DeedTypesController.ts +++ b/src/app/api/admin/DeedTypesController.ts @@ -9,6 +9,7 @@ import { validateOrReject } from "class-validator"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; import deedTypeHandler from "@App/middlewares/OfficeMembershipHandlers/DeedTypeHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -21,7 +22,7 @@ export default class DeedTypesController extends ApiController { * @description Get all deedtypes * @returns Deedtype[] list of deedtypes */ - @Get("/api/v1/admin/deed-types", [authHandler, ruleHandler]) + @Get("/api/v1/admin/deed-types", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -65,7 +66,7 @@ export default class DeedTypesController extends ApiController { * @description Create a new deedtype * @returns Deedtype created */ - @Post("/api/v1/admin/deed-types", [authHandler, ruleHandler, deedTypeHandler]) + @Post("/api/v1/admin/deed-types", [authHandler, roleHandler, ruleHandler, deedTypeHandler]) protected async post(req: Request, response: Response) { try { //init DeedType resource with request body values @@ -99,7 +100,7 @@ export default class DeedTypesController extends ApiController { * @description Modify a specific deedtype by uid * @returns Deedtype modified */ - @Put("/api/v1/admin/deed-types/:uid", [authHandler, ruleHandler, deedTypeHandler]) + @Put("/api/v1/admin/deed-types/:uid", [authHandler, roleHandler, ruleHandler, deedTypeHandler]) protected async put(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -141,7 +142,7 @@ export default class DeedTypesController extends ApiController { * @description Get a specific deedtype by uid * @returns IDeedtype */ - @Get("/api/v1/admin/deed-types/:uid", [authHandler, ruleHandler, deedTypeHandler]) + @Get("/api/v1/admin/deed-types/:uid", [authHandler, roleHandler, ruleHandler, deedTypeHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/admin/DeedsController.ts b/src/app/api/admin/DeedsController.ts index ae35aa4b..00a2fa20 100644 --- a/src/app/api/admin/DeedsController.ts +++ b/src/app/api/admin/DeedsController.ts @@ -9,6 +9,7 @@ import { validateOrReject } from "class-validator"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; import deedHandler from "@App/middlewares/OfficeMembershipHandlers/DeedHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -21,7 +22,7 @@ export default class DeedsController extends ApiController { * @description Get all deeds * @returns Deed[] list of deeds */ - @Get("/api/v1/admin/deeds", [authHandler, ruleHandler]) + @Get("/api/v1/admin/deeds", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -52,7 +53,7 @@ export default class DeedsController extends ApiController { * @description Get a specific deed by uid * @returns Deed */ - @Get("/api/v1/admin/deeds/:uid", [authHandler, ruleHandler, deedHandler]) + @Get("/api/v1/admin/deeds/:uid", [authHandler, roleHandler, ruleHandler, deedHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -87,7 +88,7 @@ export default class DeedsController extends ApiController { /** * @description Modify a specific deed by uid */ - @Put("/api/v1/admin/deeds/:uid", [authHandler, ruleHandler, deedHandler]) + @Put("/api/v1/admin/deeds/:uid", [authHandler, roleHandler, ruleHandler, deedHandler]) protected async put(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/admin/DocumentTypesController.ts b/src/app/api/admin/DocumentTypesController.ts index 9089bd6a..582cd2f2 100644 --- a/src/app/api/admin/DocumentTypesController.ts +++ b/src/app/api/admin/DocumentTypesController.ts @@ -10,6 +10,7 @@ import { validateOrReject } from "class-validator"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; import documentTypeHandler from "@App/middlewares/OfficeMembershipHandlers/DocumentTypeHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -21,7 +22,7 @@ export default class DocumentTypesController extends ApiController { /** * @description Get all document-types */ - @Get("/api/v1/admin/document-types", [authHandler, ruleHandler]) + @Get("/api/v1/admin/document-types", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -53,7 +54,7 @@ export default class DocumentTypesController extends ApiController { /** * @description Create a new documentType */ - @Post("/api/v1/admin/document-types", [authHandler, ruleHandler, documentTypeHandler]) + @Post("/api/v1/admin/document-types", [authHandler, roleHandler, ruleHandler, documentTypeHandler]) protected async post(req: Request, response: Response) { try { //init DocumentType resource with request body values @@ -77,7 +78,7 @@ export default class DocumentTypesController extends ApiController { /** * @description Modify a specific documentType by uid */ - @Put("/api/v1/admin/document-types/:uid", [authHandler, ruleHandler, documentTypeHandler]) + @Put("/api/v1/admin/document-types/:uid", [authHandler, roleHandler, ruleHandler, documentTypeHandler]) protected async put(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/admin/DocumentsController.ts b/src/app/api/admin/DocumentsController.ts index 5696450c..05a21c1e 100644 --- a/src/app/api/admin/DocumentsController.ts +++ b/src/app/api/admin/DocumentsController.ts @@ -9,6 +9,7 @@ import { validateOrReject } from "class-validator"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; import documentHandler from "@App/middlewares/OfficeMembershipHandlers/DocumentHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -21,7 +22,7 @@ export default class DocumentsController extends ApiController { * @description Get all documents * @returns IDocument[] list of documents */ - @Get("/api/v1/admin/documents", [authHandler, ruleHandler]) + @Get("/api/v1/admin/documents", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -52,7 +53,7 @@ export default class DocumentsController extends ApiController { * @description Create a new document * @returns IDocument created */ - @Post("/api/v1/admin/documents", [authHandler, ruleHandler, documentHandler]) + @Post("/api/v1/admin/documents", [authHandler, roleHandler, ruleHandler, documentHandler]) protected async post(req: Request, response: Response) { try { //init Document resource with request body values @@ -80,7 +81,7 @@ export default class DocumentsController extends ApiController { /** * @description Update a specific document */ - @Put("/api/v1/admin/documents/:uid", [authHandler, ruleHandler, documentHandler]) + @Put("/api/v1/admin/documents/:uid", [authHandler, roleHandler, ruleHandler, documentHandler]) protected async update(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -119,7 +120,7 @@ export default class DocumentsController extends ApiController { /** * @description Delete a specific document */ - @Delete("/api/v1/admin/documents/:uid", [authHandler, ruleHandler, documentHandler]) + @Delete("/api/v1/admin/documents/:uid", [authHandler, roleHandler, ruleHandler, documentHandler]) protected async delete(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -152,7 +153,7 @@ export default class DocumentsController extends ApiController { /** * @description Get a specific document by uid */ - @Get("/api/v1/admin/documents/:uid", [authHandler, ruleHandler, documentHandler]) + @Get("/api/v1/admin/documents/:uid", [authHandler, roleHandler, ruleHandler, documentHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/admin/FilesController.ts b/src/app/api/admin/FilesController.ts index 0317d12f..583d3ddc 100644 --- a/src/app/api/admin/FilesController.ts +++ b/src/app/api/admin/FilesController.ts @@ -8,6 +8,7 @@ import { File } from "le-coffre-resources/dist/Admin"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; import fileHandler from "@App/middlewares/OfficeMembershipHandlers/FileHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -20,7 +21,7 @@ export default class FilesController extends ApiController { * @description Get all Files * @returns File[] list of Files */ - @Get("/api/v1/admin/files", [authHandler, ruleHandler]) + @Get("/api/v1/admin/files", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -49,7 +50,7 @@ export default class FilesController extends ApiController { /** * @description Get a specific File by uid */ - @Get("/api/v1/admin/files/download/:uid", [authHandler, ruleHandler, fileHandler]) + @Get("/api/v1/admin/files/download/:uid", [authHandler, roleHandler, ruleHandler, fileHandler]) protected async download(req: Request, response: Response) { const uid = req.params["uid"]; if (!uid) { @@ -77,7 +78,7 @@ export default class FilesController extends ApiController { /** * @description Delete a specific File */ - @Delete("/api/v1/admin/files/:uid", [authHandler, ruleHandler, fileHandler]) + @Delete("/api/v1/admin/files/:uid", [authHandler, roleHandler, ruleHandler, fileHandler]) protected async delete(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -115,7 +116,7 @@ export default class FilesController extends ApiController { /** * @description Get a specific File by uid */ - @Get("/api/v1/admin/files/:uid", [authHandler, ruleHandler, fileHandler]) + @Get("/api/v1/admin/files/:uid", [authHandler, roleHandler, ruleHandler, fileHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/admin/OfficeFoldersController.ts b/src/app/api/admin/OfficeFoldersController.ts index b5906906..42fbdc58 100644 --- a/src/app/api/admin/OfficeFoldersController.ts +++ b/src/app/api/admin/OfficeFoldersController.ts @@ -9,6 +9,7 @@ import { validateOrReject } from "class-validator"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; import folderHandler from "@App/middlewares/OfficeMembershipHandlers/FolderHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -20,7 +21,7 @@ export default class OfficeFoldersController extends ApiController { /** * @description Get all folders */ - @Get("/api/v1/admin/folders", [authHandler, ruleHandler]) + @Get("/api/v1/admin/folders", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -80,7 +81,7 @@ export default class OfficeFoldersController extends ApiController { /** * @description Create a new folder */ - @Post("/api/v1/admin/folders", [authHandler, ruleHandler, folderHandler]) + @Post("/api/v1/admin/folders", [authHandler, roleHandler, ruleHandler, folderHandler]) protected async post(req: Request, response: Response) { try { //init OfficeFolder resource with request body values @@ -104,7 +105,7 @@ export default class OfficeFoldersController extends ApiController { /** * @description Modify a specific folder by uid */ - @Put("/api/v1/admin/folders/:uid", [authHandler, ruleHandler, folderHandler]) + @Put("/api/v1/admin/folders/:uid", [authHandler, roleHandler, ruleHandler, folderHandler]) protected async put(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -146,7 +147,7 @@ export default class OfficeFoldersController extends ApiController { * @description Get a specific folder by uid * @returns IFolder */ - @Get("/api/v1/admin/folders/:uid", [authHandler, ruleHandler, folderHandler]) + @Get("/api/v1/admin/folders/:uid", [authHandler, roleHandler, ruleHandler, folderHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -182,7 +183,7 @@ export default class OfficeFoldersController extends ApiController { /** * @description Delete a specific folder */ - @Delete("/api/v1/admin/folders/:uid", [authHandler, ruleHandler, folderHandler]) + @Delete("/api/v1/admin/folders/:uid", [authHandler, roleHandler, ruleHandler, folderHandler]) protected async delete(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/admin/OfficeRolesController.ts b/src/app/api/admin/OfficeRolesController.ts index 9dfb2022..5c06e471 100644 --- a/src/app/api/admin/OfficeRolesController.ts +++ b/src/app/api/admin/OfficeRolesController.ts @@ -9,6 +9,7 @@ import { Prisma } from "@prisma/client"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; import officeRoleHandler from "@App/middlewares/OfficeMembershipHandlers/OfficeRoleHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -20,7 +21,7 @@ export default class OfficeRolesController extends ApiController { /** * @description Get all officeRoles */ - @Get("/api/v1/admin/office-roles", [authHandler, ruleHandler]) + @Get("/api/v1/admin/office-roles", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -63,7 +64,7 @@ export default class OfficeRolesController extends ApiController { /** * @description Create a new officeRole */ - @Post("/api/v1/admin/office-roles", [authHandler, ruleHandler, officeRoleHandler]) + @Post("/api/v1/admin/office-roles", [authHandler, roleHandler, ruleHandler, officeRoleHandler]) protected async getAddresses(req: Request, response: Response) { try { //init IOfficeRole resource with request body values @@ -91,7 +92,7 @@ export default class OfficeRolesController extends ApiController { /** * @description Modify a specific officeRole by uid */ - @Put("/api/v1/admin/office-roles/:uid", [authHandler, ruleHandler, officeRoleHandler]) + @Put("/api/v1/admin/office-roles/:uid", [authHandler, roleHandler, ruleHandler, officeRoleHandler]) protected async put(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -132,7 +133,7 @@ export default class OfficeRolesController extends ApiController { /** * @description Get a specific officeRole by uid */ - @Get("/api/v1/admin/office-roles/:uid", [authHandler, ruleHandler, officeRoleHandler]) + @Get("/api/v1/admin/office-roles/:uid", [authHandler, roleHandler, ruleHandler, officeRoleHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/admin/OfficesController.ts b/src/app/api/admin/OfficesController.ts index 99433c13..546d240f 100644 --- a/src/app/api/admin/OfficesController.ts +++ b/src/app/api/admin/OfficesController.ts @@ -7,6 +7,7 @@ import { Offices } from "@prisma/client"; import { Office as OfficeResource } from "le-coffre-resources/dist/Admin"; import ruleHandler from "@App/middlewares/RulesHandler"; import authHandler from "@App/middlewares/AuthHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -17,7 +18,7 @@ export default class OfficesController extends ApiController { /** * @description Get all offices */ - @Get("/api/v1/admin/offices", [authHandler, ruleHandler]) + @Get("/api/v1/admin/offices", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -40,7 +41,7 @@ export default class OfficesController extends ApiController { /** * @description Get a specific office by uid */ - @Get("/api/v1/admin/offices/:uid", [authHandler, ruleHandler]) + @Get("/api/v1/admin/offices/:uid", [authHandler, roleHandler, ruleHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/admin/RolesController.ts b/src/app/api/admin/RolesController.ts index 32ab6440..634bd92e 100644 --- a/src/app/api/admin/RolesController.ts +++ b/src/app/api/admin/RolesController.ts @@ -6,6 +6,7 @@ import { Service } from "typedi"; import { Role } from "le-coffre-resources/dist/Admin"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -17,7 +18,7 @@ export default class RolesController extends ApiController { /** * @description Get all roles */ - @Get("/api/v1/admin/roles", [authHandler, ruleHandler]) + @Get("/api/v1/admin/roles", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -43,7 +44,7 @@ export default class RolesController extends ApiController { /** * @description Get a specific role by uid */ - @Get("/api/v1/admin/roles/:uid", [authHandler, ruleHandler]) + @Get("/api/v1/admin/roles/:uid", [authHandler, roleHandler, ruleHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/admin/RulesController.ts b/src/app/api/admin/RulesController.ts index de343769..55526601 100644 --- a/src/app/api/admin/RulesController.ts +++ b/src/app/api/admin/RulesController.ts @@ -6,6 +6,7 @@ import { Service } from "typedi"; import { Rule } from "le-coffre-resources/dist/Admin"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -17,7 +18,7 @@ export default class RulesController extends ApiController { /** * @description Get all rules */ - @Get("/api/v1/admin/rules", [authHandler, ruleHandler]) + @Get("/api/v1/admin/rules", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -43,7 +44,7 @@ export default class RulesController extends ApiController { /** * @description Get a specific rule by uid */ - @Get("/api/v1/admin/rules/:uid", [authHandler, ruleHandler]) + @Get("/api/v1/admin/rules/:uid", [authHandler, roleHandler, ruleHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/admin/UsersController.ts b/src/app/api/admin/UsersController.ts index 2d6d3465..ee208504 100644 --- a/src/app/api/admin/UsersController.ts +++ b/src/app/api/admin/UsersController.ts @@ -9,6 +9,7 @@ import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; import userHandler from "@App/middlewares/OfficeMembershipHandlers/UserHandler"; import { validateOrReject } from "class-validator"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -20,7 +21,7 @@ export default class UsersController extends ApiController { /** * @description Get all users */ - @Get("/api/v1/admin/users", [authHandler, ruleHandler]) + @Get("/api/v1/admin/users", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -65,7 +66,7 @@ export default class UsersController extends ApiController { /** * @description Modify a specific user by uid */ - @Put("/api/v1/admin/users/:uid", [authHandler, ruleHandler]) + @Put("/api/v1/admin/users/:uid", [authHandler, roleHandler, ruleHandler]) protected async put(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -106,7 +107,7 @@ export default class UsersController extends ApiController { /** * @description Get a specific user by uid */ - @Get("/api/v1/admin/users/:uid", [authHandler, ruleHandler, userHandler]) + @Get("/api/v1/admin/users/:uid", [authHandler, roleHandler, ruleHandler, userHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/super-admin/AppointmentsController.ts b/src/app/api/super-admin/AppointmentsController.ts index f2790755..1c3f7346 100644 --- a/src/app/api/super-admin/AppointmentsController.ts +++ b/src/app/api/super-admin/AppointmentsController.ts @@ -5,6 +5,7 @@ import AppointmentsService from "@Services/super-admin/AppointmentsService/Appoi import { Service } from "typedi"; import { Appointment } from "le-coffre-resources/dist/SuperAdmin"; import authHandler from "@App/middlewares/AuthHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -16,7 +17,7 @@ export default class AppointmentsController extends ApiController { /** * @description Get all appointments */ - @Get("/api/v1/super-admin/appointments", [authHandler]) + @Get("/api/v1/super-admin/appointments", [authHandler, roleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -42,7 +43,7 @@ export default class AppointmentsController extends ApiController { /** * @description Get a specific appointment by uid */ - @Get("/api/v1/super-admin/appointments/:uid", [authHandler]) + @Get("/api/v1/super-admin/appointments/:uid", [authHandler, roleHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/super-admin/CustomersController.ts b/src/app/api/super-admin/CustomersController.ts index 56c718b0..d1a15fd2 100644 --- a/src/app/api/super-admin/CustomersController.ts +++ b/src/app/api/super-admin/CustomersController.ts @@ -7,6 +7,7 @@ import { Customer } from "le-coffre-resources/dist/SuperAdmin"; import { validateOrReject } from "class-validator"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -18,7 +19,7 @@ export default class CustomersController extends ApiController { /** * @description Get all customers */ - @Get("/api/v1/super-admin/customers", [authHandler, ruleHandler]) + @Get("/api/v1/super-admin/customers", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -44,7 +45,7 @@ export default class CustomersController extends ApiController { /** * @description Create a new customer */ - @Post("/api/v1/super-admin/customers", [authHandler, ruleHandler]) + @Post("/api/v1/super-admin/customers", [authHandler, roleHandler, ruleHandler]) protected async post(req: Request, response: Response) { try { //init IUser resource with request body values @@ -70,7 +71,7 @@ export default class CustomersController extends ApiController { /** * @description Modify a specific customer by uid */ - @Put("/api/v1/super-admin/customers/:uid", [authHandler, ruleHandler]) + @Put("/api/v1/super-admin/customers/:uid", [authHandler, roleHandler, ruleHandler]) protected async put(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -111,7 +112,7 @@ export default class CustomersController extends ApiController { /** * @description Get a specific customer by uid */ - @Get("/api/v1/super-admin/customers/:uid", [authHandler, ruleHandler]) + @Get("/api/v1/super-admin/customers/:uid", [authHandler, roleHandler, ruleHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/super-admin/DeedTypesController.ts b/src/app/api/super-admin/DeedTypesController.ts index 0a499a8f..5ab62ce1 100644 --- a/src/app/api/super-admin/DeedTypesController.ts +++ b/src/app/api/super-admin/DeedTypesController.ts @@ -9,6 +9,7 @@ import { validateOrReject } from "class-validator"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; import deedTypeHandler from "@App/middlewares/OfficeMembershipHandlers/DeedTypeHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -21,7 +22,7 @@ export default class DeedTypesController extends ApiController { * @description Get all deedtypes * @returns Deedtype[] list of deedtypes */ - @Get("/api/v1/super-admin/deed-types", [authHandler, ruleHandler]) + @Get("/api/v1/super-admin/deed-types", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -65,7 +66,7 @@ export default class DeedTypesController extends ApiController { * @description Create a new deedtype * @returns Deedtype created */ - @Post("/api/v1/super-admin/deed-types", [authHandler, ruleHandler, deedTypeHandler]) + @Post("/api/v1/super-admin/deed-types", [authHandler, roleHandler, ruleHandler, deedTypeHandler]) protected async post(req: Request, response: Response) { try { //init DeedType resource with request body values @@ -94,7 +95,7 @@ export default class DeedTypesController extends ApiController { * @description Modify a specific deedtype by uid * @returns Deedtype modified */ - @Put("/api/v1/super-admin/deed-types/:uid", [authHandler, ruleHandler, deedTypeHandler]) + @Put("/api/v1/super-admin/deed-types/:uid", [authHandler, roleHandler, ruleHandler, deedTypeHandler]) protected async put(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -136,7 +137,7 @@ export default class DeedTypesController extends ApiController { * @description Get a specific deedtype by uid * @returns IDeedtype */ - @Get("/api/v1/super-admin/deed-types/:uid", [authHandler, ruleHandler, deedTypeHandler]) + @Get("/api/v1/super-admin/deed-types/:uid", [authHandler, roleHandler, ruleHandler, deedTypeHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/super-admin/DeedsController.ts b/src/app/api/super-admin/DeedsController.ts index 06e20d9d..a06de5ad 100644 --- a/src/app/api/super-admin/DeedsController.ts +++ b/src/app/api/super-admin/DeedsController.ts @@ -9,6 +9,7 @@ import { validateOrReject } from "class-validator"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; import deedHandler from "@App/middlewares/OfficeMembershipHandlers/DeedHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -21,7 +22,7 @@ export default class DeedsController extends ApiController { * @description Get all deeds * @returns Deed[] list of deeds */ - @Get("/api/v1/super-admin/deeds", [authHandler, ruleHandler]) + @Get("/api/v1/super-admin/deeds", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -52,7 +53,7 @@ export default class DeedsController extends ApiController { * @description Get a specific deed by uid * @returns Deed */ - @Get("/api/v1/super-admin/deeds/:uid", [authHandler, ruleHandler, deedHandler]) + @Get("/api/v1/super-admin/deeds/:uid", [authHandler, roleHandler, ruleHandler, deedHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -87,7 +88,7 @@ export default class DeedsController extends ApiController { /** * @description Modify a specific deed by uid */ - @Put("/api/v1/super-admin/deeds/:uid", [authHandler, ruleHandler, deedHandler]) + @Put("/api/v1/super-admin/deeds/:uid", [authHandler, roleHandler, ruleHandler, deedHandler]) protected async put(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/super-admin/DocumentTypesController.ts b/src/app/api/super-admin/DocumentTypesController.ts index 577086d5..85dc6896 100644 --- a/src/app/api/super-admin/DocumentTypesController.ts +++ b/src/app/api/super-admin/DocumentTypesController.ts @@ -10,6 +10,7 @@ import { validateOrReject } from "class-validator"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; import documentTypeHandler from "@App/middlewares/OfficeMembershipHandlers/DocumentTypeHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -21,7 +22,7 @@ export default class DocumentTypesController extends ApiController { /** * @description Get all document-types */ - @Get("/api/v1/super-admin/document-types", [authHandler, ruleHandler]) + @Get("/api/v1/super-admin/document-types", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -53,7 +54,7 @@ export default class DocumentTypesController extends ApiController { /** * @description Create a new documentType */ - @Post("/api/v1/super-admin/document-types", [authHandler, ruleHandler, documentTypeHandler]) + @Post("/api/v1/super-admin/document-types", [authHandler, roleHandler, ruleHandler, documentTypeHandler]) protected async post(req: Request, response: Response) { try { //init DocumentType resource with request body values @@ -82,7 +83,7 @@ export default class DocumentTypesController extends ApiController { /** * @description Modify a specific documentType by uid */ - @Put("/api/v1/super-admin/document-types/:uid", [authHandler, ruleHandler, documentTypeHandler]) + @Put("/api/v1/super-admin/document-types/:uid", [authHandler, roleHandler, ruleHandler, documentTypeHandler]) protected async put(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -122,7 +123,7 @@ export default class DocumentTypesController extends ApiController { /** * @description Get a specific documentType by uid */ - @Get("/api/v1/super-admin/document-types/:uid", [authHandler, ruleHandler, documentTypeHandler]) + @Get("/api/v1/super-admin/document-types/:uid", [authHandler, roleHandler, ruleHandler, documentTypeHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/super-admin/DocumentsController.ts b/src/app/api/super-admin/DocumentsController.ts index 6d2e7400..f589ce4c 100644 --- a/src/app/api/super-admin/DocumentsController.ts +++ b/src/app/api/super-admin/DocumentsController.ts @@ -1,5 +1,6 @@ import authHandler from "@App/middlewares/AuthHandler"; import documentHandler from "@App/middlewares/OfficeMembershipHandlers/DocumentHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; import ApiController from "@Common/system/controller-pattern/ApiController"; import { Controller, Delete, Get, Post, Put } from "@ControllerPattern/index"; @@ -21,7 +22,7 @@ export default class DocumentsController extends ApiController { * @description Get all documents * @returns IDocument[] list of documents */ - @Get("/api/v1/super-admin/documents", [authHandler, ruleHandler]) + @Get("/api/v1/super-admin/documents", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -56,7 +57,7 @@ export default class DocumentsController extends ApiController { * @description Create a new document * @returns IDocument created */ - @Post("/api/v1/super-admin/documents", [authHandler, ruleHandler, documentHandler]) + @Post("/api/v1/super-admin/documents", [authHandler, roleHandler, ruleHandler, documentHandler]) protected async post(req: Request, response: Response) { try { //init Document resource with request body values @@ -84,7 +85,7 @@ export default class DocumentsController extends ApiController { /** * @description Update a specific document */ - @Put("/api/v1/super-admin/documents/:uid", [authHandler, ruleHandler, documentHandler]) + @Put("/api/v1/super-admin/documents/:uid", [authHandler, roleHandler, ruleHandler, documentHandler]) protected async update(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -123,7 +124,7 @@ export default class DocumentsController extends ApiController { /** * @description Delete a specific document */ - @Delete("/api/v1/super-admin/documents/:uid", [authHandler, ruleHandler, documentHandler]) + @Delete("/api/v1/super-admin/documents/:uid", [authHandler, roleHandler, ruleHandler, documentHandler]) protected async delete(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -156,7 +157,7 @@ export default class DocumentsController extends ApiController { /** * @description Get a specific document by uid */ - @Get("/api/v1/super-admin/documents/:uid", [authHandler, ruleHandler, documentHandler]) + @Get("/api/v1/super-admin/documents/:uid", [authHandler, roleHandler, ruleHandler, documentHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/super-admin/FilesController.ts b/src/app/api/super-admin/FilesController.ts index cf085d5f..cb1b7f8d 100644 --- a/src/app/api/super-admin/FilesController.ts +++ b/src/app/api/super-admin/FilesController.ts @@ -8,6 +8,7 @@ import { File } from "le-coffre-resources/dist/SuperAdmin"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; import fileHandler from "@App/middlewares/OfficeMembershipHandlers/FileHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -20,7 +21,7 @@ export default class FilesController extends ApiController { * @description Get all Files * @returns File[] list of Files */ - @Get("/api/v1/super-admin/files", [authHandler, ruleHandler]) + @Get("/api/v1/super-admin/files", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -50,7 +51,7 @@ export default class FilesController extends ApiController { /** * @description Get a specific File by uid */ - @Get("/api/v1/super-admin/files/download/:uid", [authHandler, ruleHandler, fileHandler]) + @Get("/api/v1/super-admin/files/download/:uid", [authHandler, roleHandler, ruleHandler, fileHandler]) protected async download(req: Request, response: Response) { const uid = req.params["uid"]; if (!uid) { @@ -78,7 +79,7 @@ export default class FilesController extends ApiController { /** * @description Delete a specific File */ - @Delete("/api/v1/super-admin/files/:uid", [authHandler, ruleHandler, fileHandler]) + @Delete("/api/v1/super-admin/files/:uid", [authHandler, roleHandler, ruleHandler, fileHandler]) protected async delete(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -116,7 +117,7 @@ export default class FilesController extends ApiController { /** * @description Get a specific File by uid */ - @Get("/api/v1/super-admin/files/:uid", [authHandler, ruleHandler, fileHandler]) + @Get("/api/v1/super-admin/files/:uid", [authHandler, roleHandler, ruleHandler, fileHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/super-admin/LiveVoteController.ts b/src/app/api/super-admin/LiveVoteController.ts index 0e3307f4..4a9104ca 100644 --- a/src/app/api/super-admin/LiveVoteController.ts +++ b/src/app/api/super-admin/LiveVoteController.ts @@ -1,4 +1,5 @@ import authHandler from "@App/middlewares/AuthHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; import ApiController from "@Common/system/controller-pattern/ApiController"; import { Controller, Post } from "@ControllerPattern/index"; import { EAppointmentStatus } from "@prisma/client"; @@ -26,7 +27,7 @@ export default class LiveVoteController extends ApiController { /** * @description Create a new vote */ - @Post("/api/v1/super-admin/live-votes", [authHandler]) + @Post("/api/v1/super-admin/live-votes", [authHandler, roleHandler]) protected async post(req: Request, response: Response) { try { const userId = req.body.user.userId; diff --git a/src/app/api/super-admin/OfficeFoldersController.ts b/src/app/api/super-admin/OfficeFoldersController.ts index de9d6586..e0b01345 100644 --- a/src/app/api/super-admin/OfficeFoldersController.ts +++ b/src/app/api/super-admin/OfficeFoldersController.ts @@ -9,6 +9,7 @@ import { validateOrReject } from "class-validator"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; import folderHandler from "@App/middlewares/OfficeMembershipHandlers/FolderHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -20,7 +21,7 @@ export default class OfficeFoldersController extends ApiController { /** * @description Get all folders */ - @Get("/api/v1/super-admin/folders", [authHandler, ruleHandler]) + @Get("/api/v1/super-admin/folders", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -79,7 +80,7 @@ export default class OfficeFoldersController extends ApiController { /** * @description Create a new folder */ - @Post("/api/v1/super-admin/folders", [authHandler, ruleHandler, folderHandler]) + @Post("/api/v1/super-admin/folders", [authHandler, roleHandler, ruleHandler, folderHandler]) protected async post(req: Request, response: Response) { try { //init OfficeFolder resource with request body values @@ -103,7 +104,7 @@ export default class OfficeFoldersController extends ApiController { /** * @description Modify a specific folder by uid */ - @Put("/api/v1/super-admin/folders/:uid", [authHandler, ruleHandler, folderHandler]) + @Put("/api/v1/super-admin/folders/:uid", [authHandler, roleHandler, ruleHandler, folderHandler]) protected async put(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -145,7 +146,7 @@ export default class OfficeFoldersController extends ApiController { * @description Get a specific folder by uid * @returns IFolder */ - @Get("/api/v1/super-admin/folders/:uid", [authHandler, ruleHandler, folderHandler]) + @Get("/api/v1/super-admin/folders/:uid", [authHandler, roleHandler, ruleHandler, folderHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -180,7 +181,7 @@ export default class OfficeFoldersController extends ApiController { /** * @description Delete a specific folder */ - @Delete("/api/v1/super-admin/folders/:uid", [authHandler, ruleHandler, folderHandler]) + @Delete("/api/v1/super-admin/folders/:uid", [authHandler, roleHandler, ruleHandler, folderHandler]) protected async delete(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/super-admin/OfficeRolesController.ts b/src/app/api/super-admin/OfficeRolesController.ts index 80d54d7e..802c223e 100644 --- a/src/app/api/super-admin/OfficeRolesController.ts +++ b/src/app/api/super-admin/OfficeRolesController.ts @@ -9,6 +9,7 @@ import { Prisma } from "@prisma/client"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; import officeRoleHandler from "@App/middlewares/OfficeMembershipHandlers/OfficeRoleHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -20,7 +21,7 @@ export default class OfficeRolesController extends ApiController { /** * @description Get all officeRoles */ - @Get("/api/v1/super-admin/office-roles", [authHandler, ruleHandler]) + @Get("/api/v1/super-admin/office-roles", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -62,7 +63,7 @@ export default class OfficeRolesController extends ApiController { /** * @description Create a new officeRole */ - @Post("/api/v1/super-admin/office-roles", [authHandler, ruleHandler, officeRoleHandler]) + @Post("/api/v1/super-admin/office-roles", [authHandler, roleHandler, ruleHandler, officeRoleHandler]) protected async getAddresses(req: Request, response: Response) { try { //init IOfficeRole resource with request body values @@ -90,7 +91,7 @@ export default class OfficeRolesController extends ApiController { /** * @description Modify a specific officeRole by uid */ - @Put("/api/v1/super-admin/office-roles/:uid", [authHandler, ruleHandler, officeRoleHandler]) + @Put("/api/v1/super-admin/office-roles/:uid", [authHandler, roleHandler, ruleHandler, officeRoleHandler]) protected async put(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -131,7 +132,7 @@ export default class OfficeRolesController extends ApiController { /** * @description Get a specific officeRole by uid */ - @Get("/api/v1/super-admin/office-roles/:uid", [authHandler, ruleHandler, officeRoleHandler]) + @Get("/api/v1/super-admin/office-roles/:uid", [authHandler, roleHandler, ruleHandler, officeRoleHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/super-admin/OfficesController.ts b/src/app/api/super-admin/OfficesController.ts index e6702675..3fb1bd00 100644 --- a/src/app/api/super-admin/OfficesController.ts +++ b/src/app/api/super-admin/OfficesController.ts @@ -8,6 +8,7 @@ import { Office as OfficeResource } from "le-coffre-resources/dist/SuperAdmin"; import { validateOrReject } from "class-validator"; import ruleHandler from "@App/middlewares/RulesHandler"; import authHandler from "@App/middlewares/AuthHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -18,7 +19,7 @@ export default class OfficesController extends ApiController { /** * @description Get all offices */ - @Get("/api/v1/super-admin/offices", [authHandler, ruleHandler]) + @Get("/api/v1/super-admin/offices", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -53,7 +54,7 @@ export default class OfficesController extends ApiController { /** * @description Create a new office */ - @Post("/api/v1/super-admin/offices", [authHandler, ruleHandler]) + @Post("/api/v1/super-admin/offices", [authHandler, roleHandler, ruleHandler]) protected async post(req: Request, response: Response) { try { //init IUser resource with request body values @@ -76,7 +77,7 @@ export default class OfficesController extends ApiController { /** * @description Modify a specific office by uid */ - @Put("/api/v1/super-admin/offices/:uid", [authHandler, ruleHandler]) + @Put("/api/v1/super-admin/offices/:uid", [authHandler, roleHandler, ruleHandler]) protected async put(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -111,7 +112,7 @@ export default class OfficesController extends ApiController { /** * @description Get a specific office by uid */ - @Get("/api/v1/super-admin/offices/:uid", [authHandler, ruleHandler]) + @Get("/api/v1/super-admin/offices/:uid", [authHandler, roleHandler, ruleHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/super-admin/RolesController.ts b/src/app/api/super-admin/RolesController.ts index ba0683ab..372c02c5 100644 --- a/src/app/api/super-admin/RolesController.ts +++ b/src/app/api/super-admin/RolesController.ts @@ -7,6 +7,7 @@ import { validateOrReject } from "class-validator"; import { Role } from "le-coffre-resources/dist/SuperAdmin"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -18,7 +19,7 @@ export default class RolesController extends ApiController { /** * @description Get all roles */ - @Get("/api/v1/super-admin/roles", [authHandler, ruleHandler]) + @Get("/api/v1/super-admin/roles", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -44,7 +45,7 @@ export default class RolesController extends ApiController { /** * @description Create a new role */ - @Post("/api/v1/super-admin/roles", [authHandler, ruleHandler]) + @Post("/api/v1/super-admin/roles", [authHandler, roleHandler, ruleHandler]) protected async getAddresses(req: Request, response: Response) { try { //init IRole resource with request body values @@ -72,7 +73,7 @@ export default class RolesController extends ApiController { /** * @description Modify a specific role by uid */ - @Put("/api/v1/super-admin/roles/:uid", [authHandler, ruleHandler]) + @Put("/api/v1/super-admin/roles/:uid", [authHandler, roleHandler, ruleHandler]) protected async put(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -113,7 +114,7 @@ export default class RolesController extends ApiController { /** * @description Get a specific role by uid */ - @Get("/api/v1/super-admin/roles/:uid", [authHandler, ruleHandler]) + @Get("/api/v1/super-admin/roles/:uid", [authHandler, roleHandler, ruleHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/super-admin/RulesController.ts b/src/app/api/super-admin/RulesController.ts index c0bc87c1..025ec5c0 100644 --- a/src/app/api/super-admin/RulesController.ts +++ b/src/app/api/super-admin/RulesController.ts @@ -7,6 +7,7 @@ import { validateOrReject } from "class-validator"; import { Rule } from "le-coffre-resources/dist/SuperAdmin"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -18,7 +19,7 @@ export default class RulesController extends ApiController { /** * @description Get all rules */ - @Get("/api/v1/super-admin/rules", [authHandler, ruleHandler]) + @Get("/api/v1/super-admin/rules", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -44,7 +45,7 @@ export default class RulesController extends ApiController { /** * @description Create a new rule */ - @Post("/api/v1/super-admin/rules", [authHandler, ruleHandler]) + @Post("/api/v1/super-admin/rules", [authHandler, roleHandler, ruleHandler]) protected async getAddresses(req: Request, response: Response) { try { //init IRule resource with request body values @@ -72,7 +73,7 @@ export default class RulesController extends ApiController { /** * @description Modify a specific rule by uid */ - @Put("/api/v1/super-admin/rules/:uid", [authHandler, ruleHandler]) + @Put("/api/v1/super-admin/rules/:uid", [authHandler, roleHandler, ruleHandler]) protected async put(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -113,7 +114,7 @@ export default class RulesController extends ApiController { /** * @description Get a specific rule by uid */ - @Get("/api/v1/super-admin/rules/:uid", [authHandler, ruleHandler]) + @Get("/api/v1/super-admin/rules/:uid", [authHandler, roleHandler, ruleHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/super-admin/UsersController.ts b/src/app/api/super-admin/UsersController.ts index a9815f14..f6e28794 100644 --- a/src/app/api/super-admin/UsersController.ts +++ b/src/app/api/super-admin/UsersController.ts @@ -7,6 +7,7 @@ import { validateOrReject } from "class-validator"; import User from "le-coffre-resources/dist/SuperAdmin"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -18,7 +19,7 @@ export default class UsersController extends ApiController { /** * @description Get all users */ - @Get("/api/v1/super-admin/users", [authHandler, ruleHandler]) + @Get("/api/v1/super-admin/users", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -58,7 +59,7 @@ export default class UsersController extends ApiController { /** * @description Create a new user */ - @Post("/api/v1/super-admin/users", [authHandler, ruleHandler]) + @Post("/api/v1/super-admin/users", [authHandler, roleHandler, ruleHandler]) protected async create(req: Request, response: Response) { try { //init IUser resource with request body values @@ -86,7 +87,7 @@ export default class UsersController extends ApiController { /** * @description Modify a specific user by uid */ - @Put("/api/v1/super-admin/users/:uid", [authHandler, ruleHandler]) + @Put("/api/v1/super-admin/users/:uid", [authHandler, roleHandler, ruleHandler]) protected async put(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -128,7 +129,7 @@ export default class UsersController extends ApiController { /** * @description Get a specific user by uid */ - @Get("/api/v1/super-admin/users/:uid", [authHandler, ruleHandler]) + @Get("/api/v1/super-admin/users/:uid", [authHandler, roleHandler, ruleHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/super-admin/VotesController.ts b/src/app/api/super-admin/VotesController.ts index 4d25ef6d..308e46e3 100644 --- a/src/app/api/super-admin/VotesController.ts +++ b/src/app/api/super-admin/VotesController.ts @@ -6,6 +6,7 @@ import { Service } from "typedi"; import { Vote } from "le-coffre-resources/dist/SuperAdmin"; import authHandler from "@App/middlewares/AuthHandler"; import { Votes } from "@prisma/client"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -17,7 +18,7 @@ export default class VotesController extends ApiController { /** * @description Get all votes */ - @Get("/api/v1/super-admin/votes", [authHandler]) + @Get("/api/v1/super-admin/votes", [authHandler, roleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -43,7 +44,7 @@ export default class VotesController extends ApiController { /** * @description Get a specific vote by uid */ - @Get("/api/v1/super-admin/votes/:uid", [authHandler]) + @Get("/api/v1/super-admin/votes/:uid", [authHandler, roleHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -78,7 +79,7 @@ export default class VotesController extends ApiController { /** * @description Delete a specific vote */ - @Delete("/api/v1/super-admin/votes/:uid", [authHandler]) + @Delete("/api/v1/super-admin/votes/:uid", [authHandler, roleHandler]) protected async delete(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/middlewares/RolesHandler.ts b/src/app/middlewares/RolesHandler.ts new file mode 100644 index 00000000..3a4a9c77 --- /dev/null +++ b/src/app/middlewares/RolesHandler.ts @@ -0,0 +1,22 @@ +import HttpCodes from "@Common/system/controller-pattern/HttpCodes"; +import { NextFunction, Request, Response } from "express"; + +export default async function roleHandler(req: Request, response: Response, next: NextFunction) { + try { + + const namespace = req.path && req.path.split("/")[3]; + const role = req.body.user.role; + + if (namespace != "notary" && role != namespace && role != "super-admin") { + response.status(HttpCodes.UNAUTHORIZED).send("Unauthorized with this role"); + return; + } + + next(); + + } catch (error) { + console.log(error); + response.status(HttpCodes.INTERNAL_ERROR).send("Internal server error"); + return; + } +} diff --git a/src/app/middlewares/RulesHandler.ts b/src/app/middlewares/RulesHandler.ts index 16040875..cd35dcfe 100644 --- a/src/app/middlewares/RulesHandler.ts +++ b/src/app/middlewares/RulesHandler.ts @@ -6,19 +6,7 @@ export default async function ruleHandler(req: Request, response: Response, next const rules = req.body.user.rules; const service = req.path && req.path.split("/")[4]; - // if (!rules) { - // response.status(HttpCodes.UNAUTHORIZED).send("Missing rules in JWT"); - // return; - // } - const namespace = req.path && req.path.split("/")[3]; - const role = req.body.user.role; - - if (namespace != "notary" && role != namespace && role != "super-admin") { - response.status(HttpCodes.UNAUTHORIZED).send("Unauthorized with this role"); - return; - } - - if (!rules.includes(req.method + " " + service) && role != "super-admin") { + if (!rules.includes(req.method + " " + service)) { response.status(HttpCodes.UNAUTHORIZED).send("Unauthorized with those rules"); return; } From 24327a99a3cd44616688b3f56d5c8abbe8458821 Mon Sep 17 00:00:00 2001 From: OxSaitama Date: Wed, 16 Aug 2023 11:09:48 +0200 Subject: [PATCH 41/49] add checks on user (office)role update --- src/app/api/admin/UsersController.ts | 31 +++++++++++++++++-- src/app/api/super-admin/UsersController.ts | 30 ++++++++++++++++-- .../admin/UsersService/UsersService.ts | 10 +++++- 3 files changed, 65 insertions(+), 6 deletions(-) diff --git a/src/app/api/admin/UsersController.ts b/src/app/api/admin/UsersController.ts index ee208504..1c7c3251 100644 --- a/src/app/api/admin/UsersController.ts +++ b/src/app/api/admin/UsersController.ts @@ -10,11 +10,13 @@ import ruleHandler from "@App/middlewares/RulesHandler"; import userHandler from "@App/middlewares/OfficeMembershipHandlers/UserHandler"; import { validateOrReject } from "class-validator"; import roleHandler from "@App/middlewares/RolesHandler"; +import RolesService from "@Services/admin/RolesService/RolesService"; +import OfficeRolesService from "@Services/admin/OfficeRolesService/OfficeRolesService"; @Controller() @Service() export default class UsersController extends ApiController { - constructor(private usersService: UsersService) { + constructor(private usersService: UsersService, private roleService: RolesService, private officeRoleService: OfficeRolesService) { super(); } @@ -75,7 +77,7 @@ export default class UsersController extends ApiController { return; } - const userFound = await this.usersService.getByUid(uid); + const userFound = await this.usersService.getByUidWithRole(uid); if (!userFound) { this.httpNotFoundRequest(response, "user not found"); @@ -87,7 +89,30 @@ export default class UsersController extends ApiController { //validate user await validateOrReject(userEntity, { groups: ["updateUser"] }); - + + if(userEntity.role) { + const role = await this.roleService.getByUid(userEntity.role.uid!); + if(!role) { + this.httpBadRequest(response, "Role not found"); + return; + } + if (role.name === "super-admin" || userFound.role.name === "super-admin" ) { + this.httpBadRequest(response, "Cannot assign or remove super-admin role"); + return; + } + } + + if(userEntity.office_role) { + const officeRole = await this.officeRoleService.getByUid(userEntity.office_role.uid!); + if(!officeRole) { + this.httpBadRequest(response, "Office role not found"); + return; + } + if (officeRole.office_uid != userFound.office_uid) { + this.httpBadRequest(response, "Cannot assign an office role from another office"); + return; + } + } //call service to get prisma entity const userEntityUpdated = await this.usersService.update(uid, userEntity); diff --git a/src/app/api/super-admin/UsersController.ts b/src/app/api/super-admin/UsersController.ts index f6e28794..618c4728 100644 --- a/src/app/api/super-admin/UsersController.ts +++ b/src/app/api/super-admin/UsersController.ts @@ -8,11 +8,13 @@ import User from "le-coffre-resources/dist/SuperAdmin"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; import roleHandler from "@App/middlewares/RolesHandler"; +import RolesService from "@Services/super-admin/RolesService/RolesService"; +import OfficeRolesService from "@Services/super-admin/OfficeRolesService/OfficeRolesService"; @Controller() @Service() export default class UsersController extends ApiController { - constructor(private usersService: UsersService) { + constructor(private usersService: UsersService, private roleService: RolesService, private officeRoleService: OfficeRolesService) { super(); } @@ -97,7 +99,7 @@ export default class UsersController extends ApiController { return; } - const userFound = await this.usersService.getByUid(uid, {role: true, votes: true}); + const userFound = await this.usersService.getByUidWithRole(uid); if (!userFound) { this.httpNotFoundRequest(response, "user not found"); @@ -109,6 +111,30 @@ export default class UsersController extends ApiController { //validate user await validateOrReject(userEntity, { groups: ["updateUser"] }); + + if(userEntity.role) { + const role = await this.roleService.getByUid(userEntity.role.uid!); + if(!role) { + this.httpBadRequest(response, "Role not found"); + return; + } + if (role.name === "super-admin" || userFound.role.name === "super-admin" ) { + this.httpBadRequest(response, "Cannot assign or remove super-admin role"); + return; + } + } + + if(userEntity.office_role) { + const officeRole = await this.officeRoleService.getByUid(userEntity.office_role.uid!); + if(!officeRole) { + this.httpBadRequest(response, "Office role not found"); + return; + } + if (officeRole.office_uid != userFound.office_uid) { + this.httpBadRequest(response, "Cannot assign an office role from another office"); + return; + } + } //call service to get prisma entity const userEntityUpdated = await this.usersService.update(uid, userEntity); diff --git a/src/services/admin/UsersService/UsersService.ts b/src/services/admin/UsersService/UsersService.ts index f23c09d7..6167352e 100644 --- a/src/services/admin/UsersService/UsersService.ts +++ b/src/services/admin/UsersService/UsersService.ts @@ -31,7 +31,7 @@ export default class UsersService extends BaseService { * @description : Modify a user * @throws {Error} If user modification failed */ - public update(uid: string, userEntity: User): Promise { + public async update(uid: string, userEntity: User): Promise { return this.userRepository.updateRole(uid, userEntity); } @@ -51,6 +51,14 @@ export default class UsersService extends BaseService { return this.userRepository.findOneByUidWithOffice(uid); } + /** + * @description : Get a user by uid with office + * @throws {Error} If user cannot be get by uid + */ + public getByUidWithRole(uid: string) { + return this.userRepository.findOneByUidWithRole(uid); + } + /** * @description : Get a user by uid * @throws {Error} If user cannot be get by uid From 1ce013b5f661c663cb9ea749421d960b3859404c Mon Sep 17 00:00:00 2001 From: OxSaitama Date: Wed, 16 Aug 2023 13:53:32 +0200 Subject: [PATCH 42/49] remove uid in req body for updates --- package-lock.json | 862 ++++++++++--------- package.json | 2 +- src/app/api/admin/UsersController.ts | 4 - src/app/api/customer/FilesController.ts | 3 - src/app/api/super-admin/OfficesController.ts | 3 +- src/app/api/super-admin/RulesController.ts | 3 - src/app/api/super-admin/UsersController.ts | 3 - 7 files changed, 460 insertions(+), 420 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0290f4ae..e6e9857e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,7 @@ "cron": "^2.3.1", "express": "^4.18.2", "jsonwebtoken": "^9.0.0", - "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.66", + "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.67", "module-alias": "^2.2.2", "multer": "^1.4.5-lts.1", "next": "^13.1.5", @@ -70,17 +70,89 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz", - "integrity": "sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==", + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.10.tgz", + "integrity": "sha512-/KKIMG4UEL35WmI9OlvMhurwtytjvXoFcGNrOvyG9zIzA8YmPjVtIZUf7b05+TPO7G7/GEmLHDaoCgACHl9hhA==", "dev": true, "dependencies": { - "@babel/highlight": "^7.22.5" + "@babel/highlight": "^7.22.10", + "chalk": "^2.4.2" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@babel/code-frame/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/code-frame/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/code-frame/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/compat-data": { "version": "7.22.9", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz", @@ -91,21 +163,21 @@ } }, "node_modules/@babel/core": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.9.tgz", - "integrity": "sha512-G2EgeufBcYw27U4hhoIwFcgc1XU7TlXJ3mv04oOv1WCuo900U/anZSPzEqNjwdjgffkk2Gs0AN0dW1CKVLcG7w==", + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.10.tgz", + "integrity": "sha512-fTmqbbUBAwCcre6zPzNngvsI0aNrPZe77AeqvDxWM9Nm+04RrJ3CAmGHA9f7lJQY6ZMhRztNemy4uslDxTX4Qw==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.22.5", - "@babel/generator": "^7.22.9", - "@babel/helper-compilation-targets": "^7.22.9", + "@babel/code-frame": "^7.22.10", + "@babel/generator": "^7.22.10", + "@babel/helper-compilation-targets": "^7.22.10", "@babel/helper-module-transforms": "^7.22.9", - "@babel/helpers": "^7.22.6", - "@babel/parser": "^7.22.7", + "@babel/helpers": "^7.22.10", + "@babel/parser": "^7.22.10", "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.8", - "@babel/types": "^7.22.5", + "@babel/traverse": "^7.22.10", + "@babel/types": "^7.22.10", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -150,12 +222,12 @@ "dev": true }, "node_modules/@babel/generator": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.9.tgz", - "integrity": "sha512-KtLMbmicyuK2Ak/FTCJVbDnkN1SlT8/kceFTiuDiiRUUSMnHMidxSCdG4ndkTOHHpoomWe/4xkvHkEOncwjYIw==", + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.10.tgz", + "integrity": "sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A==", "dev": true, "dependencies": { - "@babel/types": "^7.22.5", + "@babel/types": "^7.22.10", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -165,9 +237,9 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.9.tgz", - "integrity": "sha512-7qYrNM6HjpnPHJbopxmb8hSPoZ0gsX8IvUS32JGVoy+pU9e5N0nLr1VjJoR6kA4d9dmGLxNYOjeB8sUDal2WMw==", + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.10.tgz", + "integrity": "sha512-JMSwHD4J7SLod0idLq5PKgI+6g/hLD/iuWBq08ZX49xE14VpVEojJ5rHWptpirV2j020MvypRLAXAO50igCJ5Q==", "dev": true, "dependencies": { "@babel/compat-data": "^7.22.9", @@ -178,9 +250,6 @@ }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" } }, "node_modules/@babel/helper-environment-visitor": { @@ -309,27 +378,27 @@ } }, "node_modules/@babel/helpers": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.6.tgz", - "integrity": "sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA==", + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.10.tgz", + "integrity": "sha512-a41J4NW8HyZa1I1vAndrraTlPZ/eZoga2ZgS7fEr0tZJGVU4xqdE80CEm0CcNjha5EZ8fTBYLKHF0kqDUuAwQw==", "dev": true, "dependencies": { "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.6", - "@babel/types": "^7.22.5" + "@babel/traverse": "^7.22.10", + "@babel/types": "^7.22.10" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz", - "integrity": "sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==", + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.10.tgz", + "integrity": "sha512-78aUtVcT7MUscr0K5mIEnkwxPE0MaxkR5RxRwuHaQ+JuU5AmTPhY+do2mdzVTnIJJpyBglql2pehuBIWHug+WQ==", "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.22.5", - "chalk": "^2.0.0", + "chalk": "^2.4.2", "js-tokens": "^4.0.0" }, "engines": { @@ -408,9 +477,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.22.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.7.tgz", - "integrity": "sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q==", + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.10.tgz", + "integrity": "sha512-lNbdGsQb9ekfsnjFGhEiF4hfFqGgfOP3H3d27re3n+CGhNuTSUEQdfWk556sTLNTloczcdM5TYF2LhzmDQKyvQ==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -611,19 +680,19 @@ } }, "node_modules/@babel/traverse": { - "version": "7.22.8", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.8.tgz", - "integrity": "sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==", + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.10.tgz", + "integrity": "sha512-Q/urqV4pRByiNNpb/f5OSv28ZlGJiFiiTh+GAHktbIrkPhPbl90+uW6SmpoLyZqutrg9AEaEf3Q/ZBRHBXgxig==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/generator": "^7.22.7", + "@babel/code-frame": "^7.22.10", + "@babel/generator": "^7.22.10", "@babel/helper-environment-visitor": "^7.22.5", "@babel/helper-function-name": "^7.22.5", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.22.7", - "@babel/types": "^7.22.5", + "@babel/parser": "^7.22.10", + "@babel/types": "^7.22.10", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -655,9 +724,9 @@ "dev": true }, "node_modules/@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.10.tgz", + "integrity": "sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg==", "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.22.5", @@ -720,16 +789,16 @@ } }, "node_modules/@jest/console": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.6.1.tgz", - "integrity": "sha512-Aj772AYgwTSr5w8qnyoJ0eDYvN6bMsH3ORH1ivMotrInHLKdUz6BDlaEXHdM6kODaBIkNIyQGzsMvRdOv7VG7Q==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.6.2.tgz", + "integrity": "sha512-0N0yZof5hi44HAR2pPS+ikJ3nzKNoZdVu8FffRf3wy47I7Dm7etk/3KetMdRUqzVd16V4O2m2ISpNTbnIuqy1w==", "dev": true, "dependencies": { "@jest/types": "^29.6.1", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^29.6.1", - "jest-util": "^29.6.1", + "jest-message-util": "^29.6.2", + "jest-util": "^29.6.2", "slash": "^3.0.0" }, "engines": { @@ -737,15 +806,15 @@ } }, "node_modules/@jest/core": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.6.1.tgz", - "integrity": "sha512-CcowHypRSm5oYQ1obz1wfvkjZZ2qoQlrKKvlfPwh5jUXVU12TWr2qMeH8chLMuTFzHh5a1g2yaqlqDICbr+ukQ==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.6.2.tgz", + "integrity": "sha512-Oj+5B+sDMiMWLhPFF+4/DvHOf+U10rgvCLGPHP8Xlsy/7QxS51aU/eBngudHlJXnaWD5EohAgJ4js+T6pa+zOg==", "dev": true, "dependencies": { - "@jest/console": "^29.6.1", - "@jest/reporters": "^29.6.1", - "@jest/test-result": "^29.6.1", - "@jest/transform": "^29.6.1", + "@jest/console": "^29.6.2", + "@jest/reporters": "^29.6.2", + "@jest/test-result": "^29.6.2", + "@jest/transform": "^29.6.2", "@jest/types": "^29.6.1", "@types/node": "*", "ansi-escapes": "^4.2.1", @@ -754,20 +823,20 @@ "exit": "^0.1.2", "graceful-fs": "^4.2.9", "jest-changed-files": "^29.5.0", - "jest-config": "^29.6.1", - "jest-haste-map": "^29.6.1", - "jest-message-util": "^29.6.1", + "jest-config": "^29.6.2", + "jest-haste-map": "^29.6.2", + "jest-message-util": "^29.6.2", "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.6.1", - "jest-resolve-dependencies": "^29.6.1", - "jest-runner": "^29.6.1", - "jest-runtime": "^29.6.1", - "jest-snapshot": "^29.6.1", - "jest-util": "^29.6.1", - "jest-validate": "^29.6.1", - "jest-watcher": "^29.6.1", + "jest-resolve": "^29.6.2", + "jest-resolve-dependencies": "^29.6.2", + "jest-runner": "^29.6.2", + "jest-runtime": "^29.6.2", + "jest-snapshot": "^29.6.2", + "jest-util": "^29.6.2", + "jest-validate": "^29.6.2", + "jest-watcher": "^29.6.2", "micromatch": "^4.0.4", - "pretty-format": "^29.6.1", + "pretty-format": "^29.6.2", "slash": "^3.0.0", "strip-ansi": "^6.0.0" }, @@ -784,37 +853,37 @@ } }, "node_modules/@jest/environment": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.6.1.tgz", - "integrity": "sha512-RMMXx4ws+Gbvw3DfLSuo2cfQlK7IwGbpuEWXCqyYDcqYTI+9Ju3a5hDnXaxjNsa6uKh9PQF2v+qg+RLe63tz5A==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.6.2.tgz", + "integrity": "sha512-AEcW43C7huGd/vogTddNNTDRpO6vQ2zaQNrttvWV18ArBx9Z56h7BIsXkNFJVOO4/kblWEQz30ckw0+L3izc+Q==", "dev": true, "dependencies": { - "@jest/fake-timers": "^29.6.1", + "@jest/fake-timers": "^29.6.2", "@jest/types": "^29.6.1", "@types/node": "*", - "jest-mock": "^29.6.1" + "jest-mock": "^29.6.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.6.1.tgz", - "integrity": "sha512-N5xlPrAYaRNyFgVf2s9Uyyvr795jnB6rObuPx4QFvNJz8aAjpZUDfO4bh5G/xuplMID8PrnuF1+SfSyDxhsgYg==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.6.2.tgz", + "integrity": "sha512-m6DrEJxVKjkELTVAztTLyS/7C92Y2b0VYqmDROYKLLALHn8T/04yPs70NADUYPrV3ruI+H3J0iUIuhkjp7vkfg==", "dev": true, "dependencies": { - "expect": "^29.6.1", - "jest-snapshot": "^29.6.1" + "expect": "^29.6.2", + "jest-snapshot": "^29.6.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect-utils": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.6.1.tgz", - "integrity": "sha512-o319vIf5pEMx0LmzSxxkYYxo4wrRLKHq9dP1yJU7FoPTB0LfAKSz8SWD6D/6U3v/O52t9cF5t+MeJiRsfk7zMw==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.6.2.tgz", + "integrity": "sha512-6zIhM8go3RV2IG4aIZaZbxwpOzz3ZiM23oxAlkquOIole+G6TrbeXnykxWYlqF7kz2HlBjdKtca20x9atkEQYg==", "dev": true, "dependencies": { "jest-get-type": "^29.4.3" @@ -824,47 +893,47 @@ } }, "node_modules/@jest/fake-timers": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.6.1.tgz", - "integrity": "sha512-RdgHgbXyosCDMVYmj7lLpUwXA4c69vcNzhrt69dJJdf8azUrpRh3ckFCaTPNjsEeRi27Cig0oKDGxy5j7hOgHg==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.6.2.tgz", + "integrity": "sha512-euZDmIlWjm1Z0lJ1D0f7a0/y5Kh/koLFMUBE5SUYWrmy8oNhJpbTBDAP6CxKnadcMLDoDf4waRYCe35cH6G6PA==", "dev": true, "dependencies": { "@jest/types": "^29.6.1", "@sinonjs/fake-timers": "^10.0.2", "@types/node": "*", - "jest-message-util": "^29.6.1", - "jest-mock": "^29.6.1", - "jest-util": "^29.6.1" + "jest-message-util": "^29.6.2", + "jest-mock": "^29.6.2", + "jest-util": "^29.6.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/globals": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.6.1.tgz", - "integrity": "sha512-2VjpaGy78JY9n9370H8zGRCFbYVWwjY6RdDMhoJHa1sYfwe6XM/azGN0SjY8kk7BOZApIejQ1BFPyH7FPG0w3A==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.6.2.tgz", + "integrity": "sha512-cjuJmNDjs6aMijCmSa1g2TNG4Lby/AeU7/02VtpW+SLcZXzOLK2GpN2nLqcFjmhy3B3AoPeQVx7BnyOf681bAw==", "dev": true, "dependencies": { - "@jest/environment": "^29.6.1", - "@jest/expect": "^29.6.1", + "@jest/environment": "^29.6.2", + "@jest/expect": "^29.6.2", "@jest/types": "^29.6.1", - "jest-mock": "^29.6.1" + "jest-mock": "^29.6.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/reporters": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.6.1.tgz", - "integrity": "sha512-9zuaI9QKr9JnoZtFQlw4GREQbxgmNYXU6QuWtmuODvk5nvPUeBYapVR/VYMyi2WSx3jXTLJTJji8rN6+Cm4+FA==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.6.2.tgz", + "integrity": "sha512-sWtijrvIav8LgfJZlrGCdN0nP2EWbakglJY49J1Y5QihcQLfy7ovyxxjJBRXMNltgt4uPtEcFmIMbVshEDfFWw==", "dev": true, "dependencies": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.6.1", - "@jest/test-result": "^29.6.1", - "@jest/transform": "^29.6.1", + "@jest/console": "^29.6.2", + "@jest/test-result": "^29.6.2", + "@jest/transform": "^29.6.2", "@jest/types": "^29.6.1", "@jridgewell/trace-mapping": "^0.3.18", "@types/node": "*", @@ -878,9 +947,9 @@ "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.6.1", - "jest-util": "^29.6.1", - "jest-worker": "^29.6.1", + "jest-message-util": "^29.6.2", + "jest-util": "^29.6.2", + "jest-worker": "^29.6.2", "slash": "^3.0.0", "string-length": "^4.0.1", "strip-ansi": "^6.0.0", @@ -925,12 +994,12 @@ } }, "node_modules/@jest/test-result": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.6.1.tgz", - "integrity": "sha512-Ynr13ZRcpX6INak0TPUukU8GWRfm/vAytE3JbJNGAvINySWYdfE7dGZMbk36oVuK4CigpbhMn8eg1dixZ7ZJOw==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.6.2.tgz", + "integrity": "sha512-3VKFXzcV42EYhMCsJQURptSqnyjqCGbtLuX5Xxb6Pm6gUf1wIRIl+mandIRGJyWKgNKYF9cnstti6Ls5ekduqw==", "dev": true, "dependencies": { - "@jest/console": "^29.6.1", + "@jest/console": "^29.6.2", "@jest/types": "^29.6.1", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" @@ -940,14 +1009,14 @@ } }, "node_modules/@jest/test-sequencer": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.6.1.tgz", - "integrity": "sha512-oBkC36PCDf/wb6dWeQIhaviU0l5u6VCsXa119yqdUosYAt7/FbQU2M2UoziO3igj/HBDEgp57ONQ3fm0v9uyyg==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.6.2.tgz", + "integrity": "sha512-GVYi6PfPwVejO7slw6IDO0qKVum5jtrJ3KoLGbgBWyr2qr4GaxFV6su+ZAjdTX75Sr1DkMFRk09r2ZVa+wtCGw==", "dev": true, "dependencies": { - "@jest/test-result": "^29.6.1", + "@jest/test-result": "^29.6.2", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.1", + "jest-haste-map": "^29.6.2", "slash": "^3.0.0" }, "engines": { @@ -955,9 +1024,9 @@ } }, "node_modules/@jest/transform": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.6.1.tgz", - "integrity": "sha512-URnTneIU3ZjRSaf906cvf6Hpox3hIeJXRnz3VDSw5/X93gR8ycdfSIEy19FlVx8NFmpN7fe3Gb1xF+NjXaQLWg==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.6.2.tgz", + "integrity": "sha512-ZqCqEISr58Ce3U+buNFJYUktLJZOggfyvR+bZMaiV1e8B1SIvJbwZMrYz3gx/KAPn9EXmOmN+uB08yLCjWkQQg==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", @@ -968,9 +1037,9 @@ "convert-source-map": "^2.0.0", "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.1", + "jest-haste-map": "^29.6.2", "jest-regex-util": "^29.4.3", - "jest-util": "^29.6.1", + "jest-util": "^29.6.2", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", @@ -1012,9 +1081,9 @@ } }, "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", "engines": { "node": ">=6.0.0" } @@ -1034,21 +1103,15 @@ "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", - "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", + "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", "dev": true, "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, "node_modules/@mailchimp/mailchimp_transactional": { "version": "1.0.50", "resolved": "https://registry.npmjs.org/@mailchimp/mailchimp_transactional/-/mailchimp_transactional-1.0.50.tgz", @@ -1061,14 +1124,14 @@ } }, "node_modules/@next/env": { - "version": "13.4.12", - "resolved": "https://registry.npmjs.org/@next/env/-/env-13.4.12.tgz", - "integrity": "sha512-RmHanbV21saP/6OEPBJ7yJMuys68cIf8OBBWd7+uj40LdpmswVAwe1uzeuFyUsd6SfeITWT3XnQfn6wULeKwDQ==" + "version": "13.4.16", + "resolved": "https://registry.npmjs.org/@next/env/-/env-13.4.16.tgz", + "integrity": "sha512-pCU0sJBqdfKP9mwDadxvZd+eLz3fZrTlmmDHY12Hdpl3DD0vy8ou5HWKVfG0zZS6tqhL4wnQqRbspdY5nqa7MA==" }, "node_modules/@next/swc-darwin-arm64": { - "version": "13.4.12", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.12.tgz", - "integrity": "sha512-deUrbCXTMZ6ZhbOoloqecnUeNpUOupi8SE2tx4jPfNS9uyUR9zK4iXBvH65opVcA/9F5I/p8vDXSYbUlbmBjZg==", + "version": "13.4.16", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.16.tgz", + "integrity": "sha512-Rl6i1uUq0ciRa3VfEpw6GnWAJTSKo9oM2OrkGXPsm7rMxdd2FR5NkKc0C9xzFCI4+QtmBviWBdF2m3ur3Nqstw==", "cpu": [ "arm64" ], @@ -1081,9 +1144,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "13.4.12", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.12.tgz", - "integrity": "sha512-WRvH7RxgRHlC1yb5oG0ZLx8F7uci9AivM5/HGGv9ZyG2Als8Ij64GC3d+mQ5sJhWjusyU6T6V1WKTUoTmOB0zQ==", + "version": "13.4.16", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.16.tgz", + "integrity": "sha512-o1vIKYbZORyDmTrPV1hApt9NLyWrS5vr2p5hhLGpOnkBY1cz6DAXjv8Lgan8t6X87+83F0EUDlu7klN8ieZ06A==", "cpu": [ "x64" ], @@ -1096,9 +1159,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "13.4.12", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.12.tgz", - "integrity": "sha512-YEKracAWuxp54tKiAvvq73PUs9lok57cc8meYRibTWe/VdPB2vLgkTVWFcw31YDuRXdEhdX0fWS6Q+ESBhnEig==", + "version": "13.4.16", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.16.tgz", + "integrity": "sha512-JRyAl8lCfyTng4zoOmE6hNI2f1MFUr7JyTYCHl1RxX42H4a5LMwJhDVQ7a9tmDZ/yj+0hpBn+Aan+d6lA3v0UQ==", "cpu": [ "arm64" ], @@ -1111,9 +1174,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "13.4.12", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.12.tgz", - "integrity": "sha512-LhJR7/RAjdHJ2Isl2pgc/JaoxNk0KtBgkVpiDJPVExVWA1c6gzY57+3zWuxuyWzTG+fhLZo2Y80pLXgIJv7g3g==", + "version": "13.4.16", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.16.tgz", + "integrity": "sha512-9gqVqNzUMWbUDgDiND18xoUqhwSm2gmksqXgCU0qaOKt6oAjWz8cWYjgpPVD0WICKFylEY/gvPEP1fMZDVFZ/g==", "cpu": [ "arm64" ], @@ -1126,9 +1189,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "13.4.12", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.12.tgz", - "integrity": "sha512-1DWLL/B9nBNiQRng+1aqs3OaZcxC16Nf+mOnpcrZZSdyKHek3WQh6j/fkbukObgNGwmCoVevLUa/p3UFTTqgqg==", + "version": "13.4.16", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.16.tgz", + "integrity": "sha512-KcQGwchAKmZVPa8i5PLTxvTs1/rcFnSltfpTm803Tr/BtBV3AxCkHLfhtoyVtVzx/kl/oue8oS+DSmbepQKwhw==", "cpu": [ "x64" ], @@ -1141,9 +1204,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "13.4.12", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.12.tgz", - "integrity": "sha512-kEAJmgYFhp0VL+eRWmUkVxLVunn7oL9Mdue/FS8yzRBVj7Z0AnIrHpTIeIUl1bbdQq1VaoOztnKicAjfkLTRCQ==", + "version": "13.4.16", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.16.tgz", + "integrity": "sha512-2RbMZNxYnJmW8EPHVBsGZPq5zqWAyBOc/YFxq/jIQ/Yn3RMFZ1dZVCjtIcsiaKmgh7mjA/W0ApbumutHNxRqqQ==", "cpu": [ "x64" ], @@ -1156,9 +1219,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "13.4.12", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.12.tgz", - "integrity": "sha512-GMLuL/loR6yIIRTnPRY6UGbLL9MBdw2anxkOnANxvLvsml4F0HNIgvnU3Ej4BjbqMTNjD4hcPFdlEow4XHPdZA==", + "version": "13.4.16", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.16.tgz", + "integrity": "sha512-thDcGonELN7edUKzjzlHrdoKkm7y8IAdItQpRvvMxNUXa4d9r0ElofhTZj5emR7AiXft17hpen+QAkcWpqG7Jg==", "cpu": [ "arm64" ], @@ -1171,9 +1234,9 @@ } }, "node_modules/@next/swc-win32-ia32-msvc": { - "version": "13.4.12", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.12.tgz", - "integrity": "sha512-PhgNqN2Vnkm7XaMdRmmX0ZSwZXQAtamBVSa9A/V1dfKQCV1rjIZeiy/dbBnVYGdj63ANfsOR/30XpxP71W0eww==", + "version": "13.4.16", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.16.tgz", + "integrity": "sha512-f7SE1Mo4JAchUWl0LQsbtySR9xCa+x55C0taetjUApKtcLR3AgAjASrrP+oE1inmLmw573qRnE1eZN8YJfEBQw==", "cpu": [ "ia32" ], @@ -1186,9 +1249,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "13.4.12", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.12.tgz", - "integrity": "sha512-Z+56e/Ljt0bUs+T+jPjhFyxYBcdY2RIq9ELFU+qAMQMteHo7ymbV7CKmlcX59RI9C4YzN8PgMgLyAoi916b5HA==", + "version": "13.4.16", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.16.tgz", + "integrity": "sha512-WamDZm1M/OEM4QLce3lOmD1XdLEl37zYZwlmOLhmF7qYJ2G6oYm9+ejZVv+LakQIsIuXhSpVlOvrxIAHqwRkPQ==", "cpu": [ "x64" ], @@ -1365,13 +1428,13 @@ } }, "node_modules/@types/cron": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/cron/-/cron-2.0.1.tgz", - "integrity": "sha512-WHa/1rtNtD2Q/H0+YTTZoty+/5rcE66iAFX2IY+JuUoOACsevYyFkSYu/2vdw+G5LrmO7Lxowrqm0av4k3qWNQ==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@types/cron/-/cron-2.4.0.tgz", + "integrity": "sha512-5bBaAkqvSFBX8JMi/xCofNzG5E594TNsApMz68dLd/sQYz/HGQqgcxGHTRjOvD4G3Y+YF1Oo3S7QdCvKt1KAJQ==", + "deprecated": "This is a stub types definition. cron provides its own type definitions, so you do not need this installed.", "dev": true, "dependencies": { - "@types/luxon": "*", - "@types/node": "*" + "cron": "*" } }, "node_modules/@types/express": { @@ -1456,12 +1519,6 @@ "@types/node": "*" } }, - "node_modules/@types/luxon": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.3.1.tgz", - "integrity": "sha512-XOS5nBcgEeP2PpcqJHjCWhUCAzGfXIU8ILOSLpx2FhxqMW9KdxgCGXNOEKGVBfveKtIpztHzKK5vSRVLyW/NqA==", - "dev": true - }, "node_modules/@types/mailchimp__mailchimp_transactional": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/mailchimp__mailchimp_transactional/-/mailchimp__mailchimp_transactional-1.0.5.tgz", @@ -1478,9 +1535,9 @@ "dev": true }, "node_modules/@types/module-alias": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/module-alias/-/module-alias-2.0.1.tgz", - "integrity": "sha512-DN/CCT1HQG6HquBNJdLkvV+4v5l/oEuwOHUPLxI+Eub0NED+lk0YUfba04WGH90EINiUrNgClkNnwGmbICeWMQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@types/module-alias/-/module-alias-2.0.2.tgz", + "integrity": "sha512-Oeo5NEjAceFgN8OzGiLXPswgv2GBmrDGuTnLS0sQ8g4Mq5sB5c97Hu5B+n9Gu/j+5Y+oUb4TSawHXkZ8MENGyw==", "dev": true }, "node_modules/@types/multer": { @@ -1493,9 +1550,9 @@ } }, "node_modules/@types/node": { - "version": "18.17.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.1.tgz", - "integrity": "sha512-xlR1jahfizdplZYRU59JlUx9uzF1ARa8jbhM11ccpCJya8kvos5jwdm2ZAgxSCwOl0fq21svP18EVwPBXMQudw==" + "version": "18.17.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.5.tgz", + "integrity": "sha512-xNbS75FxH6P4UXTPUJp/zNPq6/xsfdJKussCWNOnz4aULWIRwMgP1LgaB5RiBnMX1DPCYenuqGZfnIAx5mbFLA==" }, "node_modules/@types/node-fetch": { "version": "2.6.4", @@ -1530,12 +1587,6 @@ "@types/node": "*" } }, - "node_modules/@types/prettier": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", - "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", - "dev": true - }, "node_modules/@types/qs": { "version": "6.9.7", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", @@ -1582,9 +1633,9 @@ "dev": true }, "node_modules/@types/validator": { - "version": "13.7.17", - "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.7.17.tgz", - "integrity": "sha512-aqayTNmeWrZcvnG2MG9eGYI6b7S5fl+yKgPs6bAjOTwPS316R5SxBGKvtSExfyoJU7pIeHJfsHI0Ji41RVMkvQ==" + "version": "13.11.1", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.1.tgz", + "integrity": "sha512-d/MUkJYdOeKycmm75Arql4M5+UuXmf4cHdHKsyw1GcvnNgL6s77UkgSgJ8TE/rI5PYsnwYq5jkcWBLuN/MpQ1A==" }, "node_modules/@types/yargs": { "version": "17.0.24", @@ -1728,12 +1779,12 @@ } }, "node_modules/babel-jest": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.1.tgz", - "integrity": "sha512-qu+3bdPEQC6KZSPz+4Fyjbga5OODNcp49j6GKzG1EKbkfyJBxEYGVUmVGpwCSeGouG52R4EgYMLb6p9YeEEQ4A==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.2.tgz", + "integrity": "sha512-BYCzImLos6J3BH/+HvUCHG1dTf2MzmAB4jaVxHV+29RZLjR29XuYTmsf2sdDwkrb+FczkGo3kOhE7ga6sI0P4A==", "dev": true, "dependencies": { - "@jest/transform": "^29.6.1", + "@jest/transform": "^29.6.2", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", "babel-preset-jest": "^29.5.0", @@ -1906,9 +1957,9 @@ } }, "node_modules/browserslist": { - "version": "4.21.9", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.9.tgz", - "integrity": "sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==", + "version": "4.21.10", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz", + "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==", "dev": true, "funding": [ { @@ -1925,9 +1976,9 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001503", - "electron-to-chromium": "^1.4.431", - "node-releases": "^2.0.12", + "caniuse-lite": "^1.0.30001517", + "electron-to-chromium": "^1.4.477", + "node-releases": "^2.0.13", "update-browserslist-db": "^1.0.11" }, "bin": { @@ -2049,9 +2100,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001517", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001517.tgz", - "integrity": "sha512-Vdhm5S11DaFVLlyiKu4hiUTkpZu+y1KA/rZZqVQfOD5YdDT/eQKlkt7NaE0WGOFgX32diqt9MiP9CAiFeRklaA==", + "version": "1.0.30001521", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001521.tgz", + "integrity": "sha512-fnx1grfpEOvDGH+V17eccmNjucGUnCbP6KL+l5KqBIerp26WK/+RQ7CIDE37KGJjaPyqWXXlFUyKiWmvdNNKmQ==", "funding": [ { "type": "opencollective", @@ -2335,17 +2386,17 @@ "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" }, "node_modules/cron": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/cron/-/cron-2.4.0.tgz", - "integrity": "sha512-Cx77ic1TyIAtUggr0oAhtS8MLzPBUqGNIvdDM7jE3oFIxfe8LXWI9q3iQN/H2CebAiMir53LQKWOhEKnzkJTAQ==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/cron/-/cron-2.4.1.tgz", + "integrity": "sha512-ty0hUSPuENwDtIShDFxUxWEIsqiu2vhoFtt6Vwrbg4lHGtJX2/cV2p0hH6/qaEM9Pj+i6mQoau48BO5wBpkP4w==", "dependencies": { "luxon": "^3.2.1" } }, "node_modules/cron-parser": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-4.8.1.tgz", - "integrity": "sha512-jbokKWGcyU4gl6jAfX97E1gDpY12DJ1cLJZmoDzaAln/shZ+S3KBFBuA2Q6WeUN4gJf/8klnV1EfvhA2lK5IRQ==", + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-4.9.0.tgz", + "integrity": "sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==", "dependencies": { "luxon": "^3.2.1" }, @@ -2376,10 +2427,18 @@ } }, "node_modules/dedent": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", - "dev": true + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", + "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", + "dev": true, + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } }, "node_modules/deepmerge": { "version": "4.3.1", @@ -2467,9 +2526,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron-to-chromium": { - "version": "1.4.473", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.473.tgz", - "integrity": "sha512-aVfC8+440vGfl06l8HKKn8/PD5jRfSnLkTTD65EFvU46igbpQRri1gxSzW9/+TeUlwYzrXk1sw867T96zlyECA==", + "version": "1.4.492", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.492.tgz", + "integrity": "sha512-36K9b/6skMVwAIEsC7GiQ8I8N3soCALVSHqWHzNDtGemAcI9Xu8hP02cywWM0A794rTHm0b0zHPeLJHtgFVamQ==", "dev": true }, "node_modules/emittery": { @@ -2584,17 +2643,17 @@ } }, "node_modules/expect": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.6.1.tgz", - "integrity": "sha512-XEdDLonERCU1n9uR56/Stx9OqojaLAQtZf9PrCHH9Hl8YXiEIka3H4NXJ3NOIBmQJTg7+j7buh34PMHfJujc8g==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.6.2.tgz", + "integrity": "sha512-iAErsLxJ8C+S02QbLAwgSGSezLQK+XXRDt8IuFXFpwCNw2ECmzZSmjKcCaFVp5VRMk+WAvz6h6jokzEzBFZEuA==", "dev": true, "dependencies": { - "@jest/expect-utils": "^29.6.1", + "@jest/expect-utils": "^29.6.2", "@types/node": "*", "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.6.1", - "jest-message-util": "^29.6.1", - "jest-util": "^29.6.1" + "jest-matcher-utils": "^29.6.2", + "jest-message-util": "^29.6.2", + "jest-util": "^29.6.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -3061,9 +3120,9 @@ } }, "node_modules/is-core-module": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz", - "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==", + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", + "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", "dev": true, "dependencies": { "has": "^1.0.3" @@ -3257,15 +3316,15 @@ } }, "node_modules/jest": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.6.1.tgz", - "integrity": "sha512-Nirw5B4nn69rVUZtemCQhwxOBhm0nsp3hmtF4rzCeWD7BkjAXRIji7xWQfnTNbz9g0aVsBX6aZK3n+23LM6uDw==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.6.2.tgz", + "integrity": "sha512-8eQg2mqFbaP7CwfsTpCxQ+sHzw1WuNWL5UUvjnWP4hx2riGz9fPSzYOaU5q8/GqWn1TfgZIVTqYJygbGbWAANg==", "dev": true, "dependencies": { - "@jest/core": "^29.6.1", + "@jest/core": "^29.6.2", "@jest/types": "^29.6.1", "import-local": "^3.0.2", - "jest-cli": "^29.6.1" + "jest-cli": "^29.6.2" }, "bin": { "jest": "bin/jest.js" @@ -3296,28 +3355,28 @@ } }, "node_modules/jest-circus": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.6.1.tgz", - "integrity": "sha512-tPbYLEiBU4MYAL2XoZme/bgfUeotpDBd81lgHLCbDZZFaGmECk0b+/xejPFtmiBP87GgP/y4jplcRpbH+fgCzQ==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.6.2.tgz", + "integrity": "sha512-G9mN+KOYIUe2sB9kpJkO9Bk18J4dTDArNFPwoZ7WKHKel55eKIS/u2bLthxgojwlf9NLCVQfgzM/WsOVvoC6Fw==", "dev": true, "dependencies": { - "@jest/environment": "^29.6.1", - "@jest/expect": "^29.6.1", - "@jest/test-result": "^29.6.1", + "@jest/environment": "^29.6.2", + "@jest/expect": "^29.6.2", + "@jest/test-result": "^29.6.2", "@jest/types": "^29.6.1", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", - "dedent": "^0.7.0", + "dedent": "^1.0.0", "is-generator-fn": "^2.0.0", - "jest-each": "^29.6.1", - "jest-matcher-utils": "^29.6.1", - "jest-message-util": "^29.6.1", - "jest-runtime": "^29.6.1", - "jest-snapshot": "^29.6.1", - "jest-util": "^29.6.1", + "jest-each": "^29.6.2", + "jest-matcher-utils": "^29.6.2", + "jest-message-util": "^29.6.2", + "jest-runtime": "^29.6.2", + "jest-snapshot": "^29.6.2", + "jest-util": "^29.6.2", "p-limit": "^3.1.0", - "pretty-format": "^29.6.1", + "pretty-format": "^29.6.2", "pure-rand": "^6.0.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" @@ -3327,21 +3386,21 @@ } }, "node_modules/jest-cli": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.6.1.tgz", - "integrity": "sha512-607dSgTA4ODIN6go9w6xY3EYkyPFGicx51a69H7yfvt7lN53xNswEVLovq+E77VsTRi5fWprLH0yl4DJgE8Ing==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.6.2.tgz", + "integrity": "sha512-TT6O247v6dCEX2UGHGyflMpxhnrL0DNqP2fRTKYm3nJJpCTfXX3GCMQPGFjXDoj0i5/Blp3jriKXFgdfmbYB6Q==", "dev": true, "dependencies": { - "@jest/core": "^29.6.1", - "@jest/test-result": "^29.6.1", + "@jest/core": "^29.6.2", + "@jest/test-result": "^29.6.2", "@jest/types": "^29.6.1", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "import-local": "^3.0.2", - "jest-config": "^29.6.1", - "jest-util": "^29.6.1", - "jest-validate": "^29.6.1", + "jest-config": "^29.6.2", + "jest-util": "^29.6.2", + "jest-validate": "^29.6.2", "prompts": "^2.0.1", "yargs": "^17.3.1" }, @@ -3361,31 +3420,31 @@ } }, "node_modules/jest-config": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.6.1.tgz", - "integrity": "sha512-XdjYV2fy2xYixUiV2Wc54t3Z4oxYPAELUzWnV6+mcbq0rh742X2p52pii5A3oeRzYjLnQxCsZmp0qpI6klE2cQ==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.6.2.tgz", + "integrity": "sha512-VxwFOC8gkiJbuodG9CPtMRjBUNZEHxwfQXmIudSTzFWxaci3Qub1ddTRbFNQlD/zUeaifLndh/eDccFX4wCMQw==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.6.1", + "@jest/test-sequencer": "^29.6.2", "@jest/types": "^29.6.1", - "babel-jest": "^29.6.1", + "babel-jest": "^29.6.2", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-circus": "^29.6.1", - "jest-environment-node": "^29.6.1", + "jest-circus": "^29.6.2", + "jest-environment-node": "^29.6.2", "jest-get-type": "^29.4.3", "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.6.1", - "jest-runner": "^29.6.1", - "jest-util": "^29.6.1", - "jest-validate": "^29.6.1", + "jest-resolve": "^29.6.2", + "jest-runner": "^29.6.2", + "jest-util": "^29.6.2", + "jest-validate": "^29.6.2", "micromatch": "^4.0.4", "parse-json": "^5.2.0", - "pretty-format": "^29.6.1", + "pretty-format": "^29.6.2", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" }, @@ -3406,15 +3465,15 @@ } }, "node_modules/jest-diff": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.6.1.tgz", - "integrity": "sha512-FsNCvinvl8oVxpNLttNQX7FAq7vR+gMDGj90tiP7siWw1UdakWUGqrylpsYrpvj908IYckm5Y0Q7azNAozU1Kg==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.6.2.tgz", + "integrity": "sha512-t+ST7CB9GX5F2xKwhwCf0TAR17uNDiaPTZnVymP9lw0lssa9vG+AFyDZoeIHStU3WowFFwT+ky+er0WVl2yGhA==", "dev": true, "dependencies": { "chalk": "^4.0.0", "diff-sequences": "^29.4.3", "jest-get-type": "^29.4.3", - "pretty-format": "^29.6.1" + "pretty-format": "^29.6.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -3433,33 +3492,33 @@ } }, "node_modules/jest-each": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.6.1.tgz", - "integrity": "sha512-n5eoj5eiTHpKQCAVcNTT7DRqeUmJ01hsAL0Q1SMiBHcBcvTKDELixQOGMCpqhbIuTcfC4kMfSnpmDqRgRJcLNQ==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.6.2.tgz", + "integrity": "sha512-MsrsqA0Ia99cIpABBc3izS1ZYoYfhIy0NNWqPSE0YXbQjwchyt6B1HD2khzyPe1WiJA7hbxXy77ZoUQxn8UlSw==", "dev": true, "dependencies": { "@jest/types": "^29.6.1", "chalk": "^4.0.0", "jest-get-type": "^29.4.3", - "jest-util": "^29.6.1", - "pretty-format": "^29.6.1" + "jest-util": "^29.6.2", + "pretty-format": "^29.6.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-environment-node": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.6.1.tgz", - "integrity": "sha512-ZNIfAiE+foBog24W+2caIldl4Irh8Lx1PUhg/GZ0odM1d/h2qORAsejiFc7zb+SEmYPn1yDZzEDSU5PmDkmVLQ==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.6.2.tgz", + "integrity": "sha512-YGdFeZ3T9a+/612c5mTQIllvWkddPbYcN2v95ZH24oWMbGA4GGS2XdIF92QMhUhvrjjuQWYgUGW2zawOyH63MQ==", "dev": true, "dependencies": { - "@jest/environment": "^29.6.1", - "@jest/fake-timers": "^29.6.1", + "@jest/environment": "^29.6.2", + "@jest/fake-timers": "^29.6.2", "@jest/types": "^29.6.1", "@types/node": "*", - "jest-mock": "^29.6.1", - "jest-util": "^29.6.1" + "jest-mock": "^29.6.2", + "jest-util": "^29.6.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -3475,9 +3534,9 @@ } }, "node_modules/jest-haste-map": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.6.1.tgz", - "integrity": "sha512-0m7f9PZXxOCk1gRACiVgX85knUKPKLPg4oRCjLoqIm9brTHXaorMA0JpmtmVkQiT8nmXyIVoZd/nnH1cfC33ig==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.6.2.tgz", + "integrity": "sha512-+51XleTDAAysvU8rT6AnS1ZJ+WHVNqhj1k6nTvN2PYP+HjU3kqlaKQ1Lnw3NYW3bm2r8vq82X0Z1nDDHZMzHVA==", "dev": true, "dependencies": { "@jest/types": "^29.6.1", @@ -3487,8 +3546,8 @@ "fb-watchman": "^2.0.0", "graceful-fs": "^4.2.9", "jest-regex-util": "^29.4.3", - "jest-util": "^29.6.1", - "jest-worker": "^29.6.1", + "jest-util": "^29.6.2", + "jest-worker": "^29.6.2", "micromatch": "^4.0.4", "walker": "^1.0.8" }, @@ -3500,37 +3559,37 @@ } }, "node_modules/jest-leak-detector": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.6.1.tgz", - "integrity": "sha512-OrxMNyZirpOEwkF3UHnIkAiZbtkBWiye+hhBweCHkVbCgyEy71Mwbb5zgeTNYWJBi1qgDVfPC1IwO9dVEeTLwQ==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.6.2.tgz", + "integrity": "sha512-aNqYhfp5uYEO3tdWMb2bfWv6f0b4I0LOxVRpnRLAeque2uqOVVMLh6khnTcE2qJ5wAKop0HcreM1btoysD6bPQ==", "dev": true, "dependencies": { "jest-get-type": "^29.4.3", - "pretty-format": "^29.6.1" + "pretty-format": "^29.6.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-matcher-utils": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.6.1.tgz", - "integrity": "sha512-SLaztw9d2mfQQKHmJXKM0HCbl2PPVld/t9Xa6P9sgiExijviSp7TnZZpw2Fpt+OI3nwUO/slJbOfzfUMKKC5QA==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.6.2.tgz", + "integrity": "sha512-4LiAk3hSSobtomeIAzFTe+N8kL6z0JtF3n6I4fg29iIW7tt99R7ZcIFW34QkX+DuVrf+CUe6wuVOpm7ZKFJzZQ==", "dev": true, "dependencies": { "chalk": "^4.0.0", - "jest-diff": "^29.6.1", + "jest-diff": "^29.6.2", "jest-get-type": "^29.4.3", - "pretty-format": "^29.6.1" + "pretty-format": "^29.6.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-message-util": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.1.tgz", - "integrity": "sha512-KoAW2zAmNSd3Gk88uJ56qXUWbFk787QKmjjJVOjtGFmmGSZgDBrlIL4AfQw1xyMYPNVD7dNInfIbur9B2rd/wQ==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.2.tgz", + "integrity": "sha512-vnIGYEjoPSuRqV8W9t+Wow95SDp6KPX2Uf7EoeG9G99J2OVh7OSwpS4B6J0NfpEIpfkBNHlBZpA2rblEuEFhZQ==", "dev": true, "dependencies": { "@babel/code-frame": "^7.12.13", @@ -3539,7 +3598,7 @@ "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^29.6.1", + "pretty-format": "^29.6.2", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, @@ -3548,14 +3607,14 @@ } }, "node_modules/jest-mock": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.6.1.tgz", - "integrity": "sha512-brovyV9HBkjXAEdRooaTQK42n8usKoSRR3gihzUpYeV/vwqgSoNfrksO7UfSACnPmxasO/8TmHM3w9Hp3G1dgw==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.6.2.tgz", + "integrity": "sha512-hoSv3lb3byzdKfwqCuT6uTscan471GUECqgNYykg6ob0yiAw3zYc7OrPnI9Qv8Wwoa4lC7AZ9hyS4AiIx5U2zg==", "dev": true, "dependencies": { "@jest/types": "^29.6.1", "@types/node": "*", - "jest-util": "^29.6.1" + "jest-util": "^29.6.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -3588,17 +3647,17 @@ } }, "node_modules/jest-resolve": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.6.1.tgz", - "integrity": "sha512-AeRkyS8g37UyJiP9w3mmI/VXU/q8l/IH52vj/cDAyScDcemRbSBhfX/NMYIGilQgSVwsjxrCHf3XJu4f+lxCMg==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.6.2.tgz", + "integrity": "sha512-G/iQUvZWI5e3SMFssc4ug4dH0aZiZpsDq9o1PtXTV1210Ztyb2+w+ZgQkB3iOiC5SmAEzJBOHWz6Hvrd+QnNPw==", "dev": true, "dependencies": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.1", + "jest-haste-map": "^29.6.2", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.6.1", - "jest-validate": "^29.6.1", + "jest-util": "^29.6.2", + "jest-validate": "^29.6.2", "resolve": "^1.20.0", "resolve.exports": "^2.0.0", "slash": "^3.0.0" @@ -3608,43 +3667,43 @@ } }, "node_modules/jest-resolve-dependencies": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.1.tgz", - "integrity": "sha512-BbFvxLXtcldaFOhNMXmHRWx1nXQO5LoXiKSGQcA1LxxirYceZT6ch8KTE1bK3X31TNG/JbkI7OkS/ABexVahiw==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.2.tgz", + "integrity": "sha512-LGqjDWxg2fuQQm7ypDxduLu/m4+4Lb4gczc13v51VMZbVP5tSBILqVx8qfWcsdP8f0G7aIqByIALDB0R93yL+w==", "dev": true, "dependencies": { "jest-regex-util": "^29.4.3", - "jest-snapshot": "^29.6.1" + "jest-snapshot": "^29.6.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runner": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.6.1.tgz", - "integrity": "sha512-tw0wb2Q9yhjAQ2w8rHRDxteryyIck7gIzQE4Reu3JuOBpGp96xWgF0nY8MDdejzrLCZKDcp8JlZrBN/EtkQvPQ==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.6.2.tgz", + "integrity": "sha512-wXOT/a0EspYgfMiYHxwGLPCZfC0c38MivAlb2lMEAlwHINKemrttu1uSbcGbfDV31sFaPWnWJPmb2qXM8pqZ4w==", "dev": true, "dependencies": { - "@jest/console": "^29.6.1", - "@jest/environment": "^29.6.1", - "@jest/test-result": "^29.6.1", - "@jest/transform": "^29.6.1", + "@jest/console": "^29.6.2", + "@jest/environment": "^29.6.2", + "@jest/test-result": "^29.6.2", + "@jest/transform": "^29.6.2", "@jest/types": "^29.6.1", "@types/node": "*", "chalk": "^4.0.0", "emittery": "^0.13.1", "graceful-fs": "^4.2.9", "jest-docblock": "^29.4.3", - "jest-environment-node": "^29.6.1", - "jest-haste-map": "^29.6.1", - "jest-leak-detector": "^29.6.1", - "jest-message-util": "^29.6.1", - "jest-resolve": "^29.6.1", - "jest-runtime": "^29.6.1", - "jest-util": "^29.6.1", - "jest-watcher": "^29.6.1", - "jest-worker": "^29.6.1", + "jest-environment-node": "^29.6.2", + "jest-haste-map": "^29.6.2", + "jest-leak-detector": "^29.6.2", + "jest-message-util": "^29.6.2", + "jest-resolve": "^29.6.2", + "jest-runtime": "^29.6.2", + "jest-util": "^29.6.2", + "jest-watcher": "^29.6.2", + "jest-worker": "^29.6.2", "p-limit": "^3.1.0", "source-map-support": "0.5.13" }, @@ -3653,17 +3712,17 @@ } }, "node_modules/jest-runtime": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.6.1.tgz", - "integrity": "sha512-D6/AYOA+Lhs5e5il8+5pSLemjtJezUr+8zx+Sn8xlmOux3XOqx4d8l/2udBea8CRPqqrzhsKUsN/gBDE/IcaPQ==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.6.2.tgz", + "integrity": "sha512-2X9dqK768KufGJyIeLmIzToDmsN0m7Iek8QNxRSI/2+iPFYHF0jTwlO3ftn7gdKd98G/VQw9XJCk77rbTGZnJg==", "dev": true, "dependencies": { - "@jest/environment": "^29.6.1", - "@jest/fake-timers": "^29.6.1", - "@jest/globals": "^29.6.1", + "@jest/environment": "^29.6.2", + "@jest/fake-timers": "^29.6.2", + "@jest/globals": "^29.6.2", "@jest/source-map": "^29.6.0", - "@jest/test-result": "^29.6.1", - "@jest/transform": "^29.6.1", + "@jest/test-result": "^29.6.2", + "@jest/transform": "^29.6.2", "@jest/types": "^29.6.1", "@types/node": "*", "chalk": "^4.0.0", @@ -3671,13 +3730,13 @@ "collect-v8-coverage": "^1.0.0", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.1", - "jest-message-util": "^29.6.1", - "jest-mock": "^29.6.1", + "jest-haste-map": "^29.6.2", + "jest-message-util": "^29.6.2", + "jest-mock": "^29.6.2", "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.6.1", - "jest-snapshot": "^29.6.1", - "jest-util": "^29.6.1", + "jest-resolve": "^29.6.2", + "jest-snapshot": "^29.6.2", + "jest-util": "^29.6.2", "slash": "^3.0.0", "strip-bom": "^4.0.0" }, @@ -3686,9 +3745,9 @@ } }, "node_modules/jest-snapshot": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.6.1.tgz", - "integrity": "sha512-G4UQE1QQ6OaCgfY+A0uR1W2AY0tGXUPQpoUClhWHq1Xdnx1H6JOrC2nH5lqnOEqaDgbHFgIwZ7bNq24HpB180A==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.6.2.tgz", + "integrity": "sha512-1OdjqvqmRdGNvWXr/YZHuyhh5DeaLp1p/F8Tht/MrMw4Kr1Uu/j4lRG+iKl1DAqUJDWxtQBMk41Lnf/JETYBRA==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", @@ -3696,21 +3755,20 @@ "@babel/plugin-syntax-jsx": "^7.7.2", "@babel/plugin-syntax-typescript": "^7.7.2", "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.6.1", - "@jest/transform": "^29.6.1", + "@jest/expect-utils": "^29.6.2", + "@jest/transform": "^29.6.2", "@jest/types": "^29.6.1", - "@types/prettier": "^2.1.5", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "expect": "^29.6.1", + "expect": "^29.6.2", "graceful-fs": "^4.2.9", - "jest-diff": "^29.6.1", + "jest-diff": "^29.6.2", "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.6.1", - "jest-message-util": "^29.6.1", - "jest-util": "^29.6.1", + "jest-matcher-utils": "^29.6.2", + "jest-message-util": "^29.6.2", + "jest-util": "^29.6.2", "natural-compare": "^1.4.0", - "pretty-format": "^29.6.1", + "pretty-format": "^29.6.2", "semver": "^7.5.3" }, "engines": { @@ -3751,9 +3809,9 @@ "dev": true }, "node_modules/jest-util": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.6.1.tgz", - "integrity": "sha512-NRFCcjc+/uO3ijUVyNOQJluf8PtGCe/W6cix36+M3cTFgiYqFOOW5MgN4JOOcvbUhcKTYVd1CvHz/LWi8d16Mg==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.6.2.tgz", + "integrity": "sha512-3eX1qb6L88lJNCFlEADKOkjpXJQyZRiavX1INZ4tRnrBVr2COd3RgcTLyUiEXMNBlDU/cgYq6taUS0fExrWW4w==", "dev": true, "dependencies": { "@jest/types": "^29.6.1", @@ -3768,9 +3826,9 @@ } }, "node_modules/jest-validate": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.6.1.tgz", - "integrity": "sha512-r3Ds69/0KCN4vx4sYAbGL1EVpZ7MSS0vLmd3gV78O+NAx3PDQQukRU5hNHPXlyqCgFY8XUk7EuTMLugh0KzahA==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.6.2.tgz", + "integrity": "sha512-vGz0yMN5fUFRRbpJDPwxMpgSXW1LDKROHfBopAvDcmD6s+B/s8WJrwi+4bfH4SdInBA5C3P3BI19dBtKzx1Arg==", "dev": true, "dependencies": { "@jest/types": "^29.6.1", @@ -3778,7 +3836,7 @@ "chalk": "^4.0.0", "jest-get-type": "^29.4.3", "leven": "^3.1.0", - "pretty-format": "^29.6.1" + "pretty-format": "^29.6.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -3797,18 +3855,18 @@ } }, "node_modules/jest-watcher": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.6.1.tgz", - "integrity": "sha512-d4wpjWTS7HEZPaaj8m36QiaP856JthRZkrgcIY/7ISoUWPIillrXM23WPboZVLbiwZBt4/qn2Jke84Sla6JhFA==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.6.2.tgz", + "integrity": "sha512-GZitlqkMkhkefjfN/p3SJjrDaxPflqxEAv3/ik10OirZqJGYH5rPiIsgVcfof0Tdqg3shQGdEIxDBx+B4tuLzA==", "dev": true, "dependencies": { - "@jest/test-result": "^29.6.1", + "@jest/test-result": "^29.6.2", "@jest/types": "^29.6.1", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "emittery": "^0.13.1", - "jest-util": "^29.6.1", + "jest-util": "^29.6.2", "string-length": "^4.0.1" }, "engines": { @@ -3816,13 +3874,13 @@ } }, "node_modules/jest-worker": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.1.tgz", - "integrity": "sha512-U+Wrbca7S8ZAxAe9L6nb6g8kPdia5hj32Puu5iOqBCMTMWFHXuK6dOV2IFrpedbTV8fjMFLdWNttQTBL6u2MRA==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.2.tgz", + "integrity": "sha512-l3ccBOabTdkng8I/ORCkADz4eSMKejTYv1vB/Z83UiubqhC1oQ5Li6dWCyqOIvSifGjUBxuvxvlm6KGK2DtuAQ==", "dev": true, "dependencies": { "@types/node": "*", - "jest-util": "^29.6.1", + "jest-util": "^29.6.2", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, @@ -3972,7 +4030,7 @@ } }, "node_modules/le-coffre-resources": { - "resolved": "git+ssh://git@github.com/smart-chain-fr/leCoffre-resources.git#e7916d516fe434c93ef13e765d8d63a7ce3c56b2", + "resolved": "git+ssh://git@github.com/smart-chain-fr/leCoffre-resources.git#e0b1ff55a860f624b7708d37f5bfe3072ef63e5f", "license": "MIT", "dependencies": { "class-transformer": "^0.5.1", @@ -3990,9 +4048,9 @@ } }, "node_modules/libphonenumber-js": { - "version": "1.10.38", - "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.38.tgz", - "integrity": "sha512-4NjVXVUmpZ9Zsqq6FXa2+MKI+KAI3tOqA0pxXgXGluhpj4ge5didmbWJpMBqGB3AVGv1SnEtKdGTbxjSEG1kCQ==" + "version": "1.10.41", + "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.41.tgz", + "integrity": "sha512-4rmmF4u4vD3eGNuuCGjCPwRwO+fIuu1WWcS7VwbPTiMFkJd8F02v8o5pY5tlYuMR+xOvJ88mtOHpkm0Tnu2LcQ==" }, "node_modules/lines-and-columns": { "version": "1.2.4", @@ -4050,9 +4108,9 @@ } }, "node_modules/luxon": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.3.0.tgz", - "integrity": "sha512-An0UCfG/rSiqtAIiBPO0Y9/zAnHUZxAMiCpTd5h2smgsj7GGmcenvrvww2cqNA8/4A5ZrD1gJpHN2mIHZQF+Mg==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.4.0.tgz", + "integrity": "sha512-7eDo4Pt7aGhoCheGFIuq4Xa2fJm4ZpmldpGhjTYBNUYNCN6TIEP6v7chwwwt3KRp7YR+rghbfvjyo3V5y9hgBw==", "engines": { "node": ">=12" } @@ -4419,11 +4477,11 @@ } }, "node_modules/next": { - "version": "13.4.12", - "resolved": "https://registry.npmjs.org/next/-/next-13.4.12.tgz", - "integrity": "sha512-eHfnru9x6NRmTMcjQp6Nz0J4XH9OubmzOa7CkWL+AUrUxpibub3vWwttjduu9No16dug1kq04hiUUpo7J3m3Xw==", + "version": "13.4.16", + "resolved": "https://registry.npmjs.org/next/-/next-13.4.16.tgz", + "integrity": "sha512-1xaA/5DrfpPu0eV31Iro7JfPeqO8uxQWb1zYNTe+KDKdzqkAGapLcDYHMLNKXKB7lHjZ7LfKUOf9dyuzcibrhA==", "dependencies": { - "@next/env": "13.4.12", + "@next/env": "13.4.16", "@swc/helpers": "0.5.1", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001406", @@ -4439,19 +4497,18 @@ "node": ">=16.8.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "13.4.12", - "@next/swc-darwin-x64": "13.4.12", - "@next/swc-linux-arm64-gnu": "13.4.12", - "@next/swc-linux-arm64-musl": "13.4.12", - "@next/swc-linux-x64-gnu": "13.4.12", - "@next/swc-linux-x64-musl": "13.4.12", - "@next/swc-win32-arm64-msvc": "13.4.12", - "@next/swc-win32-ia32-msvc": "13.4.12", - "@next/swc-win32-x64-msvc": "13.4.12" + "@next/swc-darwin-arm64": "13.4.16", + "@next/swc-darwin-x64": "13.4.16", + "@next/swc-linux-arm64-gnu": "13.4.16", + "@next/swc-linux-arm64-musl": "13.4.16", + "@next/swc-linux-x64-gnu": "13.4.16", + "@next/swc-linux-x64-musl": "13.4.16", + "@next/swc-win32-arm64-msvc": "13.4.16", + "@next/swc-win32-ia32-msvc": "13.4.16", + "@next/swc-win32-x64-msvc": "13.4.16" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", - "fibers": ">= 3.1.0", "react": "^18.2.0", "react-dom": "^18.2.0", "sass": "^1.3.0" @@ -4460,9 +4517,6 @@ "@opentelemetry/api": { "optional": true }, - "fibers": { - "optional": true - }, "sass": { "optional": true } @@ -4884,9 +4938,9 @@ } }, "node_modules/pretty-format": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.1.tgz", - "integrity": "sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog==", + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.2.tgz", + "integrity": "sha512-1q0oC8eRveTg5nnBEWMXAU2qpv65Gnuf2eCQzSjxpWFkPaPARwqZZDGuNE0zPAZfTCHzIk3A8dIjwlQKKLphyg==", "dev": true, "dependencies": { "@jest/schemas": "^29.6.0", @@ -5104,12 +5158,12 @@ } }, "node_modules/resolve": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", - "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", + "version": "1.22.4", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz", + "integrity": "sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==", "dev": true, "dependencies": { - "is-core-module": "^2.11.0", + "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -5879,9 +5933,9 @@ "dev": true }, "node_modules/validator": { - "version": "13.9.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.9.0.tgz", - "integrity": "sha512-B+dGG8U3fdtM0/aNK4/X8CXq/EcxU2WPrPEkJGslb47qyHsxmbggTWK0yEA4qnYVNF+nxNlN88o14hIcPmSIEA==", + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.11.0.tgz", + "integrity": "sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==", "engines": { "node": ">= 0.10" } diff --git a/package.json b/package.json index fd68c5be..02c81b78 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "cron": "^2.3.1", "express": "^4.18.2", "jsonwebtoken": "^9.0.0", - "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.66", + "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.67", "module-alias": "^2.2.2", "multer": "^1.4.5-lts.1", "next": "^13.1.5", diff --git a/src/app/api/admin/UsersController.ts b/src/app/api/admin/UsersController.ts index 1c7c3251..cc4cde87 100644 --- a/src/app/api/admin/UsersController.ts +++ b/src/app/api/admin/UsersController.ts @@ -8,7 +8,6 @@ import { Prisma } from "@prisma/client"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; import userHandler from "@App/middlewares/OfficeMembershipHandlers/UserHandler"; -import { validateOrReject } from "class-validator"; import roleHandler from "@App/middlewares/RolesHandler"; import RolesService from "@Services/admin/RolesService/RolesService"; import OfficeRolesService from "@Services/admin/OfficeRolesService/OfficeRolesService"; @@ -87,9 +86,6 @@ export default class UsersController extends ApiController { //init IUser resource with request body values const userEntity = User.hydrate(req.body); - //validate user - await validateOrReject(userEntity, { groups: ["updateUser"] }); - if(userEntity.role) { const role = await this.roleService.getByUid(userEntity.role.uid!); if(!role) { diff --git a/src/app/api/customer/FilesController.ts b/src/app/api/customer/FilesController.ts index 76dd93ee..f58b3944 100644 --- a/src/app/api/customer/FilesController.ts +++ b/src/app/api/customer/FilesController.ts @@ -135,9 +135,6 @@ export default class FilesController extends ApiController { //init File resource with request body values const fileEntity = File.hydrate(req.body); - //validate file - await validateOrReject(fileEntity, { groups: ["updateFile"] }); - //call service to get prisma entity const fileEntityUpdated: Files = await this.filesService.update(uid, fileEntity); diff --git a/src/app/api/super-admin/OfficesController.ts b/src/app/api/super-admin/OfficesController.ts index 3fb1bd00..f4edab79 100644 --- a/src/app/api/super-admin/OfficesController.ts +++ b/src/app/api/super-admin/OfficesController.ts @@ -94,8 +94,7 @@ export default class OfficesController extends ApiController { } //init IUser resource with request body values const officeEntity = OfficeResource.hydrate(req.body); - //validate user - await validateOrReject(officeEntity, { groups: ["updateOffice"] }); + //call service to get prisma entity const officeEntityUpdated = await this.officesService.update(uid, officeEntity); //Hydrate ressource with prisma entity diff --git a/src/app/api/super-admin/RulesController.ts b/src/app/api/super-admin/RulesController.ts index 025ec5c0..6f2f21a4 100644 --- a/src/app/api/super-admin/RulesController.ts +++ b/src/app/api/super-admin/RulesController.ts @@ -92,9 +92,6 @@ export default class RulesController extends ApiController { //init IRule resource with request body values const ruleEntity = Rule.hydrate(req.body); - //validate rule - await validateOrReject(ruleEntity, { groups: ["updateRule"] }); - //call service to get prisma entity const ruleEntityUpdated = await this.rulesService.update(ruleEntity); diff --git a/src/app/api/super-admin/UsersController.ts b/src/app/api/super-admin/UsersController.ts index 618c4728..fd135312 100644 --- a/src/app/api/super-admin/UsersController.ts +++ b/src/app/api/super-admin/UsersController.ts @@ -109,9 +109,6 @@ export default class UsersController extends ApiController { //init IUser resource with request body values const userEntity = User.hydrate(req.body); - //validate user - await validateOrReject(userEntity, { groups: ["updateUser"] }); - if(userEntity.role) { const role = await this.roleService.getByUid(userEntity.role.uid!); if(!role) { From 232633fc937d4626498013a84a4e0b30aa93fcb0 Mon Sep 17 00:00:00 2001 From: OxSaitama Date: Wed, 16 Aug 2023 16:27:52 +0200 Subject: [PATCH 43/49] add role and rules label --- package-lock.json | 4 +- package.json | 2 +- .../20230816144031_v22/migration.sql | 12 ++ src/common/databases/schema.prisma | 2 + src/common/databases/seeders/seeder.ts | 114 +++++++++--------- src/common/repositories/UsersRepository.ts | 1 + .../notary/RolesService/RolesService.ts | 1 - .../notary/RulesService/RulesService.ts | 1 - .../notary/UsersService/UsersService.ts | 20 +-- 9 files changed, 73 insertions(+), 84 deletions(-) create mode 100644 src/common/databases/migrations/20230816144031_v22/migration.sql diff --git a/package-lock.json b/package-lock.json index e6e9857e..d147eb2c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,7 @@ "cron": "^2.3.1", "express": "^4.18.2", "jsonwebtoken": "^9.0.0", - "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.67", + "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.68", "module-alias": "^2.2.2", "multer": "^1.4.5-lts.1", "next": "^13.1.5", @@ -4030,7 +4030,7 @@ } }, "node_modules/le-coffre-resources": { - "resolved": "git+ssh://git@github.com/smart-chain-fr/leCoffre-resources.git#e0b1ff55a860f624b7708d37f5bfe3072ef63e5f", + "resolved": "git+ssh://git@github.com/smart-chain-fr/leCoffre-resources.git#ad0660abcb9de6ee7f396dce9b25fa7731a8e3b8", "license": "MIT", "dependencies": { "class-transformer": "^0.5.1", diff --git a/package.json b/package.json index 02c81b78..19fd003b 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "cron": "^2.3.1", "express": "^4.18.2", "jsonwebtoken": "^9.0.0", - "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.67", + "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.68", "module-alias": "^2.2.2", "multer": "^1.4.5-lts.1", "next": "^13.1.5", diff --git a/src/common/databases/migrations/20230816144031_v22/migration.sql b/src/common/databases/migrations/20230816144031_v22/migration.sql new file mode 100644 index 00000000..59a287ba --- /dev/null +++ b/src/common/databases/migrations/20230816144031_v22/migration.sql @@ -0,0 +1,12 @@ +/* + Warnings: + + - Added the required column `label` to the `roles` table without a default value. This is not possible if the table is not empty. + - Added the required column `label` to the `rules` table without a default value. This is not possible if the table is not empty. + +*/ +-- AlterTable +ALTER TABLE "roles" ADD COLUMN "label" VARCHAR(255) NOT NULL; + +-- AlterTable +ALTER TABLE "rules" ADD COLUMN "label" VARCHAR(255) NOT NULL; diff --git a/src/common/databases/schema.prisma b/src/common/databases/schema.prisma index 98ff92ea..858709ed 100644 --- a/src/common/databases/schema.prisma +++ b/src/common/databases/schema.prisma @@ -241,6 +241,7 @@ model DeedTypes { model Roles { uid String @id @unique @default(uuid()) name String @db.VarChar(255) + label String @db.VarChar(255) created_at DateTime? @default(now()) updated_at DateTime? @updatedAt rules Rules[] @relation("RolesHasRules") @@ -265,6 +266,7 @@ model OfficeRoles { model Rules { uid String @id @unique @default(uuid()) name String @db.VarChar(255) + label String @db.VarChar(255) created_at DateTime? @default(now()) updated_at DateTime? @updatedAt role Roles[] @relation("RolesHasRules") diff --git a/src/common/databases/seeders/seeder.ts b/src/common/databases/seeders/seeder.ts index 700442cf..cfc8ccda 100644 --- a/src/common/databases/seeders/seeder.ts +++ b/src/common/databases/seeders/seeder.ts @@ -515,301 +515,289 @@ export default async function main() { const rules: Rule[] = [ { name: "GET users", + label: "Lecture des utilisateurs", created_at: new Date(), updated_at: new Date(), }, { name: "GET offices", + label: "Lecture des offices", created_at: new Date(), updated_at: new Date(), }, { name: "GET customers", + label: "Lecture des clients", created_at: new Date(), updated_at: new Date(), }, { name: "GET deeds", + label: "Lecture des actes", created_at: new Date(), updated_at: new Date(), }, { name: "GET deed-types", + label: "Lecture des types d'actes", created_at: new Date(), updated_at: new Date(), }, { name: "GET documents", + label: "Lecture des documents", created_at: new Date(), updated_at: new Date(), }, { name: "GET document-types", + label: "Lecture des types de documents", created_at: new Date(), updated_at: new Date(), }, { name: "GET files", + label: "Lecture des fichiers", created_at: new Date(), updated_at: new Date(), }, { name: "GET folders", + label: "Lecture des dossiers", created_at: new Date(), updated_at: new Date(), }, { name: "GET roles", + label: "Lecture utilisateurs", created_at: new Date(), updated_at: new Date(), }, { name: "GET rules", + label: "Lecture des droits", created_at: new Date(), updated_at: new Date(), }, { name: "GET office-roles", + label: "Lecture des rôles d'office", created_at: new Date(), updated_at: new Date(), }, { name: "PUT users", + label: "Modification des utilisateurs", created_at: new Date(), updated_at: new Date(), }, { name: "PUT offices", + label: "Modification des offices", created_at: new Date(), updated_at: new Date(), }, { name: "PUT customers", + label: "Modification des clients", created_at: new Date(), updated_at: new Date(), }, { name: "PUT deeds", + label: "Modification des actes", created_at: new Date(), updated_at: new Date(), }, { name: "PUT deed-types", + label: "Modification des types d'actes", created_at: new Date(), updated_at: new Date(), }, { name: "PUT documents", + label: "Modification des documents", created_at: new Date(), updated_at: new Date(), }, { name: "PUT document-types", + label: "Modification des types de documents", created_at: new Date(), updated_at: new Date(), }, { name: "PUT files", + label: "Modification des fichiers", created_at: new Date(), updated_at: new Date(), }, { name: "PUT folders", + label: "Modification des dossiers", created_at: new Date(), updated_at: new Date(), }, { name: "PUT roles", + label: "Modification des rôles", created_at: new Date(), updated_at: new Date(), }, { name: "PUT rules", + label: "Modification des droits", created_at: new Date(), updated_at: new Date(), }, { name: "PUT office-roles", + label: "Modification des rôles d'office", created_at: new Date(), updated_at: new Date(), }, { name: "POST users", + label: "Création des utilisateurs", created_at: new Date(), updated_at: new Date(), }, { name: "POST offices", + label: "Création des offices", created_at: new Date(), updated_at: new Date(), }, { name: "POST customers", + label: "Création des clients", created_at: new Date(), updated_at: new Date(), }, { name: "POST deeds", + label: "Création des actes", created_at: new Date(), updated_at: new Date(), }, { name: "POST deed-types", + label: "Création des types d'actes", created_at: new Date(), updated_at: new Date(), }, { name: "POST documents", + label: "Création des documents", created_at: new Date(), updated_at: new Date(), }, { name: "POST document-types", + label: "Création des types de documents", created_at: new Date(), updated_at: new Date(), }, { name: "POST files", + label: "Création des fichiers", created_at: new Date(), updated_at: new Date(), }, { name: "POST folders", + label: "Création des dossiers", created_at: new Date(), updated_at: new Date(), }, { name: "POST roles", + label: "Création des rôles", created_at: new Date(), updated_at: new Date(), }, { name: "POST rules", + label: "Création des droits", created_at: new Date(), updated_at: new Date(), }, { name: "POST office-roles", - created_at: new Date(), - updated_at: new Date(), - }, - { - name: "POST users", - created_at: new Date(), - updated_at: new Date(), - }, - { - name: "POST offices", - created_at: new Date(), - updated_at: new Date(), - }, - { - name: "POST customers", - created_at: new Date(), - updated_at: new Date(), - }, - { - name: "POST deeds", - created_at: new Date(), - updated_at: new Date(), - }, - { - name: "POST deed-types", - created_at: new Date(), - updated_at: new Date(), - }, - { - name: "POST documents", - created_at: new Date(), - updated_at: new Date(), - }, - { - name: "POST document-types", - created_at: new Date(), - updated_at: new Date(), - }, - { - name: "POST files", - created_at: new Date(), - updated_at: new Date(), - }, - { - name: "POST folders", - created_at: new Date(), - updated_at: new Date(), - }, - { - name: "POST roles", - created_at: new Date(), - updated_at: new Date(), - }, - { - name: "POST rules", - created_at: new Date(), - updated_at: new Date(), - }, - { - name: "POST office-roles", + label: "Création des rôles d'office", created_at: new Date(), updated_at: new Date(), }, { name: "DELETE users", + label: "Suppression des utilisateurs", created_at: new Date(), updated_at: new Date(), }, { name: "DELETE offices", + label: "Suppression des offices", created_at: new Date(), updated_at: new Date(), }, { name: "DELETE customers", + label: "Suppression des clients", created_at: new Date(), updated_at: new Date(), }, { name: "DELETE deeds", + label: "Suppression des actes", created_at: new Date(), updated_at: new Date(), }, { name: "DELETE deed-types", + label: "Suppression des types d'actes", created_at: new Date(), updated_at: new Date(), }, { name: "DELETE documents", + label: "Suppression des documents", created_at: new Date(), updated_at: new Date(), }, { name: "DELETE document-types", + label: "Suppression des types de documents", created_at: new Date(), updated_at: new Date(), }, { name: "DELETE files", + label: "Suppression des fichiers", created_at: new Date(), updated_at: new Date(), }, { name: "DELETE folders", + label: "Suppression des dossiers", created_at: new Date(), updated_at: new Date(), }, { name: "DELETE roles", + label: "Suppression des rôles", created_at: new Date(), updated_at: new Date(), }, { name: "DELETE rules", + label: "Suppression des droits", created_at: new Date(), updated_at: new Date(), }, { name: "DELETE office-roles", + label: "Suppression des rôles d'office", created_at: new Date(), updated_at: new Date(), }, @@ -818,24 +806,28 @@ export default async function main() { const roles: Role[] = [ { name: "super-admin", + label: "Super administrateur", created_at: new Date(), updated_at: new Date(), rules: rules, }, { name: "admin", + label: "Administrateur", created_at: new Date(), updated_at: new Date(), rules: rules.slice(0, 33), }, { name: "notary", + label: "Notaire", created_at: new Date(), updated_at: new Date(), rules: rules.slice(0, 22), }, { name: "default", + label: "Utilisateur", created_at: new Date(), updated_at: new Date(), rules: rules.slice(0, 11), @@ -1381,6 +1373,7 @@ export default async function main() { const ruleCreated = await prisma.rules.create({ data: { name: rule.name, + label: rule.label, }, }); rule.uid = ruleCreated.uid; @@ -1390,6 +1383,7 @@ export default async function main() { const roleCreated = await prisma.roles.create({ data: { name: role.name, + label: role.label, rules: { connect: role.rules?.map((rule) => ({ uid: rule.uid!, diff --git a/src/common/repositories/UsersRepository.ts b/src/common/repositories/UsersRepository.ts index 49673146..739aea8f 100644 --- a/src/common/repositories/UsersRepository.ts +++ b/src/common/repositories/UsersRepository.ts @@ -87,6 +87,7 @@ export default class UsersRepository extends BaseRepository { /** * @description : Update data from a user */ + public async update(uid: string, user: User): Promise { const updateArgs: Prisma.UsersUpdateArgs = { where: { diff --git a/src/services/notary/RolesService/RolesService.ts b/src/services/notary/RolesService/RolesService.ts index f59c26b1..6e652687 100644 --- a/src/services/notary/RolesService/RolesService.ts +++ b/src/services/notary/RolesService/RolesService.ts @@ -1,5 +1,4 @@ import BaseService from "@Services/BaseService"; -import "reflect-metadata"; import { Service } from "typedi"; import RolesRepository from "@Repositories/RolesRepository"; import { Prisma } from "@prisma/client"; diff --git a/src/services/notary/RulesService/RulesService.ts b/src/services/notary/RulesService/RulesService.ts index e52ad9bf..c59c9133 100644 --- a/src/services/notary/RulesService/RulesService.ts +++ b/src/services/notary/RulesService/RulesService.ts @@ -1,5 +1,4 @@ import BaseService from "@Services/BaseService"; -import "reflect-metadata"; import { Service } from "typedi"; import RulesRepository from "@Repositories/RulesRepository"; import { Prisma } from "@prisma/client"; diff --git a/src/services/notary/UsersService/UsersService.ts b/src/services/notary/UsersService/UsersService.ts index f6927c87..5efbfff9 100644 --- a/src/services/notary/UsersService/UsersService.ts +++ b/src/services/notary/UsersService/UsersService.ts @@ -1,9 +1,7 @@ import BaseService from "@Services/BaseService"; -import "reflect-metadata"; import { Service } from "typedi"; import UsersRepository from "@Repositories/UsersRepository"; -import User from "le-coffre-resources/dist/Notary"; -import { Prisma, Users } from "@prisma/client"; +import { Prisma } from "@prisma/client"; @Service() export default class UsersService extends BaseService { @@ -19,22 +17,6 @@ export default class UsersService extends BaseService { return this.userRepository.findMany(query); } - /** - * @description : Create a user - * @throws {Error} If user couldn't be created - */ - public create(userEntity: User): Promise { - return this.userRepository.create(userEntity); - } - - /** - * @description : Modify a user - * @throws {Error} If user modification failed - */ - public update(uid: string, userEntity: User): Promise { - return this.userRepository.update(uid, userEntity); - } - /** * @description : Get a user by uid * @throws {Error} If user cannot be get by uid From 527a4fd837afba729a62fa54d780bc9821fe0481 Mon Sep 17 00:00:00 2001 From: OxSaitama Date: Thu, 17 Aug 2023 11:28:30 +0200 Subject: [PATCH 44/49] refacto rules assignment in jwt --- src/common/databases/seeders/seeder.ts | 7 ------ src/common/repositories/RolesRepository.ts | 2 ++ src/common/repositories/RulesRepository.ts | 2 ++ .../common/AuthService/AuthService.ts | 25 ++++++++----------- src/test/config/Init.ts | 3 +++ 5 files changed, 18 insertions(+), 21 deletions(-) diff --git a/src/common/databases/seeders/seeder.ts b/src/common/databases/seeders/seeder.ts index cfc8ccda..0e812e5c 100644 --- a/src/common/databases/seeders/seeder.ts +++ b/src/common/databases/seeders/seeder.ts @@ -835,13 +835,6 @@ export default async function main() { ]; const officeRoles: OfficeRole[] = [ - { - name: "admin", - created_at: new Date(), - updated_at: new Date(), - office: offices[0]!, - rules: rules.slice(0, 40), - }, { name: "Notaire", created_at: new Date(), diff --git a/src/common/repositories/RolesRepository.ts b/src/common/repositories/RolesRepository.ts index 20d203c7..5467f0a0 100644 --- a/src/common/repositories/RolesRepository.ts +++ b/src/common/repositories/RolesRepository.ts @@ -31,6 +31,7 @@ export default class RolesRepository extends BaseRepository { const createArgs: Prisma.RolesCreateArgs = { data: { name: role.name, + label: role.label, rules: { connect: role.rules?.map((rule) => ({ uid: rule.uid!, @@ -52,6 +53,7 @@ export default class RolesRepository extends BaseRepository { }, data: { name: role.name, + label: role.label, rules: { set: role.rules?.map((rule) => ({ uid: rule.uid!, diff --git a/src/common/repositories/RulesRepository.ts b/src/common/repositories/RulesRepository.ts index 7781290b..281e505b 100644 --- a/src/common/repositories/RulesRepository.ts +++ b/src/common/repositories/RulesRepository.ts @@ -31,6 +31,7 @@ export default class RulesRepository extends BaseRepository { const createArgs: Prisma.RulesCreateArgs = { data: { name: rule.name, + label: rule.label }, }; @@ -47,6 +48,7 @@ export default class RulesRepository extends BaseRepository { }, data: { name: rule.name, + label: rule.label }, }; diff --git a/src/services/common/AuthService/AuthService.ts b/src/services/common/AuthService/AuthService.ts index 0a751e21..4410cd35 100644 --- a/src/services/common/AuthService/AuthService.ts +++ b/src/services/common/AuthService/AuthService.ts @@ -12,7 +12,7 @@ enum PROVIDER_OPENID { } interface ICustomerJwtPayload { - userId: string; + customerId: string; email: string; } @@ -46,7 +46,7 @@ export default class AuthService extends BaseService { } return { - userId: customer.uid, + customerId: customer.uid, email: contact.email, }; } @@ -57,22 +57,19 @@ export default class AuthService extends BaseService { if (!user) return null; const rules: string[] = []; - if (user.office_role) { - user.office_role.rules.forEach((rule) => { - rules.push(rule.name); - }); - return { - userId: user.uid, - openId: { providerName: providerName, userId: user.idNot }, - office_Id: user.office_membership.uid, - role: user.role.name, - rules: rules, - }; - } user.role.rules.forEach((rule) => { rules.push(rule.name); }); + + if (user.office_role) { + user.office_role.rules.forEach((rule) => { + if(!rules.includes(rule.name)) { + rules.push(rule.name); + } + }); + } + return { userId: user.uid, openId: { providerName: providerName, userId: user.idNot }, diff --git a/src/test/config/Init.ts b/src/test/config/Init.ts index 74721622..c3921d70 100644 --- a/src/test/config/Init.ts +++ b/src/test/config/Init.ts @@ -95,6 +95,7 @@ export const initRules = (rule: Rule): Promise => { return prisma.rules.create({ data: { name: rule.name, + label: rule.label, }, }); }; @@ -103,6 +104,7 @@ export const initRoles = (role: Role): Promise => { return prisma.roles.create({ data: { name: role.name, + label: role.label, }, }); }; @@ -154,6 +156,7 @@ export const initUsers = (user: User): Promise => { }, create: { name: user.role!.name, + label: user.role!.label }, }, }, From f1fc9deae7f9c4a68256ae8415f9ba8387374767 Mon Sep 17 00:00:00 2001 From: OxSaitama Date: Thu, 17 Aug 2023 13:39:08 +0200 Subject: [PATCH 45/49] update resources version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 19fd003b..fd95302f 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "cron": "^2.3.1", "express": "^4.18.2", "jsonwebtoken": "^9.0.0", - "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.68", + "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.69", "module-alias": "^2.2.2", "multer": "^1.4.5-lts.1", "next": "^13.1.5", From 12ce8ddff4f66e47646d97a034a0fb783c5518f9 Mon Sep 17 00:00:00 2001 From: OxSaitama Date: Thu, 17 Aug 2023 13:44:50 +0200 Subject: [PATCH 46/49] fix where query for documents --- src/app/api/customer/DocumentsController.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/app/api/customer/DocumentsController.ts b/src/app/api/customer/DocumentsController.ts index fdfb16f2..a7f2b1a7 100644 --- a/src/app/api/customer/DocumentsController.ts +++ b/src/app/api/customer/DocumentsController.ts @@ -28,12 +28,9 @@ export default class DocumentsController extends ApiController { query = JSON.parse(req.query["q"] as string); } - - //This was useless and was causing a bug - - // const customerId: string = req.body.user.customerId; - // const customerWhereInput: Prisma.DocumentsWhereInput ={ depositor: { uid: customerId } }; - // query.where = customerWhereInput; + const customerId: string = req.body.user.customerId; + const customerWhereInput: Prisma.DocumentsWhereInput ={ depositor: { uid: customerId } }; + query.where = customerWhereInput; //call service to get prisma entity From c722edc01303eed129038ddd20fd9f6ca197ea28 Mon Sep 17 00:00:00 2001 From: OxSaitama Date: Wed, 6 Sep 2023 17:12:00 +0200 Subject: [PATCH 47/49] refacto rules & folders --- package.json | 2 +- src/app/api/notary/OfficeFoldersController.ts | 1 - src/app/middlewares/RulesHandler.ts | 5 +++++ src/services/common/FilesService/FilesService.ts | 1 - 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index fd95302f..45621fda 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "cron": "^2.3.1", "express": "^4.18.2", "jsonwebtoken": "^9.0.0", - "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.69", + "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.71", "module-alias": "^2.2.2", "multer": "^1.4.5-lts.1", "next": "^13.1.5", diff --git a/src/app/api/notary/OfficeFoldersController.ts b/src/app/api/notary/OfficeFoldersController.ts index af46d774..85b80173 100644 --- a/src/app/api/notary/OfficeFoldersController.ts +++ b/src/app/api/notary/OfficeFoldersController.ts @@ -175,7 +175,6 @@ export default class OfficeFoldersController extends ApiController { this.httpInternalError(response, error); return; } - this.httpSuccess(response, await this.officeFoldersService.getByUid("uid")); } /** diff --git a/src/app/middlewares/RulesHandler.ts b/src/app/middlewares/RulesHandler.ts index cd35dcfe..ff677652 100644 --- a/src/app/middlewares/RulesHandler.ts +++ b/src/app/middlewares/RulesHandler.ts @@ -6,6 +6,11 @@ export default async function ruleHandler(req: Request, response: Response, next const rules = req.body.user.rules; const service = req.path && req.path.split("/")[4]; + if (!rules) { + response.status(HttpCodes.UNAUTHORIZED).send("Unauthorized without rules"); + return; + } + if (!rules.includes(req.method + " " + service)) { response.status(HttpCodes.UNAUTHORIZED).send("Unauthorized with those rules"); return; diff --git a/src/services/common/FilesService/FilesService.ts b/src/services/common/FilesService/FilesService.ts index 2ec4e6b5..4023b5db 100644 --- a/src/services/common/FilesService/FilesService.ts +++ b/src/services/common/FilesService/FilesService.ts @@ -8,7 +8,6 @@ import { BackendVariables } from "@Common/config/variables/Variables"; import { Readable } from "stream"; import { v4 } from "uuid"; import { Files, Prisma } from "@prisma/client"; -import fetch from "node-fetch"; @Service() export default class FilesService extends BaseService { From 8afdac3228506dca366ca0b46164b696a441f0ab Mon Sep 17 00:00:00 2001 From: Vins Date: Wed, 6 Sep 2023 18:07:30 +0200 Subject: [PATCH 48/49] Done --- src/app/api/customer/DocumentsController.ts | 34 ++++++++++- src/app/api/customer/FilesController.ts | 56 ++++++++++++++++++- .../repositories/DocumentsRepository.ts | 2 +- .../DocumentsService/DocumentsService.ts | 18 +++++- 4 files changed, 105 insertions(+), 5 deletions(-) diff --git a/src/app/api/customer/DocumentsController.ts b/src/app/api/customer/DocumentsController.ts index fdfb16f2..5593e310 100644 --- a/src/app/api/customer/DocumentsController.ts +++ b/src/app/api/customer/DocumentsController.ts @@ -1,5 +1,5 @@ import { Response, Request } from "express"; -import { Controller, Get } from "@ControllerPattern/index"; +import { Controller, Get, Post } from "@ControllerPattern/index"; import ApiController from "@Common/system/controller-pattern/ApiController"; import { Service } from "typedi"; import DocumentsService from "@Services/customer/DocumentsService/DocumentsService"; @@ -7,6 +7,7 @@ import { Documents, Prisma } from "@prisma/client"; import { Document } from "le-coffre-resources/dist/Customer"; import authHandler from "@App/middlewares/AuthHandler"; import documentHandler from "@App/middlewares/CustomerHandler/DocumentHandler"; +import { validateOrReject } from "class-validator"; @Controller() @Service() @@ -85,4 +86,35 @@ export default class DocumentsController extends ApiController { return; } } + + /** + * @description Create a new File + * @returns File created + */ + @Post("/api/v1/customer/documents", [authHandler]) + protected async post(req: Request, response: Response) { + try { + //init Document resource with request body values + const documentEntity = Document.hydrate(req.body); + console.log(documentEntity); + + + //validate document + await validateOrReject(documentEntity, { groups: ["createDocument"], forbidUnknownValues: false }); + + //call service to get prisma entity + const documentEntityCreated = await this.documentsService.create(documentEntity); + + //Hydrate ressource with prisma entity + const document = Document.hydrate(documentEntityCreated, { + strategy: "excludeAll", + }); + + //success + this.httpCreated(response, document); + } catch (error) { + this.httpInternalError(response, error); + return; + } + } } diff --git a/src/app/api/customer/FilesController.ts b/src/app/api/customer/FilesController.ts index 76dd93ee..d3eb0338 100644 --- a/src/app/api/customer/FilesController.ts +++ b/src/app/api/customer/FilesController.ts @@ -10,11 +10,14 @@ import { validateOrReject } from "class-validator"; import DocumentsService from "@Services/customer/DocumentsService/DocumentsService"; import authHandler from "@App/middlewares/AuthHandler"; import fileHandler from "@App/middlewares/CustomerHandler/FileHandler"; +import DocumentTypesService from "@Services/super-admin/DocumentTypesService/DocumentTypesService"; +import { DocumentType } from "le-coffre-resources/dist/SuperAdmin"; +import ObjectHydrate from "@Common/helpers/ObjectHydrate"; @Controller() @Service() export default class FilesController extends ApiController { - constructor(private filesService: FilesService, private documentService: DocumentsService) { + constructor(private filesService: FilesService, private documentService: DocumentsService, private documentTypesService : DocumentTypesService) { super(); } @@ -87,9 +90,10 @@ export default class FilesController extends ApiController { //init File resource with request body values const fileEntity = File.hydrate(JSON.parse(req.body["q"])); + console.log(fileEntity); //validate File - await validateOrReject(fileEntity, { groups: ["createFile"] }); + // await validateOrReject(fileEntity, { groups: ["createFile"] }); //call service to get prisma entity const fileEntityCreated = await this.filesService.create(fileEntity, req.file); @@ -224,4 +228,52 @@ export default class FilesController extends ApiController { return; } } + + /** + * @description Create a new File + * @returns File created + */ + @Post("/api/v1/customer/addPersonalFile", [authHandler, fileHandler]) + protected async addPersonalFile(req: Request, response: Response) { + try { + //get file + if (!req.file) throw new Error("No file provided"); + + //init File resource with request body values + const fileEntity = File.hydrate(JSON.parse(req.body["q"])); + + const documentTypeEntities = await this.documentTypesService.get({ where: { name: "Other"} }); + const documentTypeEntity = documentTypeEntities[0]; + const documentType = ObjectHydrate.hydrate(new DocumentType(), documentTypeEntity!, { strategy: "excludeAll" }); + + const documentEntity = Document.hydrate({document_type: documentType}); + await validateOrReject(documentEntity, { groups: ["createDocument"], forbidUnknownValues: false }); + const documentEntityCreated = await this.documentService.create(documentEntity); + + const document = Document.hydrate(documentEntityCreated, { + strategy: "excludeAll", + }); + + fileEntity.document = document; + + const fileEntityCreated = await this.filesService.create(fileEntity, req.file); + + const documentToUpdate = Document.hydrate(document!); + + documentToUpdate!.document_status = "DEPOSITED"; + await this.documentService.update(document!.uid!, documentToUpdate); + + //Hydrate ressource with prisma entity + const fileEntityHydrated = File.hydrate(fileEntityCreated, { + strategy: "excludeAll", + }); + + //success + this.httpCreated(response, fileEntityHydrated); + + } catch (error) { + this.httpBadRequest(response, error); + return; + } + } } diff --git a/src/common/repositories/DocumentsRepository.ts b/src/common/repositories/DocumentsRepository.ts index c5110e6d..6a86cdd8 100644 --- a/src/common/repositories/DocumentsRepository.ts +++ b/src/common/repositories/DocumentsRepository.ts @@ -28,7 +28,7 @@ export default class DocumentsRepository extends BaseRepository { /** * @description : Create a document */ - public async create(document: Document): Promise { + public async create(document: DocumentCustomer): Promise { const createArgs: Prisma.DocumentsCreateArgs = { data: { folder: { diff --git a/src/services/customer/DocumentsService/DocumentsService.ts b/src/services/customer/DocumentsService/DocumentsService.ts index 26c45c6a..fb6d925c 100644 --- a/src/services/customer/DocumentsService/DocumentsService.ts +++ b/src/services/customer/DocumentsService/DocumentsService.ts @@ -3,10 +3,11 @@ import { Document } from "le-coffre-resources/dist/Customer"; import DocumentsRepository from "@Repositories/DocumentsRepository"; import BaseService from "@Services/BaseService"; import { Service } from "typedi"; +import DocumentTypesService from "@Services/notary/DocumentTypesService/DocumentTypesService"; @Service() export default class DocumentsService extends BaseService { - constructor(private documentsRepository: DocumentsRepository) { + constructor(private documentsRepository: DocumentsRepository, private documentTypeService: DocumentTypesService) { super(); } @@ -18,6 +19,21 @@ export default class DocumentsService extends BaseService { return this.documentsRepository.findMany(query); } + /** + * @description : Create a new document + * @throws {Error} If document cannot be created + */ + public async create(document: Document): Promise { + const otherDocumentType = await this.documentTypeService.get({ where: { name: "Other" } }); + + if(otherDocumentType.length < 1) throw new Error("Other document type not found"); + + document.document_type = otherDocumentType[0]; + document.document_status = "DEPOSITED"; + + return this.documentsRepository.create(document); + } + /** * @description : Modify a document * @throws {Error} If document cannot be modified From 19b6642c583dc1228c42f1b1b5b80f001033ef18 Mon Sep 17 00:00:00 2001 From: Vins Date: Thu, 7 Sep 2023 11:19:02 +0200 Subject: [PATCH 49/49] Hotfix --- package-lock.json | 1059 ++++++++++-------- src/common/databases/seeders/seeder.ts | 4 +- src/common/repositories/OfficesRepository.ts | 2 +- src/common/repositories/UsersRepository.ts | 2 +- src/test/config/Init.ts | 4 +- 5 files changed, 581 insertions(+), 490 deletions(-) diff --git a/package-lock.json b/package-lock.json index d147eb2c..41374105 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,7 @@ "cron": "^2.3.1", "express": "^4.18.2", "jsonwebtoken": "^9.0.0", - "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.68", + "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.71", "module-alias": "^2.2.2", "multer": "^1.4.5-lts.1", "next": "^13.1.5", @@ -70,12 +70,12 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.10.tgz", - "integrity": "sha512-/KKIMG4UEL35WmI9OlvMhurwtytjvXoFcGNrOvyG9zIzA8YmPjVtIZUf7b05+TPO7G7/GEmLHDaoCgACHl9hhA==", + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", "dev": true, "dependencies": { - "@babel/highlight": "^7.22.10", + "@babel/highlight": "^7.22.13", "chalk": "^2.4.2" }, "engines": { @@ -163,25 +163,25 @@ } }, "node_modules/@babel/core": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.10.tgz", - "integrity": "sha512-fTmqbbUBAwCcre6zPzNngvsI0aNrPZe77AeqvDxWM9Nm+04RrJ3CAmGHA9f7lJQY6ZMhRztNemy4uslDxTX4Qw==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.15.tgz", + "integrity": "sha512-PtZqMmgRrvj8ruoEOIwVA3yoF91O+Hgw9o7DAUTNBA6Mo2jpu31clx9a7Nz/9JznqetTR6zwfC4L3LAjKQXUwA==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.22.10", - "@babel/generator": "^7.22.10", - "@babel/helper-compilation-targets": "^7.22.10", - "@babel/helper-module-transforms": "^7.22.9", - "@babel/helpers": "^7.22.10", - "@babel/parser": "^7.22.10", - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.10", - "@babel/types": "^7.22.10", + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.22.15", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-module-transforms": "^7.22.15", + "@babel/helpers": "^7.22.15", + "@babel/parser": "^7.22.15", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.22.15", + "@babel/types": "^7.22.15", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2", + "json5": "^2.2.3", "semver": "^6.3.1" }, "engines": { @@ -222,12 +222,12 @@ "dev": true }, "node_modules/@babel/generator": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.10.tgz", - "integrity": "sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.15.tgz", + "integrity": "sha512-Zu9oWARBqeVOW0dZOjXc3JObrzuqothQ3y/n1kUtrjCoCPLkXUwMvOo/F/TCfoHMbWIFlWwpZtkZVb9ga4U2pA==", "dev": true, "dependencies": { - "@babel/types": "^7.22.10", + "@babel/types": "^7.22.15", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -237,13 +237,13 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.10.tgz", - "integrity": "sha512-JMSwHD4J7SLod0idLq5PKgI+6g/hLD/iuWBq08ZX49xE14VpVEojJ5rHWptpirV2j020MvypRLAXAO50igCJ5Q==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", + "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", "dev": true, "dependencies": { "@babel/compat-data": "^7.22.9", - "@babel/helper-validator-option": "^7.22.5", + "@babel/helper-validator-option": "^7.22.15", "browserslist": "^4.21.9", "lru-cache": "^5.1.1", "semver": "^6.3.1" @@ -287,28 +287,28 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz", - "integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", "dev": true, "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.22.15" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.9.tgz", - "integrity": "sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.15.tgz", + "integrity": "sha512-l1UiX4UyHSFsYt17iQ3Se5pQQZZHa22zyIXURmvkmLCD4t/aU+dvNWHatKac/D9Vm9UES7nvIqHs4jZqKviUmQ==", "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-module-imports": "^7.22.15", "@babel/helper-simple-access": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.5" + "@babel/helper-validator-identifier": "^7.22.15" }, "engines": { "node": ">=6.9.0" @@ -360,41 +360,41 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", - "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz", + "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz", - "integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", + "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.10.tgz", - "integrity": "sha512-a41J4NW8HyZa1I1vAndrraTlPZ/eZoga2ZgS7fEr0tZJGVU4xqdE80CEm0CcNjha5EZ8fTBYLKHF0kqDUuAwQw==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.15.tgz", + "integrity": "sha512-7pAjK0aSdxOwR+CcYAqgWOGy5dcfvzsTIfFTb2odQqW47MDfv14UaJDY6eng8ylM2EaeKXdxaSWESbkmaQHTmw==", "dev": true, "dependencies": { - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.10", - "@babel/types": "^7.22.10" + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.22.15", + "@babel/types": "^7.22.15" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.10.tgz", - "integrity": "sha512-78aUtVcT7MUscr0K5mIEnkwxPE0MaxkR5RxRwuHaQ+JuU5AmTPhY+do2mdzVTnIJJpyBglql2pehuBIWHug+WQ==", + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.13.tgz", + "integrity": "sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==", "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.22.5", @@ -477,9 +477,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.10.tgz", - "integrity": "sha512-lNbdGsQb9ekfsnjFGhEiF4hfFqGgfOP3H3d27re3n+CGhNuTSUEQdfWk556sTLNTloczcdM5TYF2LhzmDQKyvQ==", + "version": "7.22.16", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.16.tgz", + "integrity": "sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -666,33 +666,33 @@ } }, "node_modules/@babel/template": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", - "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/parser": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.10.tgz", - "integrity": "sha512-Q/urqV4pRByiNNpb/f5OSv28ZlGJiFiiTh+GAHktbIrkPhPbl90+uW6SmpoLyZqutrg9AEaEf3Q/ZBRHBXgxig==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.15.tgz", + "integrity": "sha512-DdHPwvJY0sEeN4xJU5uRLmZjgMMDIvMPniLuYzUVXj/GGzysPl0/fwt44JBkyUIzGJPV8QgHMcQdQ34XFuKTYQ==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.22.10", - "@babel/generator": "^7.22.10", + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.22.15", "@babel/helper-environment-visitor": "^7.22.5", "@babel/helper-function-name": "^7.22.5", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.22.10", - "@babel/types": "^7.22.10", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -724,13 +724,13 @@ "dev": true }, "node_modules/@babel/types": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.10.tgz", - "integrity": "sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.15.tgz", + "integrity": "sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA==", "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.15", "to-fast-properties": "^2.0.0" }, "engines": { @@ -789,16 +789,16 @@ } }, "node_modules/@jest/console": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.6.2.tgz", - "integrity": "sha512-0N0yZof5hi44HAR2pPS+ikJ3nzKNoZdVu8FffRf3wy47I7Dm7etk/3KetMdRUqzVd16V4O2m2ISpNTbnIuqy1w==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.6.4.tgz", + "integrity": "sha512-wNK6gC0Ha9QeEPSkeJedQuTQqxZYnDPuDcDhVuVatRvMkL4D0VTvFVZj+Yuh6caG2aOfzkUZ36KtCmLNtR02hw==", "dev": true, "dependencies": { - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^29.6.2", - "jest-util": "^29.6.2", + "jest-message-util": "^29.6.3", + "jest-util": "^29.6.3", "slash": "^3.0.0" }, "engines": { @@ -806,37 +806,37 @@ } }, "node_modules/@jest/core": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.6.2.tgz", - "integrity": "sha512-Oj+5B+sDMiMWLhPFF+4/DvHOf+U10rgvCLGPHP8Xlsy/7QxS51aU/eBngudHlJXnaWD5EohAgJ4js+T6pa+zOg==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.6.4.tgz", + "integrity": "sha512-U/vq5ccNTSVgYH7mHnodHmCffGWHJnz/E1BEWlLuK5pM4FZmGfBn/nrJGLjUsSmyx3otCeqc1T31F4y08AMDLg==", "dev": true, "dependencies": { - "@jest/console": "^29.6.2", - "@jest/reporters": "^29.6.2", - "@jest/test-result": "^29.6.2", - "@jest/transform": "^29.6.2", - "@jest/types": "^29.6.1", + "@jest/console": "^29.6.4", + "@jest/reporters": "^29.6.4", + "@jest/test-result": "^29.6.4", + "@jest/transform": "^29.6.4", + "@jest/types": "^29.6.3", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.5.0", - "jest-config": "^29.6.2", - "jest-haste-map": "^29.6.2", - "jest-message-util": "^29.6.2", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.6.2", - "jest-resolve-dependencies": "^29.6.2", - "jest-runner": "^29.6.2", - "jest-runtime": "^29.6.2", - "jest-snapshot": "^29.6.2", - "jest-util": "^29.6.2", - "jest-validate": "^29.6.2", - "jest-watcher": "^29.6.2", + "jest-changed-files": "^29.6.3", + "jest-config": "^29.6.4", + "jest-haste-map": "^29.6.4", + "jest-message-util": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.6.4", + "jest-resolve-dependencies": "^29.6.4", + "jest-runner": "^29.6.4", + "jest-runtime": "^29.6.4", + "jest-snapshot": "^29.6.4", + "jest-util": "^29.6.3", + "jest-validate": "^29.6.3", + "jest-watcher": "^29.6.4", "micromatch": "^4.0.4", - "pretty-format": "^29.6.2", + "pretty-format": "^29.6.3", "slash": "^3.0.0", "strip-ansi": "^6.0.0" }, @@ -853,88 +853,88 @@ } }, "node_modules/@jest/environment": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.6.2.tgz", - "integrity": "sha512-AEcW43C7huGd/vogTddNNTDRpO6vQ2zaQNrttvWV18ArBx9Z56h7BIsXkNFJVOO4/kblWEQz30ckw0+L3izc+Q==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.6.4.tgz", + "integrity": "sha512-sQ0SULEjA1XUTHmkBRl7A1dyITM9yb1yb3ZNKPX3KlTd6IG7mWUe3e2yfExtC2Zz1Q+mMckOLHmL/qLiuQJrBQ==", "dev": true, "dependencies": { - "@jest/fake-timers": "^29.6.2", - "@jest/types": "^29.6.1", + "@jest/fake-timers": "^29.6.4", + "@jest/types": "^29.6.3", "@types/node": "*", - "jest-mock": "^29.6.2" + "jest-mock": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.6.2.tgz", - "integrity": "sha512-m6DrEJxVKjkELTVAztTLyS/7C92Y2b0VYqmDROYKLLALHn8T/04yPs70NADUYPrV3ruI+H3J0iUIuhkjp7vkfg==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.6.4.tgz", + "integrity": "sha512-Warhsa7d23+3X5bLbrbYvaehcgX5TLYhI03JKoedTiI8uJU4IhqYBWF7OSSgUyz4IgLpUYPkK0AehA5/fRclAA==", "dev": true, "dependencies": { - "expect": "^29.6.2", - "jest-snapshot": "^29.6.2" + "expect": "^29.6.4", + "jest-snapshot": "^29.6.4" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect-utils": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.6.2.tgz", - "integrity": "sha512-6zIhM8go3RV2IG4aIZaZbxwpOzz3ZiM23oxAlkquOIole+G6TrbeXnykxWYlqF7kz2HlBjdKtca20x9atkEQYg==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.6.4.tgz", + "integrity": "sha512-FEhkJhqtvBwgSpiTrocquJCdXPsyvNKcl/n7A3u7X4pVoF4bswm11c9d4AV+kfq2Gpv/mM8x7E7DsRvH+djkrg==", "dev": true, "dependencies": { - "jest-get-type": "^29.4.3" + "jest-get-type": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/fake-timers": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.6.2.tgz", - "integrity": "sha512-euZDmIlWjm1Z0lJ1D0f7a0/y5Kh/koLFMUBE5SUYWrmy8oNhJpbTBDAP6CxKnadcMLDoDf4waRYCe35cH6G6PA==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.6.4.tgz", + "integrity": "sha512-6UkCwzoBK60edXIIWb0/KWkuj7R7Qq91vVInOe3De6DSpaEiqjKcJw4F7XUet24Wupahj9J6PlR09JqJ5ySDHw==", "dev": true, "dependencies": { - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "@sinonjs/fake-timers": "^10.0.2", "@types/node": "*", - "jest-message-util": "^29.6.2", - "jest-mock": "^29.6.2", - "jest-util": "^29.6.2" + "jest-message-util": "^29.6.3", + "jest-mock": "^29.6.3", + "jest-util": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/globals": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.6.2.tgz", - "integrity": "sha512-cjuJmNDjs6aMijCmSa1g2TNG4Lby/AeU7/02VtpW+SLcZXzOLK2GpN2nLqcFjmhy3B3AoPeQVx7BnyOf681bAw==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.6.4.tgz", + "integrity": "sha512-wVIn5bdtjlChhXAzVXavcY/3PEjf4VqM174BM3eGL5kMxLiZD5CLnbmkEyA1Dwh9q8XjP6E8RwjBsY/iCWrWsA==", "dev": true, "dependencies": { - "@jest/environment": "^29.6.2", - "@jest/expect": "^29.6.2", - "@jest/types": "^29.6.1", - "jest-mock": "^29.6.2" + "@jest/environment": "^29.6.4", + "@jest/expect": "^29.6.4", + "@jest/types": "^29.6.3", + "jest-mock": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/reporters": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.6.2.tgz", - "integrity": "sha512-sWtijrvIav8LgfJZlrGCdN0nP2EWbakglJY49J1Y5QihcQLfy7ovyxxjJBRXMNltgt4uPtEcFmIMbVshEDfFWw==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.6.4.tgz", + "integrity": "sha512-sxUjWxm7QdchdrD3NfWKrL8FBsortZeibSJv4XLjESOOjSUOkjQcb0ZHJwfhEGIvBvTluTzfG2yZWZhkrXJu8g==", "dev": true, "dependencies": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.6.2", - "@jest/test-result": "^29.6.2", - "@jest/transform": "^29.6.2", - "@jest/types": "^29.6.1", + "@jest/console": "^29.6.4", + "@jest/test-result": "^29.6.4", + "@jest/transform": "^29.6.4", + "@jest/types": "^29.6.3", "@jridgewell/trace-mapping": "^0.3.18", "@types/node": "*", "chalk": "^4.0.0", @@ -943,13 +943,13 @@ "glob": "^7.1.3", "graceful-fs": "^4.2.9", "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-instrument": "^6.0.0", "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.6.2", - "jest-util": "^29.6.2", - "jest-worker": "^29.6.2", + "jest-message-util": "^29.6.3", + "jest-util": "^29.6.3", + "jest-worker": "^29.6.4", "slash": "^3.0.0", "string-length": "^4.0.1", "strip-ansi": "^6.0.0", @@ -968,9 +968,9 @@ } }, "node_modules/@jest/schemas": { - "version": "29.6.0", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.0.tgz", - "integrity": "sha512-rxLjXyJBTL4LQeJW3aKo0M/+GkCOXsO+8i9Iu7eDb6KwtP65ayoDsitrdPBtujxQ88k4wI2FNYfa6TOGwSn6cQ==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, "dependencies": { "@sinclair/typebox": "^0.27.8" @@ -980,9 +980,9 @@ } }, "node_modules/@jest/source-map": { - "version": "29.6.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.0.tgz", - "integrity": "sha512-oA+I2SHHQGxDCZpbrsCQSoMLb3Bz547JnM+jUr9qEbuw0vQlWZfpPS7CO9J7XiwKicEz9OFn/IYoLkkiUD7bzA==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.18", @@ -994,13 +994,13 @@ } }, "node_modules/@jest/test-result": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.6.2.tgz", - "integrity": "sha512-3VKFXzcV42EYhMCsJQURptSqnyjqCGbtLuX5Xxb6Pm6gUf1wIRIl+mandIRGJyWKgNKYF9cnstti6Ls5ekduqw==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.6.4.tgz", + "integrity": "sha512-uQ1C0AUEN90/dsyEirgMLlouROgSY+Wc/JanVVk0OiUKa5UFh7sJpMEM3aoUBAz2BRNvUJ8j3d294WFuRxSyOQ==", "dev": true, "dependencies": { - "@jest/console": "^29.6.2", - "@jest/types": "^29.6.1", + "@jest/console": "^29.6.4", + "@jest/types": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" }, @@ -1009,14 +1009,14 @@ } }, "node_modules/@jest/test-sequencer": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.6.2.tgz", - "integrity": "sha512-GVYi6PfPwVejO7slw6IDO0qKVum5jtrJ3KoLGbgBWyr2qr4GaxFV6su+ZAjdTX75Sr1DkMFRk09r2ZVa+wtCGw==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.6.4.tgz", + "integrity": "sha512-E84M6LbpcRq3fT4ckfKs9ryVanwkaIB0Ws9bw3/yP4seRLg/VaCZ/LgW0MCq5wwk4/iP/qnilD41aj2fsw2RMg==", "dev": true, "dependencies": { - "@jest/test-result": "^29.6.2", + "@jest/test-result": "^29.6.4", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.2", + "jest-haste-map": "^29.6.4", "slash": "^3.0.0" }, "engines": { @@ -1024,22 +1024,22 @@ } }, "node_modules/@jest/transform": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.6.2.tgz", - "integrity": "sha512-ZqCqEISr58Ce3U+buNFJYUktLJZOggfyvR+bZMaiV1e8B1SIvJbwZMrYz3gx/KAPn9EXmOmN+uB08yLCjWkQQg==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.6.4.tgz", + "integrity": "sha512-8thgRSiXUqtr/pPGY/OsyHuMjGyhVnWrFAwoxmIemlBuiMyU1WFs0tXoNxzcr4A4uErs/ABre76SGmrr5ab/AA==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "@jridgewell/trace-mapping": "^0.3.18", "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", "convert-source-map": "^2.0.0", "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.2", - "jest-regex-util": "^29.4.3", - "jest-util": "^29.6.2", + "jest-haste-map": "^29.6.4", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.6.3", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", @@ -1050,12 +1050,12 @@ } }, "node_modules/@jest/types": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.1.tgz", - "integrity": "sha512-tPKQNMPuXgvdOn2/Lg9HNfUvjYVGolt04Hp03f5hAk878uwOLikN+JzeLY0HcVgKgFl9Hs3EIqpu3WX27XNhnw==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", "dev": true, "dependencies": { - "@jest/schemas": "^29.6.0", + "@jest/schemas": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -1124,14 +1124,14 @@ } }, "node_modules/@next/env": { - "version": "13.4.16", - "resolved": "https://registry.npmjs.org/@next/env/-/env-13.4.16.tgz", - "integrity": "sha512-pCU0sJBqdfKP9mwDadxvZd+eLz3fZrTlmmDHY12Hdpl3DD0vy8ou5HWKVfG0zZS6tqhL4wnQqRbspdY5nqa7MA==" + "version": "13.4.19", + "resolved": "https://registry.npmjs.org/@next/env/-/env-13.4.19.tgz", + "integrity": "sha512-FsAT5x0jF2kkhNkKkukhsyYOrRqtSxrEhfliniIq0bwWbuXLgyt3Gv0Ml+b91XwjwArmuP7NxCiGd++GGKdNMQ==" }, "node_modules/@next/swc-darwin-arm64": { - "version": "13.4.16", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.16.tgz", - "integrity": "sha512-Rl6i1uUq0ciRa3VfEpw6GnWAJTSKo9oM2OrkGXPsm7rMxdd2FR5NkKc0C9xzFCI4+QtmBviWBdF2m3ur3Nqstw==", + "version": "13.4.19", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.19.tgz", + "integrity": "sha512-vv1qrjXeGbuF2mOkhkdxMDtv9np7W4mcBtaDnHU+yJG+bBwa6rYsYSCI/9Xm5+TuF5SbZbrWO6G1NfTh1TMjvQ==", "cpu": [ "arm64" ], @@ -1144,9 +1144,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "13.4.16", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.16.tgz", - "integrity": "sha512-o1vIKYbZORyDmTrPV1hApt9NLyWrS5vr2p5hhLGpOnkBY1cz6DAXjv8Lgan8t6X87+83F0EUDlu7klN8ieZ06A==", + "version": "13.4.19", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.19.tgz", + "integrity": "sha512-jyzO6wwYhx6F+7gD8ddZfuqO4TtpJdw3wyOduR4fxTUCm3aLw7YmHGYNjS0xRSYGAkLpBkH1E0RcelyId6lNsw==", "cpu": [ "x64" ], @@ -1159,9 +1159,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "13.4.16", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.16.tgz", - "integrity": "sha512-JRyAl8lCfyTng4zoOmE6hNI2f1MFUr7JyTYCHl1RxX42H4a5LMwJhDVQ7a9tmDZ/yj+0hpBn+Aan+d6lA3v0UQ==", + "version": "13.4.19", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.19.tgz", + "integrity": "sha512-vdlnIlaAEh6H+G6HrKZB9c2zJKnpPVKnA6LBwjwT2BTjxI7e0Hx30+FoWCgi50e+YO49p6oPOtesP9mXDRiiUg==", "cpu": [ "arm64" ], @@ -1174,9 +1174,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "13.4.16", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.16.tgz", - "integrity": "sha512-9gqVqNzUMWbUDgDiND18xoUqhwSm2gmksqXgCU0qaOKt6oAjWz8cWYjgpPVD0WICKFylEY/gvPEP1fMZDVFZ/g==", + "version": "13.4.19", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.19.tgz", + "integrity": "sha512-aU0HkH2XPgxqrbNRBFb3si9Ahu/CpaR5RPmN2s9GiM9qJCiBBlZtRTiEca+DC+xRPyCThTtWYgxjWHgU7ZkyvA==", "cpu": [ "arm64" ], @@ -1189,9 +1189,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "13.4.16", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.16.tgz", - "integrity": "sha512-KcQGwchAKmZVPa8i5PLTxvTs1/rcFnSltfpTm803Tr/BtBV3AxCkHLfhtoyVtVzx/kl/oue8oS+DSmbepQKwhw==", + "version": "13.4.19", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.19.tgz", + "integrity": "sha512-htwOEagMa/CXNykFFeAHHvMJeqZfNQEoQvHfsA4wgg5QqGNqD5soeCer4oGlCol6NGUxknrQO6VEustcv+Md+g==", "cpu": [ "x64" ], @@ -1204,9 +1204,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "13.4.16", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.16.tgz", - "integrity": "sha512-2RbMZNxYnJmW8EPHVBsGZPq5zqWAyBOc/YFxq/jIQ/Yn3RMFZ1dZVCjtIcsiaKmgh7mjA/W0ApbumutHNxRqqQ==", + "version": "13.4.19", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.19.tgz", + "integrity": "sha512-4Gj4vvtbK1JH8ApWTT214b3GwUh9EKKQjY41hH/t+u55Knxi/0wesMzwQRhppK6Ddalhu0TEttbiJ+wRcoEj5Q==", "cpu": [ "x64" ], @@ -1219,9 +1219,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "13.4.16", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.16.tgz", - "integrity": "sha512-thDcGonELN7edUKzjzlHrdoKkm7y8IAdItQpRvvMxNUXa4d9r0ElofhTZj5emR7AiXft17hpen+QAkcWpqG7Jg==", + "version": "13.4.19", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.19.tgz", + "integrity": "sha512-bUfDevQK4NsIAHXs3/JNgnvEY+LRyneDN788W2NYiRIIzmILjba7LaQTfihuFawZDhRtkYCv3JDC3B4TwnmRJw==", "cpu": [ "arm64" ], @@ -1234,9 +1234,9 @@ } }, "node_modules/@next/swc-win32-ia32-msvc": { - "version": "13.4.16", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.16.tgz", - "integrity": "sha512-f7SE1Mo4JAchUWl0LQsbtySR9xCa+x55C0taetjUApKtcLR3AgAjASrrP+oE1inmLmw573qRnE1eZN8YJfEBQw==", + "version": "13.4.19", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.19.tgz", + "integrity": "sha512-Y5kikILFAr81LYIFaw6j/NrOtmiM4Sf3GtOc0pn50ez2GCkr+oejYuKGcwAwq3jiTKuzF6OF4iT2INPoxRycEA==", "cpu": [ "ia32" ], @@ -1249,9 +1249,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "13.4.16", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.16.tgz", - "integrity": "sha512-WamDZm1M/OEM4QLce3lOmD1XdLEl37zYZwlmOLhmF7qYJ2G6oYm9+ejZVv+LakQIsIuXhSpVlOvrxIAHqwRkPQ==", + "version": "13.4.19", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.19.tgz", + "integrity": "sha512-YzA78jBDXMYiINdPdJJwGgPNT3YqBNNGhsthsDoWHL9p24tEJn9ViQf/ZqTbwSpX/RrkPupLfuuTH2sf73JBAw==", "cpu": [ "x64" ], @@ -1410,18 +1410,18 @@ } }, "node_modules/@types/connect": { - "version": "3.4.35", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", - "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "version": "3.4.36", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.36.tgz", + "integrity": "sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/cors": { - "version": "2.8.13", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz", - "integrity": "sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==", + "version": "2.8.14", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.14.tgz", + "integrity": "sha512-RXHUvNWYICtbP6s18PnOCaqToK8y14DnLd75c6HfyKf228dxy7pHNOQkxPtvXKp/hINFMDjbYzsj63nnpPMSRQ==", "dev": true, "dependencies": { "@types/node": "*" @@ -1450,9 +1450,9 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "4.17.35", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz", - "integrity": "sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==", + "version": "4.17.36", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.36.tgz", + "integrity": "sha512-zbivROJ0ZqLAtMzgzIUC4oNqDG9iF0lSsAqpOD9kbs5xcIM3dTiyuHvBc7R8MtWBp3AAWGaovJa+wzWPjLYW7Q==", "dev": true, "dependencies": { "@types/node": "*", @@ -1501,9 +1501,9 @@ } }, "node_modules/@types/jest": { - "version": "29.5.3", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.3.tgz", - "integrity": "sha512-1Nq7YrO/vJE/FYnqYyw0FS8LdrjExSgIiHyKg7xPpn+yi8Q4huZryKnkJatN1ZRH89Kw2v33/8ZMB7DuZeSLlA==", + "version": "29.5.4", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.4.tgz", + "integrity": "sha512-PhglGmhWeD46FYOVLt3X7TiWjzwuVGW9wG/4qocPevXMjCmrIc5b6db9WjeGE4QYVpUAWMDv3v0IiBwObY289A==", "dev": true, "dependencies": { "expect": "^29.0.0", @@ -1519,6 +1519,11 @@ "@types/node": "*" } }, + "node_modules/@types/luxon": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.3.2.tgz", + "integrity": "sha512-l5cpE57br4BIjK+9BSkFBOsWtwv6J9bJpC7gdXIzZyI0vuKvNTk0wZZrkQxMGsUAuGW9+WMNWF2IJMD7br2yeQ==" + }, "node_modules/@types/mailchimp__mailchimp_transactional": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/mailchimp__mailchimp_transactional/-/mailchimp__mailchimp_transactional-1.0.5.tgz", @@ -1550,9 +1555,9 @@ } }, "node_modules/@types/node": { - "version": "18.17.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.5.tgz", - "integrity": "sha512-xNbS75FxH6P4UXTPUJp/zNPq6/xsfdJKussCWNOnz4aULWIRwMgP1LgaB5RiBnMX1DPCYenuqGZfnIAx5mbFLA==" + "version": "18.17.14", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.14.tgz", + "integrity": "sha512-ZE/5aB73CyGqgQULkLG87N9GnyGe5TcQjv34pwS8tfBs1IkCh0ASM69mydb2znqd6v0eX+9Ytvk6oQRqu8T1Vw==" }, "node_modules/@types/node-fetch": { "version": "2.6.4", @@ -1588,9 +1593,9 @@ } }, "node_modules/@types/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", + "version": "6.9.8", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.8.tgz", + "integrity": "sha512-u95svzDlTysU5xecFNTgfFG5RUWu1A9P0VzgpcIiGZA9iraHOdSzcxMxQ55DyeRaGCSxQi7LxXDI4rzq/MYfdg==", "dev": true }, "node_modules/@types/range-parser": { @@ -1627,9 +1632,9 @@ "dev": true }, "node_modules/@types/uuid": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.2.tgz", - "integrity": "sha512-kNnC1GFBLuhImSnV7w4njQkUiJi0ZXUycu1rUaouPqiKlXkh77JKgdRnTAp1x5eBwcIwbtI+3otwzuIDEuDoxQ==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.3.tgz", + "integrity": "sha512-taHQQH/3ZyI3zP8M/puluDEIEvtQHVYcC6y3N8ijFtAd28+Ey/G4sg1u2gB01S8MwybLOKAp9/yCMu/uR5l3Ug==", "dev": true }, "node_modules/@types/validator": { @@ -1779,15 +1784,15 @@ } }, "node_modules/babel-jest": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.2.tgz", - "integrity": "sha512-BYCzImLos6J3BH/+HvUCHG1dTf2MzmAB4jaVxHV+29RZLjR29XuYTmsf2sdDwkrb+FczkGo3kOhE7ga6sI0P4A==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.4.tgz", + "integrity": "sha512-meLj23UlSLddj6PC+YTOFRgDAtjnZom8w/ACsrx0gtPtv5cJZk0A5Unk5bV4wixD7XaPCN1fQvpww8czkZURmw==", "dev": true, "dependencies": { - "@jest/transform": "^29.6.2", + "@jest/transform": "^29.6.4", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.5.0", + "babel-preset-jest": "^29.6.3", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "slash": "^3.0.0" @@ -1815,10 +1820,26 @@ "node": ">=8" } }, + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/babel-plugin-jest-hoist": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.5.0.tgz", - "integrity": "sha512-zSuuuAlTMT4mzLj2nPnUm6fsE6270vdOfnpbJ+RmruU75UhLFvL0N2NgI7xpeS7NaB6hGqmd5pVpGTDYvi4Q3w==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", "dev": true, "dependencies": { "@babel/template": "^7.3.3", @@ -1854,12 +1875,12 @@ } }, "node_modules/babel-preset-jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.5.0.tgz", - "integrity": "sha512-JOMloxOqdiBSxMAzjRaH023/vvcaSaec49zvg+2LmNsktC7ei39LTJGw02J+9uUtTZUq6xbLyJ4dxe9sSmIuAg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", "dev": true, "dependencies": { - "babel-plugin-jest-hoist": "^29.5.0", + "babel-plugin-jest-hoist": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0" }, "engines": { @@ -2100,9 +2121,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001521", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001521.tgz", - "integrity": "sha512-fnx1grfpEOvDGH+V17eccmNjucGUnCbP6KL+l5KqBIerp26WK/+RQ7CIDE37KGJjaPyqWXXlFUyKiWmvdNNKmQ==", + "version": "1.0.30001528", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001528.tgz", + "integrity": "sha512-0Db4yyjR9QMNlsxh+kKWzQtkyflkG/snYheSzkjmvdEtEXB1+jt7A2HmSEiO6XIJPIbo92lHNGNySvE5pZcs5Q==", "funding": [ { "type": "opencollective", @@ -2386,11 +2407,12 @@ "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" }, "node_modules/cron": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/cron/-/cron-2.4.1.tgz", - "integrity": "sha512-ty0hUSPuENwDtIShDFxUxWEIsqiu2vhoFtt6Vwrbg4lHGtJX2/cV2p0hH6/qaEM9Pj+i6mQoau48BO5wBpkP4w==", + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/cron/-/cron-2.4.3.tgz", + "integrity": "sha512-YBvExkQYF7w0PxyeFLRyr817YVDhGxaCi5/uRRMqa4aWD3IFKRd+uNbpW1VWMdqQy8PZ7CElc+accXJcauPKzQ==", "dependencies": { - "luxon": "^3.2.1" + "@types/luxon": "~3.3.0", + "luxon": "~3.3.0" } }, "node_modules/cron-parser": { @@ -2492,9 +2514,9 @@ } }, "node_modules/diff-sequences": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz", - "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -2526,9 +2548,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron-to-chromium": { - "version": "1.4.492", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.492.tgz", - "integrity": "sha512-36K9b/6skMVwAIEsC7GiQ8I8N3soCALVSHqWHzNDtGemAcI9Xu8hP02cywWM0A794rTHm0b0zHPeLJHtgFVamQ==", + "version": "1.4.510", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.510.tgz", + "integrity": "sha512-xPfLIPFcN/WLXBpQ/K4UgE98oUBO5Tia6BD4rkSR0wE7ep/PwBVlgvPJQrIBpmJGVAmUzwPKuDbVt9XV6+uC2g==", "dev": true }, "node_modules/emittery": { @@ -2643,17 +2665,16 @@ } }, "node_modules/expect": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.6.2.tgz", - "integrity": "sha512-iAErsLxJ8C+S02QbLAwgSGSezLQK+XXRDt8IuFXFpwCNw2ECmzZSmjKcCaFVp5VRMk+WAvz6h6jokzEzBFZEuA==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.6.4.tgz", + "integrity": "sha512-F2W2UyQ8XYyftHT57dtfg8Ue3X5qLgm2sSug0ivvLRH/VKNRL/pDxg/TH7zVzbQB0tu80clNFy6LU7OS/VSEKA==", "dev": true, "dependencies": { - "@jest/expect-utils": "^29.6.2", - "@types/node": "*", - "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.6.2", - "jest-message-util": "^29.6.2", - "jest-util": "^29.6.2" + "@jest/expect-utils": "^29.6.4", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.6.4", + "jest-message-util": "^29.6.3", + "jest-util": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -2812,9 +2833,9 @@ "dev": true }, "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "hasInstallScript": true, "optional": true, @@ -3236,21 +3257,54 @@ } }, "node_modules/istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.0.tgz", + "integrity": "sha512-x58orMzEVfzPUKqlbLd1hXCnySCxKdDKa6Rjg97CwuLLRI4g3FHTdnExu1OqffVFay6zeMW+T6/DowFLndWnIw==", "dev": true, "dependencies": { "@babel/core": "^7.12.3", "@babel/parser": "^7.14.7", "@istanbuljs/schema": "^0.1.2", "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" + "semver": "^7.5.4" }, "engines": { - "node": ">=8" + "node": ">=10" } }, + "node_modules/istanbul-lib-instrument/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/istanbul-lib-report": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", @@ -3316,15 +3370,15 @@ } }, "node_modules/jest": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.6.2.tgz", - "integrity": "sha512-8eQg2mqFbaP7CwfsTpCxQ+sHzw1WuNWL5UUvjnWP4hx2riGz9fPSzYOaU5q8/GqWn1TfgZIVTqYJygbGbWAANg==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.6.4.tgz", + "integrity": "sha512-tEFhVQFF/bzoYV1YuGyzLPZ6vlPrdfvDmmAxudA1dLEuiztqg2Rkx20vkKY32xiDROcD2KXlgZ7Cu8RPeEHRKw==", "dev": true, "dependencies": { - "@jest/core": "^29.6.2", - "@jest/types": "^29.6.1", + "@jest/core": "^29.6.4", + "@jest/types": "^29.6.3", "import-local": "^3.0.2", - "jest-cli": "^29.6.2" + "jest-cli": "^29.6.4" }, "bin": { "jest": "bin/jest.js" @@ -3342,12 +3396,13 @@ } }, "node_modules/jest-changed-files": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.5.0.tgz", - "integrity": "sha512-IFG34IUMUaNBIxjQXF/iu7g6EcdMrGRRxaUSw92I/2g2YC6vCdTltl4nHvt7Ci5nSJwXIkCu8Ka1DKF+X7Z1Ag==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.6.3.tgz", + "integrity": "sha512-G5wDnElqLa4/c66ma5PG9eRjE342lIbF6SUnTJi26C3J28Fv2TVY2rOyKB9YGbSA5ogwevgmxc4j4aVjrEK6Yg==", "dev": true, "dependencies": { "execa": "^5.0.0", + "jest-util": "^29.6.3", "p-limit": "^3.1.0" }, "engines": { @@ -3355,28 +3410,28 @@ } }, "node_modules/jest-circus": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.6.2.tgz", - "integrity": "sha512-G9mN+KOYIUe2sB9kpJkO9Bk18J4dTDArNFPwoZ7WKHKel55eKIS/u2bLthxgojwlf9NLCVQfgzM/WsOVvoC6Fw==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.6.4.tgz", + "integrity": "sha512-YXNrRyntVUgDfZbjXWBMPslX1mQ8MrSG0oM/Y06j9EYubODIyHWP8hMUbjbZ19M3M+zamqEur7O80HODwACoJw==", "dev": true, "dependencies": { - "@jest/environment": "^29.6.2", - "@jest/expect": "^29.6.2", - "@jest/test-result": "^29.6.2", - "@jest/types": "^29.6.1", + "@jest/environment": "^29.6.4", + "@jest/expect": "^29.6.4", + "@jest/test-result": "^29.6.4", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", "dedent": "^1.0.0", "is-generator-fn": "^2.0.0", - "jest-each": "^29.6.2", - "jest-matcher-utils": "^29.6.2", - "jest-message-util": "^29.6.2", - "jest-runtime": "^29.6.2", - "jest-snapshot": "^29.6.2", - "jest-util": "^29.6.2", + "jest-each": "^29.6.3", + "jest-matcher-utils": "^29.6.4", + "jest-message-util": "^29.6.3", + "jest-runtime": "^29.6.4", + "jest-snapshot": "^29.6.4", + "jest-util": "^29.6.3", "p-limit": "^3.1.0", - "pretty-format": "^29.6.2", + "pretty-format": "^29.6.3", "pure-rand": "^6.0.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" @@ -3386,21 +3441,21 @@ } }, "node_modules/jest-cli": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.6.2.tgz", - "integrity": "sha512-TT6O247v6dCEX2UGHGyflMpxhnrL0DNqP2fRTKYm3nJJpCTfXX3GCMQPGFjXDoj0i5/Blp3jriKXFgdfmbYB6Q==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.6.4.tgz", + "integrity": "sha512-+uMCQ7oizMmh8ZwRfZzKIEszFY9ksjjEQnTEMTaL7fYiL3Kw4XhqT9bYh+A4DQKUb67hZn2KbtEnDuHvcgK4pQ==", "dev": true, "dependencies": { - "@jest/core": "^29.6.2", - "@jest/test-result": "^29.6.2", - "@jest/types": "^29.6.1", + "@jest/core": "^29.6.4", + "@jest/test-result": "^29.6.4", + "@jest/types": "^29.6.3", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "import-local": "^3.0.2", - "jest-config": "^29.6.2", - "jest-util": "^29.6.2", - "jest-validate": "^29.6.2", + "jest-config": "^29.6.4", + "jest-util": "^29.6.3", + "jest-validate": "^29.6.3", "prompts": "^2.0.1", "yargs": "^17.3.1" }, @@ -3420,31 +3475,31 @@ } }, "node_modules/jest-config": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.6.2.tgz", - "integrity": "sha512-VxwFOC8gkiJbuodG9CPtMRjBUNZEHxwfQXmIudSTzFWxaci3Qub1ddTRbFNQlD/zUeaifLndh/eDccFX4wCMQw==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.6.4.tgz", + "integrity": "sha512-JWohr3i9m2cVpBumQFv2akMEnFEPVOh+9L2xIBJhJ0zOaci2ZXuKJj0tgMKQCBZAKA09H049IR4HVS/43Qb19A==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.6.2", - "@jest/types": "^29.6.1", - "babel-jest": "^29.6.2", + "@jest/test-sequencer": "^29.6.4", + "@jest/types": "^29.6.3", + "babel-jest": "^29.6.4", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-circus": "^29.6.2", - "jest-environment-node": "^29.6.2", - "jest-get-type": "^29.4.3", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.6.2", - "jest-runner": "^29.6.2", - "jest-util": "^29.6.2", - "jest-validate": "^29.6.2", + "jest-circus": "^29.6.4", + "jest-environment-node": "^29.6.4", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.6.4", + "jest-runner": "^29.6.4", + "jest-util": "^29.6.3", + "jest-validate": "^29.6.3", "micromatch": "^4.0.4", "parse-json": "^5.2.0", - "pretty-format": "^29.6.2", + "pretty-format": "^29.6.3", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" }, @@ -3465,24 +3520,24 @@ } }, "node_modules/jest-diff": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.6.2.tgz", - "integrity": "sha512-t+ST7CB9GX5F2xKwhwCf0TAR17uNDiaPTZnVymP9lw0lssa9vG+AFyDZoeIHStU3WowFFwT+ky+er0WVl2yGhA==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.6.4.tgz", + "integrity": "sha512-9F48UxR9e4XOEZvoUXEHSWY4qC4zERJaOfrbBg9JpbJOO43R1vN76REt/aMGZoY6GD5g84nnJiBIVlscegefpw==", "dev": true, "dependencies": { "chalk": "^4.0.0", - "diff-sequences": "^29.4.3", - "jest-get-type": "^29.4.3", - "pretty-format": "^29.6.2" + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-docblock": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.4.3.tgz", - "integrity": "sha512-fzdTftThczeSD9nZ3fzA/4KkHtnmllawWrXO69vtI+L9WjEIuXWs4AmyME7lN5hU7dB0sHhuPfcKofRsUb/2Fg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.6.3.tgz", + "integrity": "sha512-2+H+GOTQBEm2+qFSQ7Ma+BvyV+waiIFxmZF5LdpBsAEjWX8QYjSCa4FrkIYtbfXUJJJnFCYrOtt6TZ+IAiTjBQ==", "dev": true, "dependencies": { "detect-newline": "^3.0.0" @@ -3492,62 +3547,62 @@ } }, "node_modules/jest-each": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.6.2.tgz", - "integrity": "sha512-MsrsqA0Ia99cIpABBc3izS1ZYoYfhIy0NNWqPSE0YXbQjwchyt6B1HD2khzyPe1WiJA7hbxXy77ZoUQxn8UlSw==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.6.3.tgz", + "integrity": "sha512-KoXfJ42k8cqbkfshW7sSHcdfnv5agDdHCPA87ZBdmHP+zJstTJc0ttQaJ/x7zK6noAL76hOuTIJ6ZkQRS5dcyg==", "dev": true, "dependencies": { - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "chalk": "^4.0.0", - "jest-get-type": "^29.4.3", - "jest-util": "^29.6.2", - "pretty-format": "^29.6.2" + "jest-get-type": "^29.6.3", + "jest-util": "^29.6.3", + "pretty-format": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-environment-node": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.6.2.tgz", - "integrity": "sha512-YGdFeZ3T9a+/612c5mTQIllvWkddPbYcN2v95ZH24oWMbGA4GGS2XdIF92QMhUhvrjjuQWYgUGW2zawOyH63MQ==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.6.4.tgz", + "integrity": "sha512-i7SbpH2dEIFGNmxGCpSc2w9cA4qVD+wfvg2ZnfQ7XVrKL0NA5uDVBIiGH8SR4F0dKEv/0qI5r+aDomDf04DpEQ==", "dev": true, "dependencies": { - "@jest/environment": "^29.6.2", - "@jest/fake-timers": "^29.6.2", - "@jest/types": "^29.6.1", + "@jest/environment": "^29.6.4", + "@jest/fake-timers": "^29.6.4", + "@jest/types": "^29.6.3", "@types/node": "*", - "jest-mock": "^29.6.2", - "jest-util": "^29.6.2" + "jest-mock": "^29.6.3", + "jest-util": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-get-type": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", - "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-haste-map": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.6.2.tgz", - "integrity": "sha512-+51XleTDAAysvU8rT6AnS1ZJ+WHVNqhj1k6nTvN2PYP+HjU3kqlaKQ1Lnw3NYW3bm2r8vq82X0Z1nDDHZMzHVA==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.6.4.tgz", + "integrity": "sha512-12Ad+VNTDHxKf7k+M65sviyynRoZYuL1/GTuhEVb8RYsNSNln71nANRb/faSyWvx0j+gHcivChXHIoMJrGYjog==", "dev": true, "dependencies": { - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.4.3", - "jest-util": "^29.6.2", - "jest-worker": "^29.6.2", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.6.3", + "jest-worker": "^29.6.4", "micromatch": "^4.0.4", "walker": "^1.0.8" }, @@ -3559,46 +3614,46 @@ } }, "node_modules/jest-leak-detector": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.6.2.tgz", - "integrity": "sha512-aNqYhfp5uYEO3tdWMb2bfWv6f0b4I0LOxVRpnRLAeque2uqOVVMLh6khnTcE2qJ5wAKop0HcreM1btoysD6bPQ==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.6.3.tgz", + "integrity": "sha512-0kfbESIHXYdhAdpLsW7xdwmYhLf1BRu4AA118/OxFm0Ho1b2RcTmO4oF6aAMaxpxdxnJ3zve2rgwzNBD4Zbm7Q==", "dev": true, "dependencies": { - "jest-get-type": "^29.4.3", - "pretty-format": "^29.6.2" + "jest-get-type": "^29.6.3", + "pretty-format": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-matcher-utils": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.6.2.tgz", - "integrity": "sha512-4LiAk3hSSobtomeIAzFTe+N8kL6z0JtF3n6I4fg29iIW7tt99R7ZcIFW34QkX+DuVrf+CUe6wuVOpm7ZKFJzZQ==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.6.4.tgz", + "integrity": "sha512-KSzwyzGvK4HcfnserYqJHYi7sZVqdREJ9DMPAKVbS98JsIAvumihaNUbjrWw0St7p9IY7A9UskCW5MYlGmBQFQ==", "dev": true, "dependencies": { "chalk": "^4.0.0", - "jest-diff": "^29.6.2", - "jest-get-type": "^29.4.3", - "pretty-format": "^29.6.2" + "jest-diff": "^29.6.4", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-message-util": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.2.tgz", - "integrity": "sha512-vnIGYEjoPSuRqV8W9t+Wow95SDp6KPX2Uf7EoeG9G99J2OVh7OSwpS4B6J0NfpEIpfkBNHlBZpA2rblEuEFhZQ==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.3.tgz", + "integrity": "sha512-FtzaEEHzjDpQp51HX4UMkPZjy46ati4T5pEMyM6Ik48ztu4T9LQplZ6OsimHx7EuM9dfEh5HJa6D3trEftu3dA==", "dev": true, "dependencies": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^29.6.2", + "pretty-format": "^29.6.3", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, @@ -3607,14 +3662,14 @@ } }, "node_modules/jest-mock": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.6.2.tgz", - "integrity": "sha512-hoSv3lb3byzdKfwqCuT6uTscan471GUECqgNYykg6ob0yiAw3zYc7OrPnI9Qv8Wwoa4lC7AZ9hyS4AiIx5U2zg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.6.3.tgz", + "integrity": "sha512-Z7Gs/mOyTSR4yPsaZ72a/MtuK6RnC3JYqWONe48oLaoEcYwEDxqvbXz85G4SJrm2Z5Ar9zp6MiHF4AlFlRM4Pg==", "dev": true, "dependencies": { - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "@types/node": "*", - "jest-util": "^29.6.2" + "jest-util": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -3638,26 +3693,26 @@ } }, "node_modules/jest-regex-util": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.4.3.tgz", - "integrity": "sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-resolve": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.6.2.tgz", - "integrity": "sha512-G/iQUvZWI5e3SMFssc4ug4dH0aZiZpsDq9o1PtXTV1210Ztyb2+w+ZgQkB3iOiC5SmAEzJBOHWz6Hvrd+QnNPw==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.6.4.tgz", + "integrity": "sha512-fPRq+0vcxsuGlG0O3gyoqGTAxasagOxEuyoxHeyxaZbc9QNek0AmJWSkhjlMG+mTsj+8knc/mWb3fXlRNVih7Q==", "dev": true, "dependencies": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.2", + "jest-haste-map": "^29.6.4", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.6.2", - "jest-validate": "^29.6.2", + "jest-util": "^29.6.3", + "jest-validate": "^29.6.3", "resolve": "^1.20.0", "resolve.exports": "^2.0.0", "slash": "^3.0.0" @@ -3667,43 +3722,43 @@ } }, "node_modules/jest-resolve-dependencies": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.2.tgz", - "integrity": "sha512-LGqjDWxg2fuQQm7ypDxduLu/m4+4Lb4gczc13v51VMZbVP5tSBILqVx8qfWcsdP8f0G7aIqByIALDB0R93yL+w==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.4.tgz", + "integrity": "sha512-7+6eAmr1ZBF3vOAJVsfLj1QdqeXG+WYhidfLHBRZqGN24MFRIiKG20ItpLw2qRAsW/D2ZUUmCNf6irUr/v6KHA==", "dev": true, "dependencies": { - "jest-regex-util": "^29.4.3", - "jest-snapshot": "^29.6.2" + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.6.4" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runner": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.6.2.tgz", - "integrity": "sha512-wXOT/a0EspYgfMiYHxwGLPCZfC0c38MivAlb2lMEAlwHINKemrttu1uSbcGbfDV31sFaPWnWJPmb2qXM8pqZ4w==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.6.4.tgz", + "integrity": "sha512-SDaLrMmtVlQYDuG0iSPYLycG8P9jLI+fRm8AF/xPKhYDB2g6xDWjXBrR5M8gEWsK6KVFlebpZ4QsrxdyIX1Jaw==", "dev": true, "dependencies": { - "@jest/console": "^29.6.2", - "@jest/environment": "^29.6.2", - "@jest/test-result": "^29.6.2", - "@jest/transform": "^29.6.2", - "@jest/types": "^29.6.1", + "@jest/console": "^29.6.4", + "@jest/environment": "^29.6.4", + "@jest/test-result": "^29.6.4", + "@jest/transform": "^29.6.4", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "emittery": "^0.13.1", "graceful-fs": "^4.2.9", - "jest-docblock": "^29.4.3", - "jest-environment-node": "^29.6.2", - "jest-haste-map": "^29.6.2", - "jest-leak-detector": "^29.6.2", - "jest-message-util": "^29.6.2", - "jest-resolve": "^29.6.2", - "jest-runtime": "^29.6.2", - "jest-util": "^29.6.2", - "jest-watcher": "^29.6.2", - "jest-worker": "^29.6.2", + "jest-docblock": "^29.6.3", + "jest-environment-node": "^29.6.4", + "jest-haste-map": "^29.6.4", + "jest-leak-detector": "^29.6.3", + "jest-message-util": "^29.6.3", + "jest-resolve": "^29.6.4", + "jest-runtime": "^29.6.4", + "jest-util": "^29.6.3", + "jest-watcher": "^29.6.4", + "jest-worker": "^29.6.4", "p-limit": "^3.1.0", "source-map-support": "0.5.13" }, @@ -3712,31 +3767,31 @@ } }, "node_modules/jest-runtime": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.6.2.tgz", - "integrity": "sha512-2X9dqK768KufGJyIeLmIzToDmsN0m7Iek8QNxRSI/2+iPFYHF0jTwlO3ftn7gdKd98G/VQw9XJCk77rbTGZnJg==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.6.4.tgz", + "integrity": "sha512-s/QxMBLvmwLdchKEjcLfwzP7h+jsHvNEtxGP5P+Fl1FMaJX2jMiIqe4rJw4tFprzCwuSvVUo9bn0uj4gNRXsbA==", "dev": true, "dependencies": { - "@jest/environment": "^29.6.2", - "@jest/fake-timers": "^29.6.2", - "@jest/globals": "^29.6.2", - "@jest/source-map": "^29.6.0", - "@jest/test-result": "^29.6.2", - "@jest/transform": "^29.6.2", - "@jest/types": "^29.6.1", + "@jest/environment": "^29.6.4", + "@jest/fake-timers": "^29.6.4", + "@jest/globals": "^29.6.4", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.6.4", + "@jest/transform": "^29.6.4", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "cjs-module-lexer": "^1.0.0", "collect-v8-coverage": "^1.0.0", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.2", - "jest-message-util": "^29.6.2", - "jest-mock": "^29.6.2", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.6.2", - "jest-snapshot": "^29.6.2", - "jest-util": "^29.6.2", + "jest-haste-map": "^29.6.4", + "jest-message-util": "^29.6.3", + "jest-mock": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.6.4", + "jest-snapshot": "^29.6.4", + "jest-util": "^29.6.3", "slash": "^3.0.0", "strip-bom": "^4.0.0" }, @@ -3745,9 +3800,9 @@ } }, "node_modules/jest-snapshot": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.6.2.tgz", - "integrity": "sha512-1OdjqvqmRdGNvWXr/YZHuyhh5DeaLp1p/F8Tht/MrMw4Kr1Uu/j4lRG+iKl1DAqUJDWxtQBMk41Lnf/JETYBRA==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.6.4.tgz", + "integrity": "sha512-VC1N8ED7+4uboUKGIDsbvNAZb6LakgIPgAF4RSpF13dN6YaMokfRqO+BaqK4zIh6X3JffgwbzuGqDEjHm/MrvA==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", @@ -3755,20 +3810,20 @@ "@babel/plugin-syntax-jsx": "^7.7.2", "@babel/plugin-syntax-typescript": "^7.7.2", "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.6.2", - "@jest/transform": "^29.6.2", - "@jest/types": "^29.6.1", + "@jest/expect-utils": "^29.6.4", + "@jest/transform": "^29.6.4", + "@jest/types": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "expect": "^29.6.2", + "expect": "^29.6.4", "graceful-fs": "^4.2.9", - "jest-diff": "^29.6.2", - "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.6.2", - "jest-message-util": "^29.6.2", - "jest-util": "^29.6.2", + "jest-diff": "^29.6.4", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.6.4", + "jest-message-util": "^29.6.3", + "jest-util": "^29.6.3", "natural-compare": "^1.4.0", - "pretty-format": "^29.6.2", + "pretty-format": "^29.6.3", "semver": "^7.5.3" }, "engines": { @@ -3809,12 +3864,12 @@ "dev": true }, "node_modules/jest-util": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.6.2.tgz", - "integrity": "sha512-3eX1qb6L88lJNCFlEADKOkjpXJQyZRiavX1INZ4tRnrBVr2COd3RgcTLyUiEXMNBlDU/cgYq6taUS0fExrWW4w==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.6.3.tgz", + "integrity": "sha512-QUjna/xSy4B32fzcKTSz1w7YYzgiHrjjJjevdRf61HYk998R5vVMMNmrHESYZVDS5DSWs+1srPLPKxXPkeSDOA==", "dev": true, "dependencies": { - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -3826,17 +3881,17 @@ } }, "node_modules/jest-validate": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.6.2.tgz", - "integrity": "sha512-vGz0yMN5fUFRRbpJDPwxMpgSXW1LDKROHfBopAvDcmD6s+B/s8WJrwi+4bfH4SdInBA5C3P3BI19dBtKzx1Arg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.6.3.tgz", + "integrity": "sha512-e7KWZcAIX+2W1o3cHfnqpGajdCs1jSM3DkXjGeLSNmCazv1EeI1ggTeK5wdZhF+7N+g44JI2Od3veojoaumlfg==", "dev": true, "dependencies": { - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "camelcase": "^6.2.0", "chalk": "^4.0.0", - "jest-get-type": "^29.4.3", + "jest-get-type": "^29.6.3", "leven": "^3.1.0", - "pretty-format": "^29.6.2" + "pretty-format": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -3855,18 +3910,18 @@ } }, "node_modules/jest-watcher": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.6.2.tgz", - "integrity": "sha512-GZitlqkMkhkefjfN/p3SJjrDaxPflqxEAv3/ik10OirZqJGYH5rPiIsgVcfof0Tdqg3shQGdEIxDBx+B4tuLzA==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.6.4.tgz", + "integrity": "sha512-oqUWvx6+On04ShsT00Ir9T4/FvBeEh2M9PTubgITPxDa739p4hoQweWPRGyYeaojgT0xTpZKF0Y/rSY1UgMxvQ==", "dev": true, "dependencies": { - "@jest/test-result": "^29.6.2", - "@jest/types": "^29.6.1", + "@jest/test-result": "^29.6.4", + "@jest/types": "^29.6.3", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "emittery": "^0.13.1", - "jest-util": "^29.6.2", + "jest-util": "^29.6.3", "string-length": "^4.0.1" }, "engines": { @@ -3874,13 +3929,13 @@ } }, "node_modules/jest-worker": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.2.tgz", - "integrity": "sha512-l3ccBOabTdkng8I/ORCkADz4eSMKejTYv1vB/Z83UiubqhC1oQ5Li6dWCyqOIvSifGjUBxuvxvlm6KGK2DtuAQ==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.4.tgz", + "integrity": "sha512-6dpvFV4WjcWbDVGgHTWo/aupl8/LbBx2NSKfiwqf79xC/yeJjKHT1+StcKy/2KTmW16hE68ccKVOtXf+WZGz7Q==", "dev": true, "dependencies": { "@types/node": "*", - "jest-util": "^29.6.2", + "jest-util": "^29.6.3", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, @@ -3952,14 +4007,20 @@ } }, "node_modules/jsonwebtoken": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.1.tgz", - "integrity": "sha512-K8wx7eJ5TPvEjuiVSkv167EVboBDv9PZdDoF7BgeQnBLVvZWW9clr2PsQHVJDTKaEIH5JBIwHujGcHp7GgI2eg==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", "dependencies": { "jws": "^3.2.2", - "lodash": "^4.17.21", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", "ms": "^2.1.1", - "semver": "^7.3.8" + "semver": "^7.5.4" }, "engines": { "node": ">=12", @@ -4030,7 +4091,7 @@ } }, "node_modules/le-coffre-resources": { - "resolved": "git+ssh://git@github.com/smart-chain-fr/leCoffre-resources.git#ad0660abcb9de6ee7f396dce9b25fa7731a8e3b8", + "resolved": "git+ssh://git@github.com/smart-chain-fr/leCoffre-resources.git#1d27e0dacb6fe9c5637601818d3ff26434cf663c", "license": "MIT", "dependencies": { "class-transformer": "^0.5.1", @@ -4048,9 +4109,9 @@ } }, "node_modules/libphonenumber-js": { - "version": "1.10.41", - "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.41.tgz", - "integrity": "sha512-4rmmF4u4vD3eGNuuCGjCPwRwO+fIuu1WWcS7VwbPTiMFkJd8F02v8o5pY5tlYuMR+xOvJ88mtOHpkm0Tnu2LcQ==" + "version": "1.10.44", + "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.44.tgz", + "integrity": "sha512-svlRdNBI5WgBjRC20GrCfbFiclbF0Cx+sCcQob/C1r57nsoq0xg8r65QbTyVyweQIlB33P+Uahyho6EMYgcOyQ==" }, "node_modules/lines-and-columns": { "version": "1.2.4", @@ -4070,10 +4131,35 @@ "node": ">=8" } }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" }, "node_modules/lodash.memoize": { "version": "4.1.2", @@ -4081,6 +4167,11 @@ "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", "dev": true }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, "node_modules/long-timeout": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/long-timeout/-/long-timeout-0.1.1.tgz", @@ -4108,9 +4199,9 @@ } }, "node_modules/luxon": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.4.0.tgz", - "integrity": "sha512-7eDo4Pt7aGhoCheGFIuq4Xa2fJm4ZpmldpGhjTYBNUYNCN6TIEP6v7chwwwt3KRp7YR+rghbfvjyo3V5y9hgBw==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.3.0.tgz", + "integrity": "sha512-An0UCfG/rSiqtAIiBPO0Y9/zAnHUZxAMiCpTd5h2smgsj7GGmcenvrvww2cqNA8/4A5ZrD1gJpHN2mIHZQF+Mg==", "engines": { "node": ">=12" } @@ -4477,11 +4568,11 @@ } }, "node_modules/next": { - "version": "13.4.16", - "resolved": "https://registry.npmjs.org/next/-/next-13.4.16.tgz", - "integrity": "sha512-1xaA/5DrfpPu0eV31Iro7JfPeqO8uxQWb1zYNTe+KDKdzqkAGapLcDYHMLNKXKB7lHjZ7LfKUOf9dyuzcibrhA==", + "version": "13.4.19", + "resolved": "https://registry.npmjs.org/next/-/next-13.4.19.tgz", + "integrity": "sha512-HuPSzzAbJ1T4BD8e0bs6B9C1kWQ6gv8ykZoRWs5AQoiIuqbGHHdQO7Ljuvg05Q0Z24E2ABozHe6FxDvI6HfyAw==", "dependencies": { - "@next/env": "13.4.16", + "@next/env": "13.4.19", "@swc/helpers": "0.5.1", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001406", @@ -4497,15 +4588,15 @@ "node": ">=16.8.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "13.4.16", - "@next/swc-darwin-x64": "13.4.16", - "@next/swc-linux-arm64-gnu": "13.4.16", - "@next/swc-linux-arm64-musl": "13.4.16", - "@next/swc-linux-x64-gnu": "13.4.16", - "@next/swc-linux-x64-musl": "13.4.16", - "@next/swc-win32-arm64-msvc": "13.4.16", - "@next/swc-win32-ia32-msvc": "13.4.16", - "@next/swc-win32-x64-msvc": "13.4.16" + "@next/swc-darwin-arm64": "13.4.19", + "@next/swc-darwin-x64": "13.4.19", + "@next/swc-linux-arm64-gnu": "13.4.19", + "@next/swc-linux-arm64-musl": "13.4.19", + "@next/swc-linux-x64-gnu": "13.4.19", + "@next/swc-linux-x64-musl": "13.4.19", + "@next/swc-win32-arm64-msvc": "13.4.19", + "@next/swc-win32-ia32-msvc": "13.4.19", + "@next/swc-win32-x64-msvc": "13.4.19" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", @@ -4534,9 +4625,9 @@ } }, "node_modules/node-fetch": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz", - "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "dependencies": { "whatwg-url": "^5.0.0" }, @@ -4938,12 +5029,12 @@ } }, "node_modules/pretty-format": { - "version": "29.6.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.2.tgz", - "integrity": "sha512-1q0oC8eRveTg5nnBEWMXAU2qpv65Gnuf2eCQzSjxpWFkPaPARwqZZDGuNE0zPAZfTCHzIk3A8dIjwlQKKLphyg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.3.tgz", + "integrity": "sha512-ZsBgjVhFAj5KeK+nHfF1305/By3lechHQSMWCTl8iHSbfOm2TN5nHEtFc/+W7fAyUeCs2n5iow72gld4gW0xDw==", "dev": true, "dependencies": { - "@jest/schemas": "^29.6.0", + "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -5030,9 +5121,9 @@ "dev": true }, "node_modules/pure-rand": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.2.tgz", - "integrity": "sha512-6Yg0ekpKICSjPswYOuC5sku/TSWaRYlA0qsXqJgM/d/4pLPHPuTxK7Nbf7jFKzAeedUhR8C7K9Uv63FBsSo8xQ==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.3.tgz", + "integrity": "sha512-KddyFewCsO0j3+np81IQ+SweXLDnDQTs5s67BOnrYmYe/yNmUhttQyGsYzy8yUnoljGAQ9sl38YB4vH8ur7Y+w==", "dev": true, "funding": [ { @@ -5748,9 +5839,9 @@ } }, "node_modules/tslib": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", - "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==" + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, "node_modules/type-detect": { "version": "4.0.8", diff --git a/src/common/databases/seeders/seeder.ts b/src/common/databases/seeders/seeder.ts index 0e812e5c..8e85cd93 100644 --- a/src/common/databases/seeders/seeder.ts +++ b/src/common/databases/seeders/seeder.ts @@ -1347,7 +1347,7 @@ export default async function main() { for (const office of offices) { const officeCreated = await prisma.offices.create({ data: { - idNot: office.idNot, + idNot: office.idNot!, name: office.name, crpcen: office.crpcen, address: { @@ -1416,7 +1416,7 @@ export default async function main() { idNot: user.office_membership!.idNot, }, create: { - idNot: user.office_membership!.idNot, + idNot: user.office_membership!.idNot!, name: user.office_membership!.name, crpcen: user.office_membership!.crpcen, address: { diff --git a/src/common/repositories/OfficesRepository.ts b/src/common/repositories/OfficesRepository.ts index cdc85202..0e0c83ed 100644 --- a/src/common/repositories/OfficesRepository.ts +++ b/src/common/repositories/OfficesRepository.ts @@ -33,7 +33,7 @@ export default class OfficesRepository extends BaseRepository { public async create(office: OfficeRessource): Promise { const createArgs: Prisma.OfficesCreateArgs = { data: { - idNot: office.idNot, + idNot: office.idNot!, name: office.name, crpcen: office.crpcen, address: { diff --git a/src/common/repositories/UsersRepository.ts b/src/common/repositories/UsersRepository.ts index 739aea8f..6df40fb6 100644 --- a/src/common/repositories/UsersRepository.ts +++ b/src/common/repositories/UsersRepository.ts @@ -37,7 +37,7 @@ export default class UsersRepository extends BaseRepository { idNot: user.office_membership!.idNot, }, create: { - idNot: user.office_membership!.idNot, + idNot: user.office_membership!.idNot!, name: user.office_membership!.name, crpcen: user.office_membership!.crpcen, address: { diff --git a/src/test/config/Init.ts b/src/test/config/Init.ts index c3921d70..4541cb77 100644 --- a/src/test/config/Init.ts +++ b/src/test/config/Init.ts @@ -18,7 +18,7 @@ const prisma = new PrismaClient(); export const initOffice = (office: Office): Promise => { return prisma.offices.create({ data: { - idNot: office.idNot, + idNot: office.idNot!, name: office.name, crpcen: office.crpcen, address: { @@ -119,7 +119,7 @@ export const initUsers = (user: User): Promise => { idNot: user.office_membership!.idNot, }, create: { - idNot: user.office_membership!.idNot, + idNot: user.office_membership!.idNot!, name: user.office_membership!.name, crpcen: user.office_membership!.crpcen, address: {