diff --git a/.circleci/config.yml b/.circleci/config.yml index a1e75a9f..2c8347dd 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -47,7 +47,10 @@ 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} + --set lecoffreCron.image.repository='rg.fr-par.scw.cloud/lecoffre/back' + --set lecoffreCron.image.tag=${CIRCLE_SHA1:0:7} + workflows: diff --git a/devops/ppd.values.yaml b/devops/ppd.values.yaml index f2532b48..ba5c13a9 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 (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 new file mode 100644 index 00000000..e524b445 --- /dev/null +++ b/src/app/api/customer/OfficeFoldersController.ts @@ -0,0 +1,113 @@ +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") + 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); + } + + + 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 officeWhereInput: Prisma.OfficesWhereInput = {}; + 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/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/api/idnot/UserController.ts b/src/app/api/idnot/UserController.ts index 8714da20..b63d3fec 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); 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" }); 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); diff --git a/src/app/index.ts b/src/app/index.ts index f550461c..dc98b2e4 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 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"; @@ -95,5 +97,7 @@ export default { Container.get(OfficeRolesControllerNotary); Container.get(FilesControllerCustomer); Container.get(DocumentsControllerCustomer); + Container.get(OfficeFoldersController); + Container.get(CustomersController) }, }; 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/common/databases/seeders/seeder.ts b/src/common/databases/seeders/seeder.ts index 941942db..700442cf 100644 --- a/src/common/databases/seeders/seeder.ts +++ b/src/common/databases/seeders/seeder.ts @@ -1246,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[] = [ diff --git a/src/services/common/AuthService/AuthService.ts b/src/services/common/AuthService/AuthService.ts index b0628cf0..0a751e21 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; } @@ -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 { - customerId: contact.customers!.uid, + userId: customer.uid, email: contact.email, }; } @@ -80,7 +81,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/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); + } +} 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); + } +}