From 99eb0a4dad5ecdf948923c25d9101987f2d5ec32 Mon Sep 17 00:00:00 2001 From: "Yassine R." Date: Tue, 16 Sep 2025 15:09:21 +0200 Subject: [PATCH 1/4] feat(backend): add new role 'agent' --- .../USER_STRUCTURE_ROLES_NOT_FACTEUR.ts | 8 ++ .../USER_STRUCTURE_ROLE_ALL.const.ts | 1 + .../users/user-structure/constants/index.ts | 1 + .../auth/guards/usager-doc-access.guard.ts | 2 +- .../src/auth/structures-auth.controller.ts | 2 + .../dto/register-user-structure-admin.dto.ts | 5 +- .../portail-usagers-manager.controller.ts | 10 +- .../controllers/structure-doc.controller.ts | 7 +- .../users/controllers/users.controller.ts | 16 +-- .../controllers/users.public.controller.ts | 5 +- .../src/modules/users/dto/update-role.dto.ts | 3 +- .../usagers/controllers/agenda.controller.ts | 5 +- .../import.controller.security-tests.ts | 2 +- .../controllers/import/import.controller.ts | 2 +- .../controllers/usager-notes.controller.ts | 3 + .../controllers/usager-options.controller.ts | 2 +- .../usager-structure-docs.controller.ts | 16 ++- .../usagers-decision.controller.ts | 12 ++ .../usagers/controllers/usagers.controller.ts | 3 +- .../ALL_USER_STRUCTURE_ROLES.const.ts | 9 ++ .../USER_STRUCTURE_ROLES_LABELS.const.ts | 1 + .../users/user-structure/constants/index.ts | 3 +- .../types/UserStructureRole.type.ts | 7 +- packages/frontend/angular.json | 8 +- packages/frontend/setup-jest.ts | 4 +- .../frontend/src/app/app-routing.module.ts | 30 ++++- .../frontend/src/app/guards/admin.guard.ts | 29 ----- .../src/app/guards/auth.guard.spec.ts | 5 +- .../frontend/src/app/guards/auth.guard.ts | 43 +++++-- .../frontend/src/app/guards/facteur.guard.ts | 30 ----- packages/frontend/src/app/guards/index.ts | 4 +- .../src/app/guards/responsable.guard.ts | 30 ----- .../components/navbar/navbar.component.html | 14 +-- .../manage-download-docs.component.html | 2 +- .../manage-usagers-page.component.html | 2 +- .../manage-usagers-table.component.ts | 8 +- .../manage-usagers-table.html | 4 +- .../edit-user/edit-user.component.html | 2 +- .../edit-user/edit-user.component.ts | 2 +- .../register-user-admin.component.html | 1 + .../user-profil/user-profil.component.html | 116 +++++++++++++----- .../user-profil/user-profil.component.ts | 2 +- .../manage-users-routing.module.ts | 13 +- .../services/manage-users.service.ts | 10 +- .../modules/shared/services/auth.service.ts | 2 +- .../reporting-form.component.html | 4 +- .../reporting-form.component.spec.ts | 2 - .../structure-stats-routing.module.ts | 4 + .../structures-custom-docs.component.html | 4 +- .../structures-edit.component.html | 4 +- .../structures/structures-routing.module.ts | 18 ++- .../step-decision.component.html | 8 +- .../step-footer/step-footer.component.html | 2 +- .../profil-general-notes.component.html | 2 +- ...t-portail-usager-preference.component.html | 5 +- ...profil-historique-decisions.component.html | 2 +- .../profil-historique-notes.component.html | 2 +- .../profil-courriers.component.html | 2 +- .../profil-dossier.component.html | 11 +- .../profil-general-section.component.html | 4 +- .../profil-head/profil-head.component.html | 6 +- .../profil-head/profil-head.component.ts | 2 +- .../usager-profil-routing.module.ts | 53 ++++++-- .../delete-usager-menu.component.html | 4 +- .../display-usager-docs.component.html | 2 +- packages/frontend/tsconfig.spec.json | 1 + .../components/users/users.component.ts | 9 +- 67 files changed, 384 insertions(+), 253 deletions(-) create mode 100644 packages/backend/src/_common/model/users/user-structure/constants/USER_STRUCTURE_ROLES_NOT_FACTEUR.ts create mode 100644 packages/common/src/users/user-structure/constants/ALL_USER_STRUCTURE_ROLES.const.ts delete mode 100644 packages/frontend/src/app/guards/admin.guard.ts delete mode 100644 packages/frontend/src/app/guards/facteur.guard.ts delete mode 100644 packages/frontend/src/app/guards/responsable.guard.ts diff --git a/packages/backend/src/_common/model/users/user-structure/constants/USER_STRUCTURE_ROLES_NOT_FACTEUR.ts b/packages/backend/src/_common/model/users/user-structure/constants/USER_STRUCTURE_ROLES_NOT_FACTEUR.ts new file mode 100644 index 0000000000..1b611f56f4 --- /dev/null +++ b/packages/backend/src/_common/model/users/user-structure/constants/USER_STRUCTURE_ROLES_NOT_FACTEUR.ts @@ -0,0 +1,8 @@ +import { UserStructureRole } from "@domifa/common"; + +export const USER_STRUCTURE_ROLES_NOT_FACTEUR: UserStructureRole[] = [ + "simple", + "admin", + "agent", + "responsable", +]; diff --git a/packages/backend/src/_common/model/users/user-structure/constants/USER_STRUCTURE_ROLE_ALL.const.ts b/packages/backend/src/_common/model/users/user-structure/constants/USER_STRUCTURE_ROLE_ALL.const.ts index 072ace36db..61fc253b98 100644 --- a/packages/backend/src/_common/model/users/user-structure/constants/USER_STRUCTURE_ROLE_ALL.const.ts +++ b/packages/backend/src/_common/model/users/user-structure/constants/USER_STRUCTURE_ROLE_ALL.const.ts @@ -4,5 +4,6 @@ export const USER_STRUCTURE_ROLE_ALL: UserStructureRole[] = [ "simple", "admin", "facteur", + "agent", "responsable", ]; diff --git a/packages/backend/src/_common/model/users/user-structure/constants/index.ts b/packages/backend/src/_common/model/users/user-structure/constants/index.ts index 85e65fc9cf..af4808956f 100644 --- a/packages/backend/src/_common/model/users/user-structure/constants/index.ts +++ b/packages/backend/src/_common/model/users/user-structure/constants/index.ts @@ -1,2 +1,3 @@ // @index('./*', f => `export * from '${f.path}'`) export * from "./USER_STRUCTURE_ROLE_ALL.const"; +export * from "./USER_STRUCTURE_ROLES_NOT_FACTEUR"; diff --git a/packages/backend/src/auth/guards/usager-doc-access.guard.ts b/packages/backend/src/auth/guards/usager-doc-access.guard.ts index 61c8221540..512909fd13 100644 --- a/packages/backend/src/auth/guards/usager-doc-access.guard.ts +++ b/packages/backend/src/auth/guards/usager-doc-access.guard.ts @@ -30,7 +30,7 @@ export class UsagerDocAccessGuard implements CanActivate { throw new HttpException("USAGER_DOC_NOT_FOUND", HttpStatus.BAD_REQUEST); } - if (user?.role === "facteur") { + if (user?.role === "facteur" || user?.role === "agent") { throw new HttpException("CANNOT_GET_DOC", HttpStatus.UNAUTHORIZED); } diff --git a/packages/backend/src/auth/structures-auth.controller.ts b/packages/backend/src/auth/structures-auth.controller.ts index 4ecfe6eca1..c012eb9da1 100644 --- a/packages/backend/src/auth/structures-auth.controller.ts +++ b/packages/backend/src/auth/structures-auth.controller.ts @@ -29,6 +29,7 @@ import { domifaConfig } from "../config"; import { userSecurityPasswordChecker } from "../modules/users/services"; import { AllowUserStructureRoles } from "./decorators"; import { UserStructure } from "@domifa/common"; +import { appLogger } from "../util"; const userProfile: UserProfile = "structure"; @@ -55,6 +56,7 @@ export class StructuresAuthController { return res.status(HttpStatus.OK).json(accessToken); } catch (err) { + appLogger.error(err); return res .status(HttpStatus.UNAUTHORIZED) .json({ message: "LOGIN_FAILED" }); diff --git a/packages/backend/src/modules/portail-admin/dto/register-user-structure-admin.dto.ts b/packages/backend/src/modules/portail-admin/dto/register-user-structure-admin.dto.ts index d03e72b88c..ad738e2b4a 100644 --- a/packages/backend/src/modules/portail-admin/dto/register-user-structure-admin.dto.ts +++ b/packages/backend/src/modules/portail-admin/dto/register-user-structure-admin.dto.ts @@ -12,6 +12,7 @@ import { import { Transform, TransformFnParams } from "class-transformer"; import { LowerCaseTransform } from "../../../_common/decorators"; import { UserStructureRole, UserFonction } from "@domifa/common"; +import { USER_STRUCTURE_ROLE_ALL } from "../../../_common/model"; export class RegisterUserStructureAdminDto { @ApiProperty({ @@ -78,10 +79,10 @@ export class RegisterUserStructureAdminDto { @ApiProperty({ type: String, required: true, - enum: ["admin", "simple", "facteur", "responsable"], + enum: USER_STRUCTURE_ROLE_ALL, }) @IsNotEmpty() - @IsIn(["admin", "simple", "facteur", "responsable"]) + @IsIn(USER_STRUCTURE_ROLE_ALL) public readonly role!: UserStructureRole; @IsNotEmpty() diff --git a/packages/backend/src/modules/portail-usagers/controllers/portail-usagers-manager/portail-usagers-manager.controller.ts b/packages/backend/src/modules/portail-usagers/controllers/portail-usagers-manager/portail-usagers-manager.controller.ts index c0f26aa7f0..b044e6bd92 100644 --- a/packages/backend/src/modules/portail-usagers/controllers/portail-usagers-manager/portail-usagers-manager.controller.ts +++ b/packages/backend/src/modules/portail-usagers/controllers/portail-usagers-manager/portail-usagers-manager.controller.ts @@ -53,7 +53,7 @@ import * as XLSX from "xlsx"; @ApiTags("portail-usagers-manager") @UseGuards(AuthGuard("jwt"), AppUserGuard) @AllowUserProfiles("structure") -@AllowUserStructureRoles(...USER_STRUCTURE_ROLE_ALL) +@AllowUserStructureRoles("responsable", "admin") @ApiBearerAuth() export class PortailUsagersManagerController { constructor(private readonly appLogsService: AppLogsService) {} @@ -114,7 +114,6 @@ export class PortailUsagersManagerController { } } - @AllowUserStructureRoles(...USER_STRUCTURE_ROLE_ALL) @Get("stats") public async getUserUsagerStats( @CurrentUser() currentUser: UserStructureAuthenticated @@ -122,7 +121,6 @@ export class PortailUsagersManagerController { return usagerRepository.countUsagersByStatus(currentUser.structureId, true); } - @AllowUserStructureRoles(...USER_STRUCTURE_ROLE_ALL) @Get("export/all-accounts") public async exportAccountsToExcel( @Res() res: Response, @@ -197,7 +195,6 @@ export class PortailUsagersManagerController { res.send(excelBuffer); } - @AllowUserStructureRoles("admin", "responsable") @Get("generate-all-accounts") public async generateAllAccounts( @Res() res: Response, @@ -272,9 +269,9 @@ export class PortailUsagersManagerController { } @UseGuards(UsagerAccessGuard) - @AllowUserStructureRoles("simple", "responsable", "admin") + @AllowUserStructureRoles("simple", "responsable", "admin", "agent") @Post("enable-access/:usagerRef") - public async editPreupdatePortailUsagerOptionsference( + public async enablePortailForUsager( @Res() res: Response, @Body() dto: UpdatePortailUsagerOptionsDto, @CurrentUsager() usager: Usager, @@ -333,7 +330,6 @@ export class PortailUsagersManagerController { } } - @AllowUserStructureRoles(...USER_STRUCTURE_ROLE_ALL) @Post("all-accounts") public async getAllAccounts( @Body() pageOptionsDto: PageOptionsDto, diff --git a/packages/backend/src/modules/structures/controllers/structure-doc.controller.ts b/packages/backend/src/modules/structures/controllers/structure-doc.controller.ts index b0bf0b2724..e63789117e 100644 --- a/packages/backend/src/modules/structures/controllers/structure-doc.controller.ts +++ b/packages/backend/src/modules/structures/controllers/structure-doc.controller.ts @@ -37,6 +37,7 @@ import { join } from "path"; import { FileManagerService } from "../../../util/file-manager/file-manager.service"; import { validateDocTemplate } from "../../../usagers/utils/custom-docs"; import { StructureDocTypesAvailable } from "@domifa/common"; +import { appLogger } from "../../../util"; @ApiTags("structure-docs") @ApiBearerAuth() @@ -171,7 +172,8 @@ export class StructureDocController { }); return res.status(HttpStatus.OK).json(docs); - } catch (e) { + } catch (err) { + appLogger.error(err); return res .status(HttpStatus.BAD_REQUEST) .json({ message: "UPLOAD_FAIL" }); @@ -211,7 +213,8 @@ export class StructureDocController { structureId: user.structureId, }); return res.status(HttpStatus.OK).json(docs); - } catch (e) { + } catch (err) { + appLogger.error(err); return res .status(HttpStatus.BAD_REQUEST) .json({ message: "DOC_NOT_FOUND" }); diff --git a/packages/backend/src/modules/users/controllers/users.controller.ts b/packages/backend/src/modules/users/controllers/users.controller.ts index 4ccf0f0018..93eda0fb5a 100644 --- a/packages/backend/src/modules/users/controllers/users.controller.ts +++ b/packages/backend/src/modules/users/controllers/users.controller.ts @@ -52,6 +52,7 @@ import { UserStructureCreateLogContext, UserStructureRoleChangeLogContext, } from "../../app-logs/app-log-context.types"; +import { appLogger } from "../../../util"; const userProfile: UserProfile = "structure"; @@ -62,8 +63,7 @@ const userProfile: UserProfile = "structure"; @UseGuards(AuthGuard("jwt"), AppUserGuard) export class UsersController { constructor(private readonly appLogService: AppLogsService) {} - @ApiBearerAuth() - @ApiOperation({ summary: "Liste des utilisateurs" }) + @Get("") public async getUsers( @CurrentUser() user: UserStructureAuthenticated @@ -71,7 +71,11 @@ export class UsersController { const users = await userStructureRepository.getVerifiedUsersByStructureId( user.structureId ); - if (user.role === "facteur" || user.role === "simple") { + if ( + user.role === "facteur" || + user.role === "agent" || + user.role === "simple" + ) { return users.map((user) => { return { id: user.id, @@ -83,7 +87,6 @@ export class UsersController { return users; } - @ApiOperation({ summary: "Accepter les CGU" }) @Get("accept-terms") public async acceptTerms(@CurrentUser() user: UserStructureAuthenticated) { await userStructureRepository.update( @@ -100,7 +103,6 @@ export class UsersController { return true; } - @ApiOperation({ summary: "Edition du mot de passe depuis le compte user" }) @Get("last-password-update") public async getLastPasswordUpdate( @CurrentUser() user: UserStructureAuthenticated, @@ -115,8 +117,6 @@ export class UsersController { } @AllowUserStructureRoles("admin") - @ApiBearerAuth("Administrateurs") - @ApiOperation({ summary: "Editer le rôle d'un utilisateur" }) @UseGuards(CanGetUserStructureGuard) @Patch("update-role/:userUuid") public async updateRole( @@ -234,6 +234,7 @@ export class UsersController { } @Patch() + @ApiOperation({ summary: "Modifier mes informations" }) public async patch( @CurrentUser() user: UserStructureAuthenticated, @Body() userDto: UserEditDto, @@ -338,6 +339,7 @@ export class UsersController { }); return res.status(HttpStatus.OK).json({ message: "OK" }); } catch (err) { + appLogger.error(err); return res .status(HttpStatus.BAD_REQUEST) .json({ message: "EDIT_PASSWORD_FAIL" }); diff --git a/packages/backend/src/modules/users/controllers/users.public.controller.ts b/packages/backend/src/modules/users/controllers/users.public.controller.ts index 7c81fc4e72..238297fd86 100644 --- a/packages/backend/src/modules/users/controllers/users.public.controller.ts +++ b/packages/backend/src/modules/users/controllers/users.public.controller.ts @@ -25,6 +25,7 @@ const userProfile: UserProfile = "structure"; @Controller("users") @ApiTags("users") export class UsersPublicController { + // TODO: add a limit for this endpoint by ip @Post("validate-email") public async validateEmail( @Body() emailDto: EmailDto, @@ -57,6 +58,7 @@ export class UsersPublicController { }); return res.status(HttpStatus.OK).json({ message: "OK" }); } catch (err) { + appLogger.error(err); return res .status(HttpStatus.BAD_REQUEST) .json({ message: "TOKEN_INVALID" }); @@ -77,6 +79,7 @@ export class UsersPublicController { }); return res.status(HttpStatus.OK).json({ message: "OK" }); } catch (err) { + appLogger.error(err); return res .status(HttpStatus.BAD_REQUEST) .json({ message: "TOKEN_INVALID" }); @@ -101,7 +104,7 @@ export class UsersPublicController { userProfile, }); } catch (err) { - appLogger.error("Cannot reset password"); + appLogger.error(err); } return res.status(HttpStatus.OK).json({ message: "OK" }); } diff --git a/packages/backend/src/modules/users/dto/update-role.dto.ts b/packages/backend/src/modules/users/dto/update-role.dto.ts index 531c80d01f..e8e86a1e8b 100644 --- a/packages/backend/src/modules/users/dto/update-role.dto.ts +++ b/packages/backend/src/modules/users/dto/update-role.dto.ts @@ -1,8 +1,9 @@ import { UserStructureRole } from "@domifa/common"; import { IsIn, IsNotEmpty } from "class-validator"; +import { USER_STRUCTURE_ROLE_ALL } from "../../../_common/model"; export class UpdateRoleDto { - @IsIn(["simple", "admin", "facteur", "responsable"]) + @IsIn(USER_STRUCTURE_ROLE_ALL) @IsNotEmpty() public readonly role!: UserStructureRole; } diff --git a/packages/backend/src/usagers/controllers/agenda.controller.ts b/packages/backend/src/usagers/controllers/agenda.controller.ts index 565a958b0b..1d11e5cf42 100644 --- a/packages/backend/src/usagers/controllers/agenda.controller.ts +++ b/packages/backend/src/usagers/controllers/agenda.controller.ts @@ -31,6 +31,7 @@ import { RdvDto } from "../dto/decision-form/rdv.dto"; import { UsagersService } from "../services/usagers.service"; import { getPersonFullName, Usager } from "@domifa/common"; import { usagerAppointmentCreatedEmailSender } from "../../modules/mails/services/templates-renderers"; +import { appLogger } from "../../util"; @ApiTags("agenda") @ApiBearerAuth() @@ -148,7 +149,9 @@ export class AgendaController { message, }); return res.status(HttpStatus.OK).json(updatedUsager); - } catch (e) { + } catch (err) { + appLogger.error(err); + return res .status(HttpStatus.INTERNAL_SERVER_ERROR) .json({ message: "REGISTER_ERROR" }); diff --git a/packages/backend/src/usagers/controllers/import/import.controller.security-tests.ts b/packages/backend/src/usagers/controllers/import/import.controller.security-tests.ts index 3379983cbd..65aaea9b29 100644 --- a/packages/backend/src/usagers/controllers/import/import.controller.security-tests.ts +++ b/packages/backend/src/usagers/controllers/import/import.controller.security-tests.ts @@ -44,7 +44,7 @@ export const ImportControllerSecurityTests: AppTestHttpClientSecurityTestDef[] = expectedStatus: expectedResponseStatusBuilder.allowStructureOnly( context.user, { - roles: ["simple", "responsable", "admin"], + roles: ["responsable", "admin"], validExpectedResponseStatus: HttpStatus.BAD_REQUEST, // this is an invalid xls file } ), diff --git a/packages/backend/src/usagers/controllers/import/import.controller.ts b/packages/backend/src/usagers/controllers/import/import.controller.ts index 14c15d9b44..6507208158 100644 --- a/packages/backend/src/usagers/controllers/import/import.controller.ts +++ b/packages/backend/src/usagers/controllers/import/import.controller.ts @@ -82,7 +82,7 @@ const UsagersImportFileInterceptor = FileInterceptor("file", { @ApiTags("import") @ApiBearerAuth() @Controller("import") -@AllowUserStructureRoles("simple", "responsable", "admin") +@AllowUserStructureRoles("responsable", "admin") @AllowUserProfiles("structure") export class ImportController { constructor( diff --git a/packages/backend/src/usagers/controllers/usager-notes.controller.ts b/packages/backend/src/usagers/controllers/usager-notes.controller.ts index 62a382096a..fdb229b065 100644 --- a/packages/backend/src/usagers/controllers/usager-notes.controller.ts +++ b/packages/backend/src/usagers/controllers/usager-notes.controller.ts @@ -114,6 +114,7 @@ export class UsagerNotesController { @Delete(":usagerRef/:noteUUID") @UseGuards(UsagerAccessGuard, UsagerNoteAccessGuard) + @AllowUserStructureRoles("responsable", "simple", "admin") public async deleteNote( @CurrentUser() currentUser: UserStructureAuthenticated, @CurrentUsagerNote() currentUsagerNote: UsagerNote, @@ -146,6 +147,7 @@ export class UsagerNotesController { } @Put(":usagerRef/pin/:noteUUID") + @AllowUserStructureRoles("responsable", "simple", "admin") @UseGuards(UsagerAccessGuard, UsagerNoteAccessGuard) public async pinNote( @CurrentUser() _currentUser: UserStructureAuthenticated, @@ -193,6 +195,7 @@ export class UsagerNotesController { @Put(":usagerRef/archive/:noteUUID") @UseGuards(UsagerAccessGuard, UsagerNoteAccessGuard) + @AllowUserStructureRoles("responsable", "simple", "admin") public async archiveNote( @CurrentUser() currentUser: UserStructureAuthenticated, @CurrentUsagerNote() currentUsagerNote: UsagerNote, diff --git a/packages/backend/src/usagers/controllers/usager-options.controller.ts b/packages/backend/src/usagers/controllers/usager-options.controller.ts index a002835fd9..4e5f5bc87d 100644 --- a/packages/backend/src/usagers/controllers/usager-options.controller.ts +++ b/packages/backend/src/usagers/controllers/usager-options.controller.ts @@ -54,7 +54,7 @@ export class UsagerOptionsController { @UseGuards(UsagerAccessGuard) @Get("historique/:usagerRef/:type") - public async createNote( + public async getProcurationHistory( @CurrentUsager() currentUsager: Usager, @Param("usagerRef", new ParseIntPipe()) _usagerRef: number, @Param("type", new ParseEnumPipe(UsagerOptionsHistoryTypeEnum)) diff --git a/packages/backend/src/usagers/controllers/usager-structure-docs.controller.ts b/packages/backend/src/usagers/controllers/usager-structure-docs.controller.ts index b047e048d7..01ab968d89 100644 --- a/packages/backend/src/usagers/controllers/usager-structure-docs.controller.ts +++ b/packages/backend/src/usagers/controllers/usager-structure-docs.controller.ts @@ -26,7 +26,10 @@ import { structureDocRepository, userStructureRepository, } from "../../database"; -import { UserStructureAuthenticated } from "../../_common/model"; +import { + USER_STRUCTURE_ROLES_NOT_FACTEUR, + UserStructureAuthenticated, +} from "../../_common/model"; import { buildCustomDoc, customDocTemplateLoader, @@ -35,7 +38,7 @@ import { import { AppLogsService } from "../../modules/app-logs/app-logs.service"; import { join } from "path"; -import { cleanPath } from "../../util"; +import { appLogger, cleanPath } from "../../util"; import { FileManagerService } from "../../util/file-manager/file-manager.service"; import { StructureDoc, @@ -47,7 +50,7 @@ import { @ApiTags("usagers-structure-docs") @ApiBearerAuth() @Controller("usagers-structure-docs") -@AllowUserStructureRoles("simple", "responsable", "admin") +@AllowUserStructureRoles(...USER_STRUCTURE_ROLES_NOT_FACTEUR) @AllowUserProfiles("structure") export class UsagerStructureDocsController { constructor( @@ -115,7 +118,8 @@ export class UsagerStructureDocsController { try { const docGenerated = await generateCustomDoc(content, docValues); return res.end(docGenerated); - } catch (e) { + } catch (err) { + appLogger.error(err); return res .status(HttpStatus.BAD_REQUEST) .json({ message: "CANNOT_COMPLETE_DOC" }); @@ -202,7 +206,9 @@ export class UsagerStructureDocsController { try { const docGenerated = await generateCustomDoc(content, docValues); return res.end(docGenerated); - } catch (e) { + } catch (err) { + appLogger.error(err); + return res .status(HttpStatus.BAD_REQUEST) .json({ message: "CANNOT_COMPLETE_DOMIFA_DOCS" }); diff --git a/packages/backend/src/usagers/controllers/usagers-decision.controller.ts b/packages/backend/src/usagers/controllers/usagers-decision.controller.ts index 2068c6d531..9eaf27ec64 100644 --- a/packages/backend/src/usagers/controllers/usagers-decision.controller.ts +++ b/packages/backend/src/usagers/controllers/usagers-decision.controller.ts @@ -59,12 +59,23 @@ export class UsagersDecisionController { // eslint-disable-next-line @typescript-eslint/no-unused-vars @Param("usagerRef", new ParseIntPipe()) _usagerRef: number ): Promise { + if ( + decision.statut !== "ATTENTE_DECISION" && + decision.statut !== "INSTRUCTION" && + user.role !== "responsable" && + user.role !== "admin" + ) { + throw new Error("CANNOT_SET_DECISION"); + } + decision.userName = `${user.prenom} ${user.nom}`; decision.userId = user.id; + return await this.usagersService.setDecision(usager, decision); } @UseGuards(UsagerAccessGuard) + @AllowUserStructureRoles("responsable", "admin") @Get("last-usagers-refs/:usagerRef") public async getLastUsagerIds( @CurrentUser() user: UserStructureAuthenticated, @@ -80,6 +91,7 @@ export class UsagersDecisionController { @UseGuards(UsagerAccessGuard) @Get("renouvellement/:usagerRef") + @AllowUserStructureRoles("responsable", "admin", "simple") public async renouvellement( @CurrentUser() user: UserStructureAuthenticated, @CurrentUsager() usager: Usager, diff --git a/packages/backend/src/usagers/controllers/usagers.controller.ts b/packages/backend/src/usagers/controllers/usagers.controller.ts index 1403e7463c..d5f1795543 100644 --- a/packages/backend/src/usagers/controllers/usagers.controller.ts +++ b/packages/backend/src/usagers/controllers/usagers.controller.ts @@ -43,6 +43,7 @@ import { import { UserStructureAuthenticated, USER_STRUCTURE_ROLE_ALL, + USER_STRUCTURE_ROLES_NOT_FACTEUR, } from "../../_common/model"; import { CheckDuplicateUsagerDto, @@ -366,7 +367,7 @@ export class UsagersController { } @UseGuards(UsagerAccessGuard) - @AllowUserStructureRoles(...USER_STRUCTURE_ROLE_ALL) + @AllowUserStructureRoles(...USER_STRUCTURE_ROLES_NOT_FACTEUR) @Get("cerfa/:usagerRef/:typeCerfa") public async getAttestation( @Res() res: Response, diff --git a/packages/common/src/users/user-structure/constants/ALL_USER_STRUCTURE_ROLES.const.ts b/packages/common/src/users/user-structure/constants/ALL_USER_STRUCTURE_ROLES.const.ts new file mode 100644 index 0000000000..c59a438314 --- /dev/null +++ b/packages/common/src/users/user-structure/constants/ALL_USER_STRUCTURE_ROLES.const.ts @@ -0,0 +1,9 @@ +import { UserStructureRole } from "../types"; + +export const ALL_USER_STRUCTURE_ROLES: UserStructureRole[] = [ + "simple", + "admin", + "facteur", + "agent", + "responsable", +]; diff --git a/packages/common/src/users/user-structure/constants/USER_STRUCTURE_ROLES_LABELS.const.ts b/packages/common/src/users/user-structure/constants/USER_STRUCTURE_ROLES_LABELS.const.ts index 12669e8977..7ee25224c1 100644 --- a/packages/common/src/users/user-structure/constants/USER_STRUCTURE_ROLES_LABELS.const.ts +++ b/packages/common/src/users/user-structure/constants/USER_STRUCTURE_ROLES_LABELS.const.ts @@ -7,4 +7,5 @@ export const USER_STRUCTURE_ROLES_LABELS: { responsable: "Gestionnaire", simple: "Instructeur", facteur: "Facteur", + agent: "Agent d'accueil", }; diff --git a/packages/common/src/users/user-structure/constants/index.ts b/packages/common/src/users/user-structure/constants/index.ts index 988b250921..f4351623b8 100644 --- a/packages/common/src/users/user-structure/constants/index.ts +++ b/packages/common/src/users/user-structure/constants/index.ts @@ -1,4 +1,5 @@ // @index('./*', f => `export * from '${f.path}'`) +export * from "./ALL_USER_STRUCTURE_ROLES.const"; +export * from "./USER_FONCTION_LABELS.const"; export * from "./USER_FONCTIONS.const"; export * from "./USER_STRUCTURE_ROLES_LABELS.const"; -export * from "./USER_FONCTION_LABELS.const"; diff --git a/packages/common/src/users/user-structure/types/UserStructureRole.type.ts b/packages/common/src/users/user-structure/types/UserStructureRole.type.ts index 04e3fa9472..fe1ddb22af 100644 --- a/packages/common/src/users/user-structure/types/UserStructureRole.type.ts +++ b/packages/common/src/users/user-structure/types/UserStructureRole.type.ts @@ -1 +1,6 @@ -export type UserStructureRole = "simple" | "admin" | "facteur" | "responsable"; +export type UserStructureRole = + | "simple" + | "admin" + | "facteur" + | "responsable" + | "agent"; diff --git a/packages/frontend/angular.json b/packages/frontend/angular.json index 347d5cebab..babab50787 100644 --- a/packages/frontend/angular.json +++ b/packages/frontend/angular.json @@ -60,8 +60,8 @@ "budgets": [ { "type": "initial", - "maximumWarning": "4mb", - "maximumError": "6mb" + "maximumWarning": "5mb", + "maximumError": "8mb" } ] }, @@ -83,8 +83,8 @@ "budgets": [ { "type": "initial", - "maximumWarning": "4mb", - "maximumError": "6mb" + "maximumWarning": "5mb", + "maximumError": "8mb" } ] } diff --git a/packages/frontend/setup-jest.ts b/packages/frontend/setup-jest.ts index 08ccd2e1b2..9c43e18d29 100644 --- a/packages/frontend/setup-jest.ts +++ b/packages/frontend/setup-jest.ts @@ -1,2 +1,2 @@ -import "jest-preset-angular/setup-jest"; -import "./jest-global-mocks"; +import { setupZoneTestEnv } from "jest-preset-angular/setup-env/zone"; +setupZoneTestEnv(); diff --git a/packages/frontend/src/app/app-routing.module.ts b/packages/frontend/src/app/app-routing.module.ts index a071b4601d..12c63b44be 100644 --- a/packages/frontend/src/app/app-routing.module.ts +++ b/packages/frontend/src/app/app-routing.module.ts @@ -14,8 +14,9 @@ import { LoginComponent } from "./modules/general/components/login/login.compone import { NewsComponent } from "./modules/general/components/news/news.component"; import { PlanSiteComponent } from "./modules/general/components/plan-site/plan-site.component"; import { RgaaComponent } from "./modules/general/components/static-pages/rgaa/rgaa.component"; -import { AdminGuard, AuthGuard, FacteurGuard } from "./guards"; +import { AuthGuard } from "./guards"; import { LandingPagePortailComponent } from "./modules/general/components/static-pages/landing-page-portail/landing-page-portail.component"; +import { ALL_USER_STRUCTURE_ROLES } from "@domifa/common"; export const routes: Routes = [ { @@ -69,6 +70,9 @@ export const routes: Routes = [ (m) => m.ManageUsagersModule ), path: "manage", + data: { + roles: ALL_USER_STRUCTURE_ROLES, + }, }, { canActivate: [AuthGuard], @@ -77,22 +81,31 @@ export const routes: Routes = [ (m) => m.ManageUsersModule ), path: "manage-users", + data: { + roles: ALL_USER_STRUCTURE_ROLES, + }, }, { - canActivate: [AuthGuard, FacteurGuard], + canActivate: [AuthGuard], loadChildren: () => import("./modules/import-usagers/import-usagers.module").then( (m) => m.ImportUsagersModule ), path: "import", + data: { + roles: ["admin", "responsable"], + }, }, { - canActivate: [AuthGuard, AdminGuard], + canActivate: [AuthGuard], loadChildren: () => import( "./modules/admin-portail-usagers/admin-portail-usagers.module" ).then((m) => m.AdminPortailUsagersModule), path: "portail-usagers", + data: { + roles: ["admin"], + }, }, { loadChildren: () => @@ -100,12 +113,15 @@ export const routes: Routes = [ path: "users", }, { - canActivate: [AuthGuard, FacteurGuard], + canActivate: [AuthGuard], loadChildren: () => import("./modules/usager-dossier/usager-dossier.module").then( (m) => m.UsagerDossierModule ), path: "usager", + data: { + roles: ["admin", "responsable", "simple"], + }, }, { canActivate: [AuthGuard], @@ -114,6 +130,9 @@ export const routes: Routes = [ (m) => m.UsagerProfilModule ), path: "profil", + data: { + roles: ALL_USER_STRUCTURE_ROLES, + }, }, { loadChildren: () => @@ -121,6 +140,9 @@ export const routes: Routes = [ (m) => m.StructuresModule ), path: "structures", + data: { + roles: ALL_USER_STRUCTURE_ROLES, + }, }, { component: NotFoundComponent, path: "404" }, { path: "**", redirectTo: "404" }, diff --git a/packages/frontend/src/app/guards/admin.guard.ts b/packages/frontend/src/app/guards/admin.guard.ts deleted file mode 100644 index d77bd1c925..0000000000 --- a/packages/frontend/src/app/guards/admin.guard.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { Injectable } from "@angular/core"; -import { Router } from "@angular/router"; - -import { Observable } from "rxjs"; -import { AuthService } from "../modules/shared/services/auth.service"; -import { CustomToastService } from "../modules/shared/services/custom-toast.service"; - -@Injectable({ providedIn: "root" }) -export class AdminGuard { - constructor( - private readonly router: Router, - private readonly authService: AuthService, - private readonly toastService: CustomToastService - ) {} - - public canActivate(): Observable | boolean { - if (this.authService.currentUserValue !== null) { - const role = this.authService.currentUserValue.role; - if (role === "admin") { - return true; - } - } - this.toastService.error( - "Vos droits ne vous permettent pas d'accéder à cette page" - ); - this.router.navigate(["/manage"]); - return false; - } -} diff --git a/packages/frontend/src/app/guards/auth.guard.spec.ts b/packages/frontend/src/app/guards/auth.guard.spec.ts index eb39c3df41..71781d9099 100644 --- a/packages/frontend/src/app/guards/auth.guard.spec.ts +++ b/packages/frontend/src/app/guards/auth.guard.spec.ts @@ -12,11 +12,13 @@ import { AuthService } from "../modules/shared/services/auth.service"; import { AuthGuard } from "./auth.guard"; import { StoreModule } from "@ngrx/store"; import { _usagerReducer } from "../shared"; +import { CustomToastService } from "../modules/shared/services/custom-toast.service"; describe("AuthGuard", () => { let authGuard: AuthGuard; let router: Router; let authService: AuthService; + let toastr: CustomToastService; beforeEach(() => { TestBed.configureTestingModule({ @@ -46,6 +48,7 @@ describe("AuthGuard", () => { authService = TestBed.inject(AuthService); authGuard = TestBed.inject(AuthGuard); + toastr = TestBed.inject(CustomToastService); router = TestBed.inject(Router); }); @@ -54,7 +57,7 @@ describe("AuthGuard", () => { })); it("CanActivate", () => { - authGuard = new AuthGuard(router, authService); + authGuard = new AuthGuard(authService, router, toastr); expect(authGuard).toBeTruthy(); }); }); diff --git a/packages/frontend/src/app/guards/auth.guard.ts b/packages/frontend/src/app/guards/auth.guard.ts index 2f3d7db69d..9cf4b24308 100644 --- a/packages/frontend/src/app/guards/auth.guard.ts +++ b/packages/frontend/src/app/guards/auth.guard.ts @@ -1,33 +1,54 @@ import { Injectable } from "@angular/core"; +import { Observable, of } from "rxjs"; +import { catchError, map } from "rxjs/operators"; import { - ActivatedRouteSnapshot, Router, + ActivatedRouteSnapshot, RouterStateSnapshot, } from "@angular/router"; - -import { Observable, of } from "rxjs"; -import { catchError, map } from "rxjs/operators"; - -import { AuthService } from "../modules/shared/services/auth.service"; - +import { UserStructureRole } from "@domifa/common"; +import { AuthService, CustomToastService } from "../modules/shared/services"; @Injectable({ providedIn: "root" }) export class AuthGuard { constructor( - public router: Router, - private readonly authService: AuthService + private readonly authService: AuthService, + private readonly router: Router, + private readonly toastService: CustomToastService ) {} public canActivate( - _route: ActivatedRouteSnapshot, + route: ActivatedRouteSnapshot, state: RouterStateSnapshot ): Observable { + const allowedRoles = (route.data["roles"] as UserStructureRole[]) || []; + return this.authService.isAuth().pipe( map((isAuth: boolean) => { + console.log("XXXX"); if (!isAuth) { this.authService.logoutAndRedirect(state); return false; } - return true; + + if (allowedRoles.length === 0) { + return true; + } + + if (this.authService.currentUserValue !== null) { + console.log(this.authService.currentUserValue); + const userRole = this.authService.currentUserValue.role; + + if (allowedRoles.includes(userRole)) { + return true; + } + + this.toastService.error( + "Vos droits ne vous permettent pas d'accéder à cette page" + ); + this.router.navigate(["/manage"]); + } + + return false; }), catchError(() => { this.authService.logoutAndRedirect(state); diff --git a/packages/frontend/src/app/guards/facteur.guard.ts b/packages/frontend/src/app/guards/facteur.guard.ts deleted file mode 100644 index 2590987643..0000000000 --- a/packages/frontend/src/app/guards/facteur.guard.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { Injectable } from "@angular/core"; -import { Router } from "@angular/router"; - -import { Observable } from "rxjs"; - -import { AuthService } from "../modules/shared/services/auth.service"; -import { CustomToastService } from "../modules/shared/services/custom-toast.service"; - -@Injectable({ providedIn: "root" }) -export class FacteurGuard { - constructor( - private readonly router: Router, - private readonly authService: AuthService, - private readonly toastService: CustomToastService - ) {} - - public canActivate(): Observable | boolean { - if (this.authService.currentUserValue !== null) { - const role = this.authService.currentUserValue.role; - if (role === "admin" || role === "simple" || role === "responsable") { - return true; - } - } - this.toastService.error( - "Vos droits ne vous permettent pas d'accéder à cette page" - ); - this.router.navigate(["/manage"]); - return false; - } -} diff --git a/packages/frontend/src/app/guards/index.ts b/packages/frontend/src/app/guards/index.ts index 56d40d7a2b..a5943eda65 100644 --- a/packages/frontend/src/app/guards/index.ts +++ b/packages/frontend/src/app/guards/index.ts @@ -1,6 +1,4 @@ // @index('./*', f => `export * from '${f.path}'`) -export * from "./admin.guard"; +export * from "./auth.guard.spec"; export * from "./auth.guard"; -export * from "./facteur.guard"; export * from "./logged.guard"; -export * from "./responsable.guard"; diff --git a/packages/frontend/src/app/guards/responsable.guard.ts b/packages/frontend/src/app/guards/responsable.guard.ts deleted file mode 100644 index 3376586028..0000000000 --- a/packages/frontend/src/app/guards/responsable.guard.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { Injectable } from "@angular/core"; -import { Router } from "@angular/router"; - -import { Observable } from "rxjs"; - -import { AuthService } from "../modules/shared/services/auth.service"; -import { CustomToastService } from "../modules/shared/services/custom-toast.service"; - -@Injectable({ providedIn: "root" }) -export class ResponsableGuard { - constructor( - private readonly router: Router, - private readonly authService: AuthService, - private readonly toastService: CustomToastService - ) {} - - public canActivate(): Observable | boolean { - if (this.authService.currentUserValue !== null) { - const role = this.authService.currentUserValue.role; - if (role === "admin" || role === "responsable") { - return true; - } - } - this.toastService.error( - "Vos droits ne vous permettent pas d'accéder à cette page" - ); - this.router.navigate(["/manage"]); - return false; - } -} diff --git a/packages/frontend/src/app/modules/general/components/navbar/navbar.component.html b/packages/frontend/src/app/modules/general/components/navbar/navbar.component.html index b22f07eaf3..9433cfdd6d 100644 --- a/packages/frontend/src/app/modules/general/components/navbar/navbar.component.html +++ b/packages/frontend/src/app/modules/general/components/navbar/navbar.component.html @@ -143,7 +143,7 @@
@@ -228,7 +228,7 @@ @@ -238,7 +238,7 @@ @@ -249,7 +249,7 @@ diff --git a/packages/frontend/src/app/modules/manage-usagers/components/manage-download-docs/manage-download-docs.component.html b/packages/frontend/src/app/modules/manage-usagers/components/manage-download-docs/manage-download-docs.component.html index 58454ba971..0aa610e1e0 100644 --- a/packages/frontend/src/app/modules/manage-usagers/components/manage-download-docs/manage-download-docs.component.html +++ b/packages/frontend/src/app/modules/manage-usagers/components/manage-download-docs/manage-download-docs.component.html @@ -4,7 +4,7 @@ container="body" placement="auto" class="dropdown-manage-actions p-0" - *ngIf="me.role !== 'facteur'" + *ngIf="me?.role !== 'facteur'" > -
Utilisateurs enregistrés: {{ users.length }} utilisateurs - Fonctionnalité + Fonctionnalité Facteur + Agent d'accueil Instructeur Gestionnaire Administrateur + + + GESTION DES UTILISATEURS + - Création et suppression d’un utilisateur + Création et suppression d'un utilisateur + Non Non Non Non Oui - Accès à la liste des membres actifs + Accès à la liste des membres actifs + Non Non Non Oui Oui - Changement de rôle d’un utilisateur + Changement de rôle d'un utilisateur + Non Non Non Non Oui + + + + GESTION DE LA STRUCTURE + Modification des informations de votre structure Non Non Non + Non Oui Ajout documentation interne structure Non Non + Non * Téléchargement seulement Oui - Paramètres (SMS, ID personnalisés etc.) + Paramètres (SMS, ID personnalisés etc.) + Non Non Non Non @@ -217,10 +233,12 @@

