diff --git a/src/app/api/idnot/UserController.ts b/src/app/api/idnot/UserController.ts index b63d3fec..ebd1c50b 100644 --- a/src/app/api/idnot/UserController.ts +++ b/src/app/api/idnot/UserController.ts @@ -5,10 +5,13 @@ import { Service } from "typedi"; import AuthService from "@Services/common/AuthService/AuthService"; import { JwtPayload } from "jsonwebtoken"; +import IdNotService from "@Services/common/IdNotService/IdNotService"; + + @Controller() @Service() export default class UserController extends ApiController { - constructor(private authService: AuthService) { + constructor(private authService: AuthService, private idNotService: IdNotService) { super(); } @@ -19,16 +22,21 @@ export default class UserController extends ApiController { */ @Post("/api/v1/idnot/user/:code") protected async getUserInfosFromIdnot(req: Request, response: Response) { - console.warn("/api/v1/idnot/user/:code used for test, should be removed"); - try { const code = req.params["code"]; 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 user = await this.authService.getUserFromIdNotTokens(code!); - //success - this.httpSuccess(response); + + const idNotToken = await this.idNotService.getIdNotToken(code); + const user = await this.idNotService.getOrCreateUser(idNotToken); + + 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) { console.log(error); this.httpInternalError(response); diff --git a/src/common/config/variables/Variables.ts b/src/common/config/variables/Variables.ts index a7b3cf3d..d865df6e 100644 --- a/src/common/config/variables/Variables.ts +++ b/src/common/config/variables/Variables.ts @@ -34,6 +34,12 @@ export class BackendVariables { @IsNotEmpty() public readonly APP_ROOT_URL!: string; + @IsNotEmpty() + public readonly IDNOT_BASE_URL!: string; + + @IsNotEmpty() + public readonly IDNOT_API_BASE_URL!: string; + @IsNotEmpty() public readonly IDNOT_CONNEXION_URL!: string; @@ -46,6 +52,9 @@ export class BackendVariables { @IsNotEmpty() public readonly IDNOT_REDIRECT_URL!: string; + @IsNotEmpty() + public readonly IDNOT_API_KEY!: string; + @IsNotEmpty() public readonly PINATA_API_KEY!: string; @@ -80,10 +89,13 @@ export class BackendVariables { this.APP_PORT = process.env["APP_PORT"]!; this.APP_ROOT_URL = process.env["APP_ROOT_URL"]!; 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_CLIENT_ID = process.env["IDNOT_CLIENT_ID"]!; this.IDNOT_CLIENT_SECRET = process.env["IDNOT_CLIENT_SECRET"]!; 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_SECRET = process.env["PINATA_API_SECRET"]!; this.PINATA_GATEWAY = process.env["PINATA_GATEWAY"]!; diff --git a/src/common/databases/migrations/20230915113328_v26/migration.sql b/src/common/databases/migrations/20230915113328_v26/migration.sql new file mode 100644 index 00000000..bcd32f0a --- /dev/null +++ b/src/common/databases/migrations/20230915113328_v26/migration.sql @@ -0,0 +1,5 @@ +-- AlterTable +ALTER TABLE "offices" ADD COLUMN "checked_at" TIMESTAMP(3); + +-- AlterTable +ALTER TABLE "users" ADD COLUMN "checked_at" TIMESTAMP(3); diff --git a/src/common/databases/schema.prisma b/src/common/databases/schema.prisma index 858709ed..317bf91d 100644 --- a/src/common/databases/schema.prisma +++ b/src/common/databases/schema.prisma @@ -6,8 +6,8 @@ generator client { } datasource db { - provider = "postgresql" - url = env("DEV_PRISMA_STUDIO_DB_URL") + provider = "postgresql" + url = env("DEV_PRISMA_STUDIO_DB_URL") shadowDatabaseUrl = env("DEV_PRISMA_STUDIO_SHADOW_URL") } @@ -61,6 +61,7 @@ model Users { office_role_uid String? @db.VarChar(255) created_at DateTime? @default(now()) updated_at DateTime? @updatedAt + checked_at DateTime? office_membership Offices @relation(fields: [office_uid], references: [uid], onDelete: Cascade) office_uid String @db.VarChar(255) notifications Notifications[] @relation("UserHasNotifications") @@ -81,6 +82,7 @@ model Offices { office_status EOfficeStatus @default(DESACTIVATED) created_at DateTime? @default(now()) updated_at DateTime? @updatedAt + checked_at DateTime? deed_types DeedTypes[] users Users[] office_folders OfficeFolders[] diff --git a/src/common/repositories/OfficesRepository.ts b/src/common/repositories/OfficesRepository.ts index 0e0c83ed..fb763880 100644 --- a/src/common/repositories/OfficesRepository.ts +++ b/src/common/repositories/OfficesRepository.ts @@ -72,6 +72,31 @@ export default class OfficesRepository extends BaseRepository { 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 { + return this.model.delete({ + where: { + uid: uid, + }, + }); + } + /** * @description : Find one office */ @@ -93,4 +118,25 @@ export default class OfficesRepository extends BaseRepository { 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, + }, + }); + } } diff --git a/src/common/repositories/UsersRepository.ts b/src/common/repositories/UsersRepository.ts index 6df40fb6..718f6066 100644 --- a/src/common/repositories/UsersRepository.ts +++ b/src/common/repositories/UsersRepository.ts @@ -87,7 +87,7 @@ export default class UsersRepository extends BaseRepository { /** * @description : Update data from a user */ - + public async update(uid: string, user: User): Promise { const updateArgs: Prisma.UsersUpdateArgs = { where: { @@ -108,7 +108,7 @@ export default class UsersRepository extends BaseRepository { }, }; - if(user.office_membership) { + if (user.office_membership) { updateArgs.data.office_membership = { connect: { 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 = { connect: { uid: user.office_role.uid, @@ -132,7 +132,7 @@ export default class UsersRepository extends BaseRepository { }; } - if(user.role) { + if (user.role) { updateArgs.data.role = { connect: { 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 { + 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 { const updateArgs: Prisma.UsersUpdateArgs = { where: { uid: uid, }, - data: {} + data: {}, }; - if(user.office_role) { + if (user.office_role) { updateArgs.data.office_role = { connect: { 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 } } } }); } + /** + * @description : Delete one user + */ + public async delete(uid: string): Promise { + return this.model.delete({ + where: { + uid: uid, + }, + }); + } + /** * @description : Find one user */ @@ -200,7 +217,7 @@ export default class UsersRepository extends BaseRepository { /** * @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({ where: { 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, + }, + }); + } } diff --git a/src/entries/Cron.ts b/src/entries/Cron.ts index 25d0d4eb..0b97bcec 100644 --- a/src/entries/Cron.ts +++ b/src/entries/Cron.ts @@ -8,6 +8,7 @@ import CronService from "@Services/common/CronService/CronService"; try { const variables = await Container.get(BackendVariables).validate(); Container.get(CronService).archiveFiles(); + await Container.get(CronService).updateUsers(); if(variables.ENV !== "dev"){ Container.get(CronService).sendMails(); } diff --git a/src/services/admin/UsersService/UsersService.ts b/src/services/admin/UsersService/UsersService.ts index 6167352e..934e1341 100644 --- a/src/services/admin/UsersService/UsersService.ts +++ b/src/services/admin/UsersService/UsersService.ts @@ -19,20 +19,12 @@ export default class UsersService extends BaseService { return this.userRepository.findMany(query); } - /** - * @description : Create a user - * @throws {Error} If user couldn't be created - */ - public create(userEntity: User): Promise { - return this.userRepository.create(userEntity); - } - /** * @description : Modify a user * @throws {Error} If user modification failed */ public async update(uid: string, userEntity: User): Promise { - return this.userRepository.updateRole(uid, userEntity); + return this.userRepository.updateOfficeRole(uid, userEntity); } /** diff --git a/src/services/common/AuthService/AuthService.ts b/src/services/common/AuthService/AuthService.ts index 4410cd35..07a5f7bf 100644 --- a/src/services/common/AuthService/AuthService.ts +++ b/src/services/common/AuthService/AuthService.ts @@ -15,7 +15,12 @@ interface ICustomerJwtPayload { customerId: string; email: string; } - + +export interface IdNotJwtPayload { + sub: string, + profile_idn: string, + entity_idn: string, +} interface IUserJwtPayload { userId: string; diff --git a/src/services/common/CronService/CronService.ts b/src/services/common/CronService/CronService.ts index 80e86255..d8c6cd38 100644 --- a/src/services/common/CronService/CronService.ts +++ b/src/services/common/CronService/CronService.ts @@ -2,11 +2,12 @@ import { Service } from "typedi"; import { CronJob } from "cron"; import MailchimpService from "../MailchimpService/MailchimpService"; import FilesService from "../FilesService/FilesService"; +import IdNotService from "../IdNotService/IdNotService"; @Service() export default class CronService { - constructor(private mailchimpService: MailchimpService, private filesService: FilesService) {} + constructor(private mailchimpService: MailchimpService, private filesService: FilesService, private idNotService: IdNotService) {} public async sendMails() { const cronJob = new CronJob("*/15 * * * *", async () => { // Every 15 minutes @@ -37,4 +38,18 @@ export default class CronService { 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(); + } + } } diff --git a/src/services/common/IdNotService/IdNotService.ts b/src/services/common/IdNotService/IdNotService.ts new file mode 100644 index 00000000..17c3378b --- /dev/null +++ b/src/services/common/IdNotService/IdNotService.ts @@ -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 { + 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(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(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(userToAdd); + return await this.userService.create(userToHydrate); + } + return user; + } + + public async updateUsers() { + const usersReq = await this.userService.getUsersToBeChecked(); + const users = User.hydrateArray(usersReq); + users.forEach(async (user) => { + await this.updateUser(user.uid!); + + }); + } + + public async updateOffices() { + const officesReq = await this.officeService.getOfficesToBeChecked(); + const offices = Office.hydrateArray(officesReq); + offices.forEach(async (office) => { + await this.updateOffice(office.uid!); + }); + } +} diff --git a/src/services/super-admin/OfficesService/OfficesService.ts b/src/services/super-admin/OfficesService/OfficesService.ts index 441da71b..de1e5391 100644 --- a/src/services/super-admin/OfficesService/OfficesService.ts +++ b/src/services/super-admin/OfficesService/OfficesService.ts @@ -34,6 +34,23 @@ export default class OfficesService extends BaseService { return this.officeRepository.update(uid, officeEntity); } + /** + * @description : Modify an office check date + * @throws {Error} If user modification failed + * @deprecate + */ + public updateCheckedAt(uid: string): Promise { + return this.officeRepository.updateCheckedAt(uid); + } + + /** + * @description : delete an office + * @throws {Error} If office cannot be modified + */ + public async delete(uid: string): Promise { + return this.officeRepository.delete(uid); + } + /** * @description : Get a office by uid * @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 { return this.officeRepository.findOneByUid(uid, query); } + + /** + * @description : Get users to be checked with IdNot API + */ + public getOfficesToBeChecked() { + return this.officeRepository.findManyToCheck(); + } } diff --git a/src/services/super-admin/UsersService/UsersService.ts b/src/services/super-admin/UsersService/UsersService.ts index 241cb1e4..3598e945 100644 --- a/src/services/super-admin/UsersService/UsersService.ts +++ b/src/services/super-admin/UsersService/UsersService.ts @@ -35,6 +35,23 @@ export default class UsersService extends BaseService { return this.userRepository.update(uid, userEntity); } + /** + * @description : Modify a user check date + * @throws {Error} If user modification failed + * @deprecate + */ + public updateCheckedAt(uid: string): Promise { + return this.userRepository.updateCheckedAt(uid); + } + + /** + * @description : Delete a user + * @throws {Error} If user modification failed + */ + public delete(uid: string): Promise { + return this.userRepository.delete(uid); + } + /** * @description : Get a user 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) { return this.userRepository.findOneByProvider(providerName, id); } + + /** + * @description : Get users to be checked with IdNot API + */ + public getUsersToBeChecked() { + return this.userRepository.findManyToCheck(); + } + }