Merge Staging in Preprod

This commit is contained in:
Arnaud D. Natali 2023-10-02 00:29:02 +02:00 committed by GitHub
commit 8716964d2e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 1142 additions and 505 deletions

View File

@ -7,6 +7,8 @@ RUN npm install -D prisma@4.11.0
COPY package.json ./ COPY package.json ./
RUN apk update && apk add openssh-client git RUN apk update && apk add openssh-client git
# ENV PUPPETEER_CACHE_DIR=~/leCoffre/.cache/puppeteer
# ENV PUPPETEER_SKIP_DOWNLOAD=false
COPY id_rsa /root/.ssh/id_rsa COPY id_rsa /root/.ssh/id_rsa
RUN chmod 600 ~/.ssh/id_rsa RUN chmod 600 ~/.ssh/id_rsa
@ -22,6 +24,8 @@ WORKDIR leCoffre
COPY --from=deps leCoffre/node_modules ./node_modules COPY --from=deps leCoffre/node_modules ./node_modules
COPY --from=deps leCoffre/package.json package.json COPY --from=deps leCoffre/package.json package.json
#COPY --from=deps leCoffre/.cache ./.cache
COPY tsconfig.json tsconfig.json COPY tsconfig.json tsconfig.json
COPY src src COPY src src
@ -39,8 +43,9 @@ COPY --from=builder --chown=lecoffreuser leCoffre/node_modules ./node_modules
COPY --from=builder --chown=lecoffreuser leCoffre/dist dist COPY --from=builder --chown=lecoffreuser leCoffre/dist dist
COPY --from=builder --chown=lecoffreuser leCoffre/package.json ./package.json COPY --from=builder --chown=lecoffreuser leCoffre/package.json ./package.json
COPY --from=builder --chown=lecoffreuser leCoffre/src/common/databases ./src/common/databases COPY --from=builder --chown=lecoffreuser leCoffre/src/common/databases ./src/common/databases
#COPY --from=builder --chown=lecoffreuser leCoffre/.cache ./.cache
USER lecoffreuser USER lecoffreuser
CMD ["npm", "run", "api:start"] CMD ["npm", "run", "start"]
EXPOSE 3001 EXPOSE 3001

View File

@ -5,7 +5,7 @@ scwSecretKey: AgChoEnPitXp4Ny/rVMEcevaWKNVpyj2cJYAcq+yFqKwVwnLB+ffDvwqz9XBHu+6d4
lecoffreBack: lecoffreBack:
serviceAccountName: lecoffre-back-sa serviceAccountName: lecoffre-back-sa
envSecrets: stg-env envSecrets: stg-env
command: "'sh', '-c', 'export $(xargs </etc/env/.env) && npm run api:start'" command: "'sh', '-c', 'export $(xargs </etc/env/.env) && npm run start'"
imagePullSecrets: imagePullSecrets:
- name: docker-pull-secret - name: docker-pull-secret
image: image:

View File

@ -53,7 +53,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.84", "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.86",
"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",

View File

@ -8,6 +8,7 @@ import { validateOrReject } from "class-validator";
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()
@ -28,6 +29,12 @@ export default class CustomersController extends ApiController {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
} }
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;
const customerWhereInput: Prisma.CustomersWhereInput = { ...query.where, office_folders: { some: { office_uid: officeId } }};
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);

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 officeRoleHandler from "@App/middlewares/OfficeMembershipHandlers/OfficeRoleHandler"; import officeRoleHandler from "@App/middlewares/OfficeMembershipHandlers/OfficeRoleHandler";
import roleHandler from "@App/middlewares/RolesHandler"; import roleHandler from "@App/middlewares/RolesHandler";
import RulesService from "@Services/admin/RulesService/RulesService";
@Controller() @Controller()
@Service() @Service()
export default class OfficeRolesController extends ApiController { export default class OfficeRolesController extends ApiController {
constructor(private officeRolesService: OfficeRolesService) { constructor(private officeRolesService: OfficeRolesService, private rulesService: RulesService) {
super(); super();
} }
@ -30,7 +31,7 @@ export default class OfficeRolesController extends ApiController {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
} }
if(req.query["search"] && typeof req.query["search"] === "string") { if (req.query["search"] && typeof req.query["search"] === "string") {
const filter = req.query["search"]; const filter = req.query["search"];
query = { query = {
where: { where: {
@ -39,7 +40,7 @@ export default class OfficeRolesController extends ApiController {
mode: "insensitive", mode: "insensitive",
}, },
}, },
} };
} }
const officeId: string = req.body.user.office_Id; const officeId: string = req.body.user.office_Id;
@ -108,11 +109,23 @@ export default class OfficeRolesController extends ApiController {
return; return;
} }
if (req.body.rules) {
const allRules = await this.rulesService.get({
where: {
namespace: "notary",
},
});
req.body.rules = req.body.rules.filter((rule: any) => {
const ruleFound = allRules.find((r) => r.uid === rule.uid && r.namespace === "notary");
return ruleFound;
});
}
//init IOfficeRole resource with request body values //init IOfficeRole resource with request body values
const officeRoleEntity = OfficeRole.hydrate<OfficeRole>(req.body); const officeRoleEntity = OfficeRole.hydrate<OfficeRole>(req.body);
//validate officeRole //validate officeRole
await validateOrReject(officeRoleEntity, { groups: ["updateOfficeRole"] }); await validateOrReject(officeRoleEntity, { groups: ["updateOfficeRole"] });
//call service to get prisma entity //call service to get prisma entity
const officeRoleEntityUpdated = await this.officeRolesService.update(officeRoleEntity); const officeRoleEntityUpdated = await this.officeRolesService.update(officeRoleEntity);

View File

@ -1,79 +0,0 @@
import { Response, Request } from "express";
import { Controller, Get } from "@ControllerPattern/index";
import ApiController from "@Common/system/controller-pattern/ApiController";
import CustomersService from "@Services/customer/CustomersService/CustomersService";
import { Service } from "typedi";
import Customer from "le-coffre-resources/dist/Customer";
import authHandler from "@App/middlewares/AuthHandler";
import ruleHandler from "@App/middlewares/RulesHandler";
@Controller()
@Service()
export default class CustomersController extends ApiController {
constructor(private customersService: CustomersService) {
super();
}
/**
* @description Get all customers
*/
@Get("/api/v1/customer/customers")
protected async get(req: Request, response: Response) {
try {
//get query
let query;
if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string);
}
//call service to get prisma entity
const customersEntities = await this.customersService.get(query);
//Hydrate ressource with prisma entity
const customers = Customer.hydrateArray<Customer>(customersEntities, { strategy: "excludeAll" });
//success
this.httpSuccess(response, customers);
} catch (error) {
this.httpInternalError(response, error);
return;
}
}
/**
* @description Get a specific customer by uid
*/
@Get("/api/v1/customer/customers/:uid", [authHandler, ruleHandler])
protected async getOneByUid(req: Request, response: Response) {
try {
const uid = req.params["uid"];
if (!uid) {
this.httpBadRequest(response, "No uid provided");
return;
}
let query;
if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string);
}
const customerEntity = await this.customersService.getByUid(uid, query);
if (!customerEntity) {
this.httpNotFoundRequest(response, "customer not found");
return;
}
//Hydrate ressource with prisma entity
const customer = Customer.hydrate<Customer>(customerEntity, { strategy: "excludeAll" });
//success
this.httpSuccess(response, customer);
} catch (error) {
this.httpInternalError(response, error);
return;
}
}
}

View File

