feat(services): add idnot auth (#66)
This commit is contained in:
commit
6f88e7f091
@ -5,10 +5,13 @@ import { Service } from "typedi";
|
|||||||
import AuthService from "@Services/common/AuthService/AuthService";
|
import AuthService from "@Services/common/AuthService/AuthService";
|
||||||
import { JwtPayload } from "jsonwebtoken";
|
import { JwtPayload } from "jsonwebtoken";
|
||||||
|
|
||||||
|
import IdNotService from "@Services/common/IdNotService/IdNotService";
|
||||||
|
|
||||||
|
|
||||||
@Controller()
|
@Controller()
|
||||||
@Service()
|
@Service()
|
||||||
export default class UserController extends ApiController {
|
export default class UserController extends ApiController {
|
||||||
constructor(private authService: AuthService) {
|
constructor(private authService: AuthService, private idNotService: IdNotService) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -19,16 +22,21 @@ export default class UserController extends ApiController {
|
|||||||
*/
|
*/
|
||||||
@Post("/api/v1/idnot/user/:code")
|
@Post("/api/v1/idnot/user/:code")
|
||||||
protected async getUserInfosFromIdnot(req: Request, response: Response) {
|
protected async getUserInfosFromIdnot(req: Request, response: Response) {
|
||||||
console.warn("/api/v1/idnot/user/:code used for test, should be removed");
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const code = req.params["code"];
|
const code = req.params["code"];
|
||||||
if (!code) throw new Error("code is required");
|
if (!code) throw new Error("code is required");
|
||||||
const token = await fetch("https://qual-connexion.idnot.fr/IdPOAuth2/token/idnot_idp_v1", { method: "POST" });
|
|
||||||
console.log(token);
|
const idNotToken = await this.idNotService.getIdNotToken(code);
|
||||||
//const user = await this.authService.getUserFromIdNotTokens(code!);
|
const user = await this.idNotService.getOrCreateUser(idNotToken);
|
||||||
//success
|
|
||||||
this.httpSuccess(response);
|
await this.idNotService.updateUser(user.uid);
|
||||||
|
await this.idNotService.updateOffice(user.office_uid);
|
||||||
|
|
||||||
|
const payload = await this.authService.getUserJwtPayload(user.idNot);
|
||||||
|
const accessToken = this.authService.generateAccessToken(payload);
|
||||||
|
const refreshToken = this.authService.generateRefreshToken(payload);
|
||||||
|
|
||||||
|
this.httpSuccess(response, {accessToken, refreshToken});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
this.httpInternalError(response);
|
this.httpInternalError(response);
|
||||||
|
@ -34,6 +34,12 @@ export class BackendVariables {
|
|||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
public readonly APP_ROOT_URL!: string;
|
public readonly APP_ROOT_URL!: string;
|
||||||
|
|
||||||
|
@IsNotEmpty()
|
||||||
|
public readonly IDNOT_BASE_URL!: string;
|
||||||
|
|
||||||
|
@IsNotEmpty()
|
||||||
|
public readonly IDNOT_API_BASE_URL!: string;
|
||||||
|
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
public readonly IDNOT_CONNEXION_URL!: string;
|
public readonly IDNOT_CONNEXION_URL!: string;
|
||||||
|
|
||||||
@ -46,6 +52,9 @@ export class BackendVariables {
|
|||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
public readonly IDNOT_REDIRECT_URL!: string;
|
public readonly IDNOT_REDIRECT_URL!: string;
|
||||||
|
|
||||||
|
@IsNotEmpty()
|
||||||
|
public readonly IDNOT_API_KEY!: string;
|
||||||
|
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
public readonly PINATA_API_KEY!: string;
|
public readonly PINATA_API_KEY!: string;
|
||||||
|
|
||||||
@ -80,10 +89,13 @@ export class BackendVariables {
|
|||||||
this.APP_PORT = process.env["APP_PORT"]!;
|
this.APP_PORT = process.env["APP_PORT"]!;
|
||||||
this.APP_ROOT_URL = process.env["APP_ROOT_URL"]!;
|
this.APP_ROOT_URL = process.env["APP_ROOT_URL"]!;
|
||||||
this.APP_LABEL = process.env["APP_LABEL"]!;
|
this.APP_LABEL = process.env["APP_LABEL"]!;
|
||||||
|
this.IDNOT_BASE_URL = process.env["IDNOT_BASE_URL"]!;
|
||||||
|
this.IDNOT_API_BASE_URL = process.env["IDNOT_API_BASE_URL"]!;
|
||||||
this.IDNOT_CONNEXION_URL = process.env["IDNOT_CONNEXION_URL"]!;
|
this.IDNOT_CONNEXION_URL = process.env["IDNOT_CONNEXION_URL"]!;
|
||||||
this.IDNOT_CLIENT_ID = process.env["IDNOT_CLIENT_ID"]!;
|
this.IDNOT_CLIENT_ID = process.env["IDNOT_CLIENT_ID"]!;
|
||||||
this.IDNOT_CLIENT_SECRET = process.env["IDNOT_CLIENT_SECRET"]!;
|
this.IDNOT_CLIENT_SECRET = process.env["IDNOT_CLIENT_SECRET"]!;
|
||||||
this.IDNOT_REDIRECT_URL = process.env["IDNOT_REDIRECT_URL"]!;
|
this.IDNOT_REDIRECT_URL = process.env["IDNOT_REDIRECT_URL"]!;
|
||||||
|
this.IDNOT_API_KEY = process.env["IDNOT_API_KEY"]!;
|
||||||
this.PINATA_API_KEY = process.env["PINATA_API_KEY"]!;
|
this.PINATA_API_KEY = process.env["PINATA_API_KEY"]!;
|
||||||
this.PINATA_API_SECRET = process.env["PINATA_API_SECRET"]!;
|
this.PINATA_API_SECRET = process.env["PINATA_API_SECRET"]!;
|
||||||
this.PINATA_GATEWAY = process.env["PINATA_GATEWAY"]!;
|
this.PINATA_GATEWAY = process.env["PINATA_GATEWAY"]!;
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "offices" ADD COLUMN "checked_at" TIMESTAMP(3);
|
||||||
|
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "users" ADD COLUMN "checked_at" TIMESTAMP(3);
|
@ -6,8 +6,8 @@ generator client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
datasource db {
|
datasource db {
|
||||||
provider = "postgresql"
|
provider = "postgresql"
|
||||||
url = env("DEV_PRISMA_STUDIO_DB_URL")
|
url = env("DEV_PRISMA_STUDIO_DB_URL")
|
||||||
shadowDatabaseUrl = env("DEV_PRISMA_STUDIO_SHADOW_URL")
|
shadowDatabaseUrl = env("DEV_PRISMA_STUDIO_SHADOW_URL")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,6 +61,7 @@ model Users {
|
|||||||
office_role_uid String? @db.VarChar(255)
|
office_role_uid String? @db.VarChar(255)
|
||||||
created_at DateTime? @default(now())
|
created_at DateTime? @default(now())
|
||||||
updated_at DateTime? @updatedAt
|
updated_at DateTime? @updatedAt
|
||||||
|
checked_at DateTime?
|
||||||
office_membership Offices @relation(fields: [office_uid], references: [uid], onDelete: Cascade)
|
office_membership Offices @relation(fields: [office_uid], references: [uid], onDelete: Cascade)
|
||||||
office_uid String @db.VarChar(255)
|
office_uid String @db.VarChar(255)
|
||||||
notifications Notifications[] @relation("UserHasNotifications")
|
notifications Notifications[] @relation("UserHasNotifications")
|
||||||
@ -81,6 +82,7 @@ model Offices {
|
|||||||
office_status EOfficeStatus @default(DESACTIVATED)
|
office_status EOfficeStatus @default(DESACTIVATED)
|
||||||
created_at DateTime? @default(now())
|
created_at DateTime? @default(now())
|
||||||
updated_at DateTime? @updatedAt
|
updated_at DateTime? @updatedAt
|
||||||
|
checked_at DateTime?
|
||||||
deed_types DeedTypes[]
|
deed_types DeedTypes[]
|
||||||
users Users[]
|
users Users[]
|
||||||
office_folders OfficeFolders[]
|
office_folders OfficeFolders[]
|
||||||
|
@ -72,6 +72,31 @@ export default class OfficesRepository extends BaseRepository {
|
|||||||
return this.model.update(updateArgs);
|
return this.model.update(updateArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description : Update check date of an office
|
||||||
|
*/
|
||||||
|
public async updateCheckedAt(uid: string) {
|
||||||
|
return this.model.update({
|
||||||
|
where: {
|
||||||
|
uid: uid,
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
checked_at: new Date(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description : Delete an office
|
||||||
|
*/
|
||||||
|
public async delete(uid: string): Promise<Offices> {
|
||||||
|
return this.model.delete({
|
||||||
|
where: {
|
||||||
|
uid: uid,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description : Find one office
|
* @description : Find one office
|
||||||
*/
|
*/
|
||||||
@ -93,4 +118,25 @@ export default class OfficesRepository extends BaseRepository {
|
|||||||
include: query,
|
include: query,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description : Find offices which need to be checked with idNot API
|
||||||
|
*/
|
||||||
|
public async findManyToCheck() {
|
||||||
|
return this.model.findMany({
|
||||||
|
where: {
|
||||||
|
OR: [
|
||||||
|
{
|
||||||
|
checked_at: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
checked_at: { lt: new Date(Date.now() - 3 * 60 * 1000) }, // less than 24h ago
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
include: {
|
||||||
|
address: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -108,7 +108,7 @@ export default class UsersRepository extends BaseRepository {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
if(user.office_membership) {
|
if (user.office_membership) {
|
||||||
updateArgs.data.office_membership = {
|
updateArgs.data.office_membership = {
|
||||||
connect: {
|
connect: {
|
||||||
idNot: user.office_membership?.idNot,
|
idNot: user.office_membership?.idNot,
|
||||||
@ -124,7 +124,7 @@ export default class UsersRepository extends BaseRepository {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if(user.office_role) {
|
if (user.office_role) {
|
||||||
updateArgs.data.office_role = {
|
updateArgs.data.office_role = {
|
||||||
connect: {
|
connect: {
|
||||||
uid: user.office_role.uid,
|
uid: user.office_role.uid,
|
||||||
@ -132,7 +132,7 @@ export default class UsersRepository extends BaseRepository {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if(user.role) {
|
if (user.role) {
|
||||||
updateArgs.data.role = {
|
updateArgs.data.role = {
|
||||||
connect: {
|
connect: {
|
||||||
uid: user.role.uid,
|
uid: user.role.uid,
|
||||||
@ -144,17 +144,31 @@ export default class UsersRepository extends BaseRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description : Update role from a user
|
* @description : Update check date of a user
|
||||||
*/
|
*/
|
||||||
public async updateRole(uid: string, user: User): Promise<Users> {
|
public async updateCheckedAt(uid: string) {
|
||||||
|
return this.model.update({
|
||||||
|
where: {
|
||||||
|
uid: uid,
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
checked_at: new Date(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description : Update office role from a user
|
||||||
|
*/
|
||||||
|
public async updateOfficeRole(uid: string, user: User): Promise<Users> {
|
||||||
const updateArgs: Prisma.UsersUpdateArgs = {
|
const updateArgs: Prisma.UsersUpdateArgs = {
|
||||||
where: {
|
where: {
|
||||||
uid: uid,
|
uid: uid,
|
||||||
},
|
},
|
||||||
data: {}
|
data: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
if(user.office_role) {
|
if (user.office_role) {
|
||||||
updateArgs.data.office_role = {
|
updateArgs.data.office_role = {
|
||||||
connect: {
|
connect: {
|
||||||
uid: user.office_role.uid,
|
uid: user.office_role.uid,
|
||||||
@ -162,17 +176,20 @@ export default class UsersRepository extends BaseRepository {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if(user.role) {
|
|
||||||
updateArgs.data.role = {
|
|
||||||
connect: {
|
|
||||||
uid: user.role.uid,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.model.update({ ...updateArgs, include: { contact: true, office_membership: { include: { address: true } } } });
|
return this.model.update({ ...updateArgs, include: { contact: true, office_membership: { include: { address: true } } } });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description : Delete one user
|
||||||
|
*/
|
||||||
|
public async delete(uid: string): Promise<Users> {
|
||||||
|
return this.model.delete({
|
||||||
|
where: {
|
||||||
|
uid: uid,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description : Find one user
|
* @description : Find one user
|
||||||
*/
|
*/
|
||||||
@ -200,7 +217,7 @@ export default class UsersRepository extends BaseRepository {
|
|||||||
/**
|
/**
|
||||||
* @description : Find one user with office
|
* @description : Find one user with office
|
||||||
*/
|
*/
|
||||||
public async findOneByUidWithRole(uid: string): Promise<((Users & {role: Role} )| null)> {
|
public async findOneByUidWithRole(uid: string): Promise<(Users & { role: Role }) | null> {
|
||||||
return this.model.findUnique({
|
return this.model.findUnique({
|
||||||
where: {
|
where: {
|
||||||
uid: uid,
|
uid: uid,
|
||||||
@ -222,4 +239,27 @@ export default class UsersRepository extends BaseRepository {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description : Find users which need to be checked with idNot API
|
||||||
|
*/
|
||||||
|
public async findManyToCheck() {
|
||||||
|
return this.model.findMany({
|
||||||
|
where: {
|
||||||
|
OR: [
|
||||||
|
{
|
||||||
|
checked_at: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
checked_at: { lt: new Date(Date.now() - 3 * 60 * 1000) }, // less than 24h ago
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
include: {
|
||||||
|
contact: true,
|
||||||
|
role: true,
|
||||||
|
office_membership: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import CronService from "@Services/common/CronService/CronService";
|
|||||||
try {
|
try {
|
||||||
const variables = await Container.get(BackendVariables).validate();
|
const variables = await Container.get(BackendVariables).validate();
|
||||||
Container.get(CronService).archiveFiles();
|
Container.get(CronService).archiveFiles();
|
||||||
|
await Container.get(CronService).updateUsers();
|
||||||
if(variables.ENV !== "dev"){
|
if(variables.ENV !== "dev"){
|
||||||
Container.get(CronService).sendMails();
|
Container.get(CronService).sendMails();
|
||||||
}
|
}
|
||||||
|
@ -19,20 +19,12 @@ export default class UsersService extends BaseService {
|
|||||||
return this.userRepository.findMany(query);
|
return this.userRepository.findMany(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @description : Create a user
|
|
||||||
* @throws {Error} If user couldn't be created
|
|
||||||
*/
|
|
||||||
public create(userEntity: User): Promise<Users> {
|
|
||||||
return this.userRepository.create(userEntity);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description : Modify a user
|
* @description : Modify a user
|
||||||
* @throws {Error} If user modification failed
|
* @throws {Error} If user modification failed
|
||||||
*/
|
*/
|
||||||
public async update(uid: string, userEntity: User): Promise<Users> {
|
public async update(uid: string, userEntity: User): Promise<Users> {
|
||||||
return this.userRepository.updateRole(uid, userEntity);
|
return this.userRepository.updateOfficeRole(uid, userEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -16,6 +16,11 @@ interface ICustomerJwtPayload {
|
|||||||
email: string;
|
email: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IdNotJwtPayload {
|
||||||
|
sub: string,
|
||||||
|
profile_idn: string,
|
||||||
|
entity_idn: string,
|
||||||
|
}
|
||||||
|
|
||||||
interface IUserJwtPayload {
|
interface IUserJwtPayload {
|
||||||
userId: string;
|
userId: string;
|
||||||
|
@ -2,11 +2,12 @@ import { Service } from "typedi";
|
|||||||
import { CronJob } from "cron";
|
import { CronJob } from "cron";
|
||||||
import MailchimpService from "../MailchimpService/MailchimpService";
|
import MailchimpService from "../MailchimpService/MailchimpService";
|
||||||
import FilesService from "../FilesService/FilesService";
|
import FilesService from "../FilesService/FilesService";
|
||||||
|
import IdNotService from "../IdNotService/IdNotService";
|
||||||
|
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export default class CronService {
|
export default class CronService {
|
||||||
constructor(private mailchimpService: MailchimpService, private filesService: FilesService) {}
|
constructor(private mailchimpService: MailchimpService, private filesService: FilesService, private idNotService: IdNotService) {}
|
||||||
|
|
||||||
public async sendMails() {
|
public async sendMails() {
|
||||||
const cronJob = new CronJob("*/15 * * * *", async () => { // Every 15 minutes
|
const cronJob = new CronJob("*/15 * * * *", async () => { // Every 15 minutes
|
||||||
@ -37,4 +38,18 @@ export default class CronService {
|
|||||||
cronJob.start();
|
cronJob.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public async updateUsers() {
|
||||||
|
const cronJob = new CronJob("*/15 * * * *", async () => { // Every 15 minutes
|
||||||
|
try {
|
||||||
|
await this.idNotService.updateOffices();
|
||||||
|
await this.idNotService.updateUsers();
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Start job
|
||||||
|
if (!cronJob.running) {
|
||||||
|
cronJob.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
332
src/services/common/IdNotService/IdNotService.ts
Normal file
332
src/services/common/IdNotService/IdNotService.ts
Normal file
@ -0,0 +1,332 @@
|
|||||||
|
import BaseService from "@Services/BaseService";
|
||||||
|
import { BackendVariables } from "@Common/config/variables/Variables";
|
||||||
|
import { Service } from "typedi";
|
||||||
|
import jwt from "jsonwebtoken";
|
||||||
|
import UsersService from "@Services/super-admin/UsersService/UsersService";
|
||||||
|
import { IdNotJwtPayload } from "../AuthService/AuthService";
|
||||||
|
import User, { Office, Role } from "le-coffre-resources/dist/SuperAdmin";
|
||||||
|
import RolesService from "@Services/super-admin/RolesService/RolesService";
|
||||||
|
import OfficesService from "@Services/super-admin/OfficesService/OfficesService";
|
||||||
|
import { EOfficeStatus } from "@prisma/client";
|
||||||
|
|
||||||
|
interface IIdNotToken {
|
||||||
|
access_token: string;
|
||||||
|
expires_in: number;
|
||||||
|
id_token: string;
|
||||||
|
token_type: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IRattachementData {
|
||||||
|
entiteUrl: string;
|
||||||
|
personneUrl: string;
|
||||||
|
entite: {
|
||||||
|
codeCrpcen: string;
|
||||||
|
typeEntite: {
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
ou: string;
|
||||||
|
denominationSociale: string;
|
||||||
|
statutEntite: {
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
locationsUrl: string;
|
||||||
|
}
|
||||||
|
personne: {
|
||||||
|
numeroTelephonePro: string;
|
||||||
|
prenom: string;
|
||||||
|
nomUsuel: string;
|
||||||
|
mobilePro: string;
|
||||||
|
numeroAdherentCrpcen: string;
|
||||||
|
civilite: string;
|
||||||
|
};
|
||||||
|
typeLien: {
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
numeroMobile: string;
|
||||||
|
numeroTelephone: string;
|
||||||
|
statutDuRattachement: boolean;
|
||||||
|
mailRattachement: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IOfficeData {
|
||||||
|
ou: string;
|
||||||
|
intitule: string;
|
||||||
|
denominationSociale: string;
|
||||||
|
departementResidence: {
|
||||||
|
libelle: string;
|
||||||
|
code: string;
|
||||||
|
}[];
|
||||||
|
libelle: string;
|
||||||
|
codeCrpcen: string;
|
||||||
|
locationsUrl: string;
|
||||||
|
statutEntite: {
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IOfficeLocation {
|
||||||
|
totalResultCount: number;
|
||||||
|
page: number;
|
||||||
|
size: number;
|
||||||
|
result: {
|
||||||
|
mail: string;
|
||||||
|
numeroTelephone: string;
|
||||||
|
adrGeo4: string;
|
||||||
|
adrGeoCodePostal: string;
|
||||||
|
adrGeoVille: string;
|
||||||
|
ou: string;
|
||||||
|
lastModified: string;
|
||||||
|
deleted: boolean;
|
||||||
|
}[];
|
||||||
|
}
|
||||||
|
|
||||||
|
enum EIdnotRole {
|
||||||
|
DIRECTEUR = "Directeur général du CSN",
|
||||||
|
NOTAIRE_TITULAIRE = "Notaire titulaire",
|
||||||
|
NOTAIRE_ASSOCIE = "Notaire associé",
|
||||||
|
NOTAIRE_SALARIE = "Notaire salarié",
|
||||||
|
COLLABORATEUR = "Collaborateur",
|
||||||
|
SECRETAIRE_GENERAL = "Secrétaire général",
|
||||||
|
SUPPLEANT = "Suppléant",
|
||||||
|
ADMINISTRATEUR = "Administrateur",
|
||||||
|
RESPONSABLE = "Responsable",
|
||||||
|
}
|
||||||
|
|
||||||
|
@Service()
|
||||||
|
export default class IdNotService extends BaseService {
|
||||||
|
constructor(
|
||||||
|
protected variables: BackendVariables,
|
||||||
|
private userService: UsersService,
|
||||||
|
private officeService: OfficesService,
|
||||||
|
private rolesService: RolesService,
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getIdNotToken(code: string) {
|
||||||
|
const query = new URLSearchParams({
|
||||||
|
client_id: this.variables.IDNOT_CLIENT_ID,
|
||||||
|
client_secret: this.variables.IDNOT_CLIENT_SECRET,
|
||||||
|
redirect_uri: `http://0.0.0.0:3000/authorized-client`,
|
||||||
|
code: code,
|
||||||
|
grant_type: "authorization_code",
|
||||||
|
});
|
||||||
|
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 decodedIdToken = jwt.decode(decodedToken.id_token) as IdNotJwtPayload;
|
||||||
|
return decodedIdToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getRole(roleName: string): Promise<Role> {
|
||||||
|
switch (roleName) {
|
||||||
|
case EIdnotRole.DIRECTEUR:
|
||||||
|
return (await this.rolesService.get({ where: { name: "admin" } }))[0]!;
|
||||||
|
case EIdnotRole.NOTAIRE_TITULAIRE:
|
||||||
|
return (await this.rolesService.get({ where: { name: "notary" } }))[0]!;
|
||||||
|
case EIdnotRole.NOTAIRE_ASSOCIE:
|
||||||
|
return (await this.rolesService.get({ where: { name: "notary" } }))[0]!;
|
||||||
|
case EIdnotRole.NOTAIRE_SALARIE:
|
||||||
|
return (await this.rolesService.get({ where: { name: "notary" } }))[0]!;
|
||||||
|
case EIdnotRole.COLLABORATEUR:
|
||||||
|
return (await this.rolesService.get({ where: { name: "collaborator" } }))[0]!;
|
||||||
|
case EIdnotRole.SECRETAIRE_GENERAL:
|
||||||
|
return (await this.rolesService.get({ where: { name: "notary" } }))[0]!;
|
||||||
|
case EIdnotRole.SUPPLEANT:
|
||||||
|
return (await this.rolesService.get({ where: { name: "notary" } }))[0]!;
|
||||||
|
case EIdnotRole.ADMINISTRATEUR:
|
||||||
|
return (await this.rolesService.get({ where: { name: "admin" } }))[0]!;
|
||||||
|
case EIdnotRole.RESPONSABLE:
|
||||||
|
return (await this.rolesService.get({ where: { name: "collaborator" } }))[0]!;
|
||||||
|
default:
|
||||||
|
return (await this.rolesService.get({ where: { name: "default" } }))[0]!;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public getOfficeStatus(statusName: string) {
|
||||||
|
switch (statusName) {
|
||||||
|
case "Pourvu":
|
||||||
|
return EOfficeStatus.ACTIVATED;
|
||||||
|
case "Pourvu mais décédé":
|
||||||
|
return EOfficeStatus.ACTIVATED;
|
||||||
|
case "Sans titulaire":
|
||||||
|
return EOfficeStatus.ACTIVATED;
|
||||||
|
case "Vacance":
|
||||||
|
return EOfficeStatus.ACTIVATED;
|
||||||
|
case "En activité":
|
||||||
|
return EOfficeStatus.ACTIVATED;
|
||||||
|
default:
|
||||||
|
return EOfficeStatus.DESACTIVATED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async updateUser(userId: string) {
|
||||||
|
const userInfos = await this.userService.getByUid(userId, { contact: true, role: true, office_membership: true });
|
||||||
|
const user = User.hydrate<User>(userInfos!);
|
||||||
|
const searchParams = new URLSearchParams({
|
||||||
|
key: this.variables.IDNOT_API_KEY,
|
||||||
|
});
|
||||||
|
const userRawData = await (await fetch(
|
||||||
|
`${this.variables.IDNOT_API_BASE_URL}/api/pp/v2/personnes/${user.idNot}/rattachements?` +
|
||||||
|
searchParams,
|
||||||
|
{
|
||||||
|
method: "GET",
|
||||||
|
},
|
||||||
|
)).json() as any;
|
||||||
|
if (userRawData.totalResultCount === 0) {
|
||||||
|
await this.userService.updateCheckedAt(user.uid!);
|
||||||
|
//await this.userService.delete(user.uid!);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const userData = userRawData.result[0] as IRattachementData;
|
||||||
|
const roleFromIdNot = await this.getRole(userData.typeLien.name);
|
||||||
|
let updates = 0;
|
||||||
|
|
||||||
|
if (user.role!.uid !== roleFromIdNot.uid) {
|
||||||
|
updates++;
|
||||||
|
user.role = roleFromIdNot;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user.office_membership!.idNot !== userData.entiteUrl.split("/")[5]!) {
|
||||||
|
updates++;
|
||||||
|
let officeData = (await this.officeService.get({ where: { idNot: userData.entiteUrl.split("/")[5]! } }))[0];
|
||||||
|
if (!officeData) {
|
||||||
|
const officeIdNotData = (await (
|
||||||
|
await fetch(`${this.variables.IDNOT_API_BASE_URL + userData.entiteUrl}?` + searchParams, { method: "GET" })
|
||||||
|
).json()) as IOfficeData;
|
||||||
|
const office = {
|
||||||
|
idNot: userData.entiteUrl.split("/")[5]!,
|
||||||
|
name: officeIdNotData.denominationSociale
|
||||||
|
? officeIdNotData.denominationSociale
|
||||||
|
: `office ${userData.entiteUrl.split("/")[5]!}`,
|
||||||
|
crpcen: officeIdNotData.codeCrpcen,
|
||||||
|
office_status: this.getOfficeStatus(officeIdNotData.statutEntite.name),
|
||||||
|
address: {
|
||||||
|
address: officeIdNotData.departementResidence[0]!.libelle, //officeLocationData.result[0]!.adrPostale4,
|
||||||
|
city: "city", //officeLocationData.result[0]!.adrPostaleVille,
|
||||||
|
zip_code: Number(officeIdNotData.departementResidence[0]!.code),
|
||||||
|
created_at: null,
|
||||||
|
updated_at: null,
|
||||||
|
},
|
||||||
|
created_at: null,
|
||||||
|
updated_at: null,
|
||||||
|
};
|
||||||
|
officeData = await this.officeService.create(office);
|
||||||
|
}
|
||||||
|
user.office_membership = officeData;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user.contact!.email !== userData.mailRattachement) {
|
||||||
|
updates++;
|
||||||
|
user.contact!.email = userData.mailRattachement;
|
||||||
|
}
|
||||||
|
if (user.contact!.cell_phone_number !== userData.numeroMobile) {
|
||||||
|
updates++;
|
||||||
|
user.contact!.cell_phone_number = userData.numeroMobile;
|
||||||
|
}
|
||||||
|
if (updates != 0) await this.userService.update(user.uid!, user);
|
||||||
|
await this.userService.updateCheckedAt(user.uid!);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async updateOffice(officeId: string) {
|
||||||
|
const officeInfos = await this.officeService.getByUid(officeId);
|
||||||
|
const office = Office.hydrate<Office>(officeInfos!);
|
||||||
|
const searchParams = new URLSearchParams({
|
||||||
|
key: this.variables.IDNOT_API_KEY,
|
||||||
|
});
|
||||||
|
const officeRawData = await fetch(
|
||||||
|
`${this.variables.IDNOT_API_BASE_URL}/api/pp/v2/entities/${office.idNot}?` +
|
||||||
|
searchParams,
|
||||||
|
{
|
||||||
|
method: "GET",
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (officeRawData.status === 404) {
|
||||||
|
await this.officeService.updateCheckedAt(office.uid!);
|
||||||
|
//await this.officeService.delete(office.uid!);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const officeData = (await officeRawData.json()) as IOfficeData;
|
||||||
|
let updates = 0;
|
||||||
|
if(office.name !== officeData.denominationSociale) {
|
||||||
|
updates++;
|
||||||
|
office.name = officeData.denominationSociale;
|
||||||
|
}
|
||||||
|
if(office.office_status !== this.getOfficeStatus(officeData.statutEntite.name)) {
|
||||||
|
updates++;
|
||||||
|
office.office_status = this.getOfficeStatus(officeData.statutEntite.name);
|
||||||
|
}
|
||||||
|
if(updates != 0) await this.officeService.update(office.uid!, office);
|
||||||
|
await this.officeService.updateCheckedAt(office.uid!);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getOrCreateUser(decodedToken: IdNotJwtPayload) {
|
||||||
|
let user = await this.userService.getByProvider("idNot", decodedToken.sub);
|
||||||
|
if (!user) {
|
||||||
|
const searchParams = new URLSearchParams({
|
||||||
|
key: this.variables.IDNOT_API_KEY,
|
||||||
|
});
|
||||||
|
|
||||||
|
const userData = (await (
|
||||||
|
await fetch(`${this.variables.IDNOT_API_BASE_URL}/api/pp/v2/rattachements/${decodedToken.profile_idn}?` + searchParams, {
|
||||||
|
method: "GET",
|
||||||
|
})
|
||||||
|
).json()) as IRattachementData;
|
||||||
|
|
||||||
|
const officeLocationData = (await (
|
||||||
|
await fetch(`${this.variables.IDNOT_API_BASE_URL + userData.entite.locationsUrl}?` + searchParams, { method: "GET" })
|
||||||
|
).json()) as IOfficeLocation;
|
||||||
|
|
||||||
|
const role = await this.getRole(userData.typeLien.name);
|
||||||
|
|
||||||
|
const userToAdd = {
|
||||||
|
idNot: decodedToken.sub,
|
||||||
|
office_membership: {
|
||||||
|
idNot: decodedToken.entity_idn,
|
||||||
|
name: userData.entite.denominationSociale,
|
||||||
|
crpcen: userData.entite.codeCrpcen,
|
||||||
|
office_status: this.getOfficeStatus(userData.entite.statutEntite.name),
|
||||||
|
address: {
|
||||||
|
address: officeLocationData.result[0]!.adrGeo4,
|
||||||
|
city: officeLocationData.result[0]!.adrGeoVille.split(" ")[0] ?? officeLocationData.result[0]!.adrGeoVille, //officeLocationData.result[0]!.adrPostaleVille,
|
||||||
|
zip_code: Number(officeLocationData.result[0]!.adrGeoCodePostal),
|
||||||
|
created_at: null,
|
||||||
|
updated_at: null,
|
||||||
|
},
|
||||||
|
created_at: null,
|
||||||
|
updated_at: null,
|
||||||
|
},
|
||||||
|
role: role,
|
||||||
|
contact: {
|
||||||
|
first_name: userData.personne.prenom,
|
||||||
|
last_name: userData.personne.nomUsuel,
|
||||||
|
email: userData.mailRattachement,
|
||||||
|
phone_number: userData.numeroTelephone,
|
||||||
|
cell_phone_number: userData.numeroMobile ?? userData.numeroTelephone,
|
||||||
|
civility: userData.personne.civilite,
|
||||||
|
created_at: null,
|
||||||
|
updated_at: null,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const userToHydrate = User.hydrate<User>(userToAdd);
|
||||||
|
return await this.userService.create(userToHydrate);
|
||||||
|
}
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async updateUsers() {
|
||||||
|
const usersReq = await this.userService.getUsersToBeChecked();
|
||||||
|
const users = User.hydrateArray<User>(usersReq);
|
||||||
|
users.forEach(async (user) => {
|
||||||
|
await this.updateUser(user.uid!);
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async updateOffices() {
|
||||||
|
const officesReq = await this.officeService.getOfficesToBeChecked();
|
||||||
|
const offices = Office.hydrateArray<Office>(officesReq);
|
||||||
|
offices.forEach(async (office) => {
|
||||||
|
await this.updateOffice(office.uid!);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -34,6 +34,23 @@ export default class OfficesService extends BaseService {
|
|||||||
return this.officeRepository.update(uid, officeEntity);
|
return this.officeRepository.update(uid, officeEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description : Modify an office check date
|
||||||
|
* @throws {Error} If user modification failed
|
||||||
|
* @deprecate
|
||||||
|
*/
|
||||||
|
public updateCheckedAt(uid: string): Promise<Offices> {
|
||||||
|
return this.officeRepository.updateCheckedAt(uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description : delete an office
|
||||||
|
* @throws {Error} If office cannot be modified
|
||||||
|
*/
|
||||||
|
public async delete(uid: string): Promise<Offices> {
|
||||||
|
return this.officeRepository.delete(uid);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description : Get a office by uid
|
* @description : Get a office by uid
|
||||||
* @throws {Error} If office cannot be get
|
* @throws {Error} If office cannot be get
|
||||||
@ -41,4 +58,11 @@ export default class OfficesService extends BaseService {
|
|||||||
public async getByUid(uid: string, query?: any): Promise<Offices | null> {
|
public async getByUid(uid: string, query?: any): Promise<Offices | null> {
|
||||||
return this.officeRepository.findOneByUid(uid, query);
|
return this.officeRepository.findOneByUid(uid, query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description : Get users to be checked with IdNot API
|
||||||
|
*/
|
||||||
|
public getOfficesToBeChecked() {
|
||||||
|
return this.officeRepository.findManyToCheck();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,23 @@ export default class UsersService extends BaseService {
|
|||||||
return this.userRepository.update(uid, userEntity);
|
return this.userRepository.update(uid, userEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description : Modify a user check date
|
||||||
|
* @throws {Error} If user modification failed
|
||||||
|
* @deprecate
|
||||||
|
*/
|
||||||
|
public updateCheckedAt(uid: string): Promise<Users> {
|
||||||
|
return this.userRepository.updateCheckedAt(uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description : Delete a user
|
||||||
|
* @throws {Error} If user modification failed
|
||||||
|
*/
|
||||||
|
public delete(uid: string): Promise<Users> {
|
||||||
|
return this.userRepository.delete(uid);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description : Get a user by uid
|
* @description : Get a user by uid
|
||||||
* @throws {Error} If user cannot be get by uid
|
* @throws {Error} If user cannot be get by uid
|
||||||
@ -66,4 +83,12 @@ export default class UsersService extends BaseService {
|
|||||||
public getByProvider(providerName: string, id: string) {
|
public getByProvider(providerName: string, id: string) {
|
||||||
return this.userRepository.findOneByProvider(providerName, id);
|
return this.userRepository.findOneByProvider(providerName, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description : Get users to be checked with IdNot API
|
||||||
|
*/
|
||||||
|
public getUsersToBeChecked() {
|
||||||
|
return this.userRepository.findManyToCheck();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user