Utilisateurs enregistrés: {{ users.length }} utilisateurs

Non Non Non + Non Oui - Paramètrage des courriers + Paramétrage des courriers + Non Non Non Non @@ -228,16 +246,17 @@

Utilisateurs enregistrés: {{ users.length }} utilisateurs

- Suppression de la liste des usagers liée à votre - structure + Suppression de la liste des usagers liée à votre structure Non Non Non + Non Oui - Export des données + Export des données + Non Non Non Oui @@ -246,31 +265,38 @@

Utilisateurs enregistrés: {{ users.length }} utilisateurs

Page statistiques de la structure Non + Non Oui Oui Oui + + + + GESTION DES DOSSIERS + Instruction d'une demande ou d'un renouvellement de domiciliation Non + Non Oui Oui Oui - - Validation ou refus d’une demande ou d'un renouvellement - + Validation ou refus d'une demande ou d'un renouvellement + Non Non Non Oui Oui - Radiation d’un dossier + Radiation d'un dossier + Non Non Oui Oui @@ -278,9 +304,9 @@

Utilisateurs enregistrés: {{ users.length }} utilisateurs

- Modification de la fiche d’un domicilié : -
    -
  • état civil*
  • + Modification de la fiche d'un domicilié : +
      +
    • état civil*
    • Ayants droit*
    • Informations de contact**
    • Notifications SMS*
    • @@ -288,13 +314,17 @@

      Utilisateurs enregistrés: {{ users.length }} utilisateurs

    • Transfert de courrier**
    • Procurations de courrier**
    • Entretien
    • -
    • Pièces jointes
    • +
    • Pièces jointes

    * Lecture des informations seulement

    ** Modification et suppression possible

    + +

    * Lecture des informations seulement

    +

    ** Modification et suppression possible

    + Oui Oui Oui @@ -305,33 +335,51 @@

    Utilisateurs enregistrés: {{ users.length }} utilisateurs

    Oui Oui Oui + Oui - Gestion de la réception des courriers/colis/avis + Gestion de la réception des courriers/colis/avis + Oui Oui Oui Oui Oui - Déclaration d’un passage/appel  + Déclaration d'un passage/appel + Oui Oui Oui Oui Oui - - Téléchargement des pièces jointes - liées au dossier  - + Téléchargement des pièces jointes liées au dossier + Non Non Oui Oui Oui - Suppression du dossier d’un domicilié + Télécharger le Cerfa + Non + Oui + Oui + Oui + Oui + + + Réinitialiser les identifiants mon domifa d'un domicilié + Non + Oui + Oui + Oui + Oui + + + Suppression du dossier d'un domicilié + Non Non Non Oui @@ -341,7 +389,7 @@

    Utilisateurs enregistrés: {{ users.length }} utilisateurs

-
+
@@ -366,9 +414,9 @@

Utilisateurs enregistrés: {{ users.length }} utilisateurs

{{ note.message }}

-
+
+

Accès au portail "Mon DomiFa"

diff --git a/packages/frontend/src/app/modules/usager-profil/components/pages/profil-dossier/profil-dossier.component.html b/packages/frontend/src/app/modules/usager-profil/components/pages/profil-dossier/profil-dossier.component.html index d30ba8a31e..4f31e91d0d 100644 --- a/packages/frontend/src/app/modules/usager-profil/components/pages/profil-dossier/profil-dossier.component.html +++ b/packages/frontend/src/app/modules/usager-profil/components/pages/profil-dossier/profil-dossier.component.html @@ -16,7 +16,11 @@ >

État civil

-
+
diff --git a/packages/frontend/src/app/modules/usager-profil/components/profil-head/profil-head.component.html b/packages/frontend/src/app/modules/usager-profil/components/profil-head/profil-head.component.html index f83229c153..77df8de442 100644 --- a/packages/frontend/src/app/modules/usager-profil/components/profil-head/profil-head.component.html +++ b/packages/frontend/src/app/modules/usager-profil/components/profil-head/profil-head.component.html @@ -26,7 +26,7 @@

class="col" [ngClass]="section === 'documents' ? 'selected-section col' : 'col'" [routerLink]=" - me.role !== 'facteur' ? ['/profil/documents/' + usager.ref] : null + me?.role !== 'facteur' ? ['/profil/documents/' + usager.ref] : null " (click)="goToDocuments()" ariaCurrentWhenActive="page" >DocumentsDocuments, accès restreint diff --git a/packages/frontend/src/app/modules/usager-profil/components/profil-head/profil-head.component.ts b/packages/frontend/src/app/modules/usager-profil/components/profil-head/profil-head.component.ts index 0fa319e689..630a0d825c 100644 --- a/packages/frontend/src/app/modules/usager-profil/components/profil-head/profil-head.component.ts +++ b/packages/frontend/src/app/modules/usager-profil/components/profil-head/profil-head.component.ts @@ -57,7 +57,7 @@ export class ProfilHeadComponent implements OnDestroy { } public goToDocuments(): void { - if (this.me.role === "facteur") { + if (this.me?.role === "facteur") { this.toastService.warning( "Vos droits ne vous permettent pas d'accéder à cette page" ); diff --git a/packages/frontend/src/app/modules/usager-profil/usager-profil-routing.module.ts b/packages/frontend/src/app/modules/usager-profil/usager-profil-routing.module.ts index 1e7720e20b..ca9f0760e1 100644 --- a/packages/frontend/src/app/modules/usager-profil/usager-profil-routing.module.ts +++ b/packages/frontend/src/app/modules/usager-profil/usager-profil-routing.module.ts @@ -5,19 +5,58 @@ import { ProfilDossierComponent } from "./components/pages/profil-dossier/profil import { ProfilHistoriqueComponent } from "./components/pages/profil-historique/profil-historique.component"; import { ProfilGeneralSectionComponent } from "./components/pages/profil-general-section/profil-general-section.component"; import { ProfilDocumentsSectionComponent } from "./components/pages/profil-documents-section/profil-documents-section.component"; -import { FacteurGuard } from "../../guards"; +import { AuthGuard } from "../../guards"; import { ProfilSmsPortailComponent } from "./components/pages/profil-sms-portail/profil-sms-portail.component"; +import { ALL_USER_STRUCTURE_ROLES } from "@domifa/common"; const routes: Routes = [ - { path: "dossier/:id", component: ProfilDossierComponent }, - { path: "historique/:id/:section", component: ProfilHistoriqueComponent }, - { path: "courriers/:id", component: ProfilCourriersComponent }, - { path: "sms/:id", component: ProfilSmsPortailComponent }, - { path: "general/:id", component: ProfilGeneralSectionComponent }, + { + path: "dossier/:id", + component: ProfilDossierComponent, + canActivate: [AuthGuard], + data: { + roles: ALL_USER_STRUCTURE_ROLES, + }, + }, + { + path: "historique/:id/:section", + component: ProfilHistoriqueComponent, + canActivate: [AuthGuard], + data: { + roles: ALL_USER_STRUCTURE_ROLES, + }, + }, + { + path: "courriers/:id", + component: ProfilCourriersComponent, + canActivate: [AuthGuard], + data: { + roles: ALL_USER_STRUCTURE_ROLES, + }, + }, + { + path: "sms/:id", + component: ProfilSmsPortailComponent, + canActivate: [AuthGuard], + data: { + roles: ALL_USER_STRUCTURE_ROLES, + }, + }, + { + path: "general/:id", + component: ProfilGeneralSectionComponent, + canActivate: [AuthGuard], + data: { + roles: ALL_USER_STRUCTURE_ROLES, + }, + }, { path: "documents/:id", component: ProfilDocumentsSectionComponent, - canActivate: [FacteurGuard], + canActivate: [AuthGuard], + data: { + roles: ["admin", "responsable", "simple", "agent"], + }, }, ]; diff --git a/packages/frontend/src/app/modules/usager-shared/components/delete-usager-menu/delete-usager-menu.component.html b/packages/frontend/src/app/modules/usager-shared/components/delete-usager-menu/delete-usager-menu.component.html index 78daaacb2c..10bb4c5c09 100644 --- a/packages/frontend/src/app/modules/usager-shared/components/delete-usager-menu/delete-usager-menu.component.html +++ b/packages/frontend/src/app/modules/usager-shared/components/delete-usager-menu/delete-usager-menu.component.html @@ -1,8 +1,8 @@ - +
diff --git a/packages/frontend/src/app/modules/usager-shared/components/display-usager-docs/display-usager-docs.component.html b/packages/frontend/src/app/modules/usager-shared/components/display-usager-docs/display-usager-docs.component.html index aa9d3d4a54..483b031eec 100644 --- a/packages/frontend/src/app/modules/usager-shared/components/display-usager-docs/display-usager-docs.component.html +++ b/packages/frontend/src/app/modules/usager-shared/components/display-usager-docs/display-usager-docs.component.html @@ -1,6 +1,6 @@
diff --git a/packages/frontend/tsconfig.spec.json b/packages/frontend/tsconfig.spec.json index dccc9edd47..7c57b28b14 100644 --- a/packages/frontend/tsconfig.spec.json +++ b/packages/frontend/tsconfig.spec.json @@ -5,5 +5,6 @@ "outDir": "../out-tsc/spec", "types": ["jest", "node"] }, + "files": ["setup-jest.ts"], "include": ["**/*.spec.ts", "**/*.d.ts"] } diff --git a/packages/portail-admins/src/app/modules/structure/components/users/users.component.ts b/packages/portail-admins/src/app/modules/structure/components/users/users.component.ts index 28963c784f..02e8a1e31d 100644 --- a/packages/portail-admins/src/app/modules/structure/components/users/users.component.ts +++ b/packages/portail-admins/src/app/modules/structure/components/users/users.component.ts @@ -3,8 +3,8 @@ import { UserFonction, SortValues, StructureCommon, - UserStructureRole, UserStructure, + USER_STRUCTURE_ROLES_LABELS, } from "@domifa/common"; import { @@ -85,12 +85,7 @@ export class UsersComponent implements OnInit, OnDestroy { public readonly _USER_FONCTION_LABELS = USER_FONCTION_LABELS; public readonly USER_ACTIVITY_LABELS = UserStructureEventHistoryLabels; public readonly MODAL_ACTION = MODAL_ACTION; - public readonly USER_ROLES_LABELS: { [key in UserStructureRole]: string } = { - admin: "Administrateur", - responsable: "Gestionnaire", - simple: "Instructeur", - facteur: "Facteur", - }; + public readonly USER_ROLES_LABELS = USER_STRUCTURE_ROLES_LABELS; @Input({ required: true }) public structure: StructureCommon; private readonly subscription = new Subscription(); public searching = true; From 84c7dd080656af612755797214812323dbd91ae3 Mon Sep 17 00:00:00 2001 From: "Yassine R." Date: Wed, 17 Sep 2025 22:26:21 +0200 Subject: [PATCH 2/4] refactor(backend): delete useless variable --- .talismanrc | 2 +- .../USER_STRUCTURE_ROLES_NOT_FACTEUR.ts | 8 ------- .../USER_STRUCTURE_ROLE_ALL.const.ts | 9 ------- .../users/user-structure/constants/index.ts | 3 --- .../model/users/user-structure/index.ts | 1 - .../1757532174131-auto-migration.ts | 16 ++++++++----- ...ructures-auth.controller.security-tests.ts | 5 ++-- .../src/auth/structures-auth.controller.ts | 12 ++++------ .../interactions.controller.security-tests.ts | 5 ++-- .../interactions/interactions.controller.ts | 8 +++---- .../dto/register-user-structure-admin.dto.ts | 11 +++++---- .../portail-usagers-manager.controller.ts | 8 +++---- .../sms/sms.controller.security-tests.ts | 5 ++-- .../backend/src/modules/sms/sms.controller.ts | 10 +++++--- ...stats.private.controller.security-tests.ts | 6 ++--- .../controllers/stats.private.controller.ts | 12 +++++----- .../structures.controller.security-tests.ts | 4 ++-- .../controllers/structures.controller.ts | 11 ++++----- .../users.controller.security-tests.ts | 4 ++-- .../users/controllers/users.controller.ts | 9 ++++--- .../src/modules/users/dto/update-role.dto.ts | 5 ++-- .../controllers/search-usagers.controller.ts | 8 +++---- ...earch-usagers.controller.security-tests.ts | 4 ++-- .../controllers/usager-docs.controller.ts | 1 + .../controllers/usager-notes.controller.ts | 9 +++---- .../controllers/usager-options.controller.ts | 8 +++---- .../usager-structure-docs.controller.ts | 7 ++---- .../usagers/controllers/usagers.controller.ts | 24 +++++++++---------- .../user-profil/user-profil.component.html | 4 ++-- 29 files changed, 96 insertions(+), 123 deletions(-) delete mode 100644 packages/backend/src/_common/model/users/user-structure/constants/USER_STRUCTURE_ROLES_NOT_FACTEUR.ts delete mode 100644 packages/backend/src/_common/model/users/user-structure/constants/USER_STRUCTURE_ROLE_ALL.const.ts delete mode 100644 packages/backend/src/_common/model/users/user-structure/constants/index.ts diff --git a/.talismanrc b/.talismanrc index 1b8ea46ea9..ac18d8b737 100644 --- a/.talismanrc +++ b/.talismanrc @@ -14,7 +14,7 @@ fileignoreconfig: - filename: packages/backend/package.json checksum: 2f5813dbc35cdc3659516beabf9f93e2978eb62d1b5403cfbb2907f22bb25355 - filename: packages/backend/src/_migrations/1757532174131-auto-migration.ts - checksum: 22a788509a5f08a8dbccbab49ed7b835df73ab56444b5c2a0e327fe51de2f748 + checksum: e2d06e63d58935b349f2591b0a3c407c254be26c4e833456829e7c605fc7411b - filename: packages/backend/src/_migrations/_init-db/domifa_test_schema.sql checksum: 8b421c413bab4f2419972dec548a5399879f497a8c75c9b240bbf8c123cfab06 - filename: packages/portail-admins/src/app/modules/admin-structures/components/admin-structures-list/admin-structures-list.component.spec.ts diff --git a/packages/backend/src/_common/model/users/user-structure/constants/USER_STRUCTURE_ROLES_NOT_FACTEUR.ts b/packages/backend/src/_common/model/users/user-structure/constants/USER_STRUCTURE_ROLES_NOT_FACTEUR.ts deleted file mode 100644 index 1b611f56f4..0000000000 --- a/packages/backend/src/_common/model/users/user-structure/constants/USER_STRUCTURE_ROLES_NOT_FACTEUR.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { UserStructureRole } from "@domifa/common"; - -export const USER_STRUCTURE_ROLES_NOT_FACTEUR: UserStructureRole[] = [ - "simple", - "admin", - "agent", - "responsable", -]; diff --git a/packages/backend/src/_common/model/users/user-structure/constants/USER_STRUCTURE_ROLE_ALL.const.ts b/packages/backend/src/_common/model/users/user-structure/constants/USER_STRUCTURE_ROLE_ALL.const.ts deleted file mode 100644 index 61fc253b98..0000000000 --- a/packages/backend/src/_common/model/users/user-structure/constants/USER_STRUCTURE_ROLE_ALL.const.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { UserStructureRole } from "@domifa/common"; - -export const USER_STRUCTURE_ROLE_ALL: UserStructureRole[] = [ - "simple", - "admin", - "facteur", - "agent", - "responsable", -]; diff --git a/packages/backend/src/_common/model/users/user-structure/constants/index.ts b/packages/backend/src/_common/model/users/user-structure/constants/index.ts deleted file mode 100644 index af4808956f..0000000000 --- a/packages/backend/src/_common/model/users/user-structure/constants/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -// @index('./*', f => `export * from '${f.path}'`) -export * from "./USER_STRUCTURE_ROLE_ALL.const"; -export * from "./USER_STRUCTURE_ROLES_NOT_FACTEUR"; diff --git a/packages/backend/src/_common/model/users/user-structure/index.ts b/packages/backend/src/_common/model/users/user-structure/index.ts index cea80f291d..27b7ddc71f 100644 --- a/packages/backend/src/_common/model/users/user-structure/index.ts +++ b/packages/backend/src/_common/model/users/user-structure/index.ts @@ -1,4 +1,3 @@ // @index('./*', f => `export * from '${f.path}'`) -export * from "./constants"; export * from "./UserStructureAuthenticated.type"; export * from "./UserStructurePublic.type"; diff --git a/packages/backend/src/_migrations/1757532174131-auto-migration.ts b/packages/backend/src/_migrations/1757532174131-auto-migration.ts index 73fa7ddf78..102d844940 100644 --- a/packages/backend/src/_migrations/1757532174131-auto-migration.ts +++ b/packages/backend/src/_migrations/1757532174131-auto-migration.ts @@ -10,12 +10,16 @@ export class AutoMigration1757532174131 implements MigrationInterface { domifaConfig().envId === "preprod" || domifaConfig().envId === "local" ) { - await queryRunner.query( - `ALTER TABLE "user_usager" DROP COLUMN "isTemporaryPassword"` - ); - await queryRunner.query( - `CREATE INDEX "IDX_b2ad525cbadf911e833bf61597" ON "open_data_places" ("cityCode") ` - ); + try { + await queryRunner.query( + `ALTER TABLE "user_usager" DROP COLUMN "isTemporaryPassword"` + ); + await queryRunner.query( + `CREATE INDEX "IDX_b2ad525cbadf911e833bf61597" ON "open_data_places" ("cityCode") ` + ); + } catch (e) { + console.log(e); + } } } diff --git a/packages/backend/src/auth/structures-auth.controller.security-tests.ts b/packages/backend/src/auth/structures-auth.controller.security-tests.ts index fcaeea3900..3aabcd6b72 100644 --- a/packages/backend/src/auth/structures-auth.controller.security-tests.ts +++ b/packages/backend/src/auth/structures-auth.controller.security-tests.ts @@ -1,9 +1,10 @@ import { AppTestContext, AppTestHttpClient } from "../util/test"; -import { USER_STRUCTURE_ROLE_ALL } from "../_common/model"; + import { AppTestHttpClientSecurityTestDef, expectedResponseStatusBuilder, } from "../_tests"; +import { ALL_USER_STRUCTURE_ROLES } from "@domifa/common"; ////////////////// IMPORTANT ////////////////// // @@ -25,7 +26,7 @@ export const StructuresAuthControllerSecurityTests: AppTestHttpClientSecurityTes expectedStatus: expectedResponseStatusBuilder.allowStructureOnly( context.user, { - roles: USER_STRUCTURE_ROLE_ALL, + roles: ALL_USER_STRUCTURE_ROLES, } ), }; diff --git a/packages/backend/src/auth/structures-auth.controller.ts b/packages/backend/src/auth/structures-auth.controller.ts index c012eb9da1..88a2dac9f7 100644 --- a/packages/backend/src/auth/structures-auth.controller.ts +++ b/packages/backend/src/auth/structures-auth.controller.ts @@ -15,11 +15,7 @@ import { Response } from "express"; import { StructureLoginDto } from "../modules/users/dto"; import { ExpressRequest, ExpressResponse } from "../util/express"; -import { - USER_STRUCTURE_ROLE_ALL, - UserProfile, - UserStructureAuthenticated, -} from "../_common/model"; +import { UserProfile, UserStructureAuthenticated } from "../_common/model"; import { AllowUserProfiles } from "./decorators/AllowUserProfiles.decorator"; import { CurrentUser } from "./decorators/current-user.decorator"; import { AppUserGuard } from "./guards/AppUserGuard.guard"; @@ -28,7 +24,7 @@ import { ExpiredTokenTable, expiredTokenRepositiory } from "../database"; import { domifaConfig } from "../config"; import { userSecurityPasswordChecker } from "../modules/users/services"; import { AllowUserStructureRoles } from "./decorators"; -import { UserStructure } from "@domifa/common"; +import { ALL_USER_STRUCTURE_ROLES, UserStructure } from "@domifa/common"; import { appLogger } from "../util"; const userProfile: UserProfile = "structure"; @@ -66,7 +62,7 @@ export class StructuresAuthController { @ApiBearerAuth() @UseGuards(AuthGuard("jwt"), AppUserGuard) @AllowUserProfiles("structure") - @AllowUserStructureRoles(...USER_STRUCTURE_ROLE_ALL) + @AllowUserStructureRoles(...ALL_USER_STRUCTURE_ROLES) @ApiOperation({ summary: "Déconnexion" }) @Get("logout") public async logout( @@ -86,7 +82,7 @@ export class StructuresAuthController { @ApiBearerAuth() @UseGuards(AuthGuard("jwt"), AppUserGuard) @AllowUserProfiles("structure") - @AllowUserStructureRoles(...USER_STRUCTURE_ROLE_ALL) + @AllowUserStructureRoles(...ALL_USER_STRUCTURE_ROLES) @Get("me") public me( @Res() res: Response, diff --git a/packages/backend/src/modules/interactions/interactions.controller.security-tests.ts b/packages/backend/src/modules/interactions/interactions.controller.security-tests.ts index 4ad03a731d..8f26e3178d 100644 --- a/packages/backend/src/modules/interactions/interactions.controller.security-tests.ts +++ b/packages/backend/src/modules/interactions/interactions.controller.security-tests.ts @@ -1,9 +1,10 @@ import { AppTestContext, AppTestHttpClient } from "../../util/test"; -import { USER_STRUCTURE_ROLE_ALL } from "../../_common/model"; + import { AppTestHttpClientSecurityTestDef, expectedResponseStatusBuilder, } from "../../_tests"; +import { ALL_USER_STRUCTURE_ROLES } from "@domifa/common"; ////////////////// IMPORTANT ////////////////// // @@ -30,7 +31,7 @@ export const InteractionsControllerSecurityTests: AppTestHttpClientSecurityTestD expectedStatus: expectedResponseStatusBuilder.allowStructureOnly( context.user, { - roles: USER_STRUCTURE_ROLE_ALL, + roles: ALL_USER_STRUCTURE_ROLES, validExpectedResponseStatus: 400, // car on utilise un faux id } ), diff --git a/packages/backend/src/modules/interactions/interactions.controller.ts b/packages/backend/src/modules/interactions/interactions.controller.ts index 56875802a0..3e0a010388 100644 --- a/packages/backend/src/modules/interactions/interactions.controller.ts +++ b/packages/backend/src/modules/interactions/interactions.controller.ts @@ -24,10 +24,7 @@ import { InteractionsGuard, } from "../../auth/guards"; import { userUsagerLoginRepository } from "../../database"; -import { - USER_STRUCTURE_ROLE_ALL, - UserStructureAuthenticated, -} from "../../_common/model"; +import { UserStructureAuthenticated } from "../../_common/model"; import { InteractionDto } from "./dto"; import { InteractionsDeletor, @@ -40,13 +37,14 @@ import { Usager, PageMeta, PageResults, + ALL_USER_STRUCTURE_ROLES, } from "@domifa/common"; import { MessageSmsService } from "../sms/services/message-sms.service"; @UseGuards(AuthGuard("jwt"), AppUserGuard) @ApiTags("interactions") @AllowUserProfiles("structure") -@AllowUserStructureRoles(...USER_STRUCTURE_ROLE_ALL) +@AllowUserStructureRoles(...ALL_USER_STRUCTURE_ROLES) @Controller("interactions") export class InteractionsController { constructor( diff --git a/packages/backend/src/modules/portail-admin/dto/register-user-structure-admin.dto.ts b/packages/backend/src/modules/portail-admin/dto/register-user-structure-admin.dto.ts index ad738e2b4a..d61499631a 100644 --- a/packages/backend/src/modules/portail-admin/dto/register-user-structure-admin.dto.ts +++ b/packages/backend/src/modules/portail-admin/dto/register-user-structure-admin.dto.ts @@ -11,8 +11,11 @@ import { } from "class-validator"; import { Transform, TransformFnParams } from "class-transformer"; import { LowerCaseTransform } from "../../../_common/decorators"; -import { UserStructureRole, UserFonction } from "@domifa/common"; -import { USER_STRUCTURE_ROLE_ALL } from "../../../_common/model"; +import { + UserStructureRole, + UserFonction, + ALL_USER_STRUCTURE_ROLES, +} from "@domifa/common"; export class RegisterUserStructureAdminDto { @ApiProperty({ @@ -79,10 +82,10 @@ export class RegisterUserStructureAdminDto { @ApiProperty({ type: String, required: true, - enum: USER_STRUCTURE_ROLE_ALL, + enum: ALL_USER_STRUCTURE_ROLES, }) @IsNotEmpty() - @IsIn(USER_STRUCTURE_ROLE_ALL) + @IsIn(ALL_USER_STRUCTURE_ROLES) public readonly role!: UserStructureRole; @IsNotEmpty() diff --git a/packages/backend/src/modules/portail-usagers/controllers/portail-usagers-manager/portail-usagers-manager.controller.ts b/packages/backend/src/modules/portail-usagers/controllers/portail-usagers-manager/portail-usagers-manager.controller.ts index b044e6bd92..36850e9192 100644 --- a/packages/backend/src/modules/portail-usagers/controllers/portail-usagers-manager/portail-usagers-manager.controller.ts +++ b/packages/backend/src/modules/portail-usagers/controllers/portail-usagers-manager/portail-usagers-manager.controller.ts @@ -5,6 +5,7 @@ import { UserUsagerWithUsagerInfo, PageMeta, PageResults, + ALL_USER_STRUCTURE_ROLES, } from "@domifa/common"; import { Body, @@ -18,10 +19,7 @@ import { Res, UseGuards, } from "@nestjs/common"; -import { - USER_STRUCTURE_ROLE_ALL, - UserStructureAuthenticated, -} from "../../../../_common/model"; +import { UserStructureAuthenticated } from "../../../../_common/model"; import { AllowUserProfiles, AllowUserStructureRoles, @@ -350,7 +348,7 @@ export class PortailUsagersManagerController { } @UseGuards(UsagerAccessGuard) - @AllowUserStructureRoles(...USER_STRUCTURE_ROLE_ALL) + @AllowUserStructureRoles(...ALL_USER_STRUCTURE_ROLES) @Get("profile/:usagerRef") public async findOne( @Param("usagerRef", new ParseIntPipe()) _usagerRef: number, diff --git a/packages/backend/src/modules/sms/sms.controller.security-tests.ts b/packages/backend/src/modules/sms/sms.controller.security-tests.ts index 115f588d62..de0b1c5e0e 100644 --- a/packages/backend/src/modules/sms/sms.controller.security-tests.ts +++ b/packages/backend/src/modules/sms/sms.controller.security-tests.ts @@ -1,11 +1,10 @@ import { HttpStatus } from "@nestjs/common"; -import { USER_STRUCTURE_ROLE_ALL } from "../../_common/model"; import { AppTestHttpClientSecurityTestDef, expectedResponseStatusBuilder, } from "../../_tests"; import { AppTestContext, AppTestHttpClient } from "../../util/test"; -import { PageOptions } from "@domifa/common"; +import { ALL_USER_STRUCTURE_ROLES, PageOptions } from "@domifa/common"; ////////////////// IMPORTANT ////////////////// // @@ -27,7 +26,7 @@ export const SmsControllerSecurityTests: AppTestHttpClientSecurityTestDef[] = [ expectedStatus: expectedResponseStatusBuilder.allowStructureOnly( context.user, { - roles: USER_STRUCTURE_ROLE_ALL, + roles: ALL_USER_STRUCTURE_ROLES, validExpectedResponseStatus: HttpStatus.BAD_REQUEST, invalidStructureIdExpectedResponseStatus: HttpStatus.BAD_REQUEST, } diff --git a/packages/backend/src/modules/sms/sms.controller.ts b/packages/backend/src/modules/sms/sms.controller.ts index 0b5a1b4972..da2b3d54fa 100644 --- a/packages/backend/src/modules/sms/sms.controller.ts +++ b/packages/backend/src/modules/sms/sms.controller.ts @@ -1,8 +1,12 @@ -import { PageMeta, PageResults, Usager } from "@domifa/common"; +import { + ALL_USER_STRUCTURE_ROLES, + PageMeta, + PageResults, + Usager, +} from "@domifa/common"; import { Controller, UseGuards, Post, Body } from "@nestjs/common"; import { AuthGuard } from "@nestjs/passport"; import { ApiTags, ApiBearerAuth } from "@nestjs/swagger"; -import { USER_STRUCTURE_ROLE_ALL } from "../../_common/model"; import { AllowUserProfiles, AllowUserStructureRoles, @@ -15,7 +19,7 @@ import { PageOptionsDto } from "../../usagers/dto"; @Controller("sms") @UseGuards(AuthGuard("jwt"), AppUserGuard) @AllowUserProfiles("structure") -@AllowUserStructureRoles(...USER_STRUCTURE_ROLE_ALL) +@AllowUserStructureRoles(...ALL_USER_STRUCTURE_ROLES) @ApiTags("sms") export class SmsController { @ApiBearerAuth() diff --git a/packages/backend/src/modules/stats/controllers/stats.private.controller.security-tests.ts b/packages/backend/src/modules/stats/controllers/stats.private.controller.security-tests.ts index bde0acc90c..6c5de67cda 100644 --- a/packages/backend/src/modules/stats/controllers/stats.private.controller.security-tests.ts +++ b/packages/backend/src/modules/stats/controllers/stats.private.controller.security-tests.ts @@ -11,7 +11,7 @@ import { expectedResponseStatusBuilder, } from "../../../_tests"; import { AppTestContext, AppTestHttpClient } from "../../../util/test"; -import { USER_STRUCTURE_ROLE_ALL } from "../../../_common/model"; +import { ALL_USER_STRUCTURE_ROLES } from "@domifa/common"; const CONTROLLER = "StatsPrivateController"; @@ -33,7 +33,7 @@ export const StatsPrivateControllerSecurityTests: AppTestHttpClientSecurityTestD expectedStatus: expectedResponseStatusBuilder.allowStructureOnly( context.user, { - roles: USER_STRUCTURE_ROLE_ALL, + roles: ALL_USER_STRUCTURE_ROLES, validExpectedResponseStatus: HttpStatus.CREATED, } ), @@ -56,7 +56,7 @@ export const StatsPrivateControllerSecurityTests: AppTestHttpClientSecurityTestD expectedStatus: expectedResponseStatusBuilder.allowStructureOnly( context.user, { - roles: USER_STRUCTURE_ROLE_ALL, + roles: ALL_USER_STRUCTURE_ROLES, validExpectedResponseStatus: HttpStatus.OK, } ), diff --git a/packages/backend/src/modules/stats/controllers/stats.private.controller.ts b/packages/backend/src/modules/stats/controllers/stats.private.controller.ts index f8202a2269..0e6b14786b 100644 --- a/packages/backend/src/modules/stats/controllers/stats.private.controller.ts +++ b/packages/backend/src/modules/stats/controllers/stats.private.controller.ts @@ -1,4 +1,7 @@ -import { StructureStatsReportingQuestions } from "@domifa/common"; +import { + ALL_USER_STRUCTURE_ROLES, + StructureStatsReportingQuestions, +} from "@domifa/common"; import { Body, Controller, @@ -12,10 +15,7 @@ import { AuthGuard } from "@nestjs/passport"; import { ApiTags } from "@nestjs/swagger"; import { Response } from "express"; import { format } from "date-fns"; -import { - USER_STRUCTURE_ROLE_ALL, - UserStructureAuthenticated, -} from "../../../_common/model"; +import { UserStructureAuthenticated } from "../../../_common/model"; import { AllowUserProfiles, AllowUserStructureRoles, @@ -35,7 +35,7 @@ import { structureStatsInPeriodGenerator } from "../services"; @Controller("stats") @ApiTags("stats") @AllowUserProfiles("structure") -@AllowUserStructureRoles(...USER_STRUCTURE_ROLE_ALL) +@AllowUserStructureRoles(...ALL_USER_STRUCTURE_ROLES) @UseGuards(AuthGuard("jwt"), AppUserGuard) export class StatsPrivateController { constructor(private readonly appLogsService: AppLogsService) {} diff --git a/packages/backend/src/modules/structures/controllers/structures.controller.security-tests.ts b/packages/backend/src/modules/structures/controllers/structures.controller.security-tests.ts index 786640fc56..096d252b60 100644 --- a/packages/backend/src/modules/structures/controllers/structures.controller.security-tests.ts +++ b/packages/backend/src/modules/structures/controllers/structures.controller.security-tests.ts @@ -1,6 +1,6 @@ import { HttpStatus } from "@nestjs/common"; import { AppTestContext, AppTestHttpClient } from "../../../util/test"; -import { USER_STRUCTURE_ROLE_ALL } from "../../../_common/model"; +import { ALL_USER_STRUCTURE_ROLES } from "@domifa/common"; import { AppTestHttpClientSecurityTestDef, expectedResponseStatusBuilder, @@ -25,7 +25,7 @@ export const StructuresControllerSecurityTests: AppTestHttpClientSecurityTestDef expectedStatus: expectedResponseStatusBuilder.allowStructureOnly( context.user, { - roles: USER_STRUCTURE_ROLE_ALL, + roles: ALL_USER_STRUCTURE_ROLES, } ), }), diff --git a/packages/backend/src/modules/structures/controllers/structures.controller.ts b/packages/backend/src/modules/structures/controllers/structures.controller.ts index fa7c930e13..0245adf6a7 100644 --- a/packages/backend/src/modules/structures/controllers/structures.controller.ts +++ b/packages/backend/src/modules/structures/controllers/structures.controller.ts @@ -17,12 +17,8 @@ import { } from "../../../auth/decorators"; import { structureRepository } from "../../../database"; import { ExpressResponse } from "../../../util/express"; -import { - UserStructureAuthenticated, - USER_STRUCTURE_ROLE_ALL, -} from "../../../_common/model"; -import { StructureDto } from "../dto"; -import { StructureEditSmsDto } from "../dto/structure-edit-sms.dto"; +import { UserStructureAuthenticated } from "../../../_common/model"; +import { StructureDto, StructureEditSmsDto } from "../dto"; import { resetUsagers } from "../services/structure-deletor.service"; import { StructureHardResetService } from "../services/structureHardReset.service"; @@ -34,6 +30,7 @@ import { ParseHardResetTokenPipe } from "../../../_common/decorators"; import { faker } from "@faker-js/faker"; import { AppUserGuard } from "../../../auth/guards"; import { + ALL_USER_STRUCTURE_ROLES, DEPARTEMENTS_MAP, getDepartementFromCodePostal, getRegionCodeFromDepartement, @@ -137,7 +134,7 @@ export class StructuresController { return res.status(HttpStatus.OK).json(retour); } - @AllowUserStructureRoles(...USER_STRUCTURE_ROLE_ALL) + @AllowUserStructureRoles(...ALL_USER_STRUCTURE_ROLES) @Get("ma-structure") public getMyStructure(@CurrentUser() user: UserStructureAuthenticated) { return user.structure; diff --git a/packages/backend/src/modules/users/controllers/users.controller.security-tests.ts b/packages/backend/src/modules/users/controllers/users.controller.security-tests.ts index 7da8ee4441..cf84975cb5 100644 --- a/packages/backend/src/modules/users/controllers/users.controller.security-tests.ts +++ b/packages/backend/src/modules/users/controllers/users.controller.security-tests.ts @@ -11,7 +11,7 @@ import { expectedResponseStatusBuilder, securityTestDataBuilder, } from "../../../_tests"; -import { USER_STRUCTURE_ROLE_ALL } from "../../../_common/model"; +import { ALL_USER_STRUCTURE_ROLES } from "@domifa/common"; const CONTROLLER = "UserController"; @@ -25,7 +25,7 @@ export const UserControllerSecurityTests: AppTestHttpClientSecurityTestDef[] = [ expectedStatus: expectedResponseStatusBuilder.allowStructureOnly( context.user, { - roles: USER_STRUCTURE_ROLE_ALL, + roles: ALL_USER_STRUCTURE_ROLES, } ), }), diff --git a/packages/backend/src/modules/users/controllers/users.controller.ts b/packages/backend/src/modules/users/controllers/users.controller.ts index 93eda0fb5a..6c20fd63b8 100644 --- a/packages/backend/src/modules/users/controllers/users.controller.ts +++ b/packages/backend/src/modules/users/controllers/users.controller.ts @@ -1,4 +1,8 @@ -import { UserStructureProfile, UserStructure } from "@domifa/common"; +import { + UserStructureProfile, + UserStructure, + ALL_USER_STRUCTURE_ROLES, +} from "@domifa/common"; import { Body, Controller, @@ -17,7 +21,6 @@ import { AuthGuard } from "@nestjs/passport"; import { ApiBearerAuth, ApiOperation, ApiTags } from "@nestjs/swagger"; import { Response } from "express"; import { - USER_STRUCTURE_ROLE_ALL, UserAdminAuthenticated, UserProfile, UserStructureAuthenticated, @@ -59,7 +62,7 @@ const userProfile: UserProfile = "structure"; @Controller("users") @ApiTags("users") @AllowUserProfiles("structure") -@AllowUserStructureRoles(...USER_STRUCTURE_ROLE_ALL) +@AllowUserStructureRoles(...ALL_USER_STRUCTURE_ROLES) @UseGuards(AuthGuard("jwt"), AppUserGuard) export class UsersController { constructor(private readonly appLogService: AppLogsService) {} diff --git a/packages/backend/src/modules/users/dto/update-role.dto.ts b/packages/backend/src/modules/users/dto/update-role.dto.ts index e8e86a1e8b..39fb0b2b42 100644 --- a/packages/backend/src/modules/users/dto/update-role.dto.ts +++ b/packages/backend/src/modules/users/dto/update-role.dto.ts @@ -1,9 +1,8 @@ -import { UserStructureRole } from "@domifa/common"; +import { ALL_USER_STRUCTURE_ROLES, UserStructureRole } from "@domifa/common"; import { IsIn, IsNotEmpty } from "class-validator"; -import { USER_STRUCTURE_ROLE_ALL } from "../../../_common/model"; export class UpdateRoleDto { - @IsIn(USER_STRUCTURE_ROLE_ALL) + @IsIn(ALL_USER_STRUCTURE_ROLES) @IsNotEmpty() public readonly role!: UserStructureRole; } diff --git a/packages/backend/src/usagers/controllers/search-usagers.controller.ts b/packages/backend/src/usagers/controllers/search-usagers.controller.ts index de22e59f21..e00ba9adf5 100644 --- a/packages/backend/src/usagers/controllers/search-usagers.controller.ts +++ b/packages/backend/src/usagers/controllers/search-usagers.controller.ts @@ -4,6 +4,7 @@ import { CriteriaSearchField, getUsagerDeadlines, ETAPE_ENTRETIEN, + ALL_USER_STRUCTURE_ROLES, } from "@domifa/common"; import { Body, @@ -18,10 +19,7 @@ import { AuthGuard } from "@nestjs/passport"; import { ApiBearerAuth } from "@nestjs/swagger"; import { format, parse, subMinutes } from "date-fns"; import { Not } from "typeorm"; -import { - USER_STRUCTURE_ROLE_ALL, - UserStructureAuthenticated, -} from "../../_common/model"; +import { UserStructureAuthenticated } from "../../_common/model"; import { AllowUserProfiles, AllowUserStructureRoles, @@ -39,7 +37,7 @@ import { SearchUsagerDto } from "../dto"; @Controller("search-usagers") @UseGuards(AuthGuard("jwt"), AppUserGuard) @AllowUserProfiles("structure") -@AllowUserStructureRoles(...USER_STRUCTURE_ROLE_ALL) +@AllowUserStructureRoles(...ALL_USER_STRUCTURE_ROLES) @ApiBearerAuth() export class SearchUsagersController { @Get() diff --git a/packages/backend/src/usagers/controllers/security-tests/search-usagers.controller.security-tests.ts b/packages/backend/src/usagers/controllers/security-tests/search-usagers.controller.security-tests.ts index 423faa0408..fc2417a6a6 100644 --- a/packages/backend/src/usagers/controllers/security-tests/search-usagers.controller.security-tests.ts +++ b/packages/backend/src/usagers/controllers/security-tests/search-usagers.controller.security-tests.ts @@ -1,5 +1,5 @@ import { AppTestContext, AppTestHttpClient } from "../../../util/test"; -import { USER_STRUCTURE_ROLE_ALL } from "../../../_common/model"; +import { ALL_USER_STRUCTURE_ROLES } from "@domifa/common"; import { AppTestHttpClientSecurityTestDef, expectedResponseStatusBuilder, @@ -27,7 +27,7 @@ export const UsagersControllerSecurityTests: AppTestHttpClientSecurityTestDef[] expectedStatus: expectedResponseStatusBuilder.allowStructureOnly( context.user, { - roles: USER_STRUCTURE_ROLE_ALL, + roles: ALL_USER_STRUCTURE_ROLES, } ), }), diff --git a/packages/backend/src/usagers/controllers/usager-docs.controller.ts b/packages/backend/src/usagers/controllers/usager-docs.controller.ts index e6526e6530..75777176b7 100644 --- a/packages/backend/src/usagers/controllers/usager-docs.controller.ts +++ b/packages/backend/src/usagers/controllers/usager-docs.controller.ts @@ -119,6 +119,7 @@ export class UsagerDocsController { await this.fileManagerService.saveEncryptedFile(filePath, newDoc, file); } catch (e) { + appLogger.error(e); return res .status(HttpStatus.INTERNAL_SERVER_ERROR) .json({ message: "CANNOT_ENCRYPT_FILE" }); diff --git a/packages/backend/src/usagers/controllers/usager-notes.controller.ts b/packages/backend/src/usagers/controllers/usager-notes.controller.ts index fdb229b065..68fa4827db 100644 --- a/packages/backend/src/usagers/controllers/usager-notes.controller.ts +++ b/packages/backend/src/usagers/controllers/usager-notes.controller.ts @@ -17,11 +17,7 @@ import { ApiBearerAuth, ApiTags } from "@nestjs/swagger"; import { CurrentUsager } from "../../auth/decorators/current-usager.decorator"; import { CurrentUser } from "../../auth/decorators/current-user.decorator"; import { UsagerAccessGuard } from "../../auth/guards/usager-access.guard"; - -import { - USER_STRUCTURE_ROLE_ALL, - UserStructureAuthenticated, -} from "../../_common/model"; +import { UserStructureAuthenticated } from "../../_common/model"; import { UserStructureResume, UsagerNote, @@ -29,6 +25,7 @@ import { UsagerPinnedNote, PageMeta, PageResults, + ALL_USER_STRUCTURE_ROLES, } from "@domifa/common"; import { CreateNoteDto } from "../dto/create-note.dto"; import { @@ -52,7 +49,7 @@ import { PageOptionsDto } from "../dto"; @Controller("usagers-notes") @UseGuards(AuthGuard("jwt"), AppUserGuard) @AllowUserProfiles("structure") -@AllowUserStructureRoles(...USER_STRUCTURE_ROLE_ALL) +@AllowUserStructureRoles(...ALL_USER_STRUCTURE_ROLES) export class UsagerNotesController { @Post("search/:usagerRef/:archived") @UseGuards(UsagerAccessGuard) diff --git a/packages/backend/src/usagers/controllers/usager-options.controller.ts b/packages/backend/src/usagers/controllers/usager-options.controller.ts index 4e5f5bc87d..f26e28b1e9 100644 --- a/packages/backend/src/usagers/controllers/usager-options.controller.ts +++ b/packages/backend/src/usagers/controllers/usager-options.controller.ts @@ -18,10 +18,7 @@ import { ApiBearerAuth, ApiTags } from "@nestjs/swagger"; import { CurrentUsager } from "../../auth/decorators/current-usager.decorator"; import { UsagerAccessGuard } from "../../auth/guards/usager-access.guard"; -import { - USER_STRUCTURE_ROLE_ALL, - UserStructureAuthenticated, -} from "../../_common/model"; +import { UserStructureAuthenticated } from "../../_common/model"; import { usagerOptionsHistoryRepository } from "../../database/services/usager/usagerOptionsHistoryRepository.service"; import { AllowUserProfiles, @@ -35,6 +32,7 @@ import { isEqual } from "lodash"; import { usagerRepository } from "../../database"; import { + ALL_USER_STRUCTURE_ROLES, Usager, UsagerOptionsHistoryAction, UsagerOptionsHistoryTypeEnum, @@ -45,7 +43,7 @@ import { AppUserGuard } from "../../auth/guards"; @ApiBearerAuth() @Controller("usagers-options") @UseGuards(AuthGuard("jwt"), AppUserGuard) -@AllowUserStructureRoles(...USER_STRUCTURE_ROLE_ALL) +@AllowUserStructureRoles(...ALL_USER_STRUCTURE_ROLES) @AllowUserProfiles("structure") export class UsagerOptionsController { constructor( diff --git a/packages/backend/src/usagers/controllers/usager-structure-docs.controller.ts b/packages/backend/src/usagers/controllers/usager-structure-docs.controller.ts index 01ab968d89..b1baa51e3a 100644 --- a/packages/backend/src/usagers/controllers/usager-structure-docs.controller.ts +++ b/packages/backend/src/usagers/controllers/usager-structure-docs.controller.ts @@ -26,10 +26,7 @@ import { structureDocRepository, userStructureRepository, } from "../../database"; -import { - USER_STRUCTURE_ROLES_NOT_FACTEUR, - UserStructureAuthenticated, -} from "../../_common/model"; +import { UserStructureAuthenticated } from "../../_common/model"; import { buildCustomDoc, customDocTemplateLoader, @@ -50,7 +47,7 @@ import { @ApiTags("usagers-structure-docs") @ApiBearerAuth() @Controller("usagers-structure-docs") -@AllowUserStructureRoles(...USER_STRUCTURE_ROLES_NOT_FACTEUR) +@AllowUserStructureRoles("simple", "admin", "agent", "responsable") @AllowUserProfiles("structure") export class UsagerStructureDocsController { constructor( diff --git a/packages/backend/src/usagers/controllers/usagers.controller.ts b/packages/backend/src/usagers/controllers/usagers.controller.ts index d5f1795543..ebbd8f0a7e 100644 --- a/packages/backend/src/usagers/controllers/usagers.controller.ts +++ b/packages/backend/src/usagers/controllers/usagers.controller.ts @@ -40,11 +40,7 @@ import { cleanPath, getPhoneString, } from "../../util"; -import { - UserStructureAuthenticated, - USER_STRUCTURE_ROLE_ALL, - USER_STRUCTURE_ROLES_NOT_FACTEUR, -} from "../../_common/model"; +import { UserStructureAuthenticated } from "../../_common/model"; import { CheckDuplicateUsagerDto, CreateUsagerDto, @@ -58,7 +54,12 @@ import { generateCerfaData } from "../utils/cerfa"; import { join, resolve } from "path"; import { readFile } from "fs-extra"; import { ExpressResponse } from "../../util/express"; -import { Usager, ETAPE_DOCUMENTS, CerfaDocType } from "@domifa/common"; +import { + Usager, + ETAPE_DOCUMENTS, + CerfaDocType, + ALL_USER_STRUCTURE_ROLES, +} from "@domifa/common"; import { UsagerHistoryStateService } from "../services/usagerHistoryState.service"; import { domifaConfig } from "../../config"; import { FileManagerService } from "../../util/file-manager/file-manager.service"; @@ -66,7 +67,6 @@ import { AssignReferrersDto } from "../dto/assign-referrers.dto"; import { In } from "typeorm"; import { UsagersLogsService } from "../services/usagers-logs.service"; import { input } from "node-pdftk"; - @Controller("usagers") @ApiTags("usagers") @UseGuards(AuthGuard("jwt"), AppUserGuard) @@ -166,7 +166,7 @@ export class UsagersController { } @UseGuards(UsagerAccessGuard) - @AllowUserStructureRoles(...USER_STRUCTURE_ROLE_ALL) + @AllowUserStructureRoles(...ALL_USER_STRUCTURE_ROLES) @Patch("contact-details/:usagerRef") public async patchMailAndPhone( @Body() contactDetails: ContactDetailsDto, @@ -266,7 +266,7 @@ export class UsagersController { } @UseGuards(UsagerAccessGuard) - @AllowUserStructureRoles(...USER_STRUCTURE_ROLE_ALL) + @AllowUserStructureRoles(...ALL_USER_STRUCTURE_ROLES) @Get("stop-courrier/:usagerRef") public async stopCourrier( @CurrentUsager() currentUsager: Usager, @@ -367,7 +367,7 @@ export class UsagersController { } @UseGuards(UsagerAccessGuard) - @AllowUserStructureRoles(...USER_STRUCTURE_ROLES_NOT_FACTEUR) + @AllowUserStructureRoles("admin", "agent", "responsable", "simple") @Get("cerfa/:usagerRef/:typeCerfa") public async getAttestation( @Res() res: Response, @@ -399,7 +399,7 @@ export class UsagersController { } @UseGuards(UsagerAccessGuard) - @AllowUserStructureRoles(...USER_STRUCTURE_ROLE_ALL) + @AllowUserStructureRoles(...ALL_USER_STRUCTURE_ROLES) @Get(":usagerRef") public findOne( @Param("usagerRef", new ParseIntPipe()) _usagerRef: number, @@ -409,7 +409,7 @@ export class UsagersController { } @Post("assign-referrers") - @AllowUserStructureRoles(...USER_STRUCTURE_ROLE_ALL) + @AllowUserStructureRoles(...ALL_USER_STRUCTURE_ROLES) public async assignReferrersToAnotherUser( @CurrentUser() userStructureAuth: UserStructureAuthenticated, @Body() body: AssignReferrersDto, diff --git a/packages/frontend/src/app/modules/manage-users/components/user-profil/user-profil.component.html b/packages/frontend/src/app/modules/manage-users/components/user-profil/user-profil.component.html index 68f230922d..08086ceebd 100644 --- a/packages/frontend/src/app/modules/manage-users/components/user-profil/user-profil.component.html +++ b/packages/frontend/src/app/modules/manage-users/components/user-profil/user-profil.component.html @@ -264,8 +264,8 @@

Utilisateurs enregistrés: {{ users.length }} utilisateurs

Page statistiques de la structure - Non - Non + Oui + Oui Oui Oui Oui From 2e46f81150b2f7a2dcb1d0c3108966e326106ec2 Mon Sep 17 00:00:00 2001 From: "Yassine R." Date: Thu, 18 Sep 2025 09:43:54 +0200 Subject: [PATCH 3/4] fix(backend): update useless migrations --- .../db/dumps/domifa_test.postgres.custom.gz | Bin 111470 -> 111470 bytes .../1751572909099-auto-migration.ts | 33 ------ .../1751927912971-manual-migration.ts | 66 ------------ .../1753607421699-auto-migration.ts | 32 ------ .../1754405019897-auto-migration.ts | 97 ------------------ .../1754664216664-manual-migration.ts | 47 --------- .../1755033531923-manual-migration.ts | 51 --------- .../1755523274894-auto-migration.ts | 28 ----- .../1755523274895-auto-migration.ts | 80 --------------- 9 files changed, 434 deletions(-) delete mode 100644 packages/backend/src/_migrations/1751572909099-auto-migration.ts delete mode 100644 packages/backend/src/_migrations/1751927912971-manual-migration.ts delete mode 100644 packages/backend/src/_migrations/1753607421699-auto-migration.ts delete mode 100644 packages/backend/src/_migrations/1754405019897-auto-migration.ts delete mode 100644 packages/backend/src/_migrations/1754664216664-manual-migration.ts delete mode 100644 packages/backend/src/_migrations/1755033531923-manual-migration.ts delete mode 100644 packages/backend/src/_migrations/1755523274894-auto-migration.ts delete mode 100644 packages/backend/src/_migrations/1755523274895-auto-migration.ts diff --git a/_scripts/db/dumps/domifa_test.postgres.custom.gz b/_scripts/db/dumps/domifa_test.postgres.custom.gz index 6ee06685fa38224d40dc52de062f38d1b9a49daf..f3b416e7db984e3aeeabe5074c5e8b92323de183 100644 GIT binary patch delta 2945 zcmY+GdvI386~MpEi-Z(SLP8!l`I1N(9s;?Ky?5^hB99;_G&G@-5ot6T9+ox@@d5a3 zfogRSqHv3!mV#!O{t?;&;dER=BLo~M87!?s3)Rs8)N?6YW|^^*IhX=B~7~0frgZPX2^vV zsXJMEV0*%a-1J?Dp$B~#Q&NmpI{UJoA(F5$yUHN91@w(*N;T+&a7%6(qAOrlelMaY zAiZduiN(1KZt-|r#yx1Z&LjFR%!zj+1`gb)*pOy?1HHwVw3Oi*g}{`f>kEqk#$L-X zW@*FT$z`c&f$iH-nPw6jfQG|-R$ezE>s6M%nrWeM3XwoVX?eS zqJ(cvtw$%9LubuB>Bh+u`)WT%I}hN~+w)99zR#m|FIrGOcdI#;A8_cY`v{!`kFGQn z!@>Ge5`8$kU<5ja90nHlBT63*Epk(a>7_D=6($bXvl7VrZmn6Ob#TwU^HQ}jaQxV) zM0XP#35QzHJ#d0pkk4H{d5&UsQAzC~?I@?(YDXo{7 z3CNvTeqvw-D}?N}+34Wg(AZvU4juRo?08@rp$q39{5GKn!Ncutn|1U9`@`@>KPSkTeA7<}7 zW*$S}hmgB#H97`%ER3o;N@3TpevCl^7bgE^H6e$t-Af6BX!m=gVBFqT5<_^o`%y$; zCk`)XrQpFMB)hQpw+|6=824Hd19(;4PudW^(L-xP8#WwBq6?Y5&!U5V1Y2KkBMcz( z5aktyu(9t6)Ji*XsGgOlU>_XQYKP2RdJxweQ@@UdEfCI-ilPQGy;~fTtZ6^j6 zF$)I!u?WI;V|H||GasHmv637(r2gR{Qy^gnG5wI&7s1w(YsjXH_owxUjtwupl|&cH zPhqCQ;jr`1SV7?g5I>E*B%CmcpDu(wXIe0`fkbm}#jxo^itL3jc;P{`a2r;A zyn@h;%1;%*wTl#zb69d|6-(8JkIr2zfiEsMGd(E<7qPgRl(|>q@Z^s znKuu_;rib#H0#M>{e!a+dbRJM`OaB)C-zL&wO{jDF1fg{>2pcw!HF+?LJsNw#E~O> zAL_2*$Ps=3oBxH6TKEFq{L;sb{g5{9`zj9Ozbd8m66W6UaAV!!CT+8^U8gtx^-!+8pYm8MBdTLq>+lQJ%Zr`6~a?%Zer8P zhpXP3*<@m0UCm+BFbffUo$2&*mTJ@~kdIK!BUufWOi;-ZEd?yDj^?vU@{sCM0ke@q zTU8XYkl0a8MU3t!bk(+EMupcy+*CI4gr%cgD`8pW%~eJz6PQc*->NOXXsKmox@xAC zLdr2wRIXQUjSp$5eu<_ElT|q@qj;hEsDe4fQkC7ps*t6v8b<4V%!8JW+Vst2hSF6h z#^?-D@2T{$L(J8*ammw3Up+it-q4rm^W2kU&RH*G!*&8HFwd^+5hwO4SVfqkDGg4I6%%tpbb+VQnF=H(BBz-;< z+|EwoO3tGL$1K%3haDwZsvq2$WM3a-IV)Fp&C|3S1km_5&en+xYYwt=X9&&X@qmE)ChEf&W&CVc8uJo9HAEQf|jDC4BJ7}!Z z=1PAmJ|UKB$9)Wt9j+Q%*a>2ZyG~ugdQjG7`En`cu7Ce3eV7kWuS?SPJ<33OQmy`e e(uZ^Np^2--tyDY7rK)J7YDk}}Pgb(0YX1W()FDp* delta 2945 zcmY+Fd2p506~N!kMnZ}vAtB34UJ{WZP$2i)?+rwjuqYTzP%ghmKB&}2}oLkrc>L9yZjf>ArAB5ChE=S8RQk2k-2&beoQ z_gy-lcIkXtdEK0uwRP;eNJ=`3WJL7mM)Or+zH-c0R#*9iq?Evu9@Ho0GDAMBNZ!R# zJ>dsFWT);%6an<6O-?dW>Fv*W%22=^*pyj`Xj#xZqA}S>Z5wXLEyy=vt6k zP+@!pt`BzMIK1Wt&=fs~==m@w)`jSMaII`Zim?rJh%qTi!!-&ED+sSHECd*PCC#X% z3;QNvEWzC{<`lt2tK3)%?nSb6ePREi(NN`HHGu{9p~}BzLI}$XC$^WuVtEmdwgb0L zsY4@MKu7gmsm92)_SbxhdXK{wvvN#E!V}@T=b}(Lcbln8_yW3XKS85FgqP|I;ZR*M z9VMJyFanK)fPsbmh*HAgMRw9KPe{%q`SBxltO#;`Qe&=2F5#}b=Or7ZB_pHaU5#uc z9Bw9an@0+aBpPP6X2IyCMR>)QFk^X}aV;GYTAc;(){1=8I5Irjkq=2N7npJAdXe1t zz;u=mnXR+Yz;mIYt;Q5BJr8!?H))@?<0@EI&08zFs{8 zbv}oxhi0;Dy&EEk4AWh2Zfm=zW#zqL*4ol=&%@v72zqO_X5>N7BNNOOvpHWpnuVx0 zC+YDg5cTG4{AC-WW9?u2Mb%9(?MoISC7PKK&Xh^r|#%TxHD79=yA0KBDEp#P+p_wiE7u<{hKgEAZ^II1#-9 z@Q?Kq;Es^ z?$v1MyAcsqwimU~6j1Rhq2Tbcx)-Iwh97m)UE#upg9-E@z2|8%5U}mFRz%4m{V?SvZP?WN z7)jmu;W}0Vo;kjIRv{^f8uczg??4Rw9(EX7FUUoO%q5B8fL z=%XLu;fEc$@XU#oWGW!}%?D6t@rWC)TVDX%POd?nrF-|+^@J`w|8@d>C_QBomE01r z>u;uklG_|&r_Cy9w8PlxeAs)Y8Qt1LZFk}((U-!;wErUI(oqeL7Id*0uUQpbk* zXA@Evj()J5q(0R<@7$wUnG@dD7ln^M+JIWuOsx<$e@u>D8wStcPZ}3ieY%3s4@*zw z!IjU*qbp#^1RV>s8Q(jNMPbd?*<|9w=5Hin04M(C5ei8Cw|R2(MG3W6%#$Ozen7VT z$NZ=@TJXlV9tQSp3f%i$490y|Olk+_UUM+8-f)w)3CwGC;NK7Cl8Fb0{##Axzsgt@ zVW6favGK%0wI;La zM(G69CS&w=gEl&l!LBDGSG_TuO(gczVCE3}ijQFC1=SG(wdOiDjaaCj>)9k?sV--+ zshEY}-)B1Q!>DS|DWHw8RMSXSjV%+@vUqbIi>YI|teh+ybs>*&Vpo;rGePXB#sWq& z6297A$f)u95jUNUKNi(qt`xBhvKA_>m<5!}4_#aQSyU}6(OomEBq_&uL8-pEEjA>j z{>2;1Ojf0=1pP@{eNx6OVn>zSz$%GdRX)q~^o)O0SEes8ggmLKb=r^mA>NfWv3n4qPF6Lf8Q!WO5#nc>y1)We%Qk&PsC znrb|=Qky?HiDi)n*m3h#SeAJ! z)Q&0ab=2FAT6PobB^GM@v;;d&Sl3siGG+{&g*sWoj+$r8avl2jP%w*~#G9@N4<3)I zjydcYo;^qX{FWisbu4G4>W+E(y6J@PsAw(gLs!0_M_3KcXFaG59HkRJPb|#;kLq2( z{)}hgsI_+_5*I?<+@QS}kJ3?jcd|3YLJcfp9~kd8cM{$&E@p>}*5*R#e~QnMEl2IV zhXJur4bAKXvi_$xQKu|n-EAf^_# WQ15Krjj~qihV2RU`AYUg&Hn&Cp(Jzw diff --git a/packages/backend/src/_migrations/1751572909099-auto-migration.ts b/packages/backend/src/_migrations/1751572909099-auto-migration.ts deleted file mode 100644 index 389380b2c1..0000000000 --- a/packages/backend/src/_migrations/1751572909099-auto-migration.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { MigrationInterface, QueryRunner } from "typeorm"; -import { domifaConfig } from "../config"; - -export class AutoMigration1751572909099 implements MigrationInterface { - name = "AutoMigration1751572909099"; - - public async up(queryRunner: QueryRunner): Promise { - if ( - domifaConfig().envId === "prod" || - domifaConfig().envId === "preprod" || - domifaConfig().envId === "local" - ) { - // Votre migration de schéma ici - await queryRunner.query(` - ALTER TABLE user_structure - ADD COLUMN "fonctionDetail" VARCHAR(255) - `); - } - } - - public async down(queryRunner: QueryRunner): Promise { - if ( - domifaConfig().envId === "prod" || - domifaConfig().envId === "preprod" || - domifaConfig().envId === "local" - ) { - await queryRunner.query(` - ALTER TABLE user_structure - DROP COLUMN "fonctionDetail" - `); - } - } -} diff --git a/packages/backend/src/_migrations/1751927912971-manual-migration.ts b/packages/backend/src/_migrations/1751927912971-manual-migration.ts deleted file mode 100644 index 0b2a8fa548..0000000000 --- a/packages/backend/src/_migrations/1751927912971-manual-migration.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { IsNull, MigrationInterface, Not } from "typeorm"; -import { domifaConfig } from "../config"; -import { matchFonctionUtilisateur, UserFonction } from "@domifa/common"; -import { userStructureRepository } from "../database"; - -export class ManualMigration1751927912971 implements MigrationInterface { - name = "ManualMigration1751927912971"; - - public async up(): Promise { - const stats = []; - if ( - domifaConfig().envId === "prod" || - domifaConfig().envId === "preprod" || - domifaConfig().envId === "local" - ) { - console.log("Application de la migration"); - - const users = await userStructureRepository.find({ - where: { - fonction: Not(IsNull()), - }, - select: { - id: true, - fonction: true, - fonctionDetail: true, - }, - }); - - // Process each user record - for (const user of users) { - const currentFonction = user.fonction; - const fonction = matchFonctionUtilisateur(currentFonction); - await userStructureRepository.update( - { - id: user.id, - }, - { - fonction, - fonctionDetail: - currentFonction === UserFonction.AUTRE ? user.fonction : null, - } - ); - - stats.push({ - userId: user.id, - oldFonction: currentFonction, - newFonction: fonction, - }); - } - - console.table(stats); - } - } - - public async down(): Promise { - if ( - domifaConfig().envId === "prod" || - domifaConfig().envId === "preprod" || - domifaConfig().envId === "local" - ) { - console.log( - "La récupération des données est impossible vu que la fonction est désormais fortement typée" - ); - } - } -} diff --git a/packages/backend/src/_migrations/1753607421699-auto-migration.ts b/packages/backend/src/_migrations/1753607421699-auto-migration.ts deleted file mode 100644 index 6ca6291065..0000000000 --- a/packages/backend/src/_migrations/1753607421699-auto-migration.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { MigrationInterface, QueryRunner } from "typeorm"; -import { domifaConfig } from "../config"; - -export class AutoMigration1753607421699 implements MigrationInterface { - name = "AutoMigration1753607421699"; - - public async up(queryRunner: QueryRunner): Promise { - if ( - domifaConfig().envId === "prod" || - domifaConfig().envId === "preprod" || - domifaConfig().envId === "local" - ) { - await queryRunner.query(`ALTER TABLE "app_log" ADD "context" json`); - await queryRunner.query( - `ALTER TABLE "app_log" ALTER COLUMN "userId" DROP NOT NULL` - ); - } - } - - public async down(queryRunner: QueryRunner): Promise { - if ( - domifaConfig().envId === "prod" || - domifaConfig().envId === "preprod" || - domifaConfig().envId === "local" - ) { - await queryRunner.query( - `ALTER TABLE "app_log" ALTER COLUMN "userId" SET NOT NULL` - ); - await queryRunner.query(`ALTER TABLE "app_log" DROP COLUMN "context"`); - } - } -} diff --git a/packages/backend/src/_migrations/1754405019897-auto-migration.ts b/packages/backend/src/_migrations/1754405019897-auto-migration.ts deleted file mode 100644 index a1f4b280a9..0000000000 --- a/packages/backend/src/_migrations/1754405019897-auto-migration.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { MigrationInterface, QueryRunner } from "typeorm"; -import { domifaConfig } from "../config"; - -export class AutoMigration1754405019897 implements MigrationInterface { - name = "AutoMigration1754405019897"; - - public async up(queryRunner: QueryRunner): Promise { - if ( - domifaConfig().envId === "prod" || - domifaConfig().envId === "preprod" || - domifaConfig().envId === "local" - ) { - // User Structure - await queryRunner.query( - `ALTER TABLE "user_structure_security" ADD "structureId" integer` - ); - await queryRunner.query( - `ALTER TABLE "user_structure_security" ADD CONSTRAINT "FK_57be1bdd772eb3fea1e201317e6" FOREIGN KEY ("structureId") REFERENCES "structure"("id") ON DELETE CASCADE ON UPDATE NO ACTION` - ); - await queryRunner.query( - `CREATE INDEX "IDX_57be1bdd772eb3fea1e201317e" ON "user_structure_security" ("structureId") ` - ); - // --- - - // User Usager - await queryRunner.query( - `ALTER TABLE "user_usager_security" ADD "temporaryTokens" jsonb` - ); - await queryRunner.query( - `ALTER TABLE "user_usager_security" DROP CONSTRAINT "FK_0b7885e1594c7af3a5b84a4bdb3"` - ); - await queryRunner.query( - `ALTER TABLE "user_usager_security" DROP CONSTRAINT "UQ_0b7885e1594c7af3a5b84a4bdb3"` - ); - - await queryRunner.query( - `ALTER TABLE "user_usager_security" ADD CONSTRAINT "FK_0b7885e1594c7af3a5b84a4bdb3" FOREIGN KEY ("userId") REFERENCES "user_usager"("id") ON DELETE CASCADE ON UPDATE NO ACTION` - ); - await queryRunner.query( - `ALTER TABLE "user_usager_security" ADD CONSTRAINT "UQ_a21e4892613030aa47755b46a75" UNIQUE ("userId", "structureId")` - ); - // ------ - - // User Supervisor - await queryRunner.query( - `ALTER TABLE "user_supervisor_security" DROP CONSTRAINT "FK_94c17da6c8fc82ac679eefd3ecb"` - ); - await queryRunner.query( - `ALTER TABLE "user_supervisor_security" ADD CONSTRAINT "UQ_94c17da6c8fc82ac679eefd3ecb" UNIQUE ("userId")` - ); - await queryRunner.query( - `ALTER TABLE "user_supervisor_security" ADD CONSTRAINT "FK_94c17da6c8fc82ac679eefd3ecb" FOREIGN KEY ("userId") REFERENCES "user_supervisor"("id") ON DELETE CASCADE ON UPDATE NO ACTION` - ); - } - } - - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query( - `ALTER TABLE "user_usager_security" DROP CONSTRAINT "FK_0b7885e1594c7af3a5b84a4bdb3"` - ); - await queryRunner.query( - `ALTER TABLE "user_structure_security" DROP CONSTRAINT "FK_57be1bdd772eb3fea1e201317e6"` - ); - await queryRunner.query( - `ALTER TABLE "user_supervisor_security" DROP CONSTRAINT "FK_94c17da6c8fc82ac679eefd3ecb"` - ); - await queryRunner.query( - `ALTER TABLE "user_usager_security" DROP CONSTRAINT "UQ_a21e4892613030aa47755b46a75"` - ); - await queryRunner.query( - `DROP INDEX "public"."IDX_57be1bdd772eb3fea1e201317e"` - ); - await queryRunner.query( - `DROP INDEX "public"."IDX_b2ad525cbadf911e833bf61597"` - ); - - await queryRunner.query( - `ALTER TABLE "user_usager_security" ADD CONSTRAINT "UQ_0b7885e1594c7af3a5b84a4bdb3" UNIQUE ("userId")` - ); - await queryRunner.query( - `ALTER TABLE "user_usager_security" ADD CONSTRAINT "FK_0b7885e1594c7af3a5b84a4bdb3" FOREIGN KEY ("userId") REFERENCES "user_usager"("id") ON DELETE CASCADE ON UPDATE NO ACTION` - ); - - await queryRunner.query( - `ALTER TABLE "user_supervisor_security" DROP CONSTRAINT "UQ_94c17da6c8fc82ac679eefd3ecb"` - ); - await queryRunner.query( - `ALTER TABLE "user_supervisor_security" ADD CONSTRAINT "FK_94c17da6c8fc82ac679eefd3ecb" FOREIGN KEY ("userId") REFERENCES "user_supervisor"("id") ON DELETE CASCADE ON UPDATE NO ACTION` - ); - await queryRunner.query( - `ALTER TABLE "user_usager_security" DROP COLUMN "temporaryTokens"` - ); - await queryRunner.query( - `ALTER TABLE "user_structure_security" DROP COLUMN "structureId"` - ); - } -} diff --git a/packages/backend/src/_migrations/1754664216664-manual-migration.ts b/packages/backend/src/_migrations/1754664216664-manual-migration.ts deleted file mode 100644 index 4cf39c07c4..0000000000 --- a/packages/backend/src/_migrations/1754664216664-manual-migration.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { MigrationInterface, QueryRunner } from "typeorm"; -import { domifaConfig } from "../config"; - -export class ManualMigration1754664216664 implements MigrationInterface { - public async up(queryRunner: QueryRunner): Promise { - if ( - domifaConfig().envId === "prod" || - domifaConfig().envId === "preprod" || - domifaConfig().envId === "local" - ) { - // Update user_structure_security table with structureId from user_structure - await queryRunner.query(` - UPDATE user_structure_security - SET "structureId" = ( - SELECT us."structureId" - FROM user_structure us - WHERE us.id = user_structure_security."userId" - ) - WHERE "structureId" IS NULL - `); - - // Update user_usager_security table with structureId from user_usager - await queryRunner.query(` - UPDATE user_usager_security - SET "structureId" = ( - SELECT uu."structureId" - FROM user_usager uu - WHERE uu.id = user_usager_security."userId" - ) - WHERE "structureId" IS NULL - `); - } - } - - public async down(queryRunner: QueryRunner): Promise { - // Set structureId values back to NULL - await queryRunner.query(` - UPDATE user_structure_security - SET "structureId" = NULL - `); - - await queryRunner.query(` - UPDATE user_usager_security - SET "structureId" = NULL - `); - } -} diff --git a/packages/backend/src/_migrations/1755033531923-manual-migration.ts b/packages/backend/src/_migrations/1755033531923-manual-migration.ts deleted file mode 100644 index 1f84bcb366..0000000000 --- a/packages/backend/src/_migrations/1755033531923-manual-migration.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { MigrationInterface, QueryRunner } from "typeorm"; -import { domifaConfig } from "../config"; -import { appLogger } from "../util"; - -export class ManualMigration1755033531923 implements MigrationInterface { - name: string = "ManualMigration1755033531923"; - public async up(queryRunner: QueryRunner): Promise { - if ( - domifaConfig().envId === "prod" || - domifaConfig().envId === "preprod" || - domifaConfig().envId === "local" - ) { - appLogger.info("Starting migration: Updating structures SMS schedules"); - await queryRunner.query(` - UPDATE structure - SET sms = sms || '{"schedule": {"monday": false, "tuesday": true, "wednesday": false, "thursday": true, "friday": false}}'::jsonb - WHERE - (sms->>'enabledByStructure')::boolean = TRUE - AND (sms->'schedule'->>'friday')::boolean = FALSE - AND (sms->'schedule'->>'monday')::boolean = FALSE - AND (sms->'schedule'->>'thursday')::boolean = FALSE - AND (sms->'schedule'->>'tuesday')::boolean = FALSE - AND (sms->'schedule'->>'wednesday')::boolean = FALSE; - `); - - const count = await queryRunner.query(` - SELECT COUNT(*) FROM structure - WHERE - (sms->>'enabledByStructure')::boolean = TRUE - AND (sms->'schedule'->>'friday')::boolean = FALSE - AND (sms->'schedule'->>'monday')::boolean = FALSE - AND (sms->'schedule'->>'thursday')::boolean = FALSE - AND (sms->'schedule'->>'tuesday')::boolean = FALSE - AND (sms->'schedule'->>'wednesday')::boolean = FALSE; - `); - - console.log(count); - appLogger.info("Migration end"); - } - } - - public async down(): Promise { - if ( - domifaConfig().envId === "prod" || - domifaConfig().envId === "preprod" || - domifaConfig().envId === "local" - ) { - appLogger.info("No down migration can be applied"); - } - } -} diff --git a/packages/backend/src/_migrations/1755523274894-auto-migration.ts b/packages/backend/src/_migrations/1755523274894-auto-migration.ts deleted file mode 100644 index 398a8c44e0..0000000000 --- a/packages/backend/src/_migrations/1755523274894-auto-migration.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { MigrationInterface, QueryRunner } from "typeorm"; -import { domifaConfig } from "../config"; - -export class AutoMigration1755523274894 implements MigrationInterface { - name = "AutoMigration1755523274894"; - - public async up(queryRunner: QueryRunner): Promise { - if ( - domifaConfig().envId === "prod" || - domifaConfig().envId === "preprod" || - domifaConfig().envId === "local" - ) { - await queryRunner.query( - `ALTER TABLE "user_usager" ADD "passwordType" text NOT NULL DEFAULT true` - ); - - await queryRunner.query( - ` ALTER TABLE "user_usager" DROP COLUMN "enabled" ` - ); - } - } - - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query( - `ALTER TABLE "user_usager" DROP COLUMN "passwordType"` - ); - } -} diff --git a/packages/backend/src/_migrations/1755523274895-auto-migration.ts b/packages/backend/src/_migrations/1755523274895-auto-migration.ts deleted file mode 100644 index c600ec80ad..0000000000 --- a/packages/backend/src/_migrations/1755523274895-auto-migration.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { MigrationInterface, QueryRunner } from "typeorm"; - -export class AutoMigration1755523274895 implements MigrationInterface { - name = "AutoMigration1755523274895"; - - public async up(queryRunner: QueryRunner): Promise { - console.log("🚀 Starting password type migration"); - - // Initial stats - const initialStats = await queryRunner.query(` - SELECT - COUNT(*) as "totalAccounts", - COUNT(*) FILTER (WHERE "isTemporaryPassword" = true) as "temporaryPasswords", - COUNT(*) FILTER (WHERE "isTemporaryPassword" = false) as "personalPasswords" - FROM user_usager - `); - - console.log(`📊 Initial stats:`, initialStats[0]); - - // Update RANDOM pour tous les mots de passe temporaires - const randomResult = await queryRunner.query(` - UPDATE user_usager - SET "passwordType" = 'RANDOM' - WHERE "isTemporaryPassword" = true - `); - - console.log(`✅ Set ${randomResult[1]} accounts to RANDOM type`); - - // Update PERSONAL pour tous les mots de passe personnels - const personalResult = await queryRunner.query(` - UPDATE user_usager - SET "passwordType" = 'PERSONAL' - WHERE "isTemporaryPassword" = false - `); - - console.log(`✅ Set ${personalResult[1]} accounts to PERSONAL type`); - - // Verification qu'aucun compte n'a passwordType NULL - const nullPasswordTypes = await queryRunner.query(` - SELECT COUNT(*) as "nullCount" - FROM user_usager - WHERE "passwordType" IS NULL - `); - - if (nullPasswordTypes[0].nullCount > 0) { - throw new Error( - `❌ Migration failed: ${nullPasswordTypes[0].nullCount} accounts still have NULL passwordType` - ); - } - - // Final verification - const finalStats = await queryRunner.query(` - SELECT - "passwordType", - COUNT(*) as count - FROM user_usager - GROUP BY "passwordType" - ORDER BY "passwordType" - `); - - console.log("📊 Final distribution:"); - finalStats.forEach((stat) => { - console.log(` ${stat.passwordType}: ${stat.count} accounts`); - }); - - // Rendre la colonne NOT NULL maintenant qu'elle est peuplée - await queryRunner.query(` - ALTER TABLE "user_usager" - ALTER COLUMN "passwordType" SET NOT NULL - `); - - console.log("🎉 Password type migration completed!"); - } - - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query(` - ALTER TABLE "user_usager" DROP COLUMN "passwordType" - `); - } -} From f4481f5d8a15131000c42fa1f917fb5ecc47bfb1 Mon Sep 17 00:00:00 2001 From: "Yassine R." Date: Thu, 18 Sep 2025 15:56:47 +0200 Subject: [PATCH 4/4] fix(frontend): update of guards --- .../1756117243336-manual-migration.ts | 27 ----- .../1756117243337-manual-migration.ts | 19 ---- .../1757532174131-auto-migration.ts | 41 ------- .../controllers/users.public.controller.ts | 1 - .../usagers-decision.controller.ts | 6 +- .../frontend/src/app/guards/auth.guard.ts | 6 +- .../interceptors/server-error.interceptor.ts | 104 ++++++++---------- .../idle-manager/idle-manager.component.ts | 2 +- .../modules/shared/services/auth.service.ts | 43 ++++---- .../step-footer/step-footer.component.html | 2 +- .../step-footer/step-footer.component.ts | 5 +- ...profil-historique-decisions.component.html | 2 +- .../profil-historique-decisions.component.ts | 10 +- .../base-usager-profil-page.component.ts | 4 + .../profil-courriers.component.html | 2 +- .../profil-documents-section.component.html | 3 +- .../profil-dossier.component.html | 13 +-- .../profil-general-section.component.html | 1 + .../profil-historique.component.html | 1 + .../profil-head/profil-head.component.html | 1 - 20 files changed, 104 insertions(+), 189 deletions(-) delete mode 100644 packages/backend/src/_migrations/1756117243336-manual-migration.ts delete mode 100644 packages/backend/src/_migrations/1756117243337-manual-migration.ts delete mode 100644 packages/backend/src/_migrations/1757532174131-auto-migration.ts diff --git a/packages/backend/src/_migrations/1756117243336-manual-migration.ts b/packages/backend/src/_migrations/1756117243336-manual-migration.ts deleted file mode 100644 index 3db8e736ca..0000000000 --- a/packages/backend/src/_migrations/1756117243336-manual-migration.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { MigrationInterface, QueryRunner } from "typeorm"; - -export class ManualMigration1756117243336 implements MigrationInterface { - public async up(queryRunner: QueryRunner): Promise { - await queryRunner.query(` - UPDATE "app_log" - SET action = CASE - WHEN action = 'DOWNLOAD_IMPORT_GUIDE' THEN 'IMPORT_DOWNLOAD_GUIDE' - WHEN action = 'DOWNLOAD_IMPORT_TEMPLATE' THEN 'IMPORT_TEMPLATE_DOWNLOAD' - ELSE action - END - WHERE action IN ('DOWNLOAD_IMPORT_GUIDE', 'DOWNLOAD_IMPORT_TEMPLATE'); - `); - } - - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query(` - UPDATE "app_log" - SET action = CASE - WHEN action = 'IMPORT_DOWNLOAD_GUIDE' THEN 'DOWNLOAD_IMPORT_GUIDE' - WHEN action = 'IMPORT_TEMPLATE_DOWNLOAD' THEN 'DOWNLOAD_IMPORT_TEMPLATE' - ELSE action - END - WHERE action IN ('IMPORT_DOWNLOAD_GUIDE', 'IMPORT_TEMPLATE_DOWNLOAD'); - `); - } -} diff --git a/packages/backend/src/_migrations/1756117243337-manual-migration.ts b/packages/backend/src/_migrations/1756117243337-manual-migration.ts deleted file mode 100644 index 4f88bf4edf..0000000000 --- a/packages/backend/src/_migrations/1756117243337-manual-migration.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { MigrationInterface, QueryRunner } from "typeorm"; - -export class ManualMigration1756117243337 implements MigrationInterface { - public async up(queryRunner: QueryRunner): Promise { - await queryRunner.query(` - UPDATE app_log - SET action = 'USAGER_DELETE' - WHERE action = 'SUPPRIMER_DOMICILIE' - `); - } - - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query(` - UPDATE app_log - SET action = 'SUPPRIMER_DOMICILIE' - WHERE action = 'USAGER_DELETE' - `); - } -} diff --git a/packages/backend/src/_migrations/1757532174131-auto-migration.ts b/packages/backend/src/_migrations/1757532174131-auto-migration.ts deleted file mode 100644 index 102d844940..0000000000 --- a/packages/backend/src/_migrations/1757532174131-auto-migration.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { MigrationInterface, QueryRunner } from "typeorm"; -import { domifaConfig } from "../config"; - -export class AutoMigration1757532174131 implements MigrationInterface { - name = "AutoMigration1757532174131"; - - public async up(queryRunner: QueryRunner): Promise { - if ( - domifaConfig().envId === "prod" || - domifaConfig().envId === "preprod" || - domifaConfig().envId === "local" - ) { - try { - await queryRunner.query( - `ALTER TABLE "user_usager" DROP COLUMN "isTemporaryPassword"` - ); - await queryRunner.query( - `CREATE INDEX "IDX_b2ad525cbadf911e833bf61597" ON "open_data_places" ("cityCode") ` - ); - } catch (e) { - console.log(e); - } - } - } - - public async down(queryRunner: QueryRunner): Promise { - if ( - domifaConfig().envId === "prod" || - domifaConfig().envId === "preprod" || - domifaConfig().envId === "local" - ) { - await queryRunner.query( - `DROP INDEX "public"."IDX_b2ad525cbadf911e833bf61597"` - ); - - await queryRunner.query( - `ALTER TABLE "user_usager" ADD "isTemporaryPassword" boolean NOT NULL DEFAULT false` - ); - } - } -} diff --git a/packages/backend/src/modules/users/controllers/users.public.controller.ts b/packages/backend/src/modules/users/controllers/users.public.controller.ts index 238297fd86..19172c21e8 100644 --- a/packages/backend/src/modules/users/controllers/users.public.controller.ts +++ b/packages/backend/src/modules/users/controllers/users.public.controller.ts @@ -25,7 +25,6 @@ const userProfile: UserProfile = "structure"; @Controller("users") @ApiTags("users") export class UsersPublicController { - // TODO: add a limit for this endpoint by ip @Post("validate-email") public async validateEmail( @Body() emailDto: EmailDto, diff --git a/packages/backend/src/usagers/controllers/usagers-decision.controller.ts b/packages/backend/src/usagers/controllers/usagers-decision.controller.ts index 9eaf27ec64..c198bc6c4c 100644 --- a/packages/backend/src/usagers/controllers/usagers-decision.controller.ts +++ b/packages/backend/src/usagers/controllers/usagers-decision.controller.ts @@ -60,10 +60,8 @@ export class UsagersDecisionController { @Param("usagerRef", new ParseIntPipe()) _usagerRef: number ): Promise { if ( - decision.statut !== "ATTENTE_DECISION" && - decision.statut !== "INSTRUCTION" && - user.role !== "responsable" && - user.role !== "admin" + !["ATTENTE_DECISION", "INSTRUCTION"].includes(decision.statut) && + !["reposable", "admmin"].includes(user.role) ) { throw new Error("CANNOT_SET_DECISION"); } diff --git a/packages/frontend/src/app/guards/auth.guard.ts b/packages/frontend/src/app/guards/auth.guard.ts index 9cf4b24308..4771515a85 100644 --- a/packages/frontend/src/app/guards/auth.guard.ts +++ b/packages/frontend/src/app/guards/auth.guard.ts @@ -24,9 +24,8 @@ export class AuthGuard { return this.authService.isAuth().pipe( map((isAuth: boolean) => { - console.log("XXXX"); if (!isAuth) { - this.authService.logoutAndRedirect(state); + this.authService.logout(state); return false; } @@ -35,7 +34,6 @@ export class AuthGuard { } if (this.authService.currentUserValue !== null) { - console.log(this.authService.currentUserValue); const userRole = this.authService.currentUserValue.role; if (allowedRoles.includes(userRole)) { @@ -51,7 +49,7 @@ export class AuthGuard { return false; }), catchError(() => { - this.authService.logoutAndRedirect(state); + this.authService.logout(state); return of(false); }) ); diff --git a/packages/frontend/src/app/interceptors/server-error.interceptor.ts b/packages/frontend/src/app/interceptors/server-error.interceptor.ts index 38dfcc0d9f..868f56485d 100644 --- a/packages/frontend/src/app/interceptors/server-error.interceptor.ts +++ b/packages/frontend/src/app/interceptors/server-error.interceptor.ts @@ -11,7 +11,6 @@ import { Injectable, Injector } from "@angular/core"; import { Observable, throwError, timer } from "rxjs"; import { catchError, retry } from "rxjs/operators"; import { AuthService } from "../modules/shared/services/auth.service"; -import { getCurrentScope } from "@sentry/angular"; import { CustomToastService } from "../modules/shared/services"; const MAX_RETRIES = 2; @@ -28,77 +27,70 @@ export class ServerErrorInterceptor implements HttpInterceptor { request: HttpRequest, next: HttpHandler ): Observable> { - const authService = this.injector.get(AuthService); - const toastr = this.injector.get(CustomToastService); - - if (authService?.currentUserValue) { - const user = authService.currentUserValue; - getCurrentScope().setTag("structure", user?.structureId?.toString()); - getCurrentScope().setUser({ - email: user.email, - username: `STRUCTURE ${user?.structureId?.toString()} : ${ - user?.prenom - }`, - }); - } - return next.handle(request).pipe( retry({ count: MAX_RETRIES, - delay: (error, retryCount) => { - if (this.isRetryable(error)) { - console.log(error); - console.log(`Tentative de nouvelle requête ${retryCount}`); + delay: (error: HttpErrorResponse, retryCount: number) => { + if (this.shouldRetry(error)) { + console.warn( + `Retry attempt ${retryCount} for ${request.url}`, + error + ); return timer(RETRY_DELAY); } - return throwError(() => error); + throw error; // Pas de retry, on passe au catchError }, }), - catchError((error: HttpErrorResponse) => { - if (error.error instanceof ErrorEvent) { - if (!navigator.onLine) { - toastr.error( - "Vous êtes actuellement hors-ligne. Veuillez vérifier votre connexion internet" - ); - return throwError(() => "NAVIGATOR_OFFLINE"); - } - return throwError(() => error.error); - } else if (error instanceof HttpErrorResponse) { - if (error.status === 0) { - console.warn("Erreur de connexion:", error.message); - toastr.error( - "Problème de connexion au serveur. Veuillez réessayer plus tard." - ); - } - if (error.status === 401) { - authService.logoutAndRedirect(undefined, true); - toastr.error( - "Votre session a expiré, merci de vous connecter à nouveau" - ); - } - } else { - toastr.error( - "Une erreur serveur est survenue. Nos équipes ont été notifiées." - ); - } - this.logError(request, error); - return throwError(() => error); - }) + catchError((error: HttpErrorResponse) => this.handleError(error)) ); } - private isRetryable(error: HttpErrorResponse): boolean { - return !error.status || ERROR_STATUS_CODES_TO_RETRY.includes(error.status); + private shouldRetry(error: HttpErrorResponse): boolean { + if (error.status >= 400 && error.status < 500) { + return false; + } + return ERROR_STATUS_CODES_TO_RETRY.includes(error.status); + } + + private handleError(error: HttpErrorResponse): Observable { + const authService = this.injector.get(AuthService); + const toastr = this.injector.get(CustomToastService); + + if (error.error instanceof ErrorEvent) { + if (!navigator.onLine) { + toastr.error( + "Vous êtes actuellement hors-ligne. Veuillez vérifier votre connexion internet" + ); + return throwError(() => new Error("NAVIGATOR_OFFLINE")); + } + toastr.error("Erreur de connexion réseau"); + return throwError(() => error); + } + + if (error.status === 0) { + toastr.error( + "Problème de connexion au serveur. Veuillez réessayer plus tard." + ); + } else if (error.status === 401) { + authService.logout(undefined, true); + } else if (error.status === 403) { + toastr.error("Vous n'avez pas les droits pour effectuer cette action"); + } else if (error.status >= 500 && error.status <= 504) { + toastr.error( + "Une erreur serveur est survenue. Nos équipes ont été notifiées." + ); + } + + this.logError(error); + return throwError(() => error); } - private logError(request: HttpRequest, error: HttpErrorResponse): void { - console.warn(error.message, { + private logError(error: HttpErrorResponse): void { + console.error("HTTP Error:", { status: error.status, statusText: error.statusText, url: error.url, message: error.message, - error: error.error, - request, }); } } diff --git a/packages/frontend/src/app/modules/general/components/static-modals/idle-manager/idle-manager.component.ts b/packages/frontend/src/app/modules/general/components/static-modals/idle-manager/idle-manager.component.ts index 9cd6bdecb4..7a8a07f577 100644 --- a/packages/frontend/src/app/modules/general/components/static-modals/idle-manager/idle-manager.component.ts +++ b/packages/frontend/src/app/modules/general/components/static-modals/idle-manager/idle-manager.component.ts @@ -93,7 +93,7 @@ export class IdleManagerComponent implements OnInit, OnDestroy { public logout(): void { this.closeModals(); - this.authService.logoutAndRedirect(); + this.authService.logout(); } public openIdleModal(): void { diff --git a/packages/frontend/src/app/modules/shared/services/auth.service.ts b/packages/frontend/src/app/modules/shared/services/auth.service.ts index 8cfac25d86..4f8278109d 100644 --- a/packages/frontend/src/app/modules/shared/services/auth.service.ts +++ b/packages/frontend/src/app/modules/shared/services/auth.service.ts @@ -81,14 +81,20 @@ export class AuthService { ); } - public logoutFromBackend = async () => { + public logoutFromBackend = async ( + state?: RouterStateSnapshot, + sessionExpired?: boolean + ) => { if (this.currentUserValue?.access_token) { await firstValueFrom(this.http.get(`${this.endPoint}/logout`)); } - this.logout(); + await this.logout(state, sessionExpired); }; - public async logout(): Promise { + public async logout( + state?: RouterStateSnapshot, + sessionExpired?: boolean + ): Promise { this.currentUserSubject.next(null); this.store.dispatch(usagerActions.clearCache()); localStorage.removeItem("currentUser"); @@ -97,29 +103,24 @@ export class AuthService { getCurrentScope().setTag("structure", "none"); getCurrentScope().setUser({}); - this.router.navigate(["/connexion"]); - } - - public logoutAndRedirect( - state?: RouterStateSnapshot, - sessionExpired?: boolean - ): void { if (sessionExpired) { this.toastr.warning("Votre session a expiré, merci de vous reconnecter"); } - this.logout(); + // Navigation avec query params si nécessaire + if (state?.url) { + const cleanPath = state.url.split("?")[0]; + const matomoParams = this.getMatomoParams(); + const queryParams: Record = { ...matomoParams }; - const cleanPath = state?.url?.split("?")[0] || "/"; - const matomoParams = this.getMatomoParams(); + if (cleanPath !== "/") { + queryParams.returnUrl = cleanPath; + } - const queryParams: Record = { ...matomoParams }; - - if (cleanPath !== "/") { - queryParams.returnUrl = cleanPath; + this.router.navigate(["/connexion"], { queryParams }); + } else { + this.router.navigate(["/connexion"]); } - - this.router.navigate(["/connexion"], { queryParams }); } private getMatomoParams(): Record { @@ -136,11 +137,11 @@ export class AuthService { localStorage.setItem("currentUser", JSON.stringify(user)); this.currentUserSubject.next(user); + // Configuration Sentry centralisée ici getCurrentScope().setTag("structure", user.structureId?.toString()); getCurrentScope().setUser({ email: user.email, - username: - "STRUCTURE " + user.structureId?.toString() + " : " + user.prenom, + username: `STRUCTURE ${user.structureId?.toString()}`, }); } } diff --git a/packages/frontend/src/app/modules/usager-dossier/components/step-footer/step-footer.component.html b/packages/frontend/src/app/modules/usager-dossier/components/step-footer/step-footer.component.html index 2c8fc5bb08..512d40e054 100644 --- a/packages/frontend/src/app/modules/usager-dossier/components/step-footer/step-footer.component.html +++ b/packages/frontend/src/app/modules/usager-dossier/components/step-footer/step-footer.component.html @@ -6,7 +6,7 @@

Commentaires privés

Historique des décisions

{{ histo.userName }}
diff --git a/packages/frontend/src/app/modules/usager-profil/components/pages/profil-documents-section/profil-documents-section.component.html b/packages/frontend/src/app/modules/usager-profil/components/pages/profil-documents-section/profil-documents-section.component.html index 584e606aca..49db0670ca 100644 --- a/packages/frontend/src/app/modules/usager-profil/components/pages/profil-documents-section/profil-documents-section.component.html +++ b/packages/frontend/src/app/modules/usager-profil/components/pages/profil-documents-section/profil-documents-section.component.html @@ -61,7 +61,7 @@

Documents mis à disposition par la structure

-
+

Documents de l'usager

Documents de l'usager [usager]="usager" context="PROFIL" [me]="me" + *ngIf="displayDeleteButton" >
diff --git a/packages/frontend/src/app/modules/usager-profil/components/pages/profil-dossier/profil-dossier.component.html b/packages/frontend/src/app/modules/usager-profil/components/pages/profil-dossier/profil-dossier.component.html index 4f31e91d0d..a8e3274945 100644 --- a/packages/frontend/src/app/modules/usager-profil/components/pages/profil-dossier/profil-dossier.component.html +++ b/packages/frontend/src/app/modules/usager-profil/components/pages/profil-dossier/profil-dossier.component.html @@ -16,11 +16,7 @@ >

État civil

diff --git a/packages/frontend/src/app/modules/usager-profil/components/pages/profil-general-section/profil-general-section.component.html b/packages/frontend/src/app/modules/usager-profil/components/pages/profil-general-section/profil-general-section.component.html index e25ff17988..3a4694ef72 100644 --- a/packages/frontend/src/app/modules/usager-profil/components/pages/profil-general-section/profil-general-section.component.html +++ b/packages/frontend/src/app/modules/usager-profil/components/pages/profil-general-section/profil-general-section.component.html @@ -455,6 +455,7 @@

Notes

diff --git a/packages/frontend/src/app/modules/usager-profil/components/pages/profil-historique/profil-historique.component.html b/packages/frontend/src/app/modules/usager-profil/components/pages/profil-historique/profil-historique.component.html index 37d207e5a5..1cd984f7bf 100644 --- a/packages/frontend/src/app/modules/usager-profil/components/pages/profil-historique/profil-historique.component.html +++ b/packages/frontend/src/app/modules/usager-profil/components/pages/profil-historique/profil-historique.component.html @@ -144,6 +144,7 @@

Historique du dossier

[usager]="usager" [me]="me" context="PROFIL" + *ngIf="displayDeleteButton" > diff --git a/packages/frontend/src/app/modules/usager-profil/components/profil-head/profil-head.component.html b/packages/frontend/src/app/modules/usager-profil/components/profil-head/profil-head.component.html index 77df8de442..5ddaf9a2fb 100644 --- a/packages/frontend/src/app/modules/usager-profil/components/profil-head/profil-head.component.html +++ b/packages/frontend/src/app/modules/usager-profil/components/profil-head/profil-head.component.html @@ -157,7 +157,6 @@

>, accès restreint - , onglet actif