@ -24,13 +24,14 @@ export default class DocumentsController extends ApiController {
protected async get(req: Request, response: Response) { protected async get(req: Request, response: Response) {
try { try {
//get query //get query
let query: Prisma.CustomersFindManyArgs = {}; 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);
} }
const customerId: string = req.body.user.customerId; const customerId: string = req.body.user.customerId;
const customerWhereInput: Prisma.DocumentsWhereInput ={ depositor: { uid: customerId } }; 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: { uid: customerId } };
query.where = customerWhereInput; query.where = customerWhereInput;

View File

@ -5,6 +5,8 @@ import OfficeFoldersService from "@Services/customer/OfficeFoldersService/Office
import { Service } from "typedi"; import { Service } from "typedi";
import { OfficeFolders, Prisma } from "@prisma/client"; 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 authHandler from "@App/middlewares/AuthHandler";
// 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 folderHandler from "@App/middlewares/OfficeMembershipHandlers/FolderHandler"; // import folderHandler from "@App/middlewares/OfficeMembershipHandlers/FolderHandler";
@ -19,7 +21,7 @@ export default class OfficeFoldersController extends ApiController {
/** /**
* @description Get all folders * @description Get all folders
*/ */
@Get("/api/v1/customer/folders") @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
@ -28,37 +30,14 @@ export default class OfficeFoldersController extends ApiController {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
} }
const customerId: string = req.body.user.customerId;
if (req.query["search"] && typeof req.query["search"] === "string") { if(!customerId) {
const filter = req.query["search"]; this.httpBadRequest(response, "No customerId provided");
query = { return;
where: {
OR: [
{
name: { contains: filter, mode: "insensitive" },
},
{
folder_number: { contains: filter, mode: "insensitive" },
},
{
customers: {
some: {
contact: {
OR: [
{ first_name: { contains: filter, mode: "insensitive" } },
{ last_name: { contains: filter, mode: "insensitive" } },
],
},
},
},
},
],
},
};
} }
const officeWhereInput: Prisma.OfficesWhereInput = {}; if(query.where?.customers) delete query.where.customers;
if (!query.where) query.where = { office: officeWhereInput }; const officeFolderWhereInput: Prisma.OfficeFoldersWhereInput = { ...query.where, customers: { some: { uid: customerId } }};
query.where.office = officeWhereInput; query.where = officeFolderWhereInput;
//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);
@ -79,7 +58,7 @@ export default class OfficeFoldersController extends ApiController {
* @description Get a specific folder by uid * @description Get a specific folder by uid
* @returns IFolder * @returns IFolder
*/ */
@Get("/api/v1/customer/folders/:uid") @Get("/api/v1/customer/folders/:uid", [authHandler, officeFolderHandler])
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"];
@ -91,8 +70,10 @@ export default class OfficeFoldersController 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?.customers) {
query.customers = true;
}
} }
const officeFolderEntity = await this.officeFoldersService.getByUid(uid, query); const officeFolderEntity = await this.officeFoldersService.getByUid(uid, query);
if (!officeFolderEntity) { if (!officeFolderEntity) {

View File

@ -35,13 +35,11 @@ export default class CustomerController extends ApiController {
} }
try { try {
const enrollment = await this.id360Service.getEnrollment(callbackToken); const enrollment = await this.id360Service.getEnrollment(callbackToken);
console.log("enrollment", enrollment);
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);
console.log(customerData.external_methods.france_connect.results);
const customer = await this.customerService.get({ const customer = await this.customerService.get({
where: { where: {
contact: { contact: {
@ -55,7 +53,6 @@ export default class CustomerController extends ApiController {
contact: true, contact: true,
} }
}); });
console.log(customer);
// 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,
// ); // );

View File

@ -50,10 +50,7 @@ export default class DocumentController extends ApiController {
this.httpBadRequest(response, "Missing document id"); this.httpBadRequest(response, "Missing document id");
return; return;
} }
await this.id360Service.createEnrollment(documentId!);
const enrl = await this.id360Service.createEnrollment(documentId!);
console.log(enrl)
//success //success
this.httpSuccess(response); this.httpSuccess(response);
} catch (error) { } catch (error) {

View File

@ -37,30 +37,7 @@ export default class UserController extends ApiController {
const payload = await this.authService.getUserJwtPayload(user.idNot); const payload = await this.authService.getUserJwtPayload(user.idNot);
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 });
} catch (error) {
console.log(error);
this.httpInternalError(response);
return;
}
}
@Post("/api/v1/idnot/user/login/:idnot")
protected async login(req: Request, response: Response) {
try {
const id = req.params["idnot"];
if (!id) throw new Error("idnot is required");
const payload = await this.authService.getUserJwtPayload(id);
if (!payload) {
this.httpNotFoundRequest(response);
return;
}
const accessToken = this.authService.generateAccessToken(payload);
const refreshToken = this.authService.generateRefreshToken(payload);
//success
this.httpSuccess(response, { accessToken, refreshToken }); this.httpSuccess(response, { accessToken, refreshToken });
} catch (error) { } catch (error) {
console.log(error); console.log(error);

View File

@ -7,6 +7,7 @@ import { Customer } 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";
import ruleHandler from "@App/middlewares/RulesHandler"; import ruleHandler from "@App/middlewares/RulesHandler";
import { Prisma } from "@prisma/client";
@Controller() @Controller()
@Service() @Service()
@ -22,11 +23,17 @@ 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);
} }
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;
const customerWhereInput: Prisma.CustomersWhereInput = { ...query.where, office_folders: { some: { office_uid: officeId } }};
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);

View File

@ -5,15 +5,35 @@ import { Service } from "typedi";
import { OfficeFolder } from "le-coffre-resources/dist/Notary"; import { OfficeFolder } from "le-coffre-resources/dist/Notary";
import { getFolderHashes } from "@Common/optics/notary"; import { getFolderHashes } from "@Common/optics/notary";
import OfficeFoldersService from "@Services/notary/OfficeFoldersService/OfficeFoldersService"; import OfficeFoldersService from "@Services/notary/OfficeFoldersService/OfficeFoldersService";
import OfficeFolderAnchorsRepository from "@Repositories/OfficeFolderAnchorsRepository";
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";
import folderHandler from "@App/middlewares/OfficeMembershipHandlers/FolderHandler"; import folderHandler from "@App/middlewares/OfficeMembershipHandlers/FolderHandler";
import OfficeFolderAnchor from "le-coffre-resources/dist/Notary/OfficeFolderAnchor";
const hydrateOfficeFolderAnchor = (data: any): OfficeFolderAnchor =>
OfficeFolderAnchor.hydrate<OfficeFolderAnchor>(
{
hash_sources: data.hash_sources,
root_hash: data.root_hash,
blockchain: data.transactions[0].blockchain,
status: data.transactions[0].status,
anchor_nb_try: data.transactions[0].anchor_nb_try,
tx_id: data.transactions[0].tx_id?.toString() ?? undefined,
tx_link: data.transactions[0].tx_link,
tx_hash: data.transactions[0].tx_hash,
anchored_at: data.transactions[0].anchoring_timestamp,
},
{ strategy: "excludeAll" },
);
@Controller() @Controller()
@Service() @Service()
export default class OfficeFoldersController extends ApiController { export default class OfficeFoldersController extends ApiController {
constructor(private secureService: SecureService, private officeFoldersService: OfficeFoldersService) { constructor(private secureService: SecureService, private officeFolderAnchorsRepository: OfficeFolderAnchorsRepository, private officeFoldersService: OfficeFoldersService) {
super(); super();
} }
@ -83,16 +103,30 @@ export default class OfficeFoldersController extends ApiController {
files: true, files: true,
}, },
}, },
folder_anchor: true,
}; };
const officeFolderFound = await this.officeFoldersService.getByUid(uid, query); const officeFolderFound: any = await this.officeFoldersService.getByUid(uid, query);
if (!officeFolderFound) { if (!officeFolderFound) {
this.httpNotFoundRequest(response, "Office folder not found"); this.httpNotFoundRequest(response, "Office folder not found");
return; return;
} }
const officeFolderAnchorFound = OfficeFolderAnchor.hydrate<OfficeFolderAnchor>(officeFolderFound.folder_anchor, {
strategy: "excludeAll",
});
if (officeFolderAnchorFound) {
this.httpBadRequest(response, {
error: "Office folder already anchored",
folder_anchor: officeFolderAnchorFound,
});
return;
}
const officeFolder = OfficeFolder.hydrate<OfficeFolder>(officeFolderFound, { strategy: "excludeAll" }); const officeFolder = OfficeFolder.hydrate<OfficeFolder>(officeFolderFound, { strategy: "excludeAll" });
const folderHashes = getFolderHashes(officeFolder); const folderHashes = getFolderHashes(officeFolder);
if (folderHashes.length === 0) { if (folderHashes.length === 0) {
@ -101,9 +135,20 @@ export default class OfficeFoldersController extends ApiController {
} }
const sortedHashes = [...folderHashes].sort(); const sortedHashes = [...folderHashes].sort();
const anchor = await this.secureService.anchor(sortedHashes); const data = await this.secureService.anchor(sortedHashes);
this.httpSuccess(response, anchor); const officeFolderAnchor = hydrateOfficeFolderAnchor(data);
const newOfficeFolderAnchor = await this.officeFolderAnchorsRepository.create(
officeFolderAnchor
);
await this.officeFoldersService.update(
uid,
OfficeFolder.hydrate<OfficeFolder>({ uid: uid, folder_anchor: newOfficeFolderAnchor }, { strategy: "excludeAll" }),
);
this.httpSuccess(response, officeFolderAnchor);
} catch (error) { } catch (error) {
this.httpInternalError(response, error); this.httpInternalError(response, error);
return; return;
@ -129,9 +174,10 @@ export default class OfficeFoldersController extends ApiController {
files: true, files: true,
}, },
}, },
folder_anchor: true,
}; };
const officeFolderFound = await this.officeFoldersService.getByUid(uid, query); const officeFolderFound: any = await this.officeFoldersService.getByUid(uid, query);
if (!officeFolderFound) { if (!officeFolderFound) {
this.httpNotFoundRequest(response, "Office folder not found"); this.httpNotFoundRequest(response, "Office folder not found");
@ -147,9 +193,31 @@ export default class OfficeFoldersController extends ApiController {
} }
const sortedHashes = [...folderHashes].sort(); const sortedHashes = [...folderHashes].sort();
const anchor = await this.secureService.verify(sortedHashes); const officeFolderAnchorFound = OfficeFolderAnchor.hydrate<OfficeFolderAnchor>(officeFolderFound.folder_anchor, {
strategy: "excludeAll",
});
this.httpSuccess(response, anchor); if (!officeFolderAnchorFound || !officeFolderAnchorFound.uid) {
this.httpNotFoundRequest(response, {error: "Not anchored", hash_sources: sortedHashes});
return;
}
const data = await this.secureService.verify(sortedHashes);
if (data.errors || data.transactions.length === 0) {
this.httpNotFoundRequest(response, {error: "Not anchored", hash_sources: sortedHashes});
return;
}
const officeFolderAnchor = hydrateOfficeFolderAnchor(data);
const updatedOfficeFolderAnchor = await this.officeFolderAnchorsRepository.update(
officeFolderAnchorFound.uid,
officeFolderAnchor
);
this.httpSuccess(response, updatedOfficeFolderAnchor);
return;
} catch (error) { } catch (error) {
this.httpInternalError(response, error); this.httpInternalError(response, error);
return; return;

View File

@ -26,6 +26,10 @@ export default class RulesController extends ApiController {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
} }
query.where = {
...query.where,
namespace: "notary",
};
//call service to get prisma entity //call service to get prisma entity
const rulesEntities = await this.rulesService.get(query); const rulesEntities = await this.rulesService.get(query);
@ -57,6 +61,11 @@ export default class RulesController extends ApiController {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
} }
query.where = {
...query.where,
namespace: "notary",
};
const ruleEntity = await this.rulesService.getByUid(uid, query); const ruleEntity = await this.rulesService.getByUid(uid, query);
if (!ruleEntity) { if (!ruleEntity) {

View File

@ -5,6 +5,7 @@ import { Service } from "typedi";
import UserNotification from "le-coffre-resources/dist/Notary/UserNotification"; 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";
@Controller() @Controller()
@Service() @Service()
@ -16,7 +17,7 @@ export default class UserNotificationController extends ApiController {
/** /**
* @description Get all customers * @description Get all customers
*/ */
@Get("/api/v1/notifications", [authHandler]) @Get("/api/v1/notary/notifications", [authHandler])
protected async get(req: Request, response: Response) { protected async get(req: Request, response: Response) {
try { try {
//get query //get query
@ -25,11 +26,13 @@ export default class UserNotificationController extends ApiController {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
} }
if (query.where) {
query.where = { ...query.where, user: { uid: req.body.user.uid } }; const userId: string = req.body.user.userId;
} else { if(query.where?.user_uid) delete query.where.user_uid;
query.where = { user: { uid: req.body.user.uid } }; if(query.where?.user?.uid) delete query.where.user.uid;
} const notificationWhereInput: Prisma.UserNotificationsWhereInput = { ...query.where, user_uid: userId };
query.where = notificationWhereInput;
query.include = { notification: true }; query.include = { notification: true };
//call service to get prisma entity //call service to get prisma entity
const userNotificationEntities = await this.userNotificationService.get(query); const userNotificationEntities = await this.userNotificationService.get(query);
@ -48,7 +51,7 @@ export default class UserNotificationController extends ApiController {
/** /**
* @description Modify a specific customer by uid * @description Modify a specific customer by uid
*/ */
@Put("/api/v1/notifications/:uid") @Put("/api/v1/notary/notifications/:uid", [authHandler])
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"];
@ -64,6 +67,11 @@ export default class UserNotificationController extends ApiController {
return; return;
} }
if(userNotificationFound.user_uid !== req.body.user.userId) {
this.httpForbidden(response, "You are not allowed to update this user notification");
return;
}
//init IUser resource with request body values //init IUser resource with request body values
const userNotificationEntity = UserNotification.hydrate<UserNotification>(req.body); const userNotificationEntity = UserNotification.hydrate<UserNotification>(req.body);
@ -86,7 +94,7 @@ export default class UserNotificationController extends ApiController {
/** /**
* @description Get a specific customer by uid * @description Get a specific customer by uid
*/ */
@Get("/api/v1/notifications/:uid") @Get("/api/v1/notary/notifications/:uid", [authHandler])
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"];
@ -108,6 +116,11 @@ export default class UserNotificationController extends ApiController {
return; return;
} }
if(userNotificationEntity.user_uid !== req.body.userId) {
this.httpForbidden(response, "You are allowed to get this user notification");
return;
}
//Hydrate ressource with prisma entity //Hydrate ressource with prisma entity
const userNotification = UserNotification.hydrate<UserNotification>(userNotificationEntity, { strategy: "excludeAll" }); const userNotification = UserNotification.hydrate<UserNotification>(userNotificationEntity, { strategy: "excludeAll" });

View File

@ -8,6 +8,7 @@ import { validateOrReject } from "class-validator";
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()
@ -28,6 +29,12 @@ export default class CustomersController extends ApiController {
query = JSON.parse(req.query["q"] as string); query = JSON.parse(req.query["q"] as string);
} }
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;
const customerWhereInput: Prisma.CustomersWhereInput = { ...query.where, office_folders: { some: { office_uid: officeId } }};
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);

View File

@ -42,14 +42,12 @@ import FilesControllerCustomer from "./api/customer/FilesController";
import DocumentsControllerCustomer from "./api/customer/DocumentsController"; import DocumentsControllerCustomer from "./api/customer/DocumentsController";
import OfficeFoldersController from "./api/customer/OfficeFoldersController"; import OfficeFoldersController from "./api/customer/OfficeFoldersController";
import OfficeFolderAnchorsController from "./api/notary/OfficeFolderAnchorsController"; import OfficeFolderAnchorsController from "./api/notary/OfficeFolderAnchorsController";
import CustomersController from "./api/customer/CustomersController";
import AppointmentsController from "./api/super-admin/AppointmentsController"; import AppointmentsController from "./api/super-admin/AppointmentsController";
import VotesController from "./api/super-admin/VotesController"; import VotesController from "./api/super-admin/VotesController";
import LiveVoteController from "./api/super-admin/LiveVoteController"; import LiveVoteController from "./api/super-admin/LiveVoteController";
import DocumentControllerId360 from "./api/id360/DocumentController"; import DocumentControllerId360 from "./api/id360/DocumentController";
import CustomerControllerId360 from "./api/id360/CustomerController"; import CustomerControllerId360 from "./api/id360/CustomerController";
import UserNotificationController from "./api/notary/UserNotificationController";
import UserNotificationController from "./api/common/UserNotificationController";
/** /**
@ -105,7 +103,6 @@ export default {
Container.get(DocumentsControllerCustomer); Container.get(DocumentsControllerCustomer);
Container.get(OfficeFoldersController); Container.get(OfficeFoldersController);
Container.get(OfficeFolderAnchorsController); Container.get(OfficeFolderAnchorsController);
Container.get(CustomersController);
Container.get(UserNotificationController); Container.get(UserNotificationController);
Container.get(DocumentControllerId360); Container.get(DocumentControllerId360);
Container.get(CustomerControllerId360); Container.get(CustomerControllerId360);

View File

@ -0,0 +1,24 @@
import HttpCodes from "@Common/system/controller-pattern/HttpCodes";
import OfficeFoldersService from "@Services/customer/OfficeFoldersService/OfficeFoldersService";
import { NextFunction, Request, Response } from "express";
import Container from "typedi";
export default async function officeFolderHandler(req: Request, response: Response, next: NextFunction) {
const customerId = req.body.user.customerId;
const uid = req.path && req.path.split("/")[5];
if (uid) {
const officeFolderService = Container.get(OfficeFoldersService);
const officeFolder = await officeFolderService.getByUidWithCustomers(uid);
if (!officeFolder) {
response.status(HttpCodes.NOT_FOUND).send("Folder not found");
return;
}
if (!officeFolder.customers.find((customer) => customer.uid == customerId)) {
response.status(HttpCodes.UNAUTHORIZED).send("Not authorized with this depositor");
return;
}
}
next();
}

View File

@ -45,12 +45,12 @@ export default async function documentHandler(req: Request, response: Response,
const document = await documentService.getByUidWithOffice(uid!); const document = await documentService.getByUidWithOffice(uid!);
if (!document) { if (!document) {
response.sendStatus(HttpCodes.NOT_FOUND); response.sendStatus(HttpCodes.NOT_FOUND).send("Document not found");
return; return;
} }
if (document.document_type.office.uid != officeId) { if (document.folder.office.uid != officeId) {
response.sendStatus(HttpCodes.UNAUTHORIZED); response.sendStatus(HttpCodes.UNAUTHORIZED).send("Unauthorized with this office");
return; return;
} }
} }

View File

@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "rules" ADD COLUMN "namespace" VARCHAR(255) NOT NULL DEFAULT 'notary';

View File

@ -299,7 +299,7 @@ model Rules {
updated_at DateTime? @updatedAt updated_at DateTime? @updatedAt
role Roles[] @relation("RolesHasRules") role Roles[] @relation("RolesHasRules")
office_roles OfficeRoles[] @relation("OfficeRolesHasRules") office_roles OfficeRoles[] @relation("OfficeRolesHasRules")
namespace String @db.VarChar(255) @default("notary")
@@map("rules") @@map("rules")
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,11 @@
import DocumentsService from "@Services/super-admin/DocumentsService/DocumentsService"; import DocumentsService from "@Services/super-admin/DocumentsService/DocumentsService";
import { Documents } from "@prisma/client"; import { Documents, OfficeFolders } from "@prisma/client";
import User, { Document, OfficeFolder, Vote } from "le-coffre-resources/dist/SuperAdmin"; import User, { Document, OfficeFolder, Vote } from "le-coffre-resources/dist/SuperAdmin";
import { Service } from "typedi"; import { Service } from "typedi";
import NotificationsService from "@Services/common/NotificationsService/NotificationsService"; import NotificationsService from "@Services/common/NotificationsService/NotificationsService";
import UsersService from "@Services/super-admin/UsersService/UsersService"; import UsersService from "@Services/super-admin/UsersService/UsersService";
import OfficeFoldersService from "@Services/super-admin/OfficeFoldersService/OfficeFoldersService"; import OfficeFoldersService from "@Services/super-admin/OfficeFoldersService/OfficeFoldersService";
import { BackendVariables } from "@Common/config/variables/Variables";
@Service() @Service()
export default class NotificationBuilder { export default class NotificationBuilder {
@ -13,6 +14,7 @@ export default class NotificationBuilder {
private documentsService: DocumentsService, private documentsService: DocumentsService,
private usersService: UsersService, private usersService: UsersService,
private foldersService: OfficeFoldersService, private foldersService: OfficeFoldersService,
private backendVariables: BackendVariables
) {} ) {}
public async sendDocumentDepositedNotification(documentEntity: Documents) { public async sendDocumentDepositedNotification(documentEntity: Documents) {
@ -32,33 +34,33 @@ export default class NotificationBuilder {
" " + " " +
document.depositor?.contact?.last_name + document.depositor?.contact?.last_name +
" vous a envoyé un document à valider", " vous a envoyé un document à valider",
redirection_url: "", redirection_url: `${this.backendVariables.APP_HOST}/folders/${document.folder?.uid}/documents/${document.uid}`,
created_at: new Date(), created_at: new Date(),
updated_at: new Date(), updated_at: new Date(),
user: document.folder!.stakeholders || [], user: document.folder!.stakeholders || [],
}); });
} }
public async sendDocumentAnchoredNotification(documentEntity: Documents) { public async sendFolderAnchoredNotification(folderEntity: OfficeFolders) {
const documentPrisma = await this.documentsService.getByUid(documentEntity.uid, { if(!folderEntity.uid) return;
depositor: { include: { contact: true } }, const officeFolderPrisma = await this.foldersService.getByUid(folderEntity.uid,
folder: { include: { folder_anchor: true, office: true, stakeholders: true } }, { folder_anchor: true, office: true, stakeholders: true }
}); );
if (!documentPrisma) throw new Error("Document not found"); if (!officeFolderPrisma) throw new Error("Folder not found");
const document = Document.hydrate<Document>(documentPrisma); const folder = OfficeFolder.hydrate<OfficeFolder>(officeFolderPrisma);
if (document.folder?.folder_anchor?.status !== "VERIFIED_ON_CHAIN") return; if (folder.folder_anchor?.status !== "VERIFIED_ON_CHAIN") return;
this.notificationsService.create({ this.notificationsService.create({
message: message:
"Le dossier " + "Le dossier " +
document.folder?.folder_number + folder.folder_number +
" - " + " - " +
document.folder?.name + folder.name +
" a été certifié. Vous pouvez désormais télécharger le certificat de dépôt pour le mettre dans la GED de votre logiciel de rédaction d'acte.", " a été certifié. Vous pouvez désormais télécharger le certificat de dépôt pour le mettre dans la GED de votre logiciel de rédaction d'acte.",
redirection_url: "", redirection_url: `${this.backendVariables.APP_HOST}/folders/${folder?.uid}`,
created_at: new Date(), created_at: new Date(),
updated_at: new Date(), updated_at: new Date(),
user: document.folder!.stakeholders || [], user: folder.stakeholders || [],
}); });
} }
@ -80,7 +82,7 @@ export default class NotificationBuilder {
this.notificationsService.create({ this.notificationsService.create({
message: message, message: message,
redirection_url: "", redirection_url: `${this.backendVariables.APP_HOST}/users/${vote.appointment.targeted_user.uid}`,
created_at: new Date(), created_at: new Date(),
updated_at: new Date(), updated_at: new Date(),
user: superAdminList || [], user: superAdminList || [],
@ -131,7 +133,7 @@ export default class NotificationBuilder {
" avant le " + " avant le " +
formattedDate + formattedDate +
" (date limite d'expiration des documents).", " (date limite d'expiration des documents).",
redirection_url: "", redirection_url: `${this.backendVariables.APP_HOST}/folders/${folder.uid}`,
created_at: new Date(), created_at: new Date(),
updated_at: new Date(), updated_at: new Date(),
user: folder.stakeholders || [], user: folder.stakeholders || [],

View File

@ -0,0 +1,68 @@
import Database from "@Common/databases/database";
import BaseRepository from "@Repositories/BaseRepository";
import { Service } from "typedi";
import { OfficeFolderAnchors, Prisma } from "@prisma/client";
import { OfficeFolderAnchor } from "le-coffre-resources/dist/SuperAdmin";
@Service()
export default class OfficeFolderAnchorsRepository extends BaseRepository {
constructor(private database: Database) {
super();
}
protected get model() {
return this.database.getClient().officeFolderAnchors;
}
protected get instanceDb() {
return this.database.getClient();
}
/**
* @description : Create new office folder anchor
*/
public async create(officeFolderAnchor: OfficeFolderAnchor): Promise<OfficeFolderAnchors> {
const createArgs: Prisma.OfficeFolderAnchorsCreateArgs = {
data: {
hash_sources: officeFolderAnchor.hash_sources,
root_hash: officeFolderAnchor.root_hash!,
blockchain: officeFolderAnchor.blockchain as OfficeFolderAnchors["blockchain"],
status: officeFolderAnchor.status as OfficeFolderAnchors["status"],
anchor_nb_try: officeFolderAnchor.anchor_nb_try,
tx_id: officeFolderAnchor.tx_id,
tx_link: officeFolderAnchor.tx_link,
tx_hash: officeFolderAnchor.tx_hash,
anchored_at: officeFolderAnchor.anchored_at,
},
};
return this.model.create({ ...createArgs });
}
/**
* @description : Update data of an office folder anchor
*/
public async update(officeFolderAnchorUid: string, officeFolderAnchor: OfficeFolderAnchor): Promise<OfficeFolderAnchors> {
const updateArgs: Prisma.OfficeFolderAnchorsUpdateArgs = {
where: {
uid: officeFolderAnchorUid,
},
data: {
blockchain: officeFolderAnchor.blockchain as OfficeFolderAnchors["blockchain"],
status: officeFolderAnchor.status as OfficeFolderAnchors["status"],
anchor_nb_try: officeFolderAnchor.anchor_nb_try,
tx_id: officeFolderAnchor.tx_id,
tx_link: officeFolderAnchor.tx_link,
tx_hash: officeFolderAnchor.tx_hash,
anchored_at: officeFolderAnchor.anchored_at,
},
};
return this.model.update({
...updateArgs,
});
}
}

View File

@ -84,6 +84,7 @@ export default class OfficeFoldersRepository extends BaseRepository {
uid: document.uid!, uid: document.uid!,
})), })),
}, },
folder_anchor_uid: officeFolder.folder_anchor?.uid,
}, },
}; };
@ -93,6 +94,7 @@ export default class OfficeFoldersRepository extends BaseRepository {
stakeholders: true, stakeholders: true,
customers: true, customers: true,
documents: true, documents: true,
folder_anchor: true,
}, },
}); });
} }
@ -109,6 +111,20 @@ export default class OfficeFoldersRepository extends BaseRepository {
}); });
} }
/**
* @description : Find one office folder
*/
public async findOneByUidWithCustomers(uid: string) {
return this.model.findUnique({
where: {
uid: uid,
},
include: {
customers: true,
}
});
}
/** /**
* @description : Find one office folder * @description : Find one office folder
*/ */

View File

@ -31,7 +31,8 @@ export default class RulesRepository extends BaseRepository {
const createArgs: Prisma.RulesCreateArgs = { const createArgs: Prisma.RulesCreateArgs = {
data: { data: {
name: rule.name, name: rule.name,
label: rule.label label: rule.label,
namespace: rule.namespace,
}, },
}; };
@ -48,7 +49,7 @@ export default class RulesRepository extends BaseRepository {
}, },
data: { data: {
name: rule.name, name: rule.name,
label: rule.label label: rule.label,
}, },
}; };

View File

@ -40,6 +40,10 @@ export default abstract class BaseController {
return this.httpResponse(response, HttpCodes.NOT_IMPLEMENTED, responseData); return this.httpResponse(response, HttpCodes.NOT_IMPLEMENTED, responseData);
} }
protected httpForbidden(response: Response, responseData: IResponseData = "Forbidden") {
return this.httpResponse(response, HttpCodes.FORBIDDEN, responseData);
}
protected httpResponse(response: Response, httpCode: HttpCodes, responseData: IResponseData = {}) { protected httpResponse(response: Response, httpCode: HttpCodes, responseData: IResponseData = {}) {
if (responseData instanceof Error) { if (responseData instanceof Error) {
throw responseData; throw responseData;

View File

@ -8,5 +8,6 @@ enum HttpCodes {
NOT_IMPLEMENTED = 501, NOT_IMPLEMENTED = 501,
NOT_FOUND = 404, NOT_FOUND = 404,
UNAUTHORIZED = 401, UNAUTHORIZED = 401,
FORBIDDEN = 403,
} }
export default HttpCodes; export default HttpCodes;

View File

@ -53,7 +53,7 @@ export default class AnchoringProofService extends BaseService {
<text fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="12" letter-spacing="0.5px"><tspan x="333" y="187.364">[[ANCHORING_TIME]]</tspan></text> <text fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="12" letter-spacing="0.5px"><tspan x="333" y="187.364">[[ANCHORING_TIME]]</tspan></text>
<text fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="21" font-weight="600" letter-spacing="0em"><tspan x="258" y="163.136">Certificat de d&#xe9;p&#xf4;t international</tspan></text> <text fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="21" font-weight="600" letter-spacing="0em"><tspan x="258" y="163.136">Certificat de d&#xe9;p&#xf4;t international</tspan></text>
<text fill="#320756" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="11" font-weight="600" letter-spacing="0.5px"><tspan x="119" y="262">Hash :</tspan></text> <text fill="#320756" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="11" font-weight="600" letter-spacing="0.5px"><tspan x="119" y="262">Hash :</tspan></text>
<text fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="11" letter-spacing="0.5px"><tspan x="267" y="261.5">b834ce9229ee2c2283c837685772a473</tspan></text> <text fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="11" letter-spacing="0.5px"><tspan x="267" y="261.5">[[ROOT_HASH]]</tspan></text>
<path d="M119 290H723" stroke="#E7E7E7"/> <path d="M119 290H723" stroke="#E7E7E7"/>
<text fill="#320756" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="14" font-weight="600" letter-spacing="0.5px"><tspan x="119" y="327.091">D&#xe9;posant(s)</tspan></text> <text fill="#320756" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="14" font-weight="600" letter-spacing="0.5px"><tspan x="119" y="327.091">D&#xe9;posant(s)</tspan></text>
<text fill="#320756" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="11" font-weight="600" letter-spacing="0.5px"><tspan x="119" y="356">Auteur :</tspan></text> <text fill="#320756" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="11" font-weight="600" letter-spacing="0.5px"><tspan x="119" y="356">Auteur :</tspan></text>
@ -62,7 +62,7 @@ export default class AnchoringProofService extends BaseService {
<text fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="11" letter-spacing="0.5px"><tspan x="267" y="377.5">Smart-Chain</tspan></text> <text fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="11" letter-spacing="0.5px"><tspan x="267" y="377.5">Smart-Chain</tspan></text>
<path d="M119 406H723" stroke="#E7E7E7"/> <path d="M119 406H723" stroke="#E7E7E7"/>
<text fill="#320756" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="14" font-weight="600" letter-spacing="0.5px"><tspan x="119" y="443.091">Explorateur blockchain</tspan></text> <text fill="#320756" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="14" font-weight="600" letter-spacing="0.5px"><tspan x="119" y="443.091">Explorateur blockchain</tspan></text>
<text fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="11" letter-spacing="0.5px" text-decoration="underline"><tspan x="119" y="472"><a href="https://tzstats.com/opYWLHH96gbV8HPajRqmoRx3UBVbr6iXz43kuHqm8ey4LLPWqeC">https://tzstats.com/opYWLHH96gbV8HPajRqmoRx3UBVbr6iXz43kuHqm8ey4LLPWqeC</a></tspan></text> <text fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="11" letter-spacing="0.5px" text-decoration="underline"><tspan x="119" y="472"><a href="[[TX_LINK]]">[[TX_LINK]]</a></tspan></text>
</g> </g>
</svg> </svg>
`; `;
@ -73,6 +73,7 @@ export default class AnchoringProofService extends BaseService {
public async generate(data: AnchoringProofData): Promise<Buffer> { public async generate(data: AnchoringProofData): Promise<Buffer> {
const browser = await puppeteer.launch({ const browser = await puppeteer.launch({
headless: "new", headless: "new",
executablePath: process.env['PUPPETEER_EXECUTABLE_PATH'],
args: ["--no-sandbox", "--disable-setuid-sandbox"], args: ["--no-sandbox", "--disable-setuid-sandbox"],
}); });
const page = await browser.newPage(); const page = await browser.newPage();
@ -85,7 +86,10 @@ export default class AnchoringProofService extends BaseService {
</html> </html>
`; `;
htmlContent = htmlContent.replace("[[ANCHORING_TIME]]", data.anchoringTime); htmlContent = htmlContent
.replace("[[ROOT_HASH]]", data.rootHash)
.replace("[[ANCHORING_TIME]]", data.anchoringTime)
.replace(/\[\[TX_LINK\]\]/g, data.txLink);
await page.setContent(htmlContent); await page.setContent(htmlContent);
await page.addStyleTag({ await page.addStyleTag({

View File

@ -1,19 +0,0 @@
import { Contacts, Customers } from "@prisma/client";
import BaseService from "@Services/BaseService";
import { Service } from "typedi";
import ContactRepository from "@Repositories/ContactRepository";
@Service()
export default class DocumentsService extends BaseService {
constructor(private contactRepository: ContactRepository) {
super();
}
/**
* @description : Get a contact by email
* @throws {Error} If contact cannot be get by email
*/
public async getByEmail(email: string): Promise<(Contacts & {customers: Customers | null}) | null> {
return this.contactRepository.findOneByEmail(email);
}
}

View File

@ -110,7 +110,6 @@ export default class Id360Service extends BaseService {
); );
const resJson = (await res.json()) as EnrollmentResponse; const resJson = (await res.json()) as EnrollmentResponse;
console.log(resJson.id);
return { return {
franceConnectUrl: `${this.variables.DOCAPOST_BASE_URL}static/process_ui/index.html#/enrollment/${resJson.api_key}`, franceConnectUrl: `${this.variables.DOCAPOST_BASE_URL}static/process_ui/index.html#/enrollment/${resJson.api_key}`,
processId: resJson.id, processId: resJson.id,
@ -139,10 +138,8 @@ export default class Id360Service extends BaseService {
); );
const resJson = (await res.json()) as EnrollmentResponse; const resJson = (await res.json()) as EnrollmentResponse;
console.log(resJson);
const route = await this.getRouteId(resJson.api_key); const route = await this.getRouteId(resJson.api_key);
await this.selectRoute(resJson.api_key, route); await this.selectRoute(resJson.api_key, route);
console.log(route);
await this.uploadDocument(resJson.api_key, documentUid); await this.uploadDocument(resJson.api_key, documentUid);
return await this.getReport(resJson.id); return await this.getReport(resJson.id);

View File

@ -33,7 +33,7 @@ interface IRattachementData {
name: string; name: string;
}; };
locationsUrl: string; locationsUrl: string;
} };
personne: { personne: {
numeroTelephonePro: string; numeroTelephonePro: string;
prenom: string; prenom: string;
@ -67,7 +67,7 @@ interface IOfficeData {
}; };
typeEntite: { typeEntite: {
name: string; name: string;
} };
} }
interface IOfficeLocation { interface IOfficeLocation {
@ -124,7 +124,7 @@ export default class IdNotService extends BaseService {
const token = await fetch(this.variables.IDNOT_BASE_URL + this.variables.IDNOT_CONNEXION_URL + "?" + query, { method: "POST" }); const token = await fetch(this.variables.IDNOT_BASE_URL + this.variables.IDNOT_CONNEXION_URL + "?" + query, { method: "POST" });
const decodedToken = (await token.json()) as IIdNotToken; const decodedToken = (await token.json()) as IIdNotToken;
const decodedIdToken = jwt.decode(decodedToken.id_token) as IdNotJwtPayload; const decodedIdToken = jwt.decode(decodedToken.id_token) as IdNotJwtPayload;
return decodedIdToken; return decodedIdToken;
} }
@ -152,19 +152,19 @@ export default class IdNotService extends BaseService {
public async getOfficeRole(roleName: string, officeUid: string) { public async getOfficeRole(roleName: string, officeUid: string) {
switch (roleName) { switch (roleName) {
case EIdnotRole.NOTAIRE_TITULAIRE: case EIdnotRole.NOTAIRE_TITULAIRE:
return (await this.officeRolesService.get({ where: {AND:[{ name: "Notaire" }, {office_uid: officeUid}]}}))[0]!; return (await this.officeRolesService.get({ where: { AND: [{ name: "Notaire" }, { office_uid: officeUid }] } }))[0]!;
case EIdnotRole.NOTAIRE_ASSOCIE: case EIdnotRole.NOTAIRE_ASSOCIE:
return (await this.officeRolesService.get({ where: {AND:[{ name: "Notaire" }, {office_uid: officeUid}]}}))[0]!; return (await this.officeRolesService.get({ where: { AND: [{ name: "Notaire" }, { office_uid: officeUid }] } }))[0]!;
case EIdnotRole.NOTAIRE_SALARIE: case EIdnotRole.NOTAIRE_SALARIE:
return (await this.officeRolesService.get({ where: {AND:[{ name: "Notaire" }, {office_uid: officeUid}]}}))[0]!; return (await this.officeRolesService.get({ where: { AND: [{ name: "Notaire" }, { office_uid: officeUid }] } }))[0]!;
case EIdnotRole.COLLABORATEUR: case EIdnotRole.COLLABORATEUR:
return (await this.officeRolesService.get({ where: {AND:[{ name: "Collaborateur" }, {office_uid: officeUid}]}}))[0]!; return (await this.officeRolesService.get({ where: { AND: [{ name: "Collaborateur" }, { office_uid: officeUid }] } }))[0]!;
case EIdnotRole.SUPPLEANT: case EIdnotRole.SUPPLEANT:
return (await this.officeRolesService.get({ where: {AND:[{ name: "Collaborateur" }, {office_uid: officeUid}]}}))[0]!; return (await this.officeRolesService.get({ where: { AND: [{ name: "Collaborateur" }, { office_uid: officeUid }] } }))[0]!;
case EIdnotRole.ADMINISTRATEUR: case EIdnotRole.ADMINISTRATEUR:
return (await this.officeRolesService.get({ where: {AND:[{ name: "Collaborateur" }, {office_uid: officeUid}]}}))[0]!; return (await this.officeRolesService.get({ where: { AND: [{ name: "Collaborateur" }, { office_uid: officeUid }] } }))[0]!;
case EIdnotRole.CURATEUR: case EIdnotRole.CURATEUR:
return (await this.officeRolesService.get({ where: {AND:[{ name: "Collaborateur" }, {office_uid: officeUid}]}}))[0]!; return (await this.officeRolesService.get({ where: { AND: [{ name: "Collaborateur" }, { office_uid: officeUid }] } }))[0]!;
default: default:
return; return;
} }
@ -193,39 +193,37 @@ export default class IdNotService extends BaseService {
const searchParams = new URLSearchParams({ const searchParams = new URLSearchParams({
key: this.variables.IDNOT_API_KEY, key: this.variables.IDNOT_API_KEY,
}); });
let userData = await (await fetch( let userData = (await (
`${this.variables.IDNOT_API_BASE_URL}/api/pp/v2/rattachements/${user.idNot}_${user.office_membership!.idNot}?` + await fetch(
searchParams, `${this.variables.IDNOT_API_BASE_URL}/api/pp/v2/rattachements/${user.idNot}_${user.office_membership!.idNot}?` +
{
method: "GET",
},
)).json() as IRattachementData;
if (!userData.statutDuRattachement) {
const rattachements = await (await fetch(
`${this.variables.IDNOT_API_BASE_URL}/api/pp/v2/personnes/${user.idNot}/rattachements?` +
searchParams, searchParams,
{ {
method: "GET", method: "GET",
}, },
)).json() as any; )
).json()) as IRattachementData;
if (!userData.statutDuRattachement) {
const rattachements = (await (
await fetch(`${this.variables.IDNOT_API_BASE_URL}/api/pp/v2/personnes/${user.idNot}/rattachements?` + searchParams, {
method: "GET",
})
).json()) as any;
if (rattachements.totalResultCount === 0) { if (rattachements.totalResultCount === 0) {
await this.userService.updateCheckedAt(user.uid!); await this.userService.updateCheckedAt(user.uid!);
//await this.userService.delete(user.uid!); //await this.userService.delete(user.uid!);
return; return;
} }
const rattachementsResults = rattachements.result as IRattachementData[]; const rattachementsResults = rattachements.result as IRattachementData[];
if(!rattachementsResults) return; if (!rattachementsResults) return;
rattachementsResults.forEach(async (rattachement) => { rattachementsResults.forEach(async (rattachement) => {
if (rattachement.statutDuRattachement) { if (rattachement.statutDuRattachement) {
const officeData = await (await fetch( const officeData = (await (
`${this.variables.IDNOT_API_BASE_URL + rattachement.entiteUrl}?` + await fetch(`${this.variables.IDNOT_API_BASE_URL + rattachement.entiteUrl}?` + searchParams, {
searchParams,
{
method: "GET", method: "GET",
}, })
)).json() as IOfficeData; ).json()) as IOfficeData;
if(officeData.typeEntite.name === "office") { if (officeData.typeEntite.name === "office") {
userData = rattachement; userData = rattachement;
} }
} }
@ -236,7 +234,7 @@ export default class IdNotService extends BaseService {
if (user.office_membership!.idNot !== userData.entite.ou) { if (user.office_membership!.idNot !== userData.entite.ou) {
updates++; updates++;
let officeData = (await this.officeService.get({ where: { idNot:userData.entite.ou } }))[0]; let officeData = (await this.officeService.get({ where: { idNot: userData.entite.ou } }))[0];
if (!officeData) { if (!officeData) {
const officeLocationData = (await ( const officeLocationData = (await (
await fetch(`${this.variables.IDNOT_API_BASE_URL + userData.entite.locationsUrl}?` + searchParams, { method: "GET" }) await fetch(`${this.variables.IDNOT_API_BASE_URL + userData.entite.locationsUrl}?` + searchParams, { method: "GET" })
@ -248,7 +246,7 @@ export default class IdNotService extends BaseService {
office_status: this.getOfficeStatus(userData.entite.statutEntite.name), office_status: this.getOfficeStatus(userData.entite.statutEntite.name),
address: { address: {
address: officeLocationData.result[0]!.adrGeo4, address: officeLocationData.result[0]!.adrGeo4,
city: officeLocationData.result[0]!.adrGeoVille.split(" ")[0] ?? officeLocationData.result[0]!.adrGeoVille, city: officeLocationData.result[0]!.adrGeoVille.split(" ")[0] ?? officeLocationData.result[0]!.adrGeoVille,
zip_code: Number(officeLocationData.result[0]!.adrGeoCodePostal), zip_code: Number(officeLocationData.result[0]!.adrGeoCodePostal),
created_at: null, created_at: null,
updated_at: null, updated_at: null,
@ -279,13 +277,9 @@ export default class IdNotService extends BaseService {
const searchParams = new URLSearchParams({ const searchParams = new URLSearchParams({
key: this.variables.IDNOT_API_KEY, key: this.variables.IDNOT_API_KEY,
}); });
const officeRawData = await fetch( const officeRawData = await fetch(`${this.variables.IDNOT_API_BASE_URL}/api/pp/v2/entities/${office.idNot}?` + searchParams, {
`${this.variables.IDNOT_API_BASE_URL}/api/pp/v2/entities/${office.idNot}?` + method: "GET",
searchParams, });
{
method: "GET",
},
);
if (officeRawData.status === 404) { if (officeRawData.status === 404) {
await this.officeService.updateCheckedAt(office.uid!); await this.officeService.updateCheckedAt(office.uid!);
//await this.officeService.delete(office.uid!); //await this.officeService.delete(office.uid!);
@ -293,15 +287,15 @@ export default class IdNotService extends BaseService {
} }
const officeData = (await officeRawData.json()) as IOfficeData; const officeData = (await officeRawData.json()) as IOfficeData;
let updates = 0; let updates = 0;
if(office.name !== officeData.denominationSociale) { if (office.name !== officeData.denominationSociale) {
updates++; updates++;
office.name = officeData.denominationSociale; office.name = officeData.denominationSociale;
} }
if(office.office_status !== this.getOfficeStatus(officeData.statutEntite.name)) { if (office.office_status !== this.getOfficeStatus(officeData.statutEntite.name)) {
updates++; updates++;
office.office_status = this.getOfficeStatus(officeData.statutEntite.name); office.office_status = this.getOfficeStatus(officeData.statutEntite.name);
} }
if(updates != 0) await this.officeService.update(office.uid!, office); if (updates != 0) await this.officeService.update(office.uid!, office);
await this.officeService.updateCheckedAt(office.uid!); await this.officeService.updateCheckedAt(office.uid!);
} }
@ -318,14 +312,15 @@ export default class IdNotService extends BaseService {
}) })
).json()) as IRattachementData; ).json()) as IRattachementData;
if (!userData.statutDuRattachement || userData.entite.typeEntite.name !== "office") {
if(!userData.statutDuRattachement || userData.entite.typeEntite.name !== "office") {
return null; return null;
} }
const officeLocationData = (await ( const officeLocationData = (await (
await fetch(`${this.variables.IDNOT_API_BASE_URL + userData.entite.locationsUrl}?` + searchParams, { method: "GET" }) await fetch(`${this.variables.IDNOT_API_BASE_URL + userData.entite.locationsUrl}?` + searchParams, { method: "GET" })
).json()) as IOfficeLocation; ).json()) as IOfficeLocation;
const office = await this.officeService.get({ where: { idNot: decodedToken.entity_idn } });
// if(officeLocationData.result[0]!.adrGeoCodePostal.slice(0,2) !== "35") { // if(officeLocationData.result[0]!.adrGeoCodePostal.slice(0,2) !== "35") {
// return null; // return null;
@ -342,7 +337,7 @@ export default class IdNotService extends BaseService {
office_status: this.getOfficeStatus(userData.entite.statutEntite.name), office_status: this.getOfficeStatus(userData.entite.statutEntite.name),
address: { address: {
address: officeLocationData.result[0]!.adrGeo4, address: officeLocationData.result[0]!.adrGeo4,
city: officeLocationData.result[0]!.adrGeoVille.split(" ")[0] ?? officeLocationData.result[0]!.adrGeoVille, //officeLocationData.result[0]!.adrPostaleVille, city: officeLocationData.result[0]!.adrGeoVille.split(" ")[0] ?? officeLocationData.result[0]!.adrGeoVille, //officeLocationData.result[0]!.adrPostaleVille,
zip_code: Number(officeLocationData.result[0]!.adrGeoCodePostal), zip_code: Number(officeLocationData.result[0]!.adrGeoCodePostal),
created_at: null, created_at: null,
updated_at: null, updated_at: null,
@ -362,34 +357,40 @@ export default class IdNotService extends BaseService {
updated_at: null, updated_at: null,
}, },
}; };
let userHydrated = User.hydrate<User>(userToAdd); let userHydrated = User.hydrate<User>(userToAdd);
const user = await this.userService.create(userHydrated); const user = await this.userService.create(userHydrated);
const userOffice = await this.officeService.getByUid(user.office_uid);
userHydrated = User.hydrate<User>(user); userHydrated = User.hydrate<User>(user);
const userOfficeHydrated = Office.hydrate<Office>(userOffice!);
const officeRoles = await this.officeRolesService.get({ where: { office: { idNot: "0000" }}, include: { office: true, rules: true } }); if(office.length === 0) {
const documentTypes = await this.documentTypesService.get({ where: { office: { idNot: "0000" }}, include: { office: true } }); const officeRoles = await this.officeRolesService.get({
const deedTypes = await this.deedTypesService.get({ where:{ office: { idNot: "0000" }}, include: { office: true, document_types: true } }); where: { office: { idNot: "0000" } },
include: { office: true, rules: true },
const officeRolesHydrated = OfficeRole.hydrateArray<OfficeRole>(officeRoles); });
const documentTypesHydrated = DocumentType.hydrateArray<DocumentType>(documentTypes); const deedTypes = await this.deedTypesService.get({
const deedTypesHydrated = DeedType.hydrateArray<DeedType>(deedTypes); where: { office: { idNot: "0000" } },
include: { office: true, document_types: { include: { office: true } } },
officeRolesHydrated.forEach(async (officeRole) => { });
officeRole.office.uid = user.office_uid; const documentTypes = await this.documentTypesService.get({
await this.officeRolesService.create(officeRole); where: { office: { idNot: "0000" } },
}); include: { office: true },
documentTypesHydrated.forEach(async (documentType) => { });
documentType.office!.uid = user.office_uid;
await this.documentTypesService.create(documentType); const officeRolesHydrated = OfficeRole.hydrateArray<OfficeRole>(officeRoles);
}); const deedTypesHydrated = DeedType.hydrateArray<DeedType>(deedTypes);
deedTypesHydrated.forEach(async (deedType) => { const documentTypesHydrated = DocumentType.hydrateArray<DocumentType>(documentTypes);
deedType.office!.uid = user.office_uid;
await this.deedTypesService.create(deedType);
}); await this.duplicateOfficeRoles(officeRolesHydrated, userOfficeHydrated);
const documentTypesCreated = await this.duplicateDocumentTypes(documentTypesHydrated, userOfficeHydrated);
await this.duplicateDeedTypes(deedTypesHydrated, documentTypesCreated, userOfficeHydrated);
}
const officeRole = await this.getOfficeRole(userData.typeLien.name, user.office_uid); const officeRole = await this.getOfficeRole(userData.typeLien.name, user.office_uid);
if(officeRole) { if (officeRole) {
const officeRoleHydrated = OfficeRole.hydrate<OfficeRole>(officeRole!); const officeRoleHydrated = OfficeRole.hydrate<OfficeRole>(officeRole!);
userHydrated.office_role = officeRoleHydrated; userHydrated.office_role = officeRoleHydrated;
await this.userService.update(user.uid, userHydrated); await this.userService.update(user.uid, userHydrated);
@ -400,12 +401,44 @@ export default class IdNotService extends BaseService {
return user; return user;
} }
public async duplicateDocumentTypes(documentTypes: DocumentType[], office: Office): Promise<DocumentType[]> {
let newDocumentTypes: DocumentType[] = [];
for(const documentType of documentTypes) {
documentType.office = office;
const documentTypeCreated = await this.documentTypesService.create(documentType);
newDocumentTypes.push(DocumentType.hydrate<DocumentType>(documentTypeCreated));
};
return newDocumentTypes;
}
public async duplicateDeedTypes(deedTypes: DeedType[], documentTypes: DocumentType[], office: Office) {
for (const deedType of deedTypes) {
let newDocumentTypes: DocumentType[] = [];
for (const document of deedType.document_types!) {
const newDocumentType = documentTypes.find((documentType) => documentType.name === document.name);
if(!newDocumentType) continue;
newDocumentTypes.push(newDocumentType!);
};
deedType.document_types = newDocumentTypes;
deedType.office = office;
await this.deedTypesService.create(deedType);
};
}
public async duplicateOfficeRoles(officeRoles: OfficeRole[], office: Office){
for(const officeRole of officeRoles) {
officeRole.office = office;
await this.officeRolesService.create(officeRole);
};
}
public async updateUsers() { public async updateUsers() {
const usersReq = await this.userService.getUsersToBeChecked(); const usersReq = await this.userService.getUsersToBeChecked();
const users = User.hydrateArray<User>(usersReq); const users = User.hydrateArray<User>(usersReq);
users.forEach(async (user) => { users.forEach(async (user) => {
await this.updateUser(user.uid!); await this.updateUser(user.uid!);
}); });
} }

View File

@ -1,12 +1,11 @@
import { Customers, Prisma } from "@prisma/client"; import { Customers, Prisma } from "@prisma/client";
import CustomersRepository from "@Repositories/CustomersRepository"; import CustomersRepository from "@Repositories/CustomersRepository";
import ContactRepository from "@Repositories/ContactRepository";
import BaseService from "@Services/BaseService"; import BaseService from "@Services/BaseService";
import { Service } from "typedi"; import { Service } from "typedi";
@Service() @Service()
export default class CustomersService extends BaseService { export default class CustomersService extends BaseService {
constructor(private customerRepository: CustomersRepository, private contactRepository: ContactRepository) { constructor(private customerRepository: CustomersRepository) {
super(); super();
} }
@ -17,30 +16,4 @@ export default class CustomersService extends BaseService {
public async get(query: Prisma.CustomersFindManyArgs): Promise<Customers[]> { public async get(query: Prisma.CustomersFindManyArgs): Promise<Customers[]> {
return this.customerRepository.findMany(query); return this.customerRepository.findMany(query);
} }
}
/**
* @description : Get a customer by uid
* @throws {Error} If customer cannot be get by uid
*/
public async getByUid(uid: string, query?: Prisma.CustomersInclude): Promise<Customers | null> {
return this.customerRepository.findOneByUid(uid, query);
}
/**
* @description : Get a customer by contact uid
* @throws {Error} If customer cannot be get by contact uid
*/
public async getByContact(contactUid: string): Promise<Customers | null> {
return this.customerRepository.findOneByContact(contactUid);
}
/**
* @description : Get a customer by contact uid
* @throws {Error} If customer cannot be get by contact uid
*/
public async getByEmail(contactUid: string) {
return this.contactRepository.findOneByEmail(contactUid);
}
}

View File

@ -24,9 +24,9 @@ export default class DocumentsService extends BaseService {
* @throws {Error} If document cannot be created * @throws {Error} If document cannot be created
*/ */
public async create(document: Document): Promise<Documents> { public async create(document: Document): Promise<Documents> {
const otherDocumentType = await this.documentTypeService.get({ where: { name: "Other" } }); const otherDocumentType = await this.documentTypeService.get({ where: { name: "Autres documents" } });
if(otherDocumentType.length < 1) throw new Error("Other document type not found"); if(otherDocumentType.length < 1) throw new Error("Autres documents document type not found");
document.document_type = otherDocumentType[0]; document.document_type = otherDocumentType[0];
document.document_status = "DEPOSITED"; document.document_status = "DEPOSITED";

View File

@ -26,4 +26,14 @@ export default class OfficeFoldersService extends BaseService {
public async getByUid(uid: string, query?: Prisma.OfficeFoldersInclude) { public async getByUid(uid: string, query?: Prisma.OfficeFoldersInclude) {
return this.officeFoldersRepository.findOneByUid(uid, query); return this.officeFoldersRepository.findOneByUid(uid, query);
} }
/**
* @description : Get a folder by uid
* @throws {Error} If folder cannot be get by uid
*/
public async getByUidWithCustomers(uid: string) {
return this.officeFoldersRepository.findOneByUidWithCustomers(uid);
}
} }

View File

@ -23,6 +23,14 @@ 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);
} }