Merge Staging in Preprod

This commit is contained in:
Arnaud D. Natali 2023-10-24 22:01:00 +02:00 committed by GitHub
commit 258c930d09
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
76 changed files with 29554 additions and 626 deletions

File diff suppressed because it is too large Load Diff

6744
doc/swagger.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -45,6 +45,7 @@
"@mailchimp/mailchimp_transactional": "^1.0.50", "@mailchimp/mailchimp_transactional": "^1.0.50",
"@pinata/sdk": "^2.1.0", "@pinata/sdk": "^2.1.0",
"@prisma/client": "^4.11.0", "@prisma/client": "^4.11.0",
"adm-zip": "^0.5.10",
"class-transformer": "^0.5.1", "class-transformer": "^0.5.1",
"class-validator": "^0.14.0", "class-validator": "^0.14.0",
"classnames": "^2.3.2", "classnames": "^2.3.2",
@ -53,7 +54,7 @@
"express": "^4.18.2", "express": "^4.18.2",
"fp-ts": "^2.16.1", "fp-ts": "^2.16.1",
"jsonwebtoken": "^9.0.0", "jsonwebtoken": "^9.0.0",
"le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.90", "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.94",
"module-alias": "^2.2.2", "module-alias": "^2.2.2",
"monocle-ts": "^2.3.13", "monocle-ts": "^2.3.13",
"multer": "^1.4.5-lts.1", "multer": "^1.4.5-lts.1",
@ -71,6 +72,7 @@
"uuidv4": "^6.2.13" "uuidv4": "^6.2.13"
}, },
"devDependencies": { "devDependencies": {
"@types/adm-zip": "^0.5.3",
"@types/cors": "^2.8.13", "@types/cors": "^2.8.13",
"@types/cron": "^2.0.1", "@types/cron": "^2.0.1",
"@types/express": "^4.17.16", "@types/express": "^4.17.16",

View File

@ -25,15 +25,18 @@ export default class CustomersController extends ApiController {
protected async get(req: Request, response: Response) { protected async get(req: Request, response: Response) {
try { try {
//get query //get query
let query; let query: Prisma.CustomersFindManyArgs = {};
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if (query.where?.uid) {
this.httpBadRequest(response, "You can't filter by uid");
return;
}
} }
const officeId: string = req.body.user.office_Id; const officeId: string = req.body.user.office_Id;
if(query.where?.office_folders?.some?.office_uid) delete query.where.office_folders.some.office_uid; if (query.where?.office_folders) delete query.where.office_folders;
if(query.where?.office_folders?.some?.office?.uid) delete query.where?.office_folders?.some?.office?.uid; const customerWhereInput: Prisma.CustomersWhereInput = { ...query.where, office_folders: { some: { office_uid: officeId } } };
const customerWhereInput: Prisma.CustomersWhereInput = { ...query.where, office_folders: { some: { office_uid: officeId } }};
query.where = customerWhereInput; query.where = customerWhereInput;
//call service to get prisma entity //call service to get prisma entity
@ -53,14 +56,34 @@ export default class CustomersController extends ApiController {
/** /**
* @description Create a new customer * @description Create a new customer
*/ */
@Post("/api/v1/admin/customers", [authHandler, ruleHandler]) @Post("/api/v1/notary/customers", [authHandler, ruleHandler])
protected async post(req: Request, response: Response) { protected async post(req: Request, response: Response) {
try { try {
//init IUser resource with request body values //init IUser resource with request body values
const customerEntity = Customer.hydrate<Customer>(req.body); const customerEntity = Customer.hydrate<Customer>(req.body);
//validate user //validate user
await validateOrReject(customerEntity, { groups: ["createCustomer"], forbidUnknownValues: false }); try {
await validateOrReject(customerEntity, { groups: ["createCustomer"], forbidUnknownValues: false });
} catch (error) {
this.httpValidationError(response, error);
return;
}
const customers = await this.customersService.get({
where: {
contact: { email: customerEntity.contact?.email },
office_folders: {
some: {
office_uid: req.body.user.office_Id,
},
},
},
});
if (customers.length > 0) {
this.httpValidationError(response, [{ property: "email", constraints: { unique: "email déjà utilisé" } }]);
return;
}
//call service to get prisma entity //call service to get prisma entity
const customerEntityCreated = await this.customersService.create(customerEntity); const customerEntityCreated = await this.customersService.create(customerEntity);
//Hydrate ressource with prisma entity //Hydrate ressource with prisma entity
@ -79,7 +102,7 @@ export default class CustomersController extends ApiController {
/** /**
* @description Modify a specific customer by uid * @description Modify a specific customer by uid
*/ */
@Put("/api/v1/admin/customers/:uid", [authHandler, roleHandler, ruleHandler, customerHandler]) @Put("/api/v1/notary/customers/:uid", [authHandler, ruleHandler, customerHandler])
protected async put(req: Request, response: Response) { protected async put(req: Request, response: Response) {
try { try {
const uid = req.params["uid"]; const uid = req.params["uid"];
@ -95,22 +118,59 @@ export default class CustomersController extends ApiController {
return; return;
} }
req.body.contact.uid = userFound.contact_uid;
//init IUser resource with request body values //init IUser resource with request body values
const customerEntity = Customer.hydrate<Customer>(req.body); const customerEntity = Customer.hydrate<Customer>(req.body);
//validate user //validate user
await validateOrReject(customerEntity, { groups: ["updateCustomer"], forbidUnknownValues: false }); try {
await validateOrReject(customerEntity, { groups: ["updateCustomer"], forbidUnknownValues: false });
} catch (error) {
this.httpValidationError(response, error);
return;
}
if (customerEntity.contact?.email) {
const customers = await this.customersService.get({
where: {
contact: { email: customerEntity.contact?.email },
office_folders: {
some: {
office_uid: req.body.user.office_Id,
},
},
},
});
if (customers.length != 0) {
try {
customers.forEach((customer) => {
if (customer.uid != uid) {
throw new Error("email déjà utilisé");
}
});
} catch (error) {
this.httpValidationError(response, [{ property: "email", constraints: { unique: "email déjà utilisé" } }]);
return;
}
}
}
//call service to get prisma entity //call service to get prisma entity
const customerEntityUpdated = await this.customersService.update(uid, customerEntity); try {
const customerEntityUpdated = await this.customersService.update(uid, customerEntity);
//Hydrate ressource with prisma entity
const customer = Customer.hydrate<Customer>(customerEntityUpdated, {
strategy: "excludeAll",
});
//Hydrate ressource with prisma entity //success
const customer = Customer.hydrate<Customer>(customerEntityUpdated, { this.httpSuccess(response, customer);
strategy: "excludeAll", } catch (error) {
}); console.log(error);
this.httpValidationError(response, error);
//success return;
this.httpSuccess(response, customer); }
} catch (error) { } catch (error) {
this.httpInternalError(response, error); this.httpInternalError(response, error);
return; return;

View File

@ -29,6 +29,10 @@ export default class DeedTypesController extends ApiController {
let query: Prisma.DeedTypesFindManyArgs = {}; let query: Prisma.DeedTypesFindManyArgs = {};
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if(query.where?.uid) {
this.httpBadRequest(response, "You can't filter by uid");
return;
}
} }
if (req.query["search"] && typeof req.query["search"] === "string") { if (req.query["search"] && typeof req.query["search"] === "string") {
@ -74,11 +78,6 @@ export default class DeedTypesController extends ApiController {
//validate deed type //validate deed type
await validateOrReject(deedTypeEntity, { groups: ["createDeedType"], forbidUnknownValues: false }); 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 //call service to get prisma entity
const deedTypeEntityCreated = await this.deedTypesService.create(deedTypeEntity); const deedTypeEntityCreated = await this.deedTypesService.create(deedTypeEntity);

View File

@ -29,6 +29,10 @@ export default class DeedsController extends ApiController {
let query: Prisma.DeedsFindManyArgs = {}; let query: Prisma.DeedsFindManyArgs = {};
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if(query.where?.uid) {
this.httpBadRequest(response, "You can't filter by uid");
return;
}
} }
const officeId: string = req.body.user.office_Id; const officeId: string = req.body.user.office_Id;
const officeWhereInput: Prisma.OfficesWhereInput = { uid: officeId } ; const officeWhereInput: Prisma.OfficesWhereInput = { uid: officeId } ;

View File

@ -29,6 +29,10 @@ export default class DocumentTypesController extends ApiController {
let query: Prisma.DocumentTypesFindManyArgs = {}; let query: Prisma.DocumentTypesFindManyArgs = {};
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if(query.where?.uid) {
this.httpBadRequest(response, "You can't filter by uid");
return;
}
} }
const officeId: string = req.body.user.office_Id; const officeId: string = req.body.user.office_Id;
const officeWhereInput: Prisma.OfficesWhereInput = { uid: officeId } ; const officeWhereInput: Prisma.OfficesWhereInput = { uid: officeId } ;

View File

@ -10,11 +10,12 @@ import authHandler from "@App/middlewares/AuthHandler";
import ruleHandler from "@App/middlewares/RulesHandler"; import ruleHandler from "@App/middlewares/RulesHandler";
import documentHandler from "@App/middlewares/OfficeMembershipHandlers/DocumentHandler"; import documentHandler from "@App/middlewares/OfficeMembershipHandlers/DocumentHandler";
import roleHandler from "@App/middlewares/RolesHandler"; import roleHandler from "@App/middlewares/RolesHandler";
import EmailBuilder from "@Common/emails/EmailBuilder";
@Controller() @Controller()
@Service() @Service()
export default class DocumentsController extends ApiController { export default class DocumentsController extends ApiController {
constructor(private documentsService: DocumentsService) { constructor(private documentsService: DocumentsService, private emailBuilder: EmailBuilder) {
super(); super();
} }
@ -29,6 +30,10 @@ export default class DocumentsController extends ApiController {
let query: Prisma.DocumentsFindManyArgs = {}; let query: Prisma.DocumentsFindManyArgs = {};
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if(query.where?.uid) {
this.httpBadRequest(response, "You can't filter by uid");
return;
}
} }
const officeId: string = req.body.user.office_Id; const officeId: string = req.body.user.office_Id;
const officeWhereInput: Prisma.OfficesWhereInput = { uid: officeId }; const officeWhereInput: Prisma.OfficesWhereInput = { uid: officeId };
@ -70,6 +75,10 @@ export default class DocumentsController extends ApiController {
strategy: "excludeAll", strategy: "excludeAll",
}); });
//create email for asked document
await this.emailBuilder.sendDocumentEmails(documentEntityCreated);
//success //success
this.httpCreated(response, document); this.httpCreated(response, document);
} catch (error) { } catch (error) {
@ -120,7 +129,7 @@ export default class DocumentsController extends ApiController {
/** /**
* @description Update a specific document * @description Update a specific document
*/ */
@Put("/api/v1/notary/documents/:uid/refuse", [authHandler, ruleHandler, documentHandler]) @Put("/api/v1/admin/documents/:uid/refuse", [authHandler, roleHandler, ruleHandler, documentHandler])
protected async refuseDocument(req: Request, response: Response) { protected async refuseDocument(req: Request, response: Response) {
try { try {
const uid = req.params["uid"]; const uid = req.params["uid"];
@ -151,8 +160,7 @@ export default class DocumentsController extends ApiController {
const documentEntityUpdated: Documents = await this.documentsService.refuse(uid, documentEntity, req.body.refused_reason); const documentEntityUpdated: Documents = await this.documentsService.refuse(uid, documentEntity, req.body.refused_reason);
//create email for asked document //create email for asked document
// this.emailBuilder.sendDocumentEmails(documentEntityUpdated); await this.emailBuilder.sendDocumentEmails(documentEntityUpdated);
// this.notificationBuilder.sendDocumentAnchoredNotificatiom(documentEntityUpdated);
//Hydrate ressource with prisma entity //Hydrate ressource with prisma entity
const document = Document.hydrate<Document>(documentEntityUpdated, { strategy: "excludeAll" }); const document = Document.hydrate<Document>(documentEntityUpdated, { strategy: "excludeAll" });

View File

@ -1,5 +1,5 @@
import { Response, Request } from "express"; import { Response, Request } from "express";
import { Controller, Delete, Get } from "@ControllerPattern/index"; import { Controller, Get } from "@ControllerPattern/index";
import ApiController from "@Common/system/controller-pattern/ApiController"; import ApiController from "@Common/system/controller-pattern/ApiController";
import { Service } from "typedi"; import { Service } from "typedi";
import FilesService from "@Services/common/FilesService/FilesService"; import FilesService from "@Services/common/FilesService/FilesService";
@ -28,6 +28,10 @@ export default class FilesController extends ApiController {
let query: Prisma.FilesFindManyArgs = {}; let query: Prisma.FilesFindManyArgs = {};
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if(query.where?.uid) {
this.httpBadRequest(response, "You can't filter by uid");
return;
}
} }
const officeId: string = req.body.user.office_Id; const officeId: string = req.body.user.office_Id;
const officeWhereInput: Prisma.OfficesWhereInput = { uid: officeId } ; const officeWhereInput: Prisma.OfficesWhereInput = { uid: officeId } ;
@ -75,44 +79,6 @@ export default class FilesController extends ApiController {
} }
} }
/**
* @description Delete a specific File
*/
@Delete("/api/v1/admin/files/:uid", [authHandler, roleHandler, ruleHandler, fileHandler])
protected async delete(req: Request, response: Response) {
try {
const uid = req.params["uid"];
if (!uid) {
this.httpBadRequest(response, "No uid provided");
return;
}
const fileFound = await this.filesService.getByUid(uid);
if (!fileFound) {
this.httpNotFoundRequest(response, "file not found");
return;
}
//call service to get prisma entity
const fileEntity = await this.filesService.deleteKeyAndArchive(uid);
if (!fileEntity) {
this.httpNotFoundRequest(response, "file not found");
return;
}
//Hydrate ressource with prisma entity
const file = File.hydrate<File>(fileEntity, { strategy: "excludeAll" });
//success
this.httpSuccess(response, file);
} catch (error) {
this.httpInternalError(response, error);
return;
}
}
/** /**
* @description Get a specific File by uid * @description Get a specific File by uid
*/ */

View File

@ -28,6 +28,10 @@ export default class OfficeFoldersController extends ApiController {
let query: Prisma.OfficeFoldersFindManyArgs = {}; let query: Prisma.OfficeFoldersFindManyArgs = {};
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if(query.where?.uid) {
this.httpBadRequest(response, "You can't filter by uid");
return;
}
} }
if (req.query["search"] && typeof req.query["search"] === "string") { if (req.query["search"] && typeof req.query["search"] === "string") {
@ -62,7 +66,7 @@ export default class OfficeFoldersController extends ApiController {
if (query.where?.stakeholders) delete query.where.stakeholders; if (query.where?.stakeholders) delete query.where.stakeholders;
const officeFoldersWhereInput: Prisma.OfficeFoldersWhereInput = { ...query.where, stakeholders: { some: { uid: userId } } }; const officeFoldersWhereInput: Prisma.OfficeFoldersWhereInput = { ...query.where, stakeholders: { some: { uid: userId } } };
query.where = officeFoldersWhereInput; query.where = officeFoldersWhereInput;
//call service to get prisma entity //call service to get prisma entity
const officeFolderEntities: OfficeFolders[] = await this.officeFoldersService.get(query); const officeFolderEntities: OfficeFolders[] = await this.officeFoldersService.get(query);
@ -89,13 +93,18 @@ export default class OfficeFoldersController extends ApiController {
await officeFolderRessource.validateOrReject?.({ groups: ["createFolder"], forbidUnknownValues: false }); await officeFolderRessource.validateOrReject?.({ groups: ["createFolder"], forbidUnknownValues: false });
//call service to get prisma entity //call service to get prisma entity
const officeFolderEntity = await this.officeFoldersService.create(officeFolderRessource); try {
//Hydrate ressource with prisma entity const officeFolderEntity = await this.officeFoldersService.create(officeFolderRessource);
const officeFolders = OfficeFolder.hydrate<OfficeFolder>(officeFolderEntity, { //Hydrate ressource with prisma entity
strategy: "excludeAll", const officeFolders = OfficeFolder.hydrate<OfficeFolder>(officeFolderEntity, {
}); strategy: "excludeAll",
//success });
this.httpCreated(response, officeFolders); //success
this.httpCreated(response, officeFolders);
} catch (error) {
this.httpValidationError(response, error);
return;
}
} catch (error) { } catch (error) {
this.httpInternalError(response, error); this.httpInternalError(response, error);
return; return;
@ -120,7 +129,7 @@ export default class OfficeFoldersController extends ApiController {
this.httpNotFoundRequest(response, "office folder not found"); this.httpNotFoundRequest(response, "office folder not found");
return; return;
} }
//init OfficeFolder resource with request body values //init OfficeFolder resource with request body values
const officeFolderEntity = OfficeFolder.hydrate<OfficeFolder>(req.body); const officeFolderEntity = OfficeFolder.hydrate<OfficeFolder>(req.body);
@ -128,15 +137,20 @@ export default class OfficeFoldersController extends ApiController {
await validateOrReject(officeFolderEntity, { groups: ["updateFolder"], forbidUnknownValues: false }); await validateOrReject(officeFolderEntity, { groups: ["updateFolder"], forbidUnknownValues: false });
//call service to get prisma entity //call service to get prisma entity
const officeFolderEntityUpdated = await this.officeFoldersService.update(uid, officeFolderEntity); try {
const officeFolderEntityUpdated = await this.officeFoldersService.update(uid, officeFolderEntity);
//Hydrate ressource with prisma entity //Hydrate ressource with prisma entity
const officeFolders = OfficeFolder.hydrate<OfficeFolder>(officeFolderEntityUpdated, { const officeFolders = OfficeFolder.hydrate<OfficeFolder>(officeFolderEntityUpdated, {
strategy: "excludeAll", strategy: "excludeAll",
}); });
//success //success
this.httpSuccess(response, officeFolders); this.httpSuccess(response, officeFolders);
} catch (error) {
this.httpValidationError(response, error);
return;
}
} catch (error) { } catch (error) {
this.httpInternalError(response, error); this.httpInternalError(response, error);
return; return;
@ -160,7 +174,7 @@ export default class OfficeFoldersController extends ApiController {
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
} }
const officeFolderEntity = await this.officeFoldersService.getByUid(uid, query); const officeFolderEntity = await this.officeFoldersService.getByUid(uid, query);
if (!officeFolderEntity) { if (!officeFolderEntity) {

View File

@ -29,6 +29,10 @@ export default class OfficeRolesController extends ApiController {
let query: Prisma.OfficeRolesFindManyArgs = {}; let query: Prisma.OfficeRolesFindManyArgs = {};
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if(query.where?.uid) {
this.httpBadRequest(response, "You can't filter by uid");
return;
}
} }
if (req.query["search"] && typeof req.query["search"] === "string") { if (req.query["search"] && typeof req.query["search"] === "string") {

View File

@ -3,7 +3,7 @@ import { Controller, Get } from "@ControllerPattern/index";
import ApiController from "@Common/system/controller-pattern/ApiController"; import ApiController from "@Common/system/controller-pattern/ApiController";
import OfficesService from "@Services/admin/OfficesService/OfficesService"; import OfficesService from "@Services/admin/OfficesService/OfficesService";
import { Service } from "typedi"; import { Service } from "typedi";
import { Offices } from "@prisma/client"; import { Offices, Prisma } from "@prisma/client";
import { Office as OfficeResource } from "le-coffre-resources/dist/Admin"; import { Office as OfficeResource } from "le-coffre-resources/dist/Admin";
import ruleHandler from "@App/middlewares/RulesHandler"; import ruleHandler from "@App/middlewares/RulesHandler";
import authHandler from "@App/middlewares/AuthHandler"; import authHandler from "@App/middlewares/AuthHandler";
@ -22,9 +22,13 @@ export default class OfficesController extends ApiController {
protected async get(req: Request, response: Response) { protected async get(req: Request, response: Response) {
try { try {
//get query //get query
let query; let query: Prisma.OfficesFindManyArgs = {};
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if (query.where?.uid) {
this.httpBadRequest(response, "You can't filter by uid");
return;
}
} }
//call service to get prisma entity //call service to get prisma entity
const officesEntities: Offices[] = await this.officesService.get(query); const officesEntities: Offices[] = await this.officesService.get(query);

View File

@ -7,6 +7,7 @@ import { Role } from "le-coffre-resources/dist/Admin";
import authHandler from "@App/middlewares/AuthHandler"; import authHandler from "@App/middlewares/AuthHandler";
import ruleHandler from "@App/middlewares/RulesHandler"; import ruleHandler from "@App/middlewares/RulesHandler";
import roleHandler from "@App/middlewares/RolesHandler"; import roleHandler from "@App/middlewares/RolesHandler";
import { Prisma } from "@prisma/client";
@Controller() @Controller()
@Service() @Service()
@ -22,9 +23,13 @@ export default class RolesController extends ApiController {
protected async get(req: Request, response: Response) { protected async get(req: Request, response: Response) {
try { try {
//get query //get query
let query; let query: Prisma.RolesFindManyArgs = {};
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if (query.where?.uid) {
this.httpBadRequest(response, "You can't filter by uid");
return;
}
} }
//call service to get prisma entity //call service to get prisma entity

View File

@ -7,6 +7,7 @@ import { Rule } from "le-coffre-resources/dist/Admin";
import authHandler from "@App/middlewares/AuthHandler"; import authHandler from "@App/middlewares/AuthHandler";
import ruleHandler from "@App/middlewares/RulesHandler"; import ruleHandler from "@App/middlewares/RulesHandler";
import roleHandler from "@App/middlewares/RolesHandler"; import roleHandler from "@App/middlewares/RolesHandler";
import { Prisma } from "@prisma/client";
@Controller() @Controller()
@Service() @Service()
@ -22,9 +23,13 @@ export default class RulesController extends ApiController {
protected async get(req: Request, response: Response) { protected async get(req: Request, response: Response) {
try { try {
//get query //get query
let query; let query: Prisma.RulesFindManyArgs = {};
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if (query.where?.uid) {
this.httpBadRequest(response, "You can't filter by uid");
return;
}
} }
//call service to get prisma entity //call service to get prisma entity

View File

@ -29,6 +29,10 @@ export default class UsersController extends ApiController {
let query: Prisma.UsersFindManyArgs = {}; let query: Prisma.UsersFindManyArgs = {};
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if(query.where?.uid) {
this.httpBadRequest(response, "You can't filter by uid");
return;
}
} }
if (req.query["search"] && typeof req.query["search"] === "string") { if (req.query["search"] && typeof req.query["search"] === "string") {

View File

@ -4,12 +4,11 @@ import ApiController from "@Common/system/controller-pattern/ApiController";
import { Service } from "typedi"; import { Service } from "typedi";
import DocumentsService from "@Services/customer/DocumentsService/DocumentsService"; import DocumentsService from "@Services/customer/DocumentsService/DocumentsService";
import { Documents, Prisma } from "@prisma/client"; import { Documents, Prisma } from "@prisma/client";
import { Document } from "le-coffre-resources/dist/Customer"; import { Document, OfficeFolder } from "le-coffre-resources/dist/Customer";
import authHandler from "@App/middlewares/AuthHandler"; import authHandler from "@App/middlewares/AuthHandler";
import documentHandler from "@App/middlewares/CustomerHandler/DocumentHandler"; import documentHandler from "@App/middlewares/CustomerHandler/DocumentHandler";
import { validateOrReject } from "class-validator"; import { validateOrReject } from "class-validator";
import OfficeFoldersService from "@Services/super-admin/OfficeFoldersService/OfficeFoldersService"; import OfficeFoldersService from "@Services/super-admin/OfficeFoldersService/OfficeFoldersService";
import { OfficeFolder } from "le-coffre-resources/dist/Notary";
@Controller() @Controller()
@Service() @Service()
@ -29,17 +28,24 @@ export default class DocumentsController extends ApiController {
let query: Prisma.DocumentsFindManyArgs = {}; let query: Prisma.DocumentsFindManyArgs = {};
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if(query.where?.uid) {
this.httpBadRequest(response, "You can't filter by uid");
return;
}
} }
const customerId: string = req.body.user.customerId; const email: string = req.body.user.email;
if(query.where?.depositor) delete query.where.depositor; if (!email) {
if(query.where?.depositor_uid) delete query.where.depositor_uid; this.httpBadRequest(response, "Missing customer email");
const customerWhereInput: Prisma.DocumentsWhereInput = { ...query.where, depositor: { uid: customerId } }; return;
}
if (query.where?.depositor) delete query.where.depositor;
if (query.where?.depositor_uid) delete query.where.depositor_uid;
const customerWhereInput: Prisma.DocumentsWhereInput = { ...query.where, depositor: { contact: { email: email } } };
query.where = customerWhereInput; query.where = customerWhereInput;
if (query.include?.folder) delete query.include.folder;
//call service to get prisma entity //call service to get prisma entity
const documentEntities: Documents[] = await this.documentsService.get(query); const documentEntities: Documents[] = await this.documentsService.get(query);
//Hydrate ressource with prisma entity //Hydrate ressource with prisma entity
const documents = Document.hydrateArray<Document>(documentEntities, { strategy: "excludeAll" }); const documents = Document.hydrateArray<Document>(documentEntities, { strategy: "excludeAll" });
@ -55,7 +61,7 @@ export default class DocumentsController extends ApiController {
/** /**
* @description Get a specific document by uid * @description Get a specific document by uid
*/ */
@Get("/api/v1/customer/documents/:uid",[authHandler,documentHandler]) @Get("/api/v1/customer/documents/:uid", [authHandler, documentHandler])
protected async getOneByUid(req: Request, response: Response) { protected async getOneByUid(req: Request, response: Response) {
try { try {
const uid = req.params["uid"]; const uid = req.params["uid"];
@ -67,6 +73,8 @@ export default class DocumentsController extends ApiController {
let query; let query;
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if (query.folder) delete query.folder;
} }
const documentEntity = await this.documentsService.getByUid(uid, query); const documentEntity = await this.documentsService.getByUid(uid, query);
@ -82,6 +90,7 @@ export default class DocumentsController extends ApiController {
//success //success
this.httpSuccess(response, document); this.httpSuccess(response, document);
} catch (error) { } catch (error) {
console.log(error);
this.httpInternalError(response); this.httpInternalError(response);
return; return;
} }
@ -91,29 +100,43 @@ export default class DocumentsController extends ApiController {
* @description Create a new File * @description Create a new File
* @returns File created * @returns File created
*/ */
@Post("/api/v1/customer/documents", [authHandler]) @Post("/api/v1/customer/documents", [authHandler, documentHandler])
protected async post(req: Request, response: Response) { protected async post(req: Request, response: Response) {
try { try {
//init Document resource with request body values //init Document resource with request body values
const documentEntity = Document.hydrate<Document>(req.body); const documentEntity = Document.hydrate<Document>(req.body);
if(!documentEntity.folder?.uid) { const email = req.body.user.email;
if (!documentEntity.folder?.uid) {
this.httpBadRequest(response, "No folder uid provided"); this.httpBadRequest(response, "No folder uid provided");
return; return;
} }
const folder = await this.officeFoldersService.getByUid(documentEntity.folder.uid, {folder_anchor: true}); const folder = await this.officeFoldersService.getByUid(documentEntity.folder.uid, {
if(!folder) { folder_anchor: true,
customers: { include: { contact: true } },
});
if (!folder) {
this.httpBadRequest(response, "Folder not found"); this.httpBadRequest(response, "Folder not found");
return; return;
} }
const folderEntity = OfficeFolder.hydrate<OfficeFolder>(folder, { strategy: "excludeAll" });
const folderEntity = OfficeFolder.hydrate<OfficeFolder>(folder); if (!folderEntity.customers) {
if (folderEntity.folder_anchor?.status === "VERIFIED_ON_CHAIN") { this.httpBadRequest(response, "No customers found in folder");
this.httpBadRequest(response, "Cannot update a verified folder"); return;
}
const depositor = folderEntity.customers.find((customer) => customer.contact?.email === email);
delete documentEntity.depositor;
documentEntity.depositor = depositor;
try {
//validate document
await validateOrReject(documentEntity, { groups: ["createDocument"], forbidUnknownValues: false });
} catch (error) {
this.httpValidationError(response, error);
return; return;
} }
//validate document
await validateOrReject(documentEntity, { groups: ["createDocument"], forbidUnknownValues: false });
//call service to get prisma entity //call service to get prisma entity
const documentEntityCreated = await this.documentsService.create(documentEntity); const documentEntityCreated = await this.documentsService.create(documentEntity);

View File

@ -1,9 +1,9 @@
import { Response, Request } from "express"; import { Response, Request } from "express";
import { Controller, Delete, Get, Post, Put } from "@ControllerPattern/index"; import { Controller, Delete, Get, Post } from "@ControllerPattern/index";
import ApiController from "@Common/system/controller-pattern/ApiController"; import ApiController from "@Common/system/controller-pattern/ApiController";
import { Service } from "typedi"; import { Service } from "typedi";
import FilesService from "@Services/common/FilesService/FilesService"; import FilesService from "@Services/common/FilesService/FilesService";
import { Files, Prisma } from "@prisma/client"; import { Prisma } from "@prisma/client";
import { File } from "le-coffre-resources/dist/Customer"; import { File } from "le-coffre-resources/dist/Customer";
import { Document } from "le-coffre-resources/dist/Customer"; import { Document } from "le-coffre-resources/dist/Customer";
import DocumentsService from "@Services/customer/DocumentsService/DocumentsService"; import DocumentsService from "@Services/customer/DocumentsService/DocumentsService";
@ -15,7 +15,11 @@ import { validateOrReject } from "class-validator";
@Controller() @Controller()
@Service() @Service()
export default class FilesController extends ApiController { export default class FilesController extends ApiController {
constructor(private filesService: FilesService, private documentService: DocumentsService, private notificationBuilder : NotificationBuilder) { constructor(
private filesService: FilesService,
private documentService: DocumentsService,
private notificationBuilder: NotificationBuilder,
) {
super(); super();
} }
@ -30,10 +34,21 @@ export default class FilesController extends ApiController {
let query: Prisma.FilesFindManyArgs = {}; let query: Prisma.FilesFindManyArgs = {};
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if (query.where?.uid) {
this.httpBadRequest(response, "You can't filter by uid");
return;
}
} }
const customerId: string = req.body.user.customerId; const email: string = req.body.user.email;
const customerWhereInput: Prisma.FilesWhereInput = { document: { depositor: { uid: customerId } } }; if (!email) {
this.httpBadRequest(response, "Missing customer email");
return;
}
if (query.where?.document?.depositor) delete query.where.document.depositor;
const customerWhereInput: Prisma.FilesWhereInput = { ...query.where, document: { depositor: { contact: { email: email } } } };
query.where = customerWhereInput; query.where = customerWhereInput;
if (query.include?.document) delete query.include.document;
//call service to get prisma entity //call service to get prisma entity
const fileEntities = await this.filesService.get(query); const fileEntities = await this.filesService.get(query);
@ -113,7 +128,6 @@ export default class FilesController extends ApiController {
strategy: "excludeAll", strategy: "excludeAll",
}); });
//success //success
this.httpCreated(response, fileEntityHydrated); this.httpCreated(response, fileEntityHydrated);
} catch (error) { } catch (error) {
@ -122,41 +136,6 @@ export default class FilesController extends ApiController {
} }
} }
/**
* @description Update a specific file
*/
@Put("/api/v1/customer/files/:uid", [authHandler, fileHandler])
protected async update(req: Request, response: Response) {
try {
const uid = req.params["uid"];
if (!uid) {
throw new Error("No uid provided");
}
const fileFound = await this.filesService.getByUid(uid);
if (!fileFound) {
this.httpNotFoundRequest(response, "file not found");
return;
}
//init File resource with request body values
const fileEntity = File.hydrate<File>(req.body);
//call service to get prisma entity
const fileEntityUpdated: Files = await this.filesService.update(uid, fileEntity);
//Hydrate ressource with prisma entity
const file = File.hydrate<File>(fileEntityUpdated, { strategy: "excludeAll" });
//success
this.httpSuccess(response, file);
} catch (error) {
this.httpBadRequest(response, error);
return;
}
}
/** /**
* @description Delete a specific File * @description Delete a specific File
*/ */
@ -169,19 +148,22 @@ export default class FilesController extends ApiController {
return; return;
} }
const fileFound = await this.filesService.getByUid(uid); const fileFound = await this.filesService.getByUid(uid, { document: { include: { files: true, document_type: true } } });
if (!fileFound) { if (!fileFound) {
this.httpNotFoundRequest(response, "file not found"); this.httpNotFoundRequest(response, "file not found");
return; return;
} }
const fileFoundEntity = File.hydrate<File>(fileFound, { strategy: "excludeAll" });
//call service to get prisma entity //call service to get prisma entity
const fileEntity = await this.filesService.deleteKeyAndArchive(uid); const fileEntity = await this.filesService.deleteKeyAndArchive(uid);
if (
if (!fileEntity) { !(fileFoundEntity.document!.files?.find((file) => file.archived_at === null && file.uid !== uid)) &&
this.httpNotFoundRequest(response, "file not found"); fileFoundEntity.document!.document_type!.name === "Autres documents"
return; ) {
await this.documentService.delete(fileFoundEntity.document!.uid!);
} }
//Hydrate ressource with prisma entity //Hydrate ressource with prisma entity
@ -210,6 +192,7 @@ export default class FilesController extends ApiController {
let query; let query;
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if (query.document) delete query.document;
} }
const fileEntity = await this.filesService.getByUid(uid, query); const fileEntity = await this.filesService.getByUid(uid, query);

View File

@ -7,9 +7,6 @@ import { OfficeFolders, Prisma } from "@prisma/client";
import { OfficeFolder } from "le-coffre-resources/dist/Customer"; import { OfficeFolder } from "le-coffre-resources/dist/Customer";
import officeFolderHandler from "@App/middlewares/CustomerHandler/FolderHandler"; import officeFolderHandler from "@App/middlewares/CustomerHandler/FolderHandler";
import authHandler from "@App/middlewares/AuthHandler"; 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";
@Controller() @Controller()
@Service() @Service()
@ -22,22 +19,31 @@ export default class OfficeFoldersController extends ApiController {
* @description Get all folders * @description Get all folders
*/ */
@Get("/api/v1/customer/folders", [authHandler]) @Get("/api/v1/customer/folders", [authHandler])
protected async get(req: Request, response: Response) { protected async get(req: Request, response: Response) {
try { try {
//get query //get query
let query: Prisma.OfficeFoldersFindManyArgs = {}; let query: Prisma.OfficeFoldersFindManyArgs = {};
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if(query.where?.uid) {
this.httpBadRequest(response, "You can't filter by uid");
return;
}
} }
const customerId: string = req.body.user.customerId; const email: string = req.body.user.email;
if(!customerId) { if (!email) {
this.httpBadRequest(response, "No customerId provided"); this.httpBadRequest(response, "Missing customer email");
return; return;
} }
if(query.where?.customers) delete query.where.customers; if (query.where?.customers) delete query.where.customers;
const officeFolderWhereInput: Prisma.OfficeFoldersWhereInput = { ...query.where, customers: { some: { uid: customerId } }}; const officeFolderWhereInput: Prisma.OfficeFoldersWhereInput = {
...query.where,
customers: { some: { contact: { email: email } } },
};
query.where = officeFolderWhereInput; query.where = officeFolderWhereInput;
if (query.include) delete query.include;
query.include = { customers: { include: { contact: true } } };
//call service to get prisma entity //call service to get prisma entity
const officeFolderEntities: OfficeFolders[] = await this.officeFoldersService.get(query); const officeFolderEntities: OfficeFolders[] = await this.officeFoldersService.get(query);
@ -46,6 +52,11 @@ export default class OfficeFoldersController extends ApiController {
const officeFolders = OfficeFolder.hydrateArray<OfficeFolder>(officeFolderEntities, { const officeFolders = OfficeFolder.hydrateArray<OfficeFolder>(officeFolderEntities, {
strategy: "excludeAll", strategy: "excludeAll",
}); });
officeFolders.forEach((officeFolder) => {
officeFolder.customers = officeFolder.customers!.filter((customer) => customer.contact?.email === email);
});
//success //success
this.httpSuccess(response, officeFolders); this.httpSuccess(response, officeFolders);
} catch (error) { } catch (error) {
@ -53,7 +64,7 @@ export default class OfficeFoldersController extends ApiController {
return; return;
} }
} }
/** /**
* @description Get a specific folder by uid * @description Get a specific folder by uid
* @returns IFolder * @returns IFolder
@ -67,12 +78,13 @@ export default class OfficeFoldersController extends ApiController {
return; return;
} }
const email: string = req.body.user.email;
let query; let query;
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if(query?.customers) { if (query?.customers) delete query.customers;
query.customers = true; query.customers = { include: { contact: true } };
}
} }
const officeFolderEntity = await this.officeFoldersService.getByUid(uid, query); const officeFolderEntity = await this.officeFoldersService.getByUid(uid, query);
@ -84,6 +96,10 @@ export default class OfficeFoldersController extends ApiController {
//Hydrate ressource with prisma entity //Hydrate ressource with prisma entity
const officeFolder = OfficeFolder.hydrate<OfficeFolder>(officeFolderEntity, { strategy: "excludeAll" }); const officeFolder = OfficeFolder.hydrate<OfficeFolder>(officeFolderEntity, { strategy: "excludeAll" });
if(officeFolder.customers) {
officeFolder.customers = officeFolder.customers!.filter((customer) => customer.contact?.email === email);
}
//success //success
this.httpSuccess(response, officeFolder); this.httpSuccess(response, officeFolder);
} catch (error) { } catch (error) {

View File

@ -1,67 +0,0 @@
import { Response, Request } from "express";
import { Controller, Post } from "@ControllerPattern/index";
import ApiController from "@Common/system/controller-pattern/ApiController";
import { Service } from "typedi";
import AuthService, { ICustomerJwtPayload } from "@Services/common/AuthService/AuthService";
import { JwtPayload } from "jsonwebtoken";
@Controller()
@Service()
export default class CustomerController extends ApiController {
constructor(private authService: AuthService) {
super();
}
// @Post("/api/v1/france-connect/customer/login/:email")
// protected async login(req: Request, response: Response) {
// try {
// const email = req.params["email"];
// if (!email) throw new Error("email is required");
// const payload = await this.authService.getCustomerJwtPayload(email);
// if (!payload) {
// this.httpNotFoundRequest(response);
// return;
// }
// const accessToken = this.authService.generateAccessToken(payload);
// const refreshToken = this.authService.generateRefreshToken(payload);
// //success
// this.httpSuccess(response, { accessToken, refreshToken });
// } catch (error) {
// this.httpInternalError(response);
// return;
// }
// }
@Post("/api/v1/france-connect/customer/refresh-token")
protected async refreshToken(req: Request, response: Response) {
try {
const authHeader = req.headers["authorization"];
const token = authHeader && authHeader.split(" ")[1];
if (!token) {
this.httpBadRequest(response);
return;
}
let accessToken;
this.authService.verifyRefreshToken(token, (err, customerPayload) => {
if (err) {
this.httpUnauthorized(response);
return;
}
const customer = customerPayload as JwtPayload;
delete customer.iat;
delete customer!.exp;
accessToken = this.authService.generateAccessToken({...customer} as ICustomerJwtPayload);
});
//success
this.httpSuccess(response, {accessToken});
} catch (error) {
this.httpInternalError(response);
return;
}
}
}

View File

@ -4,7 +4,7 @@ import ApiController from "@Common/system/controller-pattern/ApiController";
import { Service } from "typedi"; import { Service } from "typedi";
import Id360Service, { EnrollmentResponse } from "@Services/common/Id360Service/Id360Service"; import Id360Service, { EnrollmentResponse } from "@Services/common/Id360Service/Id360Service";
import CustomersService from "@Services/customer/CustomersService/CustomersService"; import CustomersService from "@Services/customer/CustomersService/CustomersService";
import AuthService from "@Services/common/AuthService/AuthService"; import AuthService, { ICustomerJwtPayload } from "@Services/common/AuthService/AuthService";
import { Customer } from "le-coffre-resources/dist/SuperAdmin"; import { Customer } from "le-coffre-resources/dist/SuperAdmin";
@Controller() @Controller()
@ -34,28 +34,34 @@ export default class CustomerController extends ApiController {
return; return;
} }
try { try {
await new Promise((resolve) => setTimeout(resolve, 3000)); // wait 3 seconds to be sure that the enrollment is finilazed
const res = await this.id360Service.getEnrollment(callbackToken); const res = await this.id360Service.getEnrollment(callbackToken);
const enrollment = await res.json() as EnrollmentResponse; const enrollment = (await res.json()) as EnrollmentResponse;
if(enrollment.status === "STARTED") {
this.loginCallback(req, response);
}
if (enrollment.status !== "OK") { if (enrollment.status !== "OK") {
this.httpUnauthorized(response, "Enrollment status is not OK"); this.httpUnauthorized(response, "Enrollment status is not OK");
return; return;
} }
const customerData = await this.id360Service.getReport(enrollment.id); const customerData = await this.id360Service.getReport(enrollment.id);
const customer = await this.customerService.get({ const customer = await this.customerService.get({
where: { where: {
contact: { contact: {
last_name: { contains: customerData.external_methods.france_connect.results.france_connect_out_userinfo[0].family_name, last_name: {
mode: 'insensitive' }, contains: customerData.external_methods.france_connect.results.france_connect_out_userinfo[0].family_name,
first_name: { contains: customerData.external_methods.france_connect.results.france_connect_out_userinfo[0].given_name.split(" ")[0], mode: "insensitive",
mode: 'insensitive'}, },
first_name: {
contains:
customerData.external_methods.france_connect.results.france_connect_out_userinfo[0].given_name.split(
" ",
)[0],
mode: "insensitive",
},
}, },
}, },
include: { include: {
contact: true, contact: true,
} },
}); });
// const contact = await this.customerService.getByEmail( // const contact = await this.customerService.getByEmail(
// customerData.external_methods.france_connect.results.france_connect_out_userinfo[0].email, // customerData.external_methods.france_connect.results.france_connect_out_userinfo[0].email,
@ -65,8 +71,8 @@ export default class CustomerController extends ApiController {
return; return;
} }
const customersHydrated = Customer.hydrateArray<Customer>(customer); const customersHydrated = Customer.hydrateArray<Customer>(customer);
const payload = await this.authService.getCustomerJwtPayload(customersHydrated[0]!); const payload = await this.authService.getCustomerJwtPayload(customersHydrated);
const accessToken = this.authService.generateAccessToken(payload); const accessToken = this.authService.generateAccessToken(payload);
const refreshToken = this.authService.generateRefreshToken(payload); const refreshToken = this.authService.generateRefreshToken(payload);
this.httpSuccess(response, { accessToken, refreshToken }); this.httpSuccess(response, { accessToken, refreshToken });
@ -88,4 +94,38 @@ export default class CustomerController extends ApiController {
return; return;
} }
} }
@Post("/api/v1/id360/customers/refresh-token")
protected async refreshToken(req: Request, response: Response) {
try {
const authHeader = req.headers["authorization"];
const token = authHeader && authHeader.split(" ")[1];
if (!token) {
this.httpBadRequest(response);
return;
}
let accessToken;
this.authService.verifyRefreshToken(token, (err, userPayload) => {
if (err) {
console.log(err);
this.httpUnauthorized(response);
return;
}
const user = userPayload as ICustomerJwtPayload;
delete user.iat;
delete user.exp;
accessToken = this.authService.generateAccessToken(user);
});
//success
this.httpSuccess(response, { accessToken });
} catch (error) {
console.log(error);
this.httpInternalError(response);
return;
}
}
} }

View File

@ -70,12 +70,15 @@ export default class UserController extends ApiController {
} }
const user = userPayload as IUserJwtPayload; const user = userPayload as IUserJwtPayload;
delete user.iat;
delete user.exp;
accessToken = this.authService.generateAccessToken(user); accessToken = this.authService.generateAccessToken(user);
}); });
//success //success
this.httpSuccess(response, { accessToken }); this.httpSuccess(response, { accessToken });
} catch (error) { } catch (error) {
console.log(error);
this.httpInternalError(response); this.httpInternalError(response);
return; return;
} }

View File

@ -27,11 +27,15 @@ export default class CustomersController extends ApiController {
let query: Prisma.CustomersFindManyArgs = {}; let query: Prisma.CustomersFindManyArgs = {};
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if(query.where?.uid) {
this.httpBadRequest(response, "You can't filter by uid");
return;
}
} }
const officeId: string = req.body.user.office_Id; const officeId: string = req.body.user.office_Id;
if(query.where?.office_folders) delete query.where.office_folders; if (query.where?.office_folders) delete query.where.office_folders;
const customerWhereInput: Prisma.CustomersWhereInput = { ...query.where, office_folders: { some: { office_uid: officeId } }}; const customerWhereInput: Prisma.CustomersWhereInput = { ...query.where, office_folders: { some: { office_uid: officeId } } };
query.where = customerWhereInput; query.where = customerWhereInput;
//call service to get prisma entity //call service to get prisma entity
@ -57,8 +61,28 @@ export default class CustomersController extends ApiController {
//init IUser resource with request body values //init IUser resource with request body values
const customerEntity = Customer.hydrate<Customer>(req.body); const customerEntity = Customer.hydrate<Customer>(req.body);
//validate user //validate user
await validateOrReject(customerEntity, { groups: ["createCustomer"], forbidUnknownValues: false }); try {
await validateOrReject(customerEntity, { groups: ["createCustomer"], forbidUnknownValues: false });
} catch (error) {
this.httpValidationError(response, error);
return;
}
const customers = await this.customersService.get({
where: {
contact: { email: customerEntity.contact?.email },
office_folders: {
some: {
office_uid: req.body.user.office_Id,
},
},
},
});
if (customers.length > 0) {
this.httpValidationError(response, [{ property: "email", constraints: { unique: "email déjà utilisé" } }]);
return;
}
//call service to get prisma entity //call service to get prisma entity
const customerEntityCreated = await this.customersService.create(customerEntity); const customerEntityCreated = await this.customersService.create(customerEntity);
//Hydrate ressource with prisma entity //Hydrate ressource with prisma entity
@ -93,22 +117,59 @@ export default class CustomersController extends ApiController {
return; return;
} }
req.body.contact.uid = userFound.contact_uid;
//init IUser resource with request body values //init IUser resource with request body values
const customerEntity = Customer.hydrate<Customer>(req.body); const customerEntity = Customer.hydrate<Customer>(req.body);
//validate user //validate user
await validateOrReject(customerEntity, { groups: ["updateCustomer"], forbidUnknownValues: false }); try {
await validateOrReject(customerEntity, { groups: ["updateCustomer"], forbidUnknownValues: false });
} catch (error) {
this.httpValidationError(response, error);
return;
}
if (customerEntity.contact?.email) {
const customers = await this.customersService.get({
where: {
contact: { email: customerEntity.contact?.email },
office_folders: {
some: {
office_uid: req.body.user.office_Id,
},
},
},
});
if (customers.length != 0) {
try {
customers.forEach((customer) => {
if (customer.uid != uid) {
throw new Error("email déjà utilisé");
}
});
} catch (error) {
this.httpValidationError(response, [{ property: "email", constraints: { unique: "email déjà utilisé" } }]);
return;
}
}
}
//call service to get prisma entity //call service to get prisma entity
const customerEntityUpdated = await this.customersService.update(uid, customerEntity); try {
const customerEntityUpdated = await this.customersService.update(uid, customerEntity);
//Hydrate ressource with prisma entity
const customer = Customer.hydrate<Customer>(customerEntityUpdated, {
strategy: "excludeAll",
});
//Hydrate ressource with prisma entity //success
const customer = Customer.hydrate<Customer>(customerEntityUpdated, { this.httpSuccess(response, customer);
strategy: "excludeAll", } catch (error) {
}); console.log(error);
this.httpValidationError(response, error);
//success return;
this.httpSuccess(response, customer); }
} catch (error) { } catch (error) {
this.httpInternalError(response, error); this.httpInternalError(response, error);
return; return;

View File

@ -28,6 +28,10 @@ export default class DeedTypesController extends ApiController {
let query: Prisma.DeedTypesFindManyArgs = {}; let query: Prisma.DeedTypesFindManyArgs = {};
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if(query.where?.uid) {
this.httpBadRequest(response, "You can't filter by uid");
return;
}
} }
const officeId: string = req.body.user.office_Id; const officeId: string = req.body.user.office_Id;
const officeWhereInput: Prisma.OfficesWhereInput = { uid: officeId } ; const officeWhereInput: Prisma.OfficesWhereInput = { uid: officeId } ;

View File

@ -28,11 +28,15 @@ export default class DeedsController extends ApiController {
let query: Prisma.DeedsFindManyArgs = {}; let query: Prisma.DeedsFindManyArgs = {};
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if(query.where?.uid) {
this.httpBadRequest(response, "You can't filter by uid");
return;
}
} }
const officeId: string = req.body.user.office_Id; const officeId: string = req.body.user.office_Id;
const officeWhereInput: Prisma.OfficesWhereInput = { uid: officeId } ; const officeWhereInput: Prisma.OfficesWhereInput = { uid: officeId } ;
if(!query.where) query.where = { deed_type : {office: officeWhereInput}}; if(query.where?.deed_type) delete query.where.deed_type;
query.where.deed_type!.office = officeWhereInput; query.where = {...query.where, deed_type : {office: officeWhereInput}};
//call service to get prisma entity //call service to get prisma entity
const deedEntities: Deeds[] = await this.deedsService.get(query); const deedEntities: Deeds[] = await this.deedsService.get(query);

View File

@ -4,7 +4,6 @@ import ApiController from "@Common/system/controller-pattern/ApiController";
import { Service } from "typedi"; import { Service } from "typedi";
import DocumentTypesService from "@Services/notary/DocumentTypesService/DocumentTypesService"; import DocumentTypesService from "@Services/notary/DocumentTypesService/DocumentTypesService";
import { DocumentTypes, Prisma } from "@prisma/client"; import { DocumentTypes, Prisma } from "@prisma/client";
import ObjectHydrate from "@Common/helpers/ObjectHydrate";
import { DocumentType } from "le-coffre-resources/dist/Notary"; import { DocumentType } from "le-coffre-resources/dist/Notary";
import { validateOrReject } from "class-validator"; import { validateOrReject } from "class-validator";
import authHandler from "@App/middlewares/AuthHandler"; import authHandler from "@App/middlewares/AuthHandler";
@ -28,6 +27,10 @@ export default class DocumentTypesController extends ApiController {
let query: Prisma.DocumentTypesFindManyArgs = {}; let query: Prisma.DocumentTypesFindManyArgs = {};
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if(query.where?.uid) {
this.httpBadRequest(response, "You can't filter by uid");
return;
}
} }
const officeId: string = req.body.user.office_Id; const officeId: string = req.body.user.office_Id;
const officeWhereInput: Prisma.OfficesWhereInput = { uid: officeId } ; const officeWhereInput: Prisma.OfficesWhereInput = { uid: officeId } ;
@ -133,11 +136,15 @@ export default class DocumentTypesController extends ApiController {
const documentTypeEntity = await this.documentTypesService.getByUid(uid, query); const documentTypeEntity = await this.documentTypesService.getByUid(uid, query);
//Hydrate ressource with prisma entity if (!documentTypeEntity) {
const user = ObjectHydrate.hydrate<DocumentType>(new DocumentType(), documentTypeEntity!, { strategy: "excludeAll" }); this.httpNotFoundRequest(response, "document type not found");
return;
}
const documentType = DocumentType.hydrate<DocumentType>(documentTypeEntity, { strategy: "excludeAll" });
//success //success
this.httpSuccess(response, user); this.httpSuccess(response, documentType);
} catch (error) { } catch (error) {
this.httpInternalError(response, error); this.httpInternalError(response, error);
return; return;

View File

@ -35,6 +35,10 @@ export default class DocumentsController extends ApiController {
let query: Prisma.DocumentsFindManyArgs = {}; let query: Prisma.DocumentsFindManyArgs = {};
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if(query.where?.uid) {
this.httpBadRequest(response, "You can't filter by uid");
return;
}
} }
const officeId: string = req.body.user.office_Id; const officeId: string = req.body.user.office_Id;
const officeWhereInput: Prisma.OfficesWhereInput = { uid: officeId }; const officeWhereInput: Prisma.OfficesWhereInput = { uid: officeId };
@ -86,7 +90,7 @@ export default class DocumentsController extends ApiController {
const documentEntityCreated = await this.documentsService.create(documentEntity); const documentEntityCreated = await this.documentsService.create(documentEntity);
//create email for asked document //create email for asked document
this.emailBuilder.sendDocumentEmails(documentEntityCreated); await this.emailBuilder.sendDocumentEmails(documentEntityCreated);
//Hydrate ressource with prisma entity //Hydrate ressource with prisma entity
const document = Document.hydrate<Document>(documentEntityCreated, { const document = Document.hydrate<Document>(documentEntityCreated, {
@ -120,6 +124,11 @@ export default class DocumentsController extends ApiController {
return; return;
} }
if(documentFound.document_status === EDocumentStatus.REFUSED || documentFound.document_status === EDocumentStatus.VALIDATED) {
this.httpForbidden(response, "You are not allowed to update a VALIDATED or REFUSED document");
return;
}
//init Document resource with request body values //init Document resource with request body values
const documentEntity = Document.hydrate<Document>(req.body); const documentEntity = Document.hydrate<Document>(req.body);
@ -177,9 +186,10 @@ export default class DocumentsController extends ApiController {
//call service to get prisma entity //call service to get prisma entity
const documentEntityUpdated: Documents = await this.documentsService.refuse(uid, documentEntity, req.body.refused_reason); const documentEntityUpdated: Documents = await this.documentsService.refuse(uid, documentEntity, req.body.refused_reason);
//create email for asked document //create email for asked document
// this.emailBuilder.sendDocumentEmails(documentEntityUpdated); await this.emailBuilder.sendDocumentEmails(documentEntityUpdated);
// this.notificationBuilder.sendDocumentAnchoredNotificatiom(documentEntityUpdated);
//Hydrate ressource with prisma entity //Hydrate ressource with prisma entity
const document = Document.hydrate<Document>(documentEntityUpdated, { strategy: "excludeAll" }); const document = Document.hydrate<Document>(documentEntityUpdated, { strategy: "excludeAll" });

View File

@ -1,5 +1,5 @@
import { Response, Request } from "express"; import { Response, Request } from "express";
import { Controller, Delete, Get } from "@ControllerPattern/index"; import { Controller, Get } from "@ControllerPattern/index";
import ApiController from "@Common/system/controller-pattern/ApiController"; import ApiController from "@Common/system/controller-pattern/ApiController";
import { Service } from "typedi"; import { Service } from "typedi";
import FilesService from "@Services/common/FilesService/FilesService"; import FilesService from "@Services/common/FilesService/FilesService";
@ -27,6 +27,10 @@ export default class FilesController extends ApiController {
let query: Prisma.FilesFindManyArgs = {}; let query: Prisma.FilesFindManyArgs = {};
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if(query.where?.uid) {
this.httpBadRequest(response, "You can't filter by uid");
return;
}
} }
const officeId: string = req.body.user.office_Id; const officeId: string = req.body.user.office_Id;
const officeWhereInput: Prisma.OfficesWhereInput = { uid: officeId } ; const officeWhereInput: Prisma.OfficesWhereInput = { uid: officeId } ;
@ -74,44 +78,6 @@ export default class FilesController extends ApiController {
} }
} }
/**
* @description Delete a specific File
*/
@Delete("/api/v1/notary/files/:uid", [authHandler, ruleHandler, fileHandler])
protected async delete(req: Request, response: Response) {
try {
const uid = req.params["uid"];
if (!uid) {
this.httpBadRequest(response, "No uid provided");
return;
}
const fileFound = await this.filesService.getByUid(uid);
if (!fileFound) {
this.httpNotFoundRequest(response, "file not found");
return;
}
//call service to get prisma entity
const fileEntity = await this.filesService.deleteKeyAndArchive(uid);
if (!fileEntity) {
this.httpNotFoundRequest(response, "file not found");
return;
}
//Hydrate ressource with prisma entity
const file = File.hydrate<File>(fileEntity, { strategy: "excludeAll" });
//success
this.httpSuccess(response, file);
} catch (error) {
this.httpInternalError(response, error);
return;
}
}
/** /**
* @description Get a specific File by uid * @description Get a specific File by uid
*/ */

View File

@ -3,9 +3,10 @@ import { Controller, Get, Post } from "@ControllerPattern/index";
import ApiController from "@Common/system/controller-pattern/ApiController"; import ApiController from "@Common/system/controller-pattern/ApiController";
import { Service } from "typedi"; import { Service } from "typedi";
import { Document, OfficeFolder } from "le-coffre-resources/dist/Notary"; import { Document, OfficeFolder } from "le-coffre-resources/dist/Notary";
import { getFolderHashes } from "@Common/optics/notary"; import { getFolderHashes, getFolderFilesUid } from "@Common/optics/notary";
import OfficeFoldersService from "@Services/notary/OfficeFoldersService/OfficeFoldersService"; import OfficeFoldersService from "@Services/notary/OfficeFoldersService/OfficeFoldersService";
import OfficeFolderAnchorsRepository from "@Repositories/OfficeFolderAnchorsRepository"; import OfficeFolderAnchorsRepository from "@Repositories/OfficeFolderAnchorsRepository";
import FilesService from "@Services/common/FilesService/FilesService";
import SecureService from "@Services/common/SecureService/SecureService"; import SecureService from "@Services/common/SecureService/SecureService";
import authHandler from "@App/middlewares/AuthHandler"; import authHandler from "@App/middlewares/AuthHandler";
import ruleHandler from "@App/middlewares/RulesHandler"; import ruleHandler from "@App/middlewares/RulesHandler";
@ -14,6 +15,7 @@ import OfficeFolderAnchor from "le-coffre-resources/dist/Notary/OfficeFolderAnch
import NotificationBuilder from "@Common/notifications/NotificationBuilder"; import NotificationBuilder from "@Common/notifications/NotificationBuilder";
import { Prisma } from "@prisma/client"; import { Prisma } from "@prisma/client";
import OfficeFolderAnchorsService from "@Services/notary/OfficeFolderAnchorsService/OfficeFolderAnchorsService"; import OfficeFolderAnchorsService from "@Services/notary/OfficeFolderAnchorsService/OfficeFolderAnchorsService";
import Zip from "adm-zip";
const hydrateOfficeFolderAnchor = (data: any): OfficeFolderAnchor => const hydrateOfficeFolderAnchor = (data: any): OfficeFolderAnchor =>
OfficeFolderAnchor.hydrate<OfficeFolderAnchor>( OfficeFolderAnchor.hydrate<OfficeFolderAnchor>(
@ -41,13 +43,14 @@ export default class OfficeFoldersController extends ApiController {
private officeFolderAnchorsRepository: OfficeFolderAnchorsRepository, private officeFolderAnchorsRepository: OfficeFolderAnchorsRepository,
private officeFolderAnchorsService: OfficeFolderAnchorsService, private officeFolderAnchorsService: OfficeFolderAnchorsService,
private officeFoldersService: OfficeFoldersService, private officeFoldersService: OfficeFoldersService,
private filesService: FilesService,
private notificationBuilder: NotificationBuilder, private notificationBuilder: NotificationBuilder,
) { ) {
super(); super();
} }
/** /**
* @description Download a folder anchoring proof document * @description Download a folder anchoring proof document along with all accessible files
*/ */
@Get("/api/v1/notary/anchors/download/:uid", [authHandler, ruleHandler, folderHandler]) @Get("/api/v1/notary/anchors/download/:uid", [authHandler, ruleHandler, folderHandler])
protected async download(req: Request, response: Response) { protected async download(req: Request, response: Response) {
@ -76,6 +79,7 @@ export default class OfficeFoldersController extends ApiController {
const officeFolder = OfficeFolder.hydrate<OfficeFolder>(officeFolderFound, { strategy: "excludeAll" }); const officeFolder = OfficeFolder.hydrate<OfficeFolder>(officeFolderFound, { strategy: "excludeAll" });
const folderHashes = getFolderHashes(officeFolder); const folderHashes = getFolderHashes(officeFolder);
const folderFilesUid = getFolderFilesUid(officeFolder);
if (folderHashes.length === 0) { if (folderHashes.length === 0) {
this.httpNotFoundRequest(response, "No file hash to anchor"); this.httpNotFoundRequest(response, "No file hash to anchor");
@ -83,10 +87,25 @@ export default class OfficeFoldersController extends ApiController {
} }
const sortedHashes = [...folderHashes].sort(); const sortedHashes = [...folderHashes].sort();
const buffer = await this.secureService.download(sortedHashes); const anchoringProof = await this.secureService.download(sortedHashes);
response.setHeader("Content-Type", "application/pdf"); const addFileToZip = (zip: Zip) => (uid: string): Promise<void> =>
this.httpSuccess(response, buffer); (async () => {
const data = await this.filesService.download(uid);
if (!data?.buffer) return;
zip.addFile(`Documents du client/${uid}-${data.file.file_name}`, data.buffer);
})()
const uids: string[] = folderFilesUid.filter((uid): uid is string => uid !== undefined);
const zip = new Zip();
zip.addFile("Certificat de dépôt du dossier.pdf", anchoringProof);
await Promise.allSettled(
uids.map(addFileToZip(zip))
)
response.setHeader("Content-Type", "application/zip");
this.httpSuccess(response, zip.toBuffer());
} catch (error) { } catch (error) {
this.httpInternalError(response, error); this.httpInternalError(response, error);
return; return;
@ -256,6 +275,10 @@ export default class OfficeFoldersController extends ApiController {
let query: Prisma.OfficeFolderAnchorsFindManyArgs = {}; let query: Prisma.OfficeFolderAnchorsFindManyArgs = {};
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if(query.where?.uid) {
this.httpBadRequest(response, "You can't filter by uid");
return;
}
} }
query.where = { query.where = {

View File

@ -27,6 +27,10 @@ export default class OfficeFoldersController extends ApiController {
let query: Prisma.OfficeFoldersFindManyArgs = {}; let query: Prisma.OfficeFoldersFindManyArgs = {};
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if(query.where?.uid) {
this.httpBadRequest(response, "You can't filter by uid");
return;
}
} }
if (req.query["search"] && typeof req.query["search"] === "string") { if (req.query["search"] && typeof req.query["search"] === "string") {
@ -86,13 +90,18 @@ export default class OfficeFoldersController extends ApiController {
await officeFolderRessource.validateOrReject?.({ groups: ["createFolder"], forbidUnknownValues: false }); await officeFolderRessource.validateOrReject?.({ groups: ["createFolder"], forbidUnknownValues: false });
//call service to get prisma entity //call service to get prisma entity
const officeFolderEntity = await this.officeFoldersService.create(officeFolderRessource); try {
//Hydrate ressource with prisma entity const officeFolderEntity = await this.officeFoldersService.create(officeFolderRessource);
const officeFolders = OfficeFolder.hydrate<OfficeFolder>(officeFolderEntity, { //Hydrate ressource with prisma entity
strategy: "excludeAll", const officeFolders = OfficeFolder.hydrate<OfficeFolder>(officeFolderEntity, {
}); strategy: "excludeAll",
//success });
this.httpCreated(response, officeFolders); //success
this.httpCreated(response, officeFolders);
} catch (error) {
this.httpValidationError(response, error);
return;
}
} catch (error) { } catch (error) {
this.httpInternalError(response, error); this.httpInternalError(response, error);
return; return;
@ -111,9 +120,7 @@ export default class OfficeFoldersController extends ApiController {
return; return;
} }
const officeFolderFound = await this.officeFoldersService.getByUid(uid, { const officeFolderFound = await this.officeFoldersService.getByUid(uid);
folder_anchor: true,
});
if (!officeFolderFound) { if (!officeFolderFound) {
this.httpNotFoundRequest(response, "office folder not found"); this.httpNotFoundRequest(response, "office folder not found");
@ -121,25 +128,26 @@ export default class OfficeFoldersController extends ApiController {
} }
//init OfficeFolder resource with request body values //init OfficeFolder resource with request body values
const officefolderToUpdate = OfficeFolder.hydrate<OfficeFolder>(req.body); const officeFolderEntity = OfficeFolder.hydrate<OfficeFolder>(req.body);
const officeFolderFoundEntity = OfficeFolder.hydrate<OfficeFolder>(officeFolderFound);
//validate folder
await validateOrReject(officefolderToUpdate, { groups: ["updateFolder"], forbidUnknownValues: false });
if (officeFolderFoundEntity.folder_anchor?.status === "VERIFIED_ON_CHAIN") { //validate folder
this.httpBadRequest(response, "Cannot update a verified folder"); await validateOrReject(officeFolderEntity, { groups: ["updateFolder"], forbidUnknownValues: false });
//call service to get prisma entity
try {
const officeFolderEntityUpdated = await this.officeFoldersService.update(uid, officeFolderEntity);
//Hydrate ressource with prisma entity
const officeFolders = OfficeFolder.hydrate<OfficeFolder>(officeFolderEntityUpdated, {
strategy: "excludeAll",
});
//success
this.httpSuccess(response, officeFolders);
} catch (error) {
this.httpValidationError(response, error);
return; return;
} }
//call service to get prisma entity
const officeFolderEntityUpdated = await this.officeFoldersService.update(uid, officefolderToUpdate);
//Hydrate ressource with prisma entity
const officeFolders = OfficeFolder.hydrate<OfficeFolder>(officeFolderEntityUpdated, {
strategy: "excludeAll",
});
//success
this.httpSuccess(response, officeFolders);
} catch (error) { } catch (error) {
this.httpInternalError(response, error); this.httpInternalError(response, error);
return; return;
@ -182,7 +190,7 @@ export default class OfficeFoldersController extends ApiController {
} }
//call service to get prisma entity //call service to get prisma entity
const officeFolderEntityUpdated = await this.officeFoldersService.update(uid, officefolderToUpdate); const officeFolderEntityUpdated = await this.officeFoldersService.updateStatus(uid, officefolderToUpdate);
//Hydrate ressource with prisma entity //Hydrate ressource with prisma entity
const officeFolders = OfficeFolder.hydrate<OfficeFolder>(officeFolderEntityUpdated, { const officeFolders = OfficeFolder.hydrate<OfficeFolder>(officeFolderEntityUpdated, {
@ -228,7 +236,7 @@ export default class OfficeFoldersController extends ApiController {
await validateOrReject(officefolderToUpdate, { groups: ["updateFolder"], forbidUnknownValues: false }); await validateOrReject(officefolderToUpdate, { groups: ["updateFolder"], forbidUnknownValues: false });
//call service to get prisma entity //call service to get prisma entity
const officeFolderEntityUpdated = await this.officeFoldersService.update(uid, officefolderToUpdate); const officeFolderEntityUpdated = await this.officeFoldersService.updateStatus(uid, officefolderToUpdate);
//Hydrate ressource with prisma entity //Hydrate ressource with prisma entity
const officeFolders = OfficeFolder.hydrate<OfficeFolder>(officeFolderEntityUpdated, { const officeFolders = OfficeFolder.hydrate<OfficeFolder>(officeFolderEntityUpdated, {

View File

@ -26,6 +26,10 @@ export default class OfficeRolesController extends ApiController {
let query: Prisma.OfficeRolesFindManyArgs = {}; let query: Prisma.OfficeRolesFindManyArgs = {};
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if(query.where?.uid) {
this.httpBadRequest(response, "You can't filter by uid");
return;
}
} }
const officeId: string = req.body.user.office_Id; const officeId: string = req.body.user.office_Id;
const officeWhereInput: Prisma.OfficesWhereInput = { uid: officeId } ; const officeWhereInput: Prisma.OfficesWhereInput = { uid: officeId } ;

View File

@ -3,7 +3,7 @@ import { Controller, Get } from "@ControllerPattern/index";
import ApiController from "@Common/system/controller-pattern/ApiController"; import ApiController from "@Common/system/controller-pattern/ApiController";
import OfficesService from "@Services/notary/OfficesService/OfficesService"; import OfficesService from "@Services/notary/OfficesService/OfficesService";
import { Service } from "typedi"; import { Service } from "typedi";
import { Offices } from "@prisma/client"; import { Offices, Prisma } from "@prisma/client";
import { Office as OfficeResource } from "le-coffre-resources/dist/Notary"; import { Office as OfficeResource } from "le-coffre-resources/dist/Notary";
import ruleHandler from "@App/middlewares/RulesHandler"; import ruleHandler from "@App/middlewares/RulesHandler";
import authHandler from "@App/middlewares/AuthHandler"; import authHandler from "@App/middlewares/AuthHandler";
@ -21,9 +21,13 @@ export default class OfficesController extends ApiController {
protected async get(req: Request, response: Response) { protected async get(req: Request, response: Response) {
try { try {
//get query //get query
let query; let query: Prisma.OfficesFindManyArgs = {};
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if (query.where?.uid) {
this.httpBadRequest(response, "You can't filter by uid");
return;
}
} }
//call service to get prisma entity //call service to get prisma entity
const officesEntities: Offices[] = await this.officesService.get(query); const officesEntities: Offices[] = await this.officesService.get(query);

View File

@ -6,6 +6,7 @@ import { Service } from "typedi";
import { Role } from "le-coffre-resources/dist/Notary"; import { Role } from "le-coffre-resources/dist/Notary";
import authHandler from "@App/middlewares/AuthHandler"; import authHandler from "@App/middlewares/AuthHandler";
import ruleHandler from "@App/middlewares/RulesHandler"; import ruleHandler from "@App/middlewares/RulesHandler";
import { Prisma } from "@prisma/client";
@Controller() @Controller()
@Service() @Service()
@ -21,9 +22,13 @@ export default class RolesController extends ApiController {
protected async get(req: Request, response: Response) { protected async get(req: Request, response: Response) {
try { try {
//get query //get query
let query; let query: Prisma.RolesFindManyArgs = {};
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if (query.where?.uid) {
this.httpBadRequest(response, "You can't filter by uid");
return;
}
} }
//call service to get prisma entity //call service to get prisma entity

View File

@ -6,6 +6,7 @@ import { Service } from "typedi";
import { Rule } from "le-coffre-resources/dist/Notary"; import { Rule } from "le-coffre-resources/dist/Notary";
import authHandler from "@App/middlewares/AuthHandler"; import authHandler from "@App/middlewares/AuthHandler";
import ruleHandler from "@App/middlewares/RulesHandler"; import ruleHandler from "@App/middlewares/RulesHandler";
import { Prisma } from "@prisma/client";
@Controller() @Controller()
@Service() @Service()
@ -21,9 +22,13 @@ export default class RulesController extends ApiController {
protected async get(req: Request, response: Response) { protected async get(req: Request, response: Response) {
try { try {
//get query //get query
let query; let query: Prisma.RulesFindManyArgs = {};
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if (query.where?.uid) {
this.httpBadRequest(response, "You can't filter by uid");
return;
}
} }
query.where = { query.where = {

View File

@ -6,6 +6,7 @@ import UserNotification from "le-coffre-resources/dist/Notary/UserNotification";
import UserNotificationService from "@Services/common/UserNotificationService/UserNotificationService"; import UserNotificationService from "@Services/common/UserNotificationService/UserNotificationService";
import authHandler from "@App/middlewares/AuthHandler"; import authHandler from "@App/middlewares/AuthHandler";
import { Prisma } from "@prisma/client"; import { Prisma } from "@prisma/client";
import roleHandler from "@App/middlewares/RolesHandler";
@Controller() @Controller()
@Service() @Service()
@ -17,16 +18,18 @@ export default class UserNotificationController extends ApiController {
/** /**
* @description Get all customers * @description Get all customers
*/ */
@Get("/api/v1/notary/notifications", [authHandler]) @Get("/api/v1/notary/notifications", [authHandler, roleHandler])
protected async get(req: Request, response: Response) { protected async get(req: Request, response: Response) {
try { try {
//get query //get query
let query: any = {}; let query: Prisma.UserNotificationsFindManyArgs = {};
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if (query.where?.uid) {
this.httpBadRequest(response, "You can't filter by uid");
return;
}
} }
const userId: string = req.body.user.userId; const userId: string = req.body.user.userId;
if(query.where?.user_uid) delete query.where.user_uid; if(query.where?.user_uid) delete query.where.user_uid;
if(query.where?.user?.uid) delete query.where.user.uid; if(query.where?.user?.uid) delete query.where.user.uid;
@ -51,7 +54,7 @@ export default class UserNotificationController extends ApiController {
/** /**
* @description Modify a specific customer by uid * @description Modify a specific customer by uid
*/ */
@Put("/api/v1/notary/notifications/:uid", [authHandler]) @Put("/api/v1/notary/notifications/:uid", [authHandler, roleHandler])
protected async put(req: Request, response: Response) { protected async put(req: Request, response: Response) {
try { try {
const uid = req.params["uid"]; const uid = req.params["uid"];
@ -94,7 +97,7 @@ export default class UserNotificationController extends ApiController {
/** /**
* @description Get a specific customer by uid * @description Get a specific customer by uid
*/ */
@Get("/api/v1/notary/notifications/:uid", [authHandler]) @Get("/api/v1/notary/notifications/:uid", [authHandler, roleHandler])
protected async getOneByUid(req: Request, response: Response) { protected async getOneByUid(req: Request, response: Response) {
try { try {
const uid = req.params["uid"]; const uid = req.params["uid"];

View File

@ -26,6 +26,10 @@ export default class UsersController extends ApiController {
let query: Prisma.UsersFindManyArgs = {}; let query: Prisma.UsersFindManyArgs = {};
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if(query.where?.uid) {
this.httpBadRequest(response, "You can't filter by uid");
return;
}
} }
const officeId: string = req.body.user.office_Id; const officeId: string = req.body.user.office_Id;
const officeWhereInput: Prisma.OfficesWhereInput = { uid: officeId } ; const officeWhereInput: Prisma.OfficesWhereInput = { uid: officeId } ;

View File

@ -25,17 +25,21 @@ export default class CustomersController extends ApiController {
protected async get(req: Request, response: Response) { protected async get(req: Request, response: Response) {
try { try {
//get query //get query
let query; let query: Prisma.CustomersFindManyArgs = {};
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if (query.where?.uid) {
this.httpBadRequest(response, "You can't filter by uid");
return;
}
} }
const officeId: string = req.body.user.office_Id; const officeId: string = req.body.user.office_Id;
if(query.where?.office_folders?.some?.office_uid) delete query.where.office_folders.some.office_uid; if (query.where?.office_folders?.some?.office_uid) delete query.where.office_folders.some.office_uid;
if(query.where?.office_folders?.some?.office?.uid) delete query.where?.office_folders?.some?.office?.uid; if (query.where?.office_folders?.some?.office?.uid) delete query.where?.office_folders?.some?.office?.uid;
const customerWhereInput: Prisma.CustomersWhereInput = { ...query.where, office_folders: { some: { office_uid: officeId } }}; const customerWhereInput: Prisma.CustomersWhereInput = { ...query.where, office_folders: { some: { office_uid: officeId } } };
query.where = customerWhereInput; query.where = customerWhereInput;
//call service to get prisma entity //call service to get prisma entity
const customersEntities = await this.customersService.get(query); const customersEntities = await this.customersService.get(query);
@ -53,14 +57,34 @@ export default class CustomersController extends ApiController {
/** /**
* @description Create a new customer * @description Create a new customer
*/ */
@Post("/api/v1/super-admin/customers", [authHandler, roleHandler, ruleHandler]) @Post("/api/v1/notary/customers", [authHandler, ruleHandler])
protected async post(req: Request, response: Response) { protected async post(req: Request, response: Response) {
try { try {
//init IUser resource with request body values //init IUser resource with request body values
const customerEntity = Customer.hydrate<Customer>(req.body); const customerEntity = Customer.hydrate<Customer>(req.body);
//validate user //validate user
await validateOrReject(customerEntity, { groups: ["createCustomer"], forbidUnknownValues: false }); try {
await validateOrReject(customerEntity, { groups: ["createCustomer"], forbidUnknownValues: false });
} catch (error) {
this.httpValidationError(response, error);
return;
}
const customers = await this.customersService.get({
where: {
contact: { email: customerEntity.contact?.email },
office_folders: {
some: {
office_uid: req.body.user.office_Id,
},
},
},
});
if (customers.length > 0) {
this.httpValidationError(response, [{ property: "email", constraints: { unique: "email déjà utilisé" } }]);
return;
}
//call service to get prisma entity //call service to get prisma entity
const customerEntityCreated = await this.customersService.create(customerEntity); const customerEntityCreated = await this.customersService.create(customerEntity);
//Hydrate ressource with prisma entity //Hydrate ressource with prisma entity
@ -79,7 +103,7 @@ export default class CustomersController extends ApiController {
/** /**
* @description Modify a specific customer by uid * @description Modify a specific customer by uid
*/ */
@Put("/api/v1/super-admin/customers/:uid", [authHandler, roleHandler, ruleHandler, customerHandler]) @Put("/api/v1/notary/customers/:uid", [authHandler, ruleHandler, customerHandler])
protected async put(req: Request, response: Response) { protected async put(req: Request, response: Response) {
try { try {
const uid = req.params["uid"]; const uid = req.params["uid"];
@ -95,22 +119,59 @@ export default class CustomersController extends ApiController {
return; return;
} }
req.body.contact.uid = userFound.contact_uid;
//init IUser resource with request body values //init IUser resource with request body values
const customerEntity = Customer.hydrate<Customer>(req.body); const customerEntity = Customer.hydrate<Customer>(req.body);
//validate user //validate user
await validateOrReject(customerEntity, { groups: ["updateCustomer"], forbidUnknownValues: false }); try {
await validateOrReject(customerEntity, { groups: ["updateCustomer"], forbidUnknownValues: false });
} catch (error) {
this.httpValidationError(response, error);
return;
}
if (customerEntity.contact?.email) {
const customers = await this.customersService.get({
where: {
contact: { email: customerEntity.contact?.email },
office_folders: {
some: {
office_uid: req.body.user.office_Id,
},
},
},
});
if (customers.length != 0) {
try {
customers.forEach((customer) => {
if (customer.uid != uid) {
throw new Error("email déjà utilisé");
}
});
} catch (error) {
this.httpValidationError(response, [{ property: "email", constraints: { unique: "email déjà utilisé" } }]);
return;
}
}
}
//call service to get prisma entity //call service to get prisma entity
const customerEntityUpdated = await this.customersService.update(uid, customerEntity); try {
const customerEntityUpdated = await this.customersService.update(uid, customerEntity);
//Hydrate ressource with prisma entity
const customer = Customer.hydrate<Customer>(customerEntityUpdated, {
strategy: "excludeAll",
});
//Hydrate ressource with prisma entity //success
const customer = Customer.hydrate<Customer>(customerEntityUpdated, { this.httpSuccess(response, customer);
strategy: "excludeAll", } catch (error) {
}); console.log(error);
this.httpValidationError(response, error);
//success return;
this.httpSuccess(response, customer); }
} catch (error) { } catch (error) {
this.httpInternalError(response, error); this.httpInternalError(response, error);
return; return;
@ -133,7 +194,7 @@ export default class CustomersController extends ApiController {
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
} }
const customerEntity = await this.customersService.getByUid(uid, query); const customerEntity = await this.customersService.getByUid(uid, query);
if (!customerEntity) { if (!customerEntity) {

View File

@ -29,6 +29,10 @@ export default class DeedTypesController extends ApiController {
let query: Prisma.DeedTypesFindManyArgs = {}; let query: Prisma.DeedTypesFindManyArgs = {};
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if(query.where?.uid) {
this.httpBadRequest(response, "You can't filter by uid");
return;
}
} }
if (req.query["search"] && typeof req.query["search"] === "string") { if (req.query["search"] && typeof req.query["search"] === "string") {

View File

@ -29,6 +29,10 @@ export default class DeedsController extends ApiController {
let query: Prisma.DeedsFindManyArgs = {}; let query: Prisma.DeedsFindManyArgs = {};
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if(query.where?.uid) {
this.httpBadRequest(response, "You can't filter by uid");
return;
}
} }
const officeId: string = req.body.user.office_Id; const officeId: string = req.body.user.office_Id;
const officeWhereInput: Prisma.OfficesWhereInput = { uid: officeId } ; const officeWhereInput: Prisma.OfficesWhereInput = { uid: officeId } ;

View File

@ -29,6 +29,10 @@ export default class DocumentTypesController extends ApiController {
let query: Prisma.DocumentTypesFindManyArgs = {}; let query: Prisma.DocumentTypesFindManyArgs = {};
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if(query.where?.uid) {
this.httpBadRequest(response, "You can't filter by uid");
return;
}
} }
const officeId: string = req.body.user.office_Id; const officeId: string = req.body.user.office_Id;
const officeWhereInput: Prisma.OfficesWhereInput = { uid: officeId } ; const officeWhereInput: Prisma.OfficesWhereInput = { uid: officeId } ;

View File

@ -2,6 +2,7 @@ import authHandler from "@App/middlewares/AuthHandler";
import documentHandler from "@App/middlewares/OfficeMembershipHandlers/DocumentHandler"; import documentHandler from "@App/middlewares/OfficeMembershipHandlers/DocumentHandler";
import roleHandler from "@App/middlewares/RolesHandler"; import roleHandler from "@App/middlewares/RolesHandler";
import ruleHandler from "@App/middlewares/RulesHandler"; import ruleHandler from "@App/middlewares/RulesHandler";
import EmailBuilder from "@Common/emails/EmailBuilder";
import ApiController from "@Common/system/controller-pattern/ApiController"; import ApiController from "@Common/system/controller-pattern/ApiController";
import { Controller, Delete, Get, Post, Put } from "@ControllerPattern/index"; import { Controller, Delete, Get, Post, Put } from "@ControllerPattern/index";
import { Documents, EDocumentStatus, Prisma } from "@prisma/client"; import { Documents, EDocumentStatus, Prisma } from "@prisma/client";
@ -14,7 +15,7 @@ import { Service } from "typedi";
@Controller() @Controller()
@Service() @Service()
export default class DocumentsController extends ApiController { export default class DocumentsController extends ApiController {
constructor(private documentsService: DocumentsService) { constructor(private documentsService: DocumentsService, private emailBuilder: EmailBuilder) {
super(); super();
} }
@ -29,6 +30,10 @@ export default class DocumentsController extends ApiController {
let query: Prisma.DocumentsFindManyArgs = {}; let query: Prisma.DocumentsFindManyArgs = {};
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if(query.where?.uid) {
this.httpBadRequest(response, "You can't filter by uid");
return;
}
} }
const officeId: string = req.body.user.office_Id; const officeId: string = req.body.user.office_Id;
@ -36,8 +41,6 @@ export default class DocumentsController extends ApiController {
if (!query.where) query.where = { document_type: { office: officeWhereInput } }; if (!query.where) query.where = { document_type: { office: officeWhereInput } };
// query.where.document_type!.office = officeWhereInput;
//call service to get prisma entity //call service to get prisma entity
const documentEntities = await this.documentsService.get(query); const documentEntities = await this.documentsService.get(query);
@ -74,6 +77,9 @@ export default class DocumentsController extends ApiController {
strategy: "excludeAll", strategy: "excludeAll",
}); });
//create email for asked document
await this.emailBuilder.sendDocumentEmails(documentEntityCreated);
//success //success
this.httpCreated(response, document); this.httpCreated(response, document);
} catch (error) { } catch (error) {
@ -124,7 +130,7 @@ export default class DocumentsController extends ApiController {
/** /**
* @description Update a specific document * @description Update a specific document
*/ */
@Put("/api/v1/notary/documents/:uid/refuse", [authHandler, ruleHandler, documentHandler]) @Put("/api/v1/super-admin/documents/:uid/refuse", [authHandler, roleHandler, ruleHandler, documentHandler])
protected async refuseDocument(req: Request, response: Response) { protected async refuseDocument(req: Request, response: Response) {
try { try {
const uid = req.params["uid"]; const uid = req.params["uid"];
@ -155,8 +161,7 @@ export default class DocumentsController extends ApiController {
const documentEntityUpdated: Documents = await this.documentsService.refuse(uid, documentEntity, req.body.refused_reason); const documentEntityUpdated: Documents = await this.documentsService.refuse(uid, documentEntity, req.body.refused_reason);
//create email for asked document //create email for asked document
// this.emailBuilder.sendDocumentEmails(documentEntityUpdated); await this.emailBuilder.sendDocumentEmails(documentEntityUpdated);
// this.notificationBuilder.sendDocumentAnchoredNotificatiom(documentEntityUpdated);
//Hydrate ressource with prisma entity //Hydrate ressource with prisma entity
const document = Document.hydrate<Document>(documentEntityUpdated, { strategy: "excludeAll" }); const document = Document.hydrate<Document>(documentEntityUpdated, { strategy: "excludeAll" });

View File

@ -1,5 +1,5 @@
import { Response, Request } from "express"; import { Response, Request } from "express";
import { Controller, Delete, Get } from "@ControllerPattern/index"; import { Controller, Get } from "@ControllerPattern/index";
import ApiController from "@Common/system/controller-pattern/ApiController"; import ApiController from "@Common/system/controller-pattern/ApiController";
import { Service } from "typedi"; import { Service } from "typedi";
import FilesService from "@Services/common/FilesService/FilesService"; import FilesService from "@Services/common/FilesService/FilesService";
@ -28,6 +28,10 @@ export default class FilesController extends ApiController {
let query: Prisma.FilesFindManyArgs = {}; let query: Prisma.FilesFindManyArgs = {};
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if(query.where?.uid) {
this.httpBadRequest(response, "You can't filter by uid");
return;
}
} }
const officeId: string = req.body.user.office_Id; const officeId: string = req.body.user.office_Id;
const officeWhereInput: Prisma.OfficesWhereInput = { uid: officeId } ; const officeWhereInput: Prisma.OfficesWhereInput = { uid: officeId } ;
@ -76,44 +80,6 @@ export default class FilesController extends ApiController {
} }
} }
/**
* @description Delete a specific File
*/
@Delete("/api/v1/super-admin/files/:uid", [authHandler, roleHandler, ruleHandler, fileHandler])
protected async delete(req: Request, response: Response) {
try {
const uid = req.params["uid"];
if (!uid) {
this.httpBadRequest(response, "No uid provided");
return;
}
const fileFound = await this.filesService.getByUid(uid);
if (!fileFound) {
this.httpNotFoundRequest(response, "file not found");
return;
}
//call service to get prisma entity
const fileEntity = await this.filesService.deleteKeyAndArchive(uid);
if (!fileEntity) {
this.httpNotFoundRequest(response, "file not found");
return;
}
//Hydrate ressource with prisma entity
const file = File.hydrate<File>(fileEntity, { strategy: "excludeAll" });
//success
this.httpSuccess(response, file);
} catch (error) {
this.httpInternalError(response, error);
return;
}
}
/** /**
* @description Get a specific File by uid * @description Get a specific File by uid
*/ */

View File

@ -28,6 +28,10 @@ export default class OfficeFoldersController extends ApiController {
let query: Prisma.OfficeFoldersFindManyArgs = {}; let query: Prisma.OfficeFoldersFindManyArgs = {};
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if(query.where?.uid) {
this.httpBadRequest(response, "You can't filter by uid");
return;
}
} }
if (req.query["search"] && typeof req.query["search"] === "string") { if (req.query["search"] && typeof req.query["search"] === "string") {
@ -87,13 +91,18 @@ export default class OfficeFoldersController extends ApiController {
await officeFolderRessource.validateOrReject?.({ groups: ["createFolder"], forbidUnknownValues: false }); await officeFolderRessource.validateOrReject?.({ groups: ["createFolder"], forbidUnknownValues: false });
//call service to get prisma entity //call service to get prisma entity
const officeFolderEntity = await this.officeFoldersService.create(officeFolderRessource); try {
//Hydrate ressource with prisma entity const officeFolderEntity = await this.officeFoldersService.create(officeFolderRessource);
const officeFolders = OfficeFolder.hydrate<OfficeFolder>(officeFolderEntity, { //Hydrate ressource with prisma entity
strategy: "excludeAll", const officeFolders = OfficeFolder.hydrate<OfficeFolder>(officeFolderEntity, {
}); strategy: "excludeAll",
//success });
this.httpCreated(response, officeFolders); //success
this.httpCreated(response, officeFolders);
} catch (error) {
this.httpValidationError(response, error);
return;
}
} catch (error) { } catch (error) {
this.httpInternalError(response, error); this.httpInternalError(response, error);
return; return;
@ -126,15 +135,20 @@ export default class OfficeFoldersController extends ApiController {
await validateOrReject(officeFolderEntity, { groups: ["updateFolder"], forbidUnknownValues: false }); await validateOrReject(officeFolderEntity, { groups: ["updateFolder"], forbidUnknownValues: false });
//call service to get prisma entity //call service to get prisma entity
const officeFolderEntityUpdated = await this.officeFoldersService.update(uid, officeFolderEntity); try {
const officeFolderEntityUpdated = await this.officeFoldersService.update(uid, officeFolderEntity);
//Hydrate ressource with prisma entity //Hydrate ressource with prisma entity
const officeFolders = OfficeFolder.hydrate<OfficeFolder>(officeFolderEntityUpdated, { const officeFolders = OfficeFolder.hydrate<OfficeFolder>(officeFolderEntityUpdated, {
strategy: "excludeAll", strategy: "excludeAll",
}); });
//success //success
this.httpSuccess(response, officeFolders); this.httpSuccess(response, officeFolders);
} catch (error) {
this.httpValidationError(response, error);
return;
}
} catch (error) { } catch (error) {
this.httpInternalError(response, error); this.httpInternalError(response, error);
return; return;

View File

@ -28,6 +28,10 @@ export default class OfficeRolesController extends ApiController {
let query: Prisma.OfficeRolesFindManyArgs = {}; let query: Prisma.OfficeRolesFindManyArgs = {};
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if(query.where?.uid) {
this.httpBadRequest(response, "You can't filter by uid");
return;
}
} }
if(req.query["search"] && typeof req.query["search"] === "string") { if(req.query["search"] && typeof req.query["search"] === "string") {

View File

@ -3,7 +3,7 @@ import { Controller, Get, Post, Put } from "@ControllerPattern/index";
import ApiController from "@Common/system/controller-pattern/ApiController"; import ApiController from "@Common/system/controller-pattern/ApiController";
import OfficesService from "@Services/super-admin/OfficesService/OfficesService"; import OfficesService from "@Services/super-admin/OfficesService/OfficesService";
import { Service } from "typedi"; import { Service } from "typedi";
import { Offices } from "@prisma/client"; import { Offices, Prisma } from "@prisma/client";
import { Office as OfficeResource } from "le-coffre-resources/dist/SuperAdmin"; import { Office as OfficeResource } from "le-coffre-resources/dist/SuperAdmin";
import { validateOrReject } from "class-validator"; import { validateOrReject } from "class-validator";
import ruleHandler from "@App/middlewares/RulesHandler"; import ruleHandler from "@App/middlewares/RulesHandler";
@ -23,9 +23,13 @@ export default class OfficesController extends ApiController {
protected async get(req: Request, response: Response) { protected async get(req: Request, response: Response) {
try { try {
//get query //get query
let query; let query: Prisma.OfficesFindManyArgs = {};
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if (query.where?.uid) {
this.httpBadRequest(response, "You can't filter by uid");
return;
}
} }
if(req.query["search"] && typeof req.query["search"] === "string") { if(req.query["search"] && typeof req.query["search"] === "string") {

View File

@ -8,6 +8,7 @@ import { Role } from "le-coffre-resources/dist/SuperAdmin";
import authHandler from "@App/middlewares/AuthHandler"; import authHandler from "@App/middlewares/AuthHandler";
import ruleHandler from "@App/middlewares/RulesHandler"; import ruleHandler from "@App/middlewares/RulesHandler";
import roleHandler from "@App/middlewares/RolesHandler"; import roleHandler from "@App/middlewares/RolesHandler";
import { Prisma } from "@prisma/client";
@Controller() @Controller()
@Service() @Service()
@ -23,9 +24,13 @@ export default class RolesController extends ApiController {
protected async get(req: Request, response: Response) { protected async get(req: Request, response: Response) {
try { try {
//get query //get query
let query; let query: Prisma.RolesFindManyArgs = {};
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if (query.where?.uid) {
this.httpBadRequest(response, "You can't filter by uid");
return;
}
} }
//call service to get prisma entity //call service to get prisma entity

View File

@ -8,6 +8,7 @@ import { Rule } from "le-coffre-resources/dist/SuperAdmin";
import authHandler from "@App/middlewares/AuthHandler"; import authHandler from "@App/middlewares/AuthHandler";
import ruleHandler from "@App/middlewares/RulesHandler"; import ruleHandler from "@App/middlewares/RulesHandler";
import roleHandler from "@App/middlewares/RolesHandler"; import roleHandler from "@App/middlewares/RolesHandler";
import { Prisma } from "@prisma/client";
@Controller() @Controller()
@Service() @Service()
@ -23,9 +24,13 @@ export default class RulesController extends ApiController {
protected async get(req: Request, response: Response) { protected async get(req: Request, response: Response) {
try { try {
//get query //get query
let query; let query: Prisma.RulesFindManyArgs = {};
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if (query.where?.uid) {
this.httpBadRequest(response, "You can't filter by uid");
return;
}
} }
//call service to get prisma entity //call service to get prisma entity

View File

@ -10,6 +10,7 @@ import ruleHandler from "@App/middlewares/RulesHandler";
import roleHandler from "@App/middlewares/RolesHandler"; import roleHandler from "@App/middlewares/RolesHandler";
import RolesService from "@Services/super-admin/RolesService/RolesService"; import RolesService from "@Services/super-admin/RolesService/RolesService";
import OfficeRolesService from "@Services/super-admin/OfficeRolesService/OfficeRolesService"; import OfficeRolesService from "@Services/super-admin/OfficeRolesService/OfficeRolesService";
import { Prisma } from "@prisma/client";
@Controller() @Controller()
@Service() @Service()
@ -25,9 +26,13 @@ export default class UsersController extends ApiController {
protected async get(req: Request, response: Response) { protected async get(req: Request, response: Response) {
try { try {
//get query //get query
let query; let query: Prisma.UsersFindManyArgs = {};
if (req.query["q"]) { if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
if (query.where?.uid) {
this.httpBadRequest(response, "You can't filter by uid");
return;
}
} }
if (req.query["search"] && typeof req.query["search"] === "string") { if (req.query["search"] && typeof req.query["search"] === "string") {

View File

@ -9,7 +9,6 @@ import DeedTypesControllerSuperAdmin from "./api/super-admin/DeedTypesController
import DocumentsControllerSuperAdmin from "./api/super-admin/DocumentsController"; import DocumentsControllerSuperAdmin from "./api/super-admin/DocumentsController";
import DocumentTypesControllerSuperAdmin from "./api/super-admin/DocumentTypesController"; import DocumentTypesControllerSuperAdmin from "./api/super-admin/DocumentTypesController";
import IdNotUserController from "./api/idnot/UserController"; import IdNotUserController from "./api/idnot/UserController";
import FranceConnectCustomerController from "./api/franceConnect/CustomerController";
import FilesControllerSuperAdmin from "./api/super-admin/FilesController"; import FilesControllerSuperAdmin from "./api/super-admin/FilesController";
import RulesControllerSuperAdmin from "./api/super-admin/RulesController"; import RulesControllerSuperAdmin from "./api/super-admin/RulesController";
import RolesControllerSuperAdmin from "./api/super-admin/RolesController"; import RolesControllerSuperAdmin from "./api/super-admin/RolesController";
@ -64,7 +63,6 @@ export default {
Container.get(DocumentTypesControllerSuperAdmin); Container.get(DocumentTypesControllerSuperAdmin);
Container.get(LiveVoteController); Container.get(LiveVoteController);
Container.get(IdNotUserController); Container.get(IdNotUserController);
Container.get(FranceConnectCustomerController);
Container.get(FilesControllerSuperAdmin); Container.get(FilesControllerSuperAdmin);
Container.get(DocumentsControllerSuperAdmin); Container.get(DocumentsControllerSuperAdmin);
Container.get(RulesControllerSuperAdmin); Container.get(RulesControllerSuperAdmin);

View File

@ -3,36 +3,65 @@ import DocumentsService from "@Services/customer/DocumentsService/DocumentsServi
import Document from "le-coffre-resources/dist/SuperAdmin/Document"; import Document from "le-coffre-resources/dist/SuperAdmin/Document";
import { NextFunction, Request, Response } from "express"; import { NextFunction, Request, Response } from "express";
import Container from "typedi"; import Container from "typedi";
import OfficeFoldersService from "@Services/super-admin/OfficeFoldersService/OfficeFoldersService";
import { OfficeFolder } from "le-coffre-resources/dist/SuperAdmin";
import CustomersService from "@Services/super-admin/CustomersService/CustomersService";
export default async function documentHandler(req: Request, response: Response, next: NextFunction) { export default async function documentHandler(req: Request, response: Response, next: NextFunction) {
try { try {
const customerId = req.body.user.customerId; const customerId = req.body.user.customerId;
const customerEmail = req.body.user.email;
const uid = req.path && req.path.split("/")[5]; const uid = req.path && req.path.split("/")[5];
if (!uid) { if (uid) {
response.status(HttpCodes.BAD_REQUEST).send("Missing document uid"); const documentService = Container.get(DocumentsService);
return; const document = await documentService.getByUid(uid, { folder: { include: { folder_anchor: true } } });
}
const documentService = Container.get(DocumentsService); if (!document) {
const document = await documentService.getByUid(uid, { folder: { include: { folder_anchor: true } } }); response.status(HttpCodes.NOT_FOUND).send("Document not found");
if (!document) {
response.status(HttpCodes.NOT_FOUND).send("Document not found");
return;
}
if (document?.depositor_uid != customerId) {
response.status(HttpCodes.UNAUTHORIZED).send("Not authorized with this depositor");
return;
}
if (req.method === "POST" || req.method === "PUT") {
const documentEntity = Document.hydrate<Document>(document);
if (documentEntity.folder?.folder_anchor?.status === "VERIFIED_ON_CHAIN") {
response.status(HttpCodes.BAD_REQUEST).send("Cannot update a verified folder");
return; return;
} }
if (document?.depositor_uid != customerId) {
const customerService = Container.get(CustomersService);
const customers = await customerService.get({where: {contact: { email: customerEmail}}});
if (customers && !customers.find((customer) => customer.uid === document?.depositor_uid)) {
response.status(HttpCodes.UNAUTHORIZED).send("Not authorized with this depositor");
return;
}
}
if (req.method === "PUT" || req.method === "DELETE") {
const documentEntity = Document.hydrate<Document>(document);
if (documentEntity.folder!.folder_anchor?.status === "VERIFIED_ON_CHAIN") {
response.status(HttpCodes.BAD_REQUEST).send("Cannot update a verified folder");
return;
}
}
}
if (req.method === "POST") {
const documentEntity = Document.hydrate<Document>(req.body);
const officeFolderService = Container.get(OfficeFoldersService);
if (documentEntity.folder?.uid) {
const folder = await officeFolderService.getByUid(documentEntity.folder.uid, {
folder_anchor: true,
customers: { include: { contact: true } },
});
if (!folder) {
response.status(HttpCodes.NOT_FOUND).send("Folder not found");
return;
}
const folderEntity = OfficeFolder.hydrate<OfficeFolder>(folder);
if (folderEntity.folder_anchor?.status === "VERIFIED_ON_CHAIN") {
response.status(HttpCodes.BAD_REQUEST).send("Cannot update a verified folder");
return;
}
if (!folderEntity.customers?.find((customer) => customer.contact?.email === customerEmail)) {
response.status(HttpCodes.BAD_REQUEST).send("Cannot post a document in this folder");
return;
}
}
} }
next(); next();

View File

@ -5,9 +5,11 @@ import File from "le-coffre-resources/dist/SuperAdmin/File";
import { NextFunction, Request, Response } from "express"; import { NextFunction, Request, Response } from "express";
import Container from "typedi"; import Container from "typedi";
import { EDocumentStatus } from "@prisma/client"; import { EDocumentStatus } from "@prisma/client";
import CustomersService from "@Services/super-admin/CustomersService/CustomersService";
export default async function fileHandler(req: Request, response: Response, next: NextFunction) { export default async function fileHandler(req: Request, response: Response, next: NextFunction) {
const customerId = req.body.user.customerId; const customerId = req.body.user.customerId;
const customerEmail = req.body.user.email;
const uid = req.path && req.path.split("/")[5]; const uid = req.path && req.path.split("/")[5];
const file: string | undefined = req.body["q"]; const file: string | undefined = req.body["q"];
@ -24,8 +26,12 @@ export default async function fileHandler(req: Request, response: Response, next
return; return;
} }
if (file.document.depositor_uid != customerId) { if (file.document.depositor_uid != customerId) {
response.status(HttpCodes.UNAUTHORIZED).send("Not authorized with this depositor"); const customerService = Container.get(CustomersService);
return; const customers = await customerService.get({where: {contact: { email: customerEmail}}});
if (customers && !customers.find((customer) => customer.uid === file.document.depositor_uid)) {
response.status(HttpCodes.UNAUTHORIZED).send("Not authorized with this depositor");
return;
}
} }
if (req.method === "PUT") { if (req.method === "PUT") {
if (file.document.document_status === EDocumentStatus.VALIDATED) { if (file.document.document_status === EDocumentStatus.VALIDATED) {
@ -43,8 +49,12 @@ export default async function fileHandler(req: Request, response: Response, next
return; return;
} }
if (documentFound.depositor_uid != customerId) { if (documentFound.depositor_uid != customerId) {
response.status(HttpCodes.UNAUTHORIZED).send("Not authorized with this depositor"); const customerService = Container.get(CustomersService);
return; const customers = await customerService.get({where: {contact: { email: customerEmail}}});
if (customers && !customers.find((customer) => customer.uid === documentFound.depositor_uid)) {
response.status(HttpCodes.UNAUTHORIZED).send("Not authorized with this depositor");
return;
}
} }
if (documentFound.document_status === EDocumentStatus.VALIDATED) { if (documentFound.document_status === EDocumentStatus.VALIDATED) {
response.status(HttpCodes.BAD_REQUEST).send("Cannot update a validated document"); response.status(HttpCodes.BAD_REQUEST).send("Cannot update a validated document");

View File

@ -1,10 +1,12 @@
import HttpCodes from "@Common/system/controller-pattern/HttpCodes"; import HttpCodes from "@Common/system/controller-pattern/HttpCodes";
import OfficeFoldersService from "@Services/customer/OfficeFoldersService/OfficeFoldersService"; import OfficeFoldersService from "@Services/customer/OfficeFoldersService/OfficeFoldersService";
import CustomersService from "@Services/super-admin/CustomersService/CustomersService";
import { NextFunction, Request, Response } from "express"; import { NextFunction, Request, Response } from "express";
import Container from "typedi"; import Container from "typedi";
export default async function officeFolderHandler(req: Request, response: Response, next: NextFunction) { export default async function officeFolderHandler(req: Request, response: Response, next: NextFunction) {
const customerId = req.body.user.customerId; const customerId = req.body.user.customerId;
const customerEmail = req.body.user.email;
const uid = req.path && req.path.split("/")[5]; const uid = req.path && req.path.split("/")[5];
if (uid) { if (uid) {
@ -15,8 +17,12 @@ export default async function officeFolderHandler(req: Request, response: Respon
return; return;
} }
if (!officeFolder.customers.find((customer) => customer.uid == customerId)) { if (!officeFolder.customers.find((customer) => customer.uid == customerId)) {
response.status(HttpCodes.UNAUTHORIZED).send("Not authorized with this depositor"); const customerService = Container.get(CustomersService);
return; const customers = await customerService.get({where: {contact: { email: customerEmail}}});
if (customers && !customers.filter((customer) => officeFolder.customers.includes(customer))) {
response.status(HttpCodes.UNAUTHORIZED).send("Not authorized with this depositor");
return;
}
} }
} }

View File

@ -11,12 +11,24 @@ export default async function deedTypeHandler(req: Request, response: Response,
const uid = req.path && req.path.split("/")[5]; const uid = req.path && req.path.split("/")[5];
const documentTypes: DocumentType[] = req.body.document_types; const documentTypes: DocumentType[] = req.body.document_types;
const office = req.body.office; const office = req.body.office;
const name = req.body.name;
if (office && office.uid != officeId) { if (office && office.uid != officeId) {
response.status(HttpCodes.UNAUTHORIZED).send("Unauthorized with this office"); response.status(HttpCodes.UNAUTHORIZED).send("Unauthorized with this office");
return; return;
} }
if (name) {
const deedTypeService = Container.get(DeedTypesService);
const deedType = await deedTypeService.get({
where: { AND: [{ name: { equals: name, mode: "insensitive" } }, { office: { uid: officeId } }] },
});
if (deedType[0] && (!uid || deedType[0].uid != uid)) {
response.status(HttpCodes.VALIDATION_ERROR).send([{ property: "name", constraints: { name: "Nom d'acte déjà utilisé" } }]);
return;
}
}
if (uid) { if (uid) {
const deedTypeService = Container.get(DeedTypesService); const deedTypeService = Container.get(DeedTypesService);
const deedType = await deedTypeService.getByUidWithOffice(uid!); const deedType = await deedTypeService.getByUidWithOffice(uid!);

View File

@ -8,12 +8,24 @@ export default async function documentTypeHandler(req: Request, response: Respon
const officeId = req.body.user.office_Id; const officeId = req.body.user.office_Id;
const uid = req.path && req.path.split("/")[5]; const uid = req.path && req.path.split("/")[5];
const office = req.body.office; const office = req.body.office;
const name = req.body.name;
if (office && office.uid != officeId) { if (office && office.uid != officeId) {
response.status(HttpCodes.UNAUTHORIZED).send("Unauthorized with this office"); response.status(HttpCodes.UNAUTHORIZED).send("Unauthorized with this office");
return; return;
} }
if (name) {
const documentTypeService = Container.get(DocumentTypesService);
const documentType = await documentTypeService.get({
where: { AND: [{ name: { equals: name, mode: "insensitive" } }, { office: { uid: officeId } }] },
});
if (documentType[0] && (!uid || documentType[0].uid != uid)) {
response.status(HttpCodes.VALIDATION_ERROR).send([{ property: "name", constraints: { name: "Nom de document déjà utilisé" } }]);
return;
}
}
if (uid) { if (uid) {
const documentTypeService = Container.get(DocumentTypesService); const documentTypeService = Container.get(DocumentTypesService);
const documentType = await documentTypeService.getByUidWithOffice(uid!); const documentType = await documentTypeService.getByUidWithOffice(uid!);

View File

@ -10,14 +10,32 @@ export default async function folderHandler(req: Request, response: Response, ne
const userId = req.body.user.userId; const userId = req.body.user.userId;
let uid = req.path && req.path.split("/")[5]; let uid = req.path && req.path.split("/")[5];
const office = req.body.office; const office = req.body.office;
const officeFolderNumber = req.body.folder_number;
const deed = req.body.deed; const deed = req.body.deed;
const folderNumber = req.body.folder_number;
const stakeHolders = req.body.stakeholders as any[];
if (office && office.uid != officeId) { if (office && office.uid != officeId) {
response.status(HttpCodes.UNAUTHORIZED).send("Unauthorized with this office"); response.status(HttpCodes.UNAUTHORIZED).send("Unauthorized with this office");
return; return;
} }
if(folderNumber) {
const officeFolderService = Container.get(OfficeFoldersService);
const sameFolderNumber = await officeFolderService.get({
where: { AND: [{ folder_number: folderNumber }, { office_uid: officeId }] },
});
if(sameFolderNumber[0] && (!uid || uid != sameFolderNumber[0]?.uid)) {
const error = [{property: "folder_number", constraints: { folder_number: "Numéro de dossier déjà utilisé" } }];
response.status(HttpCodes.VALIDATION_ERROR).send(error);
return;
}
}
if(stakeHolders && stakeHolders.length === 0) {
response.status(HttpCodes.VALIDATION_ERROR).send([{ property: "stakeholders", constraints: { stakeholders: "Au moins un collaborateur est requis" } }]);
return;
}
if (deed && deed.deed_type) { if (deed && deed.deed_type) {
const deedTypeService = Container.get(DeedTypesService); const deedTypeService = Container.get(DeedTypesService);
const deedTypeWithOffice = await deedTypeService.getByUidWithOffice(deed.deed_type.uid!); const deedTypeWithOffice = await deedTypeService.getByUidWithOffice(deed.deed_type.uid!);
@ -25,20 +43,12 @@ export default async function folderHandler(req: Request, response: Response, ne
response.status(HttpCodes.NOT_FOUND).send("Deed type not found"); response.status(HttpCodes.NOT_FOUND).send("Deed type not found");
return; return;
} }
if (deedTypeWithOffice.office.uid != officeId) { if(deedTypeWithOffice.archived_at) {
response.status(HttpCodes.UNAUTHORIZED).send("Unauthorized with this deed type"); response.status(HttpCodes.FORBIDDEN).send("Deed type is archived");
return; return;
} }
} if (deedTypeWithOffice.office.uid != officeId) {
response.status(HttpCodes.UNAUTHORIZED).send("Unauthorized with this deed type");
const officeFolderService = Container.get(OfficeFoldersService);
if (officeFolderNumber && req.method == "POST") {
const officeFoldersWithSameNumber = await officeFolderService.get({
where: { folder_number: officeFolderNumber, office: { uid: officeId } },
});
if (officeFoldersWithSameNumber.length) {
response.status(HttpCodes.BAD_REQUEST).send("Office number already used");
return; return;
} }
} }
@ -47,6 +57,8 @@ export default async function folderHandler(req: Request, response: Response, ne
if(uid === "download") { if(uid === "download") {
uid = req.path && req.path.split("/")[6]; uid = req.path && req.path.split("/")[6];
} }
const officeFolderService = Container.get(OfficeFoldersService);
const officeFolder = await officeFolderService.getByUidWithStakeholders(uid!); const officeFolder = await officeFolderService.getByUidWithStakeholders(uid!);
if (!officeFolder) { if (!officeFolder) {

View File

@ -7,6 +7,11 @@ export default async function roleHandler(req: Request, response: Response, next
const namespace = req.path && req.path.split("/")[3]; const namespace = req.path && req.path.split("/")[3];
const role = req.body.user.role; const role = req.body.user.role;
if(!role) {
response.status(HttpCodes.UNAUTHORIZED).send("Unauthorized without role");
return;
}
if (namespace != "notary" && role != namespace && role != "super-admin") { if (namespace != "notary" && role != namespace && role != "super-admin") {
response.status(HttpCodes.UNAUTHORIZED).send("Unauthorized with this role"); response.status(HttpCodes.UNAUTHORIZED).send("Unauthorized with this role");
return; return;

View File

@ -0,0 +1,5 @@
-- DropIndex
DROP INDEX "contacts_cell_phone_number_key";
-- DropIndex
DROP INDEX "contacts_email_key";

View File

@ -35,9 +35,9 @@ model Contacts {
uid String @id @unique @default(uuid()) uid String @id @unique @default(uuid())
first_name String @db.VarChar(255) first_name String @db.VarChar(255)
last_name String @db.VarChar(255) last_name String @db.VarChar(255)
email String @unique @db.VarChar(255) email String @db.VarChar(255)
phone_number String? @db.VarChar(50) phone_number String? @db.VarChar(50)
cell_phone_number String @unique @db.VarChar(50) cell_phone_number String @db.VarChar(50)
civility ECivility @default(MALE) civility ECivility @default(MALE)
address Addresses? @relation(fields: [address_uid], references: [uid], onDelete: Cascade) address Addresses? @relation(fields: [address_uid], references: [uid], onDelete: Cascade)
address_uid String? @unique @db.VarChar(255) address_uid String? @unique @db.VarChar(255)

View File

@ -1,4 +1,3 @@
import DocumentsService from "@Services/super-admin/DocumentsService/DocumentsService"; import DocumentsService from "@Services/super-admin/DocumentsService/DocumentsService";
import { Documents } from "@prisma/client"; import { Documents } from "@prisma/client";
import User, { Document } from "le-coffre-resources/dist/SuperAdmin"; import User, { Document } from "le-coffre-resources/dist/SuperAdmin";
@ -6,85 +5,105 @@ import { Service } from "typedi";
import { ETemplates } from "./Templates/EmailTemplates"; import { ETemplates } from "./Templates/EmailTemplates";
import MailchimpService from "@Services/common/MailchimpService/MailchimpService"; import MailchimpService from "@Services/common/MailchimpService/MailchimpService";
import { BackendVariables } from "@Common/config/variables/Variables"; import { BackendVariables } from "@Common/config/variables/Variables";
import UsersService from "@Services/super-admin/UsersService/UsersService";
@Service() @Service()
export default class EmailBuilder { export default class EmailBuilder {
public constructor(private mailchimpService: MailchimpService ,private documentsService: DocumentsService, protected variables: BackendVariables){} public constructor(
private mailchimpService: MailchimpService,
private documentsService: DocumentsService,
protected variables: BackendVariables,
private usersService: UsersService,
) {}
public async sendDocumentEmails(documentEntity: Documents){ public async sendDocumentEmails(documentEntity: Documents) {
if(documentEntity.document_status !== "ASKED" && documentEntity.document_status !== "REFUSED") return; if (documentEntity.document_status !== "ASKED" && documentEntity.document_status !== "REFUSED") return;
const documentPrisma = await this.documentsService.getByUid(documentEntity.uid, { depositor: {include: {contact: true}}, folder:{include:{ office: true}} }); let templateName = ETemplates.DOCUMENT_ASKED;
if(!documentPrisma) throw new Error("Document not found"); let subject = "Votre notaire vous demande de déposer des pièces pour traiter votre dossier.";
const document = Document.hydrate<Document>(documentPrisma); if (documentEntity.document_status === "REFUSED") {
templateName = ETemplates.DOCUMENT_REFUSED;
subject = "Un ou plusieurs documents ne sont pas validés. Vous avez une nouvelle action à réaliser.";
}
//Use mailchimpService.get get if an email was sent to the user in the lst hour const documentPrisma = await this.documentsService.getByUid(documentEntity.uid, {
const lastEmail = await this.mailchimpService.get({ where: { to: document.depositor!.contact!.email, sentAt: { gte: new Date(Date.now() - 3600000) } } }); depositor: { include: { contact: true } },
if(lastEmail.length > 0) return; folder: { include: { office: true } },
});
const to = document.depositor!.contact!.email; if (!documentPrisma) throw new Error("Document not found");
const civility = this.getCivility(document.depositor!.contact!.civility); const document = Document.hydrate<Document>(documentPrisma);
const templateVariables = {
civility: civility,
last_name: document.depositor!.contact!.last_name,
office_name: document.folder!.office!.name,
link: this.variables.APP_HOST
};
let templateName = ETemplates.DOCUMENT_ASKED; //Use mailchimpService.get get if an email was sent to the user in the lst hour
let subject = "Votre notaire vous demande de déposer des pièces pour traiter votre dossier."; const lastEmail = await this.mailchimpService.get({
if(documentEntity.document_status === "REFUSED"){ where: {
templateName = ETemplates.DOCUMENT_REFUSED; to: document.depositor!.contact!.email,
subject = "Un ou plusieurs documents ne sont pas validés. Vous avez une nouvelle action à réaliser."; OR: [{ sentAt: { gte: new Date(Date.now() - 3600000) } }, { sentAt: null }],
} templateName: templateName,
},
});
if (lastEmail.length > 0) return;
this.mailchimpService.create({ const to = document.depositor!.contact!.email;
templateName, const templateVariables = {
to, first_name: document.depositor!.contact!.first_name,
subject, last_name: document.depositor!.contact!.last_name,
templateVariables, office_name: document.folder!.office!.name,
uid: "", link: `${this.variables.APP_HOST}/customer-login`,
from: null, };
cc: [],
cci: [],
sentAt: null,
nbTrySend: null,
lastTrySendDate: null,
});
}
public async sendRecapEmails(usersToEmail: User[]){ this.mailchimpService.create({
usersToEmail.forEach(user => { templateName,
const to = user.contact!.email; to,
const civility = this.getCivility(user.contact!.civility); subject,
templateVariables,
uid: "",
from: null,
cc: [],
cci: [],
sentAt: null,
nbTrySend: null,
lastTrySendDate: null,
});
}
const templateVariables = { public async sendRecapEmails() {
civility: civility, const usersToEmail: User[] = await this.usersService.get({
last_name: user.contact!.last_name, where: { office_folders: { some: { documents: { some: { document_status: "DEPOSITED" } } } } },
link: this.variables.APP_HOST distinct: ["uid"],
}; include: { contact: true },
});
const templateName = ETemplates.DOCUMENT_RECAP; usersToEmail.forEach((user) => {
const subject = "Des clients vous ont envoyé des documents qui n'ont pas été validés."; const to = user.contact!.email;
const civility = this.getCivility(user.contact!.civility);
this.mailchimpService.create({ const templateVariables = {
templateName, civility: civility,
to, last_name: user.contact!.last_name,
subject, link: this.variables.APP_HOST,
templateVariables, };
uid: "",
from: null,
cc: [],
cci: [],
sentAt: null,
nbTrySend: null,
lastTrySendDate: null,
});
});
}
public getCivility(civility: string){ const templateName = ETemplates.DOCUMENT_RECAP;
if(civility === "MALE") return "Mr" const subject = "Des clients vous ont envoyé des documents qui n'ont pas été validés.";
else return "Mme"
} this.mailchimpService.create({
templateName,
to,
subject,
templateVariables,
uid: "",
from: null,
cc: [],
cci: [],
sentAt: null,
nbTrySend: null,
lastTrySendDate: null,
});
});
}
public getCivility(civility: string) {
if (civility === "MALE") return "Mr";
else return "Mme";
}
} }

View File

@ -10,6 +10,7 @@ import { Document, File, OfficeFolder } from "le-coffre-resources/dist/Notary";
export const folderDocumentsLens = Optics.Lens.fromNullableProp<OfficeFolder>()("documents", []); export const folderDocumentsLens = Optics.Lens.fromNullableProp<OfficeFolder>()("documents", []);
export const documentFilesLens = Optics.Lens.fromNullableProp<Document>()("files", []); export const documentFilesLens = Optics.Lens.fromNullableProp<Document>()("files", []);
export const fileHashLens = Optics.Lens.fromProp<File>()("hash"); export const fileHashLens = Optics.Lens.fromProp<File>()("hash");
export const fileUidLens = Optics.Lens.fromProp<File>()("uid");
/** /**
* Traversals * Traversals
@ -17,13 +18,17 @@ export const fileHashLens = Optics.Lens.fromProp<File>()("hash");
export const documentsTraversal = Optics.fromTraversable(Array.Traversable)<Document>(); export const documentsTraversal = Optics.fromTraversable(Array.Traversable)<Document>();
export const filesTraversal = Optics.fromTraversable(Array.Traversable)<File>(); export const filesTraversal = Optics.fromTraversable(Array.Traversable)<File>();
export const folderHashesTraversal = folderDocumentsLens export const folderFilesTraversal = folderDocumentsLens
.composeTraversal(documentsTraversal) .composeTraversal(documentsTraversal)
.composeLens(documentFilesLens) .composeLens(documentFilesLens)
.composeTraversal(filesTraversal) .composeTraversal(filesTraversal);
.composeLens(fileHashLens);
export const folderHashesTraversal = folderFilesTraversal.composeLens(fileHashLens);
export const folderFilesUidTraversal = folderFilesTraversal.composeLens(fileUidLens);
/** /**
* Getters * Getters
*/ */
export const getFolderFiles = (folder: OfficeFolder) => Traversal.getAll(folder)(folderFilesTraversal);
export const getFolderHashes = (folder: OfficeFolder) => Traversal.getAll(folder)(folderHashesTraversal); export const getFolderHashes = (folder: OfficeFolder) => Traversal.getAll(folder)(folderHashesTraversal);
export const getFolderFilesUid = (folder: OfficeFolder) => Traversal.getAll(folder)(folderFilesUidTraversal);

View File

@ -18,12 +18,24 @@ export default class ContactRepository extends BaseRepository {
/** /**
* @description : Find unique customer by email * @description : Find unique customer by email
*/ */
public async findOneByEmail(email: string): Promise<(Contacts & {customers: Customers | null}) | null> { public async findSomeByEmail(email: string): Promise<(Contacts & {customers: Customers | null})[] | null> {
return this.model.findUnique({ return this.model.findMany({
where: { where: {
email: email, email: email,
}, },
include: { customers: true } include: { customers: true }
}); });
} }
/**
* @description : Find unique customer by email
*/
public async findSomeByPhoneNumber(cell_phone_number: string): Promise<(Contacts & {customers: Customers | null})[] | null> {
return this.model.findMany({
where: {
cell_phone_number: cell_phone_number,
},
include: { customers: true }
});
}
} }

View File

@ -114,16 +114,16 @@ export default class DocumentsRepository extends BaseRepository {
/** /**
* @description : Update data of a document * @description : Update data of a document
*/ */
public async refuse(uid: string, document: Partial<DocumentCustomer>, refusedReason?: string): Promise<Documents> { public async refuse(uid: string, refusedReason?: string): Promise<Documents> {
return this.model.update({ return this.model.update({
where: { where: {
uid: uid, uid: uid,
}, },
data: { data: {
document_status: EDocumentStatus[document.document_status as keyof typeof EDocumentStatus], document_status: EDocumentStatus.REFUSED,
document_history: { document_history: {
create: { create: {
document_status: EDocumentStatus[document.document_status as keyof typeof EDocumentStatus], document_status: EDocumentStatus.REFUSED,
refused_reason: refusedReason, refused_reason: refusedReason,
}, },
}, },

View File

@ -26,7 +26,7 @@ export default class EmailRepository extends BaseRepository {
/** /**
* @description : Create an email * @description : Create an email
*/ */
public async create(email: Emails): Promise<Emails> { public async create(email: Emails): Promise<Emails> {
const createArgs: Prisma.EmailsCreateArgs = { const createArgs: Prisma.EmailsCreateArgs = {
data: { data: {
templateName: email.templateName, templateName: email.templateName,

View File

@ -36,7 +36,7 @@ export default class OfficeFoldersRepository extends BaseRepository {
status: EFolderStatus.LIVE, status: EFolderStatus.LIVE,
deed: { deed: {
connect: { connect: {
uid: officeFolder.deed?.uid, uid: officeFolder.deed!.uid,
}, },
}, },
office: { office: {
@ -55,6 +55,18 @@ export default class OfficeFoldersRepository extends BaseRepository {
return this.model.create({ ...createArgs, include: { stakeholders: true } }); return this.model.create({ ...createArgs, include: { stakeholders: true } });
} }
public async updateStatus(uid: string, status: EFolderStatus, archived_description: string | null) {
return this.model.update({
where: {
uid: uid,
},
data: {
status: status,
archived_description: archived_description,
},
});
}
/** /**
* @description : Update data of an office folder * @description : Update data of an office folder
*/ */
@ -67,8 +79,6 @@ export default class OfficeFoldersRepository extends BaseRepository {
folder_number: officeFolder.folder_number, folder_number: officeFolder.folder_number,
name: officeFolder.name, name: officeFolder.name,
description: officeFolder.description, description: officeFolder.description,
status: EFolderStatus[officeFolder.status as keyof typeof EFolderStatus],
archived_description: officeFolder.archived_description,
stakeholders: { stakeholders: {
set: officeFolder.stakeholders?.map((stakeholder) => ({ set: officeFolder.stakeholders?.map((stakeholder) => ({
uid: stakeholder.uid!, uid: stakeholder.uid!,
@ -121,7 +131,7 @@ export default class OfficeFoldersRepository extends BaseRepository {
}, },
include: { include: {
customers: true, customers: true,
} },
}); });
} }

View File

@ -46,12 +46,11 @@ export default class DocumentsService extends BaseService {
public async refuse(uid: string, document: Partial<Document>, refused_reason: string): Promise<Documents> { public async refuse(uid: string, document: Partial<Document>, refused_reason: string): Promise<Documents> {
if (document.files) { if (document.files) {
for (let i = 0; i < document.files.length; i++) { for (let i = 0; i < document.files.length; i++) {
console.log("archiving file", document.files[i]?.uid);
await this.filesRepository.deleteKeyAndArchive(document.files[i]?.uid as string); await this.filesRepository.deleteKeyAndArchive(document.files[i]?.uid as string);
} }
} }
return this.documentsRepository.refuse(uid, document, refused_reason); return this.documentsRepository.refuse(uid, refused_reason);
} }
/** /**

View File

@ -3,16 +3,12 @@ import OfficeFoldersRepository from "@Repositories/OfficeFoldersRepository";
import BaseService from "@Services/BaseService"; import BaseService from "@Services/BaseService";
import { OfficeFolder } from "le-coffre-resources/dist/Admin"; import { OfficeFolder } from "le-coffre-resources/dist/Admin";
import { Service } from "typedi"; import { Service } from "typedi";
import DeedTypesService from "../DeedTypesService/DeedTypesService";
import DeedsRepository from "@Repositories/DeedsRepository";
import { Prisma } from "@prisma/client"; import { Prisma } from "@prisma/client";
@Service() @Service()
export default class OfficeFoldersService extends BaseService { export default class OfficeFoldersService extends BaseService {
constructor( constructor(
private officeFoldersRepository: OfficeFoldersRepository, private officeFoldersRepository: OfficeFoldersRepository,
private deedTypeService: DeedTypesService,
private deedRepository: DeedsRepository,
) { ) {
super(); super();
} }
@ -30,11 +26,6 @@ export default class OfficeFoldersService extends BaseService {
* @throws {Error} If folder cannot be created * @throws {Error} If folder cannot be created
*/ */
public async create(officeFolderEntity: OfficeFolder): Promise<OfficeFolders> { public async create(officeFolderEntity: OfficeFolder): Promise<OfficeFolders> {
const deedType = await this.deedTypeService.getByUid(officeFolderEntity.deed!.deed_type!.uid!);
if (!deedType) throw new Error("deed type not found");
if (deedType.archived_at) throw new Error("deed type is archived");
const deed = await this.deedRepository.create(officeFolderEntity.deed!);
officeFolderEntity.deed!.uid = deed.uid;
return this.officeFoldersRepository.create(officeFolderEntity); return this.officeFoldersRepository.create(officeFolderEntity);
} }

View File

@ -14,6 +14,8 @@ enum PROVIDER_OPENID {
export interface ICustomerJwtPayload { export interface ICustomerJwtPayload {
customerId: string; customerId: string;
email: string; email: string;
iat?: number;
exp?: number;
} }
export interface IdNotJwtPayload { export interface IdNotJwtPayload {
@ -31,6 +33,8 @@ export interface IUserJwtPayload {
office_Id: string; office_Id: string;
role: string; role: string;
rules: string[]; rules: string[];
iat?: number;
exp?: number;
} }
@Service() @Service()
@ -39,14 +43,16 @@ export default class AuthService extends BaseService {
super(); super();
} }
public async getCustomerJwtPayload(customer: Customer): Promise<ICustomerJwtPayload | null> { public async getCustomerJwtPayload(customers: Customer[]): Promise<ICustomerJwtPayload | null> {
if(customer.status === ECustomerStatus["PENDING"]) { for (const customer of customers){
customer.status = ECustomerStatus["VALIDATED"]; if (customer.status === ECustomerStatus["PENDING"]) {
this.customerService.update(customer.uid!, customer); customer.status = ECustomerStatus["VALIDATED"];
await this.customerService.update(customer.uid!, customer);
}
} }
return { return {
customerId: customer.uid!, customerId: customers[0]!.uid!,
email: customer.contact!.email, email: customers[0]!.contact!.email,
}; };
} }

View File

@ -0,0 +1,27 @@
import { Contacts, Customers } from "@prisma/client";
import ContactsRepository from "@Repositories/ContactRepository";
import BaseService from "@Services/BaseService";
import { Service } from "typedi";
@Service()
export default class ContactsService extends BaseService {
constructor(private customerRepository: ContactsRepository) {
super();
}
/**
* @description : Get all Contacts
* @throws {Error} If Contacts cannot be get
*/
public async getByEmail(email: string): Promise<(Contacts & {customers: Customers | null})[] | null> {
return this.customerRepository.findSomeByEmail(email);
}
/**
* @description : Create a new customer
* @throws {Error} If customer cannot be created
*/
public async getByPhone(cell_phone_number: string): Promise<(Contacts & {customers: Customers | null})[] | null> {
return this.customerRepository.findSomeByPhoneNumber(cell_phone_number);
}
}

View File

@ -5,6 +5,7 @@ import FilesService from "../FilesService/FilesService";
import IdNotService from "../IdNotService/IdNotService"; import IdNotService from "../IdNotService/IdNotService";
import { PrismaClient } from "@prisma/client"; import { PrismaClient } from "@prisma/client";
import NotificationBuilder from "@Common/notifications/NotificationBuilder"; import NotificationBuilder from "@Common/notifications/NotificationBuilder";
import EmailBuilder from "@Common/emails/EmailBuilder";
// import { PrismaClient } from "@prisma/client"; // import { PrismaClient } from "@prisma/client";
@Service() @Service()
@ -13,7 +14,8 @@ export default class CronService {
private mailchimpService: MailchimpService, private mailchimpService: MailchimpService,
private filesService: FilesService, private filesService: FilesService,
private idNotService: IdNotService, private idNotService: IdNotService,
private notificationBuilder: NotificationBuilder private notificationBuilder: NotificationBuilder,
private emailBuilder: EmailBuilder,
) {} ) {}
public async sendMails() { public async sendMails() {
@ -36,7 +38,7 @@ export default class CronService {
const cronJob = new CronJob("0 20 * * FRI", async () => { const cronJob = new CronJob("0 20 * * FRI", async () => {
// Every friday at 20:00 // Every friday at 20:00
try { try {
await this.mailchimpService.sendRecapEmails(); await this.emailBuilder.sendRecapEmails();
} catch (e) { } catch (e) {
console.error(e); console.error(e);
} }

View File

@ -4,18 +4,14 @@ import { Emails, Prisma } from "@prisma/client";
import { Service } from "typedi"; import { Service } from "typedi";
import MailchimpClient from "@mailchimp/mailchimp_transactional"; import MailchimpClient from "@mailchimp/mailchimp_transactional";
import { BackendVariables } from "@Common/config/variables/Variables"; import { BackendVariables } from "@Common/config/variables/Variables";
import UsersService from "@Services/super-admin/UsersService/UsersService";
import EmailBuilder from "@Common/emails/EmailBuilder";
@Service() @Service()
export default class MailchimpService extends BaseService { export default class MailchimpService extends BaseService {
private static readonly from = "vincent.alamelle@smart-chain.fr"; private static readonly from = "no-reply@smart-chain.fr";
constructor( constructor(
private emailRepository: EmailRepository, private emailRepository: EmailRepository,
protected variables: BackendVariables, protected variables: BackendVariables,
private usersService: UsersService,
private emailBuilder: EmailBuilder,
) { ) {
super(); super();
} }
@ -32,7 +28,7 @@ export default class MailchimpService extends BaseService {
* @description : Create a new email * @description : Create a new email
* @throws {Error} If email cannot be created * @throws {Error} If email cannot be created
*/ */
public async create(emailEntity: Emails): Promise<Emails> { public async create(emailEntity: Emails): Promise<Emails> {
emailEntity.from = MailchimpService.from; emailEntity.from = MailchimpService.from;
return this.emailRepository.create(emailEntity); return this.emailRepository.create(emailEntity);
} }
@ -120,10 +116,4 @@ export default class MailchimpService extends BaseService {
}; };
}); });
} }
public async sendRecapEmails() {
const usersToEmail = await this.usersService.get({ where: { office_folders: { some:{ documents: { some: { document_status: "DEPOSITED" } } }} }, distinct: ["uid"], include: { contact: true } });
await this.emailBuilder.sendRecapEmails(usersToEmail);
}
} }

View File

@ -34,6 +34,14 @@ export default class DocumentsService extends BaseService {
return this.documentsRepository.create(document); return this.documentsRepository.create(document);
} }
/**
* @description : Delete a document
* @throws {Error} If document cannot be created
*/
public async delete(uid: string): Promise<Documents> {
return this.documentsRepository.delete(uid);
}
/** /**
* @description : Modify a document * @description : Modify a document
* @throws {Error} If document cannot be modified * @throws {Error} If document cannot be modified

View File

@ -23,14 +23,6 @@ export default class CustomersService extends BaseService {
* @throws {Error} If customer cannot be created * @throws {Error} If customer cannot be created
*/ */
public async create(customerEntity: Customer): Promise<Customers> { public async create(customerEntity: Customer): Promise<Customers> {
const customers = await this.get({
where: {
contact: {
OR: [{ email: customerEntity.contact?.email }, { cell_phone_number: customerEntity.contact?.cell_phone_number }],
},
},
});
if(customers[0]) return customers[0];
return this.customerRepository.create(customerEntity); return this.customerRepository.create(customerEntity);
} }

View File

@ -46,12 +46,11 @@ export default class DocumentsService extends BaseService {
public async refuse(uid: string, document: Partial<Document>, refused_reason: string): Promise<Documents> { public async refuse(uid: string, document: Partial<Document>, refused_reason: string): Promise<Documents> {
if (document.files) { if (document.files) {
for (let i = 0; i < document.files.length; i++) { for (let i = 0; i < document.files.length; i++) {
console.log("archiving file", document.files[i]?.uid);
await this.filesRepository.deleteKeyAndArchive(document.files[i]?.uid as string); await this.filesRepository.deleteKeyAndArchive(document.files[i]?.uid as string);
} }
} }
return this.documentsRepository.refuse(uid, document, refused_reason); return this.documentsRepository.refuse(uid, refused_reason);
} }
/** /**

View File

@ -3,16 +3,14 @@ import OfficeFoldersRepository from "@Repositories/OfficeFoldersRepository";
import BaseService from "@Services/BaseService"; import BaseService from "@Services/BaseService";
import { OfficeFolder } from "le-coffre-resources/dist/Notary"; import { OfficeFolder } from "le-coffre-resources/dist/Notary";
import { Service } from "typedi"; import { Service } from "typedi";
import DeedTypesService from "../DeedTypesService/DeedTypesService"; import { EFolderStatus, Prisma } from "@prisma/client";
import DeedsRepository from "@Repositories/DeedsRepository"; import DeedsService from "../DeedsService/DeedsService";
import { Prisma } from "@prisma/client";
@Service() @Service()
export default class OfficeFoldersService extends BaseService { export default class OfficeFoldersService extends BaseService {
constructor( constructor(
private officeFoldersRepository: OfficeFoldersRepository, private officeFoldersRepository: OfficeFoldersRepository,
private deedTypeService: DeedTypesService, private deedService: DeedsService,
private deedRepository: DeedsRepository,
) { ) {
super(); super();
} }
@ -30,10 +28,7 @@ export default class OfficeFoldersService extends BaseService {
* @throws {Error} If folder cannot be created * @throws {Error} If folder cannot be created
*/ */
public async create(officeFolderEntity: OfficeFolder): Promise<OfficeFolders> { public async create(officeFolderEntity: OfficeFolder): Promise<OfficeFolders> {
const deedType = await this.deedTypeService.getByUid(officeFolderEntity.deed!.deed_type!.uid!); const deed = await this.deedService.create(officeFolderEntity.deed!);
if (!deedType) throw new Error("deed type not found");
if (deedType.archived_at) throw new Error("deed type is archived");
const deed = await this.deedRepository.create(officeFolderEntity.deed!);
officeFolderEntity.deed!.uid = deed.uid; officeFolderEntity.deed!.uid = deed.uid;
return this.officeFoldersRepository.create(officeFolderEntity); return this.officeFoldersRepository.create(officeFolderEntity);
} }
@ -46,6 +41,14 @@ export default class OfficeFoldersService extends BaseService {
return this.officeFoldersRepository.update(officeFolderuid, officeFolderEntity); return this.officeFoldersRepository.update(officeFolderuid, officeFolderEntity);
} }
/**
* @description : Modify a folder status
* @throws {Error} If folder cannot be modified
*/
public async updateStatus(uid: string, officeFolderEntity: OfficeFolder) {
return this.officeFoldersRepository.updateStatus(uid,officeFolderEntity.status as EFolderStatus, officeFolderEntity.archived_description);
}
/** /**
* @description : Get a folder by uid * @description : Get a folder by uid
* @throws {Error} If folder cannot be get by uid * @throws {Error} If folder cannot be get by uid

View File

@ -46,12 +46,11 @@ export default class DocumentsService extends BaseService {
public async refuse(uid: string, document: Partial<Document>, refused_reason: string): Promise<Documents> { public async refuse(uid: string, document: Partial<Document>, refused_reason: string): Promise<Documents> {
if (document.files) { if (document.files) {
for (let i = 0; i < document.files.length; i++) { for (let i = 0; i < document.files.length; i++) {
console.log("archiving file", document.files[i]?.uid);
await this.filesRepository.deleteKeyAndArchive(document.files[i]?.uid as string); await this.filesRepository.deleteKeyAndArchive(document.files[i]?.uid as string);
} }
} }
return this.documentsRepository.refuse(uid, document, refused_reason); return this.documentsRepository.refuse(uid, refused_reason);
} }
/** /**

View File

@ -3,16 +3,12 @@ import OfficeFoldersRepository from "@Repositories/OfficeFoldersRepository";
import BaseService from "@Services/BaseService"; import BaseService from "@Services/BaseService";
import { OfficeFolder } from "le-coffre-resources/dist/SuperAdmin"; import { OfficeFolder } from "le-coffre-resources/dist/SuperAdmin";
import { Service } from "typedi"; import { Service } from "typedi";
import DeedTypesService from "../DeedTypesService/DeedTypesService";
import DeedsRepository from "@Repositories/DeedsRepository";
import { Prisma } from "@prisma/client"; import { Prisma } from "@prisma/client";
@Service() @Service()
export default class OfficeFoldersService extends BaseService { export default class OfficeFoldersService extends BaseService {
constructor( constructor(
private officeFoldersRepository: OfficeFoldersRepository, private officeFoldersRepository: OfficeFoldersRepository,
private deedTypeService: DeedTypesService,
private deedRepository: DeedsRepository,
) { ) {
super(); super();
} }
@ -30,11 +26,6 @@ export default class OfficeFoldersService extends BaseService {
* @throws {Error} If folder cannot be created * @throws {Error} If folder cannot be created
*/ */
public async create(officeFolderEntity: OfficeFolder): Promise<OfficeFolders> { public async create(officeFolderEntity: OfficeFolder): Promise<OfficeFolders> {
const deedType = await this.deedTypeService.getByUid(officeFolderEntity.deed!.deed_type!.uid!);
if (!deedType) throw new Error("deed type not found");
if (deedType.archived_at) throw new Error("deed type is archived");
const deed = await this.deedRepository.create(officeFolderEntity.deed!);
officeFolderEntity.deed!.uid = deed.uid;
return this.officeFoldersRepository.create(officeFolderEntity); return this.officeFoldersRepository.create(officeFolderEntity);
} }

View File

@ -18,15 +18,11 @@ import OfficeFoldersRepository from "@Repositories/OfficeFoldersRepository";
import OfficeFolderService from "@Services/super-admin/OfficeFoldersService/OfficeFoldersService"; import OfficeFolderService from "@Services/super-admin/OfficeFoldersService/OfficeFoldersService";
import { initCustomers, initDeedType, initDocumentType, initOffice, initUsers } from "@Test/config/Init"; import { initCustomers, initDeedType, initDocumentType, initOffice, initUsers } from "@Test/config/Init";
import { OfficeFolder } from "le-coffre-resources/dist/SuperAdmin"; import { OfficeFolder } from "le-coffre-resources/dist/SuperAdmin";
import DeedTypesService from "@Services/super-admin/DeedTypesService/DeedTypesService";
import DeedsRepository from "@Repositories/DeedsRepository";
const prisma = new PrismaClient(); const prisma = new PrismaClient();
const OfficeFolderServiceTest = new OfficeFolderService( const OfficeFolderServiceTest = new OfficeFolderService(
Container.get(OfficeFoldersRepository), Container.get(OfficeFoldersRepository)
Container.get(DeedTypesService),
Container.get(DeedsRepository),
); );
beforeAll(async () => { beforeAll(async () => {