From 0714bbab44bc481dbee3357658a4a6fc41ac5152 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20PAILHAREY?= <rpailharey@grandlyon.com>
Date: Thu, 30 May 2024 15:12:26 +0000
Subject: [PATCH] feat: simpler urls with permalinks

---
 .../deleted-structures.component.ts           |  2 +-
 .../administred-structures.component.html     |  4 +-
 .../admin-structures-list.component.ts        |  8 +--
 .../models/adminStructureList.interface.ts    |  1 +
 .../result-list/result-list.component.ts      |  7 +-
 src/app/app-routing.module.ts                 | 35 +++++-----
 src/app/carto/carto.component.ts              |  8 ++-
 src/app/footer/footer.component.html          |  2 +-
 .../form/footer-form/footer-form.component.ts |  2 +-
 .../form-view/form-view-routing.module.ts     | 12 ++--
 .../form/form-view/form-view.component.html   |  8 +--
 src/app/form/form-view/form-view.component.ts | 29 +++++----
 src/app/form/form-view/formType.enum.ts       |  9 +++
 .../form-view/guards/personalOffer.guard.ts   | 10 +--
 .../personal-offer-form.component.ts          |  2 +-
 .../orientation-form-view.component.ts        |  2 +-
 src/app/guards/auth.guard.ts                  |  4 +-
 src/app/guards/resetPasswordToken.guard.ts    |  2 +-
 src/app/guards/role.guard.ts                  |  8 ++-
 src/app/header/header.component.html          | 12 ++--
 src/app/header/header.component.ts            |  4 +-
 src/app/login/login.component.ts              |  8 +--
 src/app/models/owner.model.ts                 |  1 +
 src/app/models/structure.model.ts             |  1 +
 src/app/models/user.model.ts                  |  2 +
 .../newsletter-subscription.component.html    |  2 +-
 .../post-card/post-card.component.ts          |  2 +-
 .../post-details/post-details.component.ts    |  4 +-
 .../post-header/post-header.component.ts      |  2 +-
 src/app/post/models/post.model.ts             |  1 +
 src/app/post/post-routing.module.ts           |  4 +-
 src/app/post/services/post.service.ts         |  4 +-
 src/app/profile/edit/edit.component.ts        |  6 +-
 .../personal-offer-edition.component.ts       |  4 +-
 src/app/profile/profile-routing.module.ts     | 12 ++--
 .../personal-offer.component.ts               |  2 +-
 .../profile-structure.component.ts            | 13 ++--
 src/app/profile/profile.component.ts          | 18 ++---
 .../structure-edition-summary.component.ts    |  4 +-
 .../structures-management.component.ts        |  4 +-
 .../forgot-password.component.ts              |  2 +-
 src/app/resolvers/structure.resolver.ts       |  6 +-
 src/app/services/auth.service.ts              |  2 +-
 src/app/services/structure.service.ts         |  4 ++
 src/app/services/user.service.ts              |  5 +-
 .../member-card/member-card.component.ts      |  2 +-
 .../components/card/card.component.ts         |  5 +-
 .../structure-details.component.ts            | 39 ++++++-----
 .../structure-list-search.component.ts        |  5 +-
 .../structure-list/services/search.service.ts |  3 +-
 .../structure-list.component.ts               | 19 ++----
 .../structure-join.component.html             | 20 +++---
 .../structure-join.component.ts               | 18 +++--
 src/sitemap.xml                               | 65 +++++++++++--------
 54 files changed, 247 insertions(+), 213 deletions(-)

diff --git a/src/app/admin/components/deleted-structures/deleted-structures.component.ts b/src/app/admin/components/deleted-structures/deleted-structures.component.ts
index 03da0fb9d..2ef8c5594 100644
--- a/src/app/admin/components/deleted-structures/deleted-structures.component.ts
+++ b/src/app/admin/components/deleted-structures/deleted-structures.component.ts
@@ -65,7 +65,7 @@ export class DeletedStructuresComponent implements OnInit {
   }
 
   private renderLink(structure: Structure): string {
-    return `<a href="/acteurs?id=${structure._id}" target="_blank">${structure.structureName}</a>`;
+    return `<a href="/acteurs?structure=${structure.permalink}" target="_blank">${structure.structureName}</a>`;
   }
 
   private restoreStructure(structureId: string): void {
diff --git a/src/app/admin/components/manage-users/administred-structures/administred-structures.component.html b/src/app/admin/components/manage-users/administred-structures/administred-structures.component.html
index 1b32cce76..cb937d29d 100644
--- a/src/app/admin/components/manage-users/administred-structures/administred-structures.component.html
+++ b/src/app/admin/components/manage-users/administred-structures/administred-structures.component.html
@@ -1,5 +1,7 @@
 <div *ngIf="structures.data.structures && structures.data.structures.length !== 0">
   <p *ngFor="let structure of structures.data.structures">
-    <a *ngIf="structure" target="_blank" href="/acteurs?id={{ structure._id }}">{{ structure.structureName }}</a>
+    <a *ngIf="structure" target="_blank" href="/acteurs?structure={{ structure.permalink }}">{{
+      structure.structureName
+    }}</a>
   </p>
 </div>
diff --git a/src/app/admin/components/structures-list/admin-structures-list.component.ts b/src/app/admin/components/structures-list/admin-structures-list.component.ts
index dca6de719..3342277bf 100644
--- a/src/app/admin/components/structures-list/admin-structures-list.component.ts
+++ b/src/app/admin/components/structures-list/admin-structures-list.component.ts
@@ -1,6 +1,5 @@
 import { DatePipe } from '@angular/common';
 import { Component, OnInit } from '@angular/core';
-import { Router } from '@angular/router';
 import { ColDef } from 'ag-grid-community';
 import { finalize } from 'rxjs/operators';
 import { AdminStructure } from '../../models/adminStructureList.interface';
@@ -15,7 +14,6 @@ export class AdminStructuresListComponent implements OnInit {
   constructor(
     private adminService: AdminService,
     private datePipe: DatePipe,
-    private router: Router,
   ) {}
   public structuresClaimed: AdminStructure[];
   public structuresInClaim: AdminStructure[];
@@ -28,7 +26,7 @@ export class AdminStructuresListComponent implements OnInit {
   public columnDefs: ColDef<AdminStructure>[] = [
     {
       headerName: 'Structure',
-      cellRenderer: (params): string => this.renderLink(params.data.structureId, params.data.structureName),
+      cellRenderer: (params): string => this.renderLink(params.data),
       comparator(_, __, nodeA, nodeB): number {
         return nodeA.data.structureName.toLowerCase() > nodeB.data.structureName.toLocaleLowerCase() ? -1 : 1;
       },
@@ -59,7 +57,7 @@ export class AdminStructuresListComponent implements OnInit {
       });
   }
 
-  private renderLink(structureId: string, structureName: string): string {
-    return `<a href="/acteurs?id=${structureId}" target="_blank">${structureName}</a>`;
+  private renderLink(structure: AdminStructure): string {
+    return `<a href="/acteurs?structure=${structure.permalink}" target="_blank">${structure.structureName}</a>`;
   }
 }
diff --git a/src/app/admin/models/adminStructureList.interface.ts b/src/app/admin/models/adminStructureList.interface.ts
index 9a751bbb6..8229ee489 100644
--- a/src/app/admin/models/adminStructureList.interface.ts
+++ b/src/app/admin/models/adminStructureList.interface.ts
@@ -10,4 +10,5 @@ export interface AdminStructure {
   structureName: string;
   updatedAt: Date;
   isOutdated: boolean;
+  permalink: string;
 }
diff --git a/src/app/annuaire/result-list/result-list.component.ts b/src/app/annuaire/result-list/result-list.component.ts
index 152027e06..fd7d3f431 100644
--- a/src/app/annuaire/result-list/result-list.component.ts
+++ b/src/app/annuaire/result-list/result-list.component.ts
@@ -53,14 +53,11 @@ export class ResultListComponent implements OnChanges, AfterViewInit {
       }, 0);
     }
   }
-  public goToUser(userId: string): void {
-    this.router.navigateByUrl(`/profile/${userId}`);
-  }
   public goLogin(): void {
-    this.router.navigate(['/login'], { queryParams: { returnUrl: '/annuaire' } });
+    this.router.navigate(['/connexion'], { queryParams: { returnUrl: '/annuaire' } });
   }
   public goRegister(): void {
-    this.router.navigateByUrl('/form/account');
+    this.router.navigateByUrl('/formulaire/compte');
   }
   public resetFilters(): void {
     this.resetEvent.emit();
diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts
index 5e92142b2..b9bc19160 100644
--- a/src/app/app-routing.module.ts
+++ b/src/app/app-routing.module.ts
@@ -42,6 +42,10 @@ const routes: Routes = [
   {
     path: 'acteurs',
     title: buildTitle('Cartographie'),
+    runGuardsAndResolvers: 'always',
+    resolve: {
+      structure: StructureResolver,
+    },
     children: [
       {
         path: '',
@@ -51,14 +55,11 @@ const routes: Routes = [
         path: '',
         outlet: 'left-pane',
         component: StructureDetailsComponent,
-        resolve: {
-          structure: StructureResolver,
-        },
       },
     ],
   },
   {
-    path: 'login',
+    path: 'connexion',
     title: buildTitle('Connexion'),
     children: [
       {
@@ -78,7 +79,7 @@ const routes: Routes = [
     ],
   },
   {
-    path: 'legal-notice',
+    path: 'mentions-legales',
     title: buildTitle('Mentions légales'),
     children: [
       {
@@ -130,7 +131,7 @@ const routes: Routes = [
     ],
   },
   {
-    path: 'profile',
+    path: 'profil',
     title: buildTitle('Profil'),
     children: [
       {
@@ -142,6 +143,7 @@ const routes: Routes = [
         path: '',
         outlet: 'left-pane',
         data: { fullScreen: true },
+        runGuardsAndResolvers: 'always',
         component: StructureDetailsComponent,
         resolve: {
           structure: StructureResolver,
@@ -150,7 +152,7 @@ const routes: Routes = [
     ],
   },
   {
-    path: 'join-request/:id',
+    path: 'join-request/:permalink',
     children: [
       {
         path: '',
@@ -176,7 +178,7 @@ const routes: Routes = [
     ],
   },
   {
-    path: 'reset-password',
+    path: 'mot-de-passe-oublie',
     children: [
       {
         path: '',
@@ -197,7 +199,7 @@ const routes: Routes = [
     ],
   },
   {
-    path: 'newsletter-unsubscribe',
+    path: 'desabonnement-newsletter',
     children: [
       {
         path: '',
@@ -218,7 +220,7 @@ const routes: Routes = [
     ],
   },
   {
-    path: 'news',
+    path: 'actualites',
     title: buildTitle('Actualités'),
     children: [
       {
@@ -240,13 +242,17 @@ const routes: Routes = [
     ],
   },
   {
-    path: 'form',
+    path: 'formulaire',
     title: buildTitle(),
     loadChildren: () => import('./form/form-view/form-view.module').then((m) => m.FormViewModule),
   },
   {
     path: 'orientation',
     title: buildTitle('Orientation'),
+    runGuardsAndResolvers: 'always',
+    resolve: {
+      structure: StructureResolver,
+    },
     children: [
       {
         path: '',
@@ -257,19 +263,16 @@ const routes: Routes = [
         outlet: 'left-pane',
         data: { fullScreen: true, meeting: false },
         component: StructureDetailsComponent,
-        resolve: {
-          structure: StructureResolver,
-        },
       },
     ],
   },
   {
     path: 'home',
-    redirectTo: 'news',
+    redirectTo: 'actualites',
   },
   {
     path: '**',
-    redirectTo: 'news',
+    redirectTo: 'actualites',
   },
 ];
 
diff --git a/src/app/carto/carto.component.ts b/src/app/carto/carto.component.ts
index 54c79feab..e0a9b8048 100644
--- a/src/app/carto/carto.component.ts
+++ b/src/app/carto/carto.component.ts
@@ -56,9 +56,11 @@ export class CartoComponent implements OnInit {
       }
     }
 
-    if (history.state.data) {
-      this.currentStructure = new Structure(history.state.data);
-    }
+    this.activatedRoute.data.subscribe((data) => {
+      if (data.structure) {
+        this.currentStructure = new Structure(data.structure);
+      }
+    });
 
     this.meta.updateTag({
       name: 'description',
diff --git a/src/app/footer/footer.component.html b/src/app/footer/footer.component.html
index 358806c4b..abb538aad 100644
--- a/src/app/footer/footer.component.html
+++ b/src/app/footer/footer.component.html
@@ -1,6 +1,6 @@
 <footer class="footer">
   <div class="links">
-    <a class="clickable text-align-center" routerLink="/legal-notice" i18n>Mentions légales</a>
+    <a class="clickable text-align-center" routerLink="/mentions-legales" i18n>Mentions légales</a>
     <a class="clickable text-align-center" routerLink="/newsletter" i18n>Newsletter</a>
     <a class="clickable text-align-center" routerLink="/contact" i18n>Contact</a>
     <a class="clickable text-align-center" routerLink="/page/qui-sommes-nous" i18n>Qui sommes-nous ?</a>
diff --git a/src/app/form/footer-form/footer-form.component.ts b/src/app/form/footer-form/footer-form.component.ts
index e9dbe8ff9..daf0dea0a 100644
--- a/src/app/form/footer-form/footer-form.component.ts
+++ b/src/app/form/footer-form/footer-form.component.ts
@@ -61,7 +61,7 @@ export class FooterFormComponent {
   }
 
   public goToProfile(): void {
-    this.router.navigateByUrl('/profile');
+    this.router.navigateByUrl('/profil');
   }
 
   /**
diff --git a/src/app/form/form-view/form-view-routing.module.ts b/src/app/form/form-view/form-view-routing.module.ts
index 73f5ba2d1..73a3a4cde 100644
--- a/src/app/form/form-view/form-view-routing.module.ts
+++ b/src/app/form/form-view/form-view-routing.module.ts
@@ -15,7 +15,7 @@ import { StructureFormComponent } from './structure-form/structure-form.componen
 
 const routes: Routes = [
   {
-    path: 'structure/:id/:step',
+    path: 'structure/:permalink/:step',
     component: FormViewComponent,
     canActivate: [RoleGuard],
     data: { allowedRoles: [RouteRole.structureAdmin] },
@@ -24,7 +24,7 @@ const routes: Routes = [
     },
   },
   {
-    path: 'register/:id',
+    path: 'inscription/:id',
     component: FormViewComponent,
     canDeactivate: [DeactivateGuard],
     resolve: {
@@ -42,22 +42,22 @@ const routes: Routes = [
         component: StructureFormComponent,
       },
       {
-        path: 'profile',
+        path: 'profil',
         canActivate: [AuthGuard],
         component: ProfileFormComponent,
       },
       {
-        path: 'personaloffer',
+        path: 'offre-personnelle',
         canActivate: [AuthGuard, PersonalOfferGuard],
         component: PersonalOfferFormComponent,
       },
       {
-        path: 'account',
+        path: 'compte',
         component: AccountFormComponent,
       },
       {
         path: '**',
-        redirectTo: 'account',
+        redirectTo: 'compte',
       },
     ],
   },
diff --git a/src/app/form/form-view/form-view.component.html b/src/app/form/form-view/form-view.component.html
index a4ee5a09a..052a59bcb 100644
--- a/src/app/form/form-view/form-view.component.html
+++ b/src/app/form/form-view/form-view.component.html
@@ -18,7 +18,7 @@
   />
   <div class="page">
     <app-account-form
-      *ngIf="formType[routeParam] === formType.account || formType[this.routeParam] === formType.register"
+      *ngIf="routeParam === formTypeParam.account || routeParam === formTypeParam.register"
       [nbSteps]="nbSteps"
       [accountForm]="accountForm"
       [currentStep]="currentPage"
@@ -27,7 +27,7 @@
       (pageValid)="validatePage($event)"
     />
     <app-profile-form
-      *ngIf="formType[routeParam] === formType.profile"
+      *ngIf="routeParam === formTypeParam.profile"
       [nbSteps]="nbSteps"
       [profileForm]="profileForm"
       [currentStep]="currentPage"
@@ -35,7 +35,7 @@
       (pageValid)="validatePage($event)"
     />
     <app-structure-form
-      *ngIf="formType[routeParam] === formType.structure"
+      *ngIf="routeParam === formTypeParam.structure"
       [nbSteps]="nbSteps"
       [structure]="structure"
       [structureForm]="structureForm"
@@ -48,7 +48,7 @@
       (setEditStep)="setCurrentStep($event)"
     />
     <app-personal-offer-form
-      *ngIf="formType[routeParam] === formType.personaloffer && structure"
+      *ngIf="routeParam === formTypeParam.personaloffer && structure"
       [nbSteps]="nbSteps"
       [personalOfferForm]="personalOfferForm"
       [currentStep]="currentPage"
diff --git a/src/app/form/form-view/form-view.component.ts b/src/app/form/form-view/form-view.component.ts
index 7cff6e41f..2db4a1406 100644
--- a/src/app/form/form-view/form-view.component.ts
+++ b/src/app/form/form-view/form-view.component.ts
@@ -18,7 +18,7 @@ import { FormUtils } from '../../utils/formUtils';
 import { Utils } from '../../utils/utils';
 import { stepType } from '../step.type';
 import { accountFormStep } from './account-form/accountFormStep.enum';
-import { formType } from './formType.enum';
+import { formType, formTypeParam } from './formType.enum';
 import { personalOfferFormStep } from './personal-offer-form/personalOfferFormStep.enum';
 import { profileFormStep } from './profile-form/profileFormStep.enum';
 import { structureFormStep } from './structure-form/structureFormStep.enum';
@@ -31,6 +31,7 @@ import { structureFormStep } from './structure-form/structureFormStep.enum';
 export class FormViewComponent implements OnInit, AfterViewInit {
   public routeParam: string;
   public formType = formType;
+  public formTypeParam = formTypeParam;
   public currentPage: stepType;
   public currentFormType: formType;
   public currentForm: UntypedFormGroup;
@@ -135,14 +136,14 @@ export class FormViewComponent implements OnInit, AfterViewInit {
     const structureFormSteps = Object.keys(structureFormStep).length / 2 - 1;
     const personalOfferFormSteps = Object.keys(personalOfferFormStep).length / 2 - 1;
     const totalFormSteps = profileFormSteps + structureFormSteps + personalOfferFormSteps;
-    if (formType[this.routeParam] === formType.account) {
+    if (this.routeParam === formTypeParam.account) {
       this.nbSteps = 3;
       this.currentPage = accountFormStep.accountInfo;
       this.currentFormType = formType.account;
       this.createAccountForm();
       this.currentForm = this.accountForm;
     }
-    if (formType[this.routeParam] === formType.register) {
+    if (this.routeParam === formTypeParam.register) {
       this.nbSteps = 3;
       this.currentPage = accountFormStep.accountInfo;
       this.currentFormType = formType.account;
@@ -155,14 +156,14 @@ export class FormViewComponent implements OnInit, AfterViewInit {
         }
       });
     }
-    if (formType[this.routeParam] === formType.profile) {
+    if (this.routeParam === formTypeParam.profile) {
       this.nbSteps = totalFormSteps;
       this.currentPage = profileFormStep.profileBeginningInfo;
       this.currentFormType = formType.profile;
       this.createProfileForm();
       this.currentForm = this.profileForm;
     }
-    if (formType[this.routeParam] === formType.structure) {
+    if (this.routeParam === formTypeParam.structure) {
       if (!this.isEditMode) {
         this.nbSteps = structureFormSteps;
         this.currentPage = structureFormStep.structureChoice;
@@ -178,7 +179,7 @@ export class FormViewComponent implements OnInit, AfterViewInit {
         }
       }
     }
-    if (formType[this.routeParam] === formType.personaloffer) {
+    if (this.routeParam === formTypeParam.personaloffer) {
       this.nbSteps = personalOfferFormSteps;
       this.currentPage = personalOfferFormStep.personalOfferAccompaniment;
       this.currentFormType = formType.personaloffer;
@@ -299,7 +300,7 @@ export class FormViewComponent implements OnInit, AfterViewInit {
           const user = await this.profileService.getProfile();
           if (user.job?.hasPersonalOffer) {
             this.previousSteps = 0;
-            this.router.navigateByUrl('form/personaloffer');
+            this.router.navigateByUrl('formulaire/offre-personnelle');
           } else {
             this.router.navigateByUrl('/');
           }
@@ -317,7 +318,7 @@ export class FormViewComponent implements OnInit, AfterViewInit {
           this.saveStructureForm();
         }
         if (type.formStep === structureFormStep.noStructure) {
-          this.router.navigateByUrl('/profile');
+          this.router.navigateByUrl('/profil');
         }
         break;
       case formType.personaloffer:
@@ -355,13 +356,13 @@ export class FormViewComponent implements OnInit, AfterViewInit {
           this.structureService.getStructure(this.profile.structuresLink[0]).subscribe((structure) => {
             this.structure = new Structure(structure);
             this.previousSteps = 0;
-            this.router.navigateByUrl('form/personaloffer');
+            this.router.navigateByUrl('formulaire/offre-personnelle');
           });
         } else {
-          this.router.navigateByUrl('/profile');
+          this.router.navigateByUrl('/profil');
         }
       } else {
-        this.router.navigateByUrl('form/structure');
+        this.router.navigateByUrl('formulaire/structure');
       }
     });
   }
@@ -369,7 +370,7 @@ export class FormViewComponent implements OnInit, AfterViewInit {
   public savePersonalOfferForm(): void {
     this.personalOfferService.createPersonalOffer(this.structure._id, this.personalOfferForm.value).subscribe(() => {
       if (this.hasOtherPersonalOffer) {
-        this.router.navigateByUrl('form/structure');
+        this.router.navigateByUrl('formulaire/structure');
       } else {
         this.nextPage();
       }
@@ -386,9 +387,9 @@ export class FormViewComponent implements OnInit, AfterViewInit {
       if (user.job?.hasPersonalOffer) {
         this.structure = struct;
         this.previousSteps = 0;
-        this.router.navigateByUrl('form/personaloffer');
+        this.router.navigateByUrl('formulaire/offre-personnelle');
       } else {
-        this.router.navigateByUrl(`acteurs?id=${struct._id}`);
+        this.router.navigateByUrl(`acteurs?structure=${struct.permalink}`);
       }
     });
   }
diff --git a/src/app/form/form-view/formType.enum.ts b/src/app/form/form-view/formType.enum.ts
index 41d8aa290..01dee2beb 100644
--- a/src/app/form/form-view/formType.enum.ts
+++ b/src/app/form/form-view/formType.enum.ts
@@ -6,3 +6,12 @@ export enum formType {
   register,
   orientation,
 }
+
+export enum formTypeParam {
+  structure = 'structure',
+  profile = 'profil',
+  personaloffer = 'offre-personnelle',
+  account = 'compte',
+  register = 'inscription',
+  orientation = 'orientation',
+}
diff --git a/src/app/form/form-view/guards/personalOffer.guard.ts b/src/app/form/form-view/guards/personalOffer.guard.ts
index 0652dbdcf..239a15de8 100644
--- a/src/app/form/form-view/guards/personalOffer.guard.ts
+++ b/src/app/form/form-view/guards/personalOffer.guard.ts
@@ -1,5 +1,5 @@
-import { ActivatedRouteSnapshot, Router, UrlTree } from '@angular/router';
 import { Injectable } from '@angular/core';
+import { ActivatedRouteSnapshot, Router, UrlTree } from '@angular/router';
 /**
  * Guard to assert that we are coming from the structure form. Otherwise redirect to home
  */
@@ -9,10 +9,10 @@ export class PersonalOfferGuard {
 
   canActivate(route: ActivatedRouteSnapshot): UrlTree | boolean {
     if (
-      route.routeConfig.path === 'personaloffer' &&
-      (this.router.routerState.snapshot.url === '/profile' ||
-        this.router.routerState.snapshot.url === '/form/profile' ||
-        this.router.routerState.snapshot.url === '/form/structure' ||
+      route.routeConfig.path === 'offre-personnelle' &&
+      (this.router.routerState.snapshot.url === '/profil' ||
+        this.router.routerState.snapshot.url === '/formulaire/profil' ||
+        this.router.routerState.snapshot.url === '/formulaire/structure' ||
         this.router.routerState.snapshot.url.includes('/join-request/'))
     ) {
       return true;
diff --git a/src/app/form/form-view/personal-offer-form/personal-offer-form.component.ts b/src/app/form/form-view/personal-offer-form/personal-offer-form.component.ts
index 1db582e46..d1a829e3a 100644
--- a/src/app/form/form-view/personal-offer-form/personal-offer-form.component.ts
+++ b/src/app/form/form-view/personal-offer-form/personal-offer-form.component.ts
@@ -77,6 +77,6 @@ export class PersonalOfferFormComponent implements OnChanges, OnInit {
   }
 
   public goToProfile(): void {
-    this.router.navigateByUrl('/profile');
+    this.router.navigateByUrl('/profil');
   }
 }
diff --git a/src/app/form/orientation-form-view/orientation-form-view.component.ts b/src/app/form/orientation-form-view/orientation-form-view.component.ts
index aab181800..991c0b6dc 100644
--- a/src/app/form/orientation-form-view/orientation-form-view.component.ts
+++ b/src/app/form/orientation-form-view/orientation-form-view.component.ts
@@ -756,6 +756,6 @@ export class OrientationFormViewComponent implements OnInit, AfterContentChecked
     }
   }
   public goLogin(): void {
-    this.router.navigate(['/login'], { queryParams: { returnUrl: '/orientation' } });
+    this.router.navigate(['/connexion'], { queryParams: { returnUrl: '/orientation' } });
   }
 }
diff --git a/src/app/guards/auth.guard.ts b/src/app/guards/auth.guard.ts
index 59f8b6b48..351fae1e5 100644
--- a/src/app/guards/auth.guard.ts
+++ b/src/app/guards/auth.guard.ts
@@ -1,5 +1,5 @@
-import { ActivatedRouteSnapshot, Router, RouterStateSnapshot } from '@angular/router';
 import { Injectable } from '@angular/core';
+import { ActivatedRouteSnapshot, Router, RouterStateSnapshot } from '@angular/router';
 import { AuthService } from '../services/auth.service';
 /**
  * Guard to assert that we are logged in. Otherwise redirect to home
@@ -15,7 +15,7 @@ export class AuthGuard {
     if (this.authService.isLoggedIn()) {
       return true;
     }
-    this.router.navigate(['/login'], { queryParams: { returnUrl: state.url } });
+    this.router.navigate(['/connexion'], { queryParams: { returnUrl: state.url } });
     return false;
   }
 }
diff --git a/src/app/guards/resetPasswordToken.guard.ts b/src/app/guards/resetPasswordToken.guard.ts
index 77f212b1b..49f20272f 100644
--- a/src/app/guards/resetPasswordToken.guard.ts
+++ b/src/app/guards/resetPasswordToken.guard.ts
@@ -18,7 +18,7 @@ export class ResetPasswordTokenGuard {
     if (token) {
       const validToken = await firstValueFrom(this.authService.checkResetPasswordToken(token));
       if (!validToken) {
-        this.router.navigate(['/login']);
+        this.router.navigate(['/connexion']);
         return false;
       }
     }
diff --git a/src/app/guards/role.guard.ts b/src/app/guards/role.guard.ts
index 216256537..36631ab12 100644
--- a/src/app/guards/role.guard.ts
+++ b/src/app/guards/role.guard.ts
@@ -1,7 +1,9 @@
 import { Injectable } from '@angular/core';
 import { ActivatedRouteSnapshot, Router, UrlTree } from '@angular/router';
+import { lastValueFrom } from 'rxjs';
 import { ProfileService } from '../profile/services/profile.service';
 import { AuthService } from '../services/auth.service';
+import { StructureService } from '../services/structure.service';
 import { RouteRole } from '../shared/enum/routeRole.enum';
 /**
  * Guard to assert that a user is authorized to access route.
@@ -13,6 +15,7 @@ export class RoleGuard {
     private router: Router,
     private profileService: ProfileService,
     private authService: AuthService,
+    private structureService: StructureService,
   ) {}
 
   async canActivate(route: ActivatedRouteSnapshot): Promise<UrlTree | boolean> {
@@ -21,8 +24,9 @@ export class RoleGuard {
     if (this.authService.isLoggedIn()) {
       if (this.profileService.isAdmin()) return true;
       if (allowedRoles.includes(RouteRole.structureAdmin)) {
-        const structureId = route.params.id;
-        if (await this.profileService.isLinkedToStructure(structureId)) {
+        const structurePermalink = route.params.permalink;
+        const structure = await lastValueFrom(this.structureService.getStructureByPermalink(structurePermalink));
+        if (await this.profileService.isLinkedToStructure(structure._id)) {
           return true;
         }
       }
diff --git a/src/app/header/header.component.html b/src/app/header/header.component.html
index 028020ab1..256280bcc 100644
--- a/src/app/header/header.component.html
+++ b/src/app/header/header.component.html
@@ -39,12 +39,12 @@
   <div class="rightHeader">
     <div class="menuItems" role="menu">
       <a
-        routerLink="/news"
+        routerLink="/actualites"
         role="menuitem"
         title="Actualités"
         [routerLinkActive]="'active'"
         i18n
-        [attr.aria-current]="isActive('/news')"
+        [attr.aria-current]="isActive('/actualites')"
       >
         Actualités
       </a>
@@ -124,10 +124,10 @@
     </div>
     <div class="links">
       <a
-        routerLink="/news"
+        routerLink="/actualites"
         role="menuitem"
         [routerLinkActive]="'active'"
-        [attr.aria-current]="isActive('/news')"
+        [attr.aria-current]="isActive('/actualites')"
         (click)="closeMenu()"
         i18n
         >Actualités</a
@@ -178,11 +178,11 @@
         >Administration</a
       >
       <a
-        routerLink="/legal-notice"
+        routerLink="/mentions-legales"
         role="menuitem"
         i18n
         [routerLinkActive]="'active'"
-        [attr.aria-current]="isActive('/legal-notice')"
+        [attr.aria-current]="isActive('/mentions-legales')"
         (click)="closeMenu()"
         >Mentions légales</a
       >
diff --git a/src/app/header/header.component.ts b/src/app/header/header.component.ts
index 2c3ae29c3..44e3e333d 100644
--- a/src/app/header/header.component.ts
+++ b/src/app/header/header.component.ts
@@ -59,7 +59,7 @@ export class HeaderComponent {
   }
   public goToProfile(): void {
     this.showProfileMenu = false;
-    this.router.navigateByUrl('/profile');
+    this.router.navigateByUrl('/profil');
   }
 
   public openMenu(): void {
@@ -96,7 +96,7 @@ export class HeaderComponent {
     return false;
   }
   public goToLoginPage(): void {
-    this.router.navigateByUrl('login');
+    this.router.navigateByUrl('connexion');
   }
   public get isAdmin(): boolean {
     return this.profileService.isAdmin();
diff --git a/src/app/login/login.component.ts b/src/app/login/login.component.ts
index dc9450ed9..5f4844aec 100644
--- a/src/app/login/login.component.ts
+++ b/src/app/login/login.component.ts
@@ -71,7 +71,7 @@ export class LoginComponent implements OnInit {
   }
 
   public switchToResetPassword(): void {
-    this.router.navigate(['/reset-password']);
+    this.router.navigate(['/mot-de-passe-oublie']);
   }
 
   public async onSubmit(): Promise<void> {
@@ -88,12 +88,12 @@ export class LoginComponent implements OnInit {
       await lastValueFrom(this.authService.login(this.f.email.value, this.f.password.value));
 
       if (this.isWelcome) {
-        this.router.navigateByUrl('form/profile');
+        this.router.navigateByUrl('formulaire/profil');
       } else {
         if (this.returnUrl) {
           this.router.navigateByUrl(this.returnUrl);
         } else {
-          this.router.navigateByUrl('news');
+          this.router.navigateByUrl('actualites');
         }
       }
     } catch (e) {
@@ -107,7 +107,7 @@ export class LoginComponent implements OnInit {
   }
 
   public goToAccountCreation(): void {
-    this.router.navigateByUrl('form/account');
+    this.router.navigateByUrl('formulaire/compte');
   }
 
   public getLoginStatusText(): string {
diff --git a/src/app/models/owner.model.ts b/src/app/models/owner.model.ts
index 89c4226c1..3152b228d 100644
--- a/src/app/models/owner.model.ts
+++ b/src/app/models/owner.model.ts
@@ -5,6 +5,7 @@ import { PersonalOffer } from './personalOffer.model';
 export class Owner {
   email: string;
   _id: string;
+  permalink: string;
   name: string;
   surname: string;
   job?: Job;
diff --git a/src/app/models/structure.model.ts b/src/app/models/structure.model.ts
index bd9df1f41..c25ad38b3 100644
--- a/src/app/models/structure.model.ts
+++ b/src/app/models/structure.model.ts
@@ -57,6 +57,7 @@ export class Structure {
   public alreadySelected? = false;
   public hasNoUserDN?: boolean = null;
   public hasUserWithAppointmentDN?: boolean = null;
+  public permalink = '';
 
   constructor(obj?: any) {
     Object.assign(this, obj, {
diff --git a/src/app/models/user.model.ts b/src/app/models/user.model.ts
index f8aaddc78..26577e5f6 100644
--- a/src/app/models/user.model.ts
+++ b/src/app/models/user.model.ts
@@ -6,6 +6,7 @@ import { PersonalOffer } from './personalOffer.model';
 export class User {
   _id: string;
   id: string;
+  permalink: string;
   createdAt: Date;
   email: string;
   name: string;
@@ -31,6 +32,7 @@ export class User {
 }
 export class UserAnnuary {
   _id: string;
+  permalink: string;
   name: string;
   surname: string;
   job: Job;
diff --git a/src/app/newsletter-subscription/newsletter-subscription.component.html b/src/app/newsletter-subscription/newsletter-subscription.component.html
index ca7ff6703..a61319183 100644
--- a/src/app/newsletter-subscription/newsletter-subscription.component.html
+++ b/src/app/newsletter-subscription/newsletter-subscription.component.html
@@ -28,7 +28,7 @@
 
     <div class="link">
       <a *ngIf="!subscriptionMod" routerLink="/newsletter">Inscription</a>
-      <a *ngIf="subscriptionMod" routerLink="/newsletter-unsubscribe">Désabonnement</a>
+      <a *ngIf="subscriptionMod" routerLink="/desabonnement-newsletter">Désabonnement</a>
     </div>
   </div>
 </form>
diff --git a/src/app/post/components/post-card/post-card.component.ts b/src/app/post/components/post-card/post-card.component.ts
index 52cf5b045..1844d30fd 100644
--- a/src/app/post/components/post-card/post-card.component.ts
+++ b/src/app/post/components/post-card/post-card.component.ts
@@ -15,7 +15,7 @@ export class PostCardComponent {
   constructor(private router: Router) {}
 
   public showDetails(post: Post): void {
-    this.router.navigateByUrl('news/details/' + post.id, { state: { data: post } });
+    this.router.navigateByUrl('actualites/details/' + post.slug, { state: { data: post } });
   }
 
   public isAppelAProjet(): boolean {
diff --git a/src/app/post/components/post-details/post-details.component.ts b/src/app/post/components/post-details/post-details.component.ts
index 0131c534f..f429423bc 100644
--- a/src/app/post/components/post-details/post-details.component.ts
+++ b/src/app/post/components/post-details/post-details.component.ts
@@ -29,8 +29,8 @@ export class PostDetailsComponent implements OnInit {
       this.post = new Post(history.state.data);
       this.post.safeHtml = this.sanitizer.bypassSecurityTrustHtml(this.post.html);
     } else {
-      const postId = this.activatedRoute.snapshot.paramMap.get('id');
-      this.postService.getPost(postId).subscribe((post) => {
+      const postSlug = this.activatedRoute.snapshot.paramMap.get('slug');
+      this.postService.getPost(postSlug).subscribe((post) => {
         this.post = post.posts[0];
         this.post.safeHtml = this.sanitizer.bypassSecurityTrustHtml(this.post.html);
       });
diff --git a/src/app/post/components/post-header/post-header.component.ts b/src/app/post/components/post-header/post-header.component.ts
index 953fc9aac..fd5c0a482 100644
--- a/src/app/post/components/post-header/post-header.component.ts
+++ b/src/app/post/components/post-header/post-header.component.ts
@@ -73,7 +73,7 @@ export class PostHeaderComponent implements OnInit {
   }
 
   private setQueryParam(): void {
-    this.router.navigate(['/news'], {
+    this.router.navigate(['/actualites'], {
       relativeTo: this.route,
       queryParams: {
         mainTag: this.getMainTag(),
diff --git a/src/app/post/models/post.model.ts b/src/app/post/models/post.model.ts
index 9ba0fe3e6..00ba5988e 100644
--- a/src/app/post/models/post.model.ts
+++ b/src/app/post/models/post.model.ts
@@ -14,6 +14,7 @@ export class Post {
   author: string;
   tags: Tag[];
   safeHtml: SafeHtml;
+  slug: string;
 
   constructor(obj?: any) {
     Object.assign(this, obj);
diff --git a/src/app/post/post-routing.module.ts b/src/app/post/post-routing.module.ts
index c95c0ba7c..a0c999376 100644
--- a/src/app/post/post-routing.module.ts
+++ b/src/app/post/post-routing.module.ts
@@ -1,5 +1,5 @@
 import { NgModule } from '@angular/core';
-import { Routes, RouterModule } from '@angular/router';
+import { RouterModule, Routes } from '@angular/router';
 import { PostDetailsComponent } from './components/post-details/post-details.component';
 import { PostListComponent } from './components/post-list/post-list.component';
 import { NewsComponent } from './news.component';
@@ -18,7 +18,7 @@ const routes: Routes = [
         component: PostListComponent,
       },
       {
-        path: 'details/:id',
+        path: 'details/:slug',
         component: PostDetailsComponent,
       },
     ],
diff --git a/src/app/post/services/post.service.ts b/src/app/post/services/post.service.ts
index 3e1d886d8..d35d23885 100644
--- a/src/app/post/services/post.service.ts
+++ b/src/app/post/services/post.service.ts
@@ -13,8 +13,8 @@ export class PostService {
   private readonly baseUrl = 'api/posts';
   constructor(private http: HttpClient) {}
 
-  public getPost(idPost: string): Observable<PostWithMeta> {
-    return this.http.get<PostWithMeta>(`${this.baseUrl}/` + idPost).pipe(
+  public getPost(postSlug: string): Observable<PostWithMeta> {
+    return this.http.get<PostWithMeta>(`${this.baseUrl}/${postSlug}`).pipe(
       map((item: PostWithMeta) => {
         item.posts.forEach((post) => this.addAuthorToPost(post));
         return new PostWithMeta(item);
diff --git a/src/app/profile/edit/edit.component.ts b/src/app/profile/edit/edit.component.ts
index a41ff417a..0ab8834a2 100644
--- a/src/app/profile/edit/edit.component.ts
+++ b/src/app/profile/edit/edit.component.ts
@@ -281,7 +281,7 @@ export class EditComponent implements OnInit {
         localStorage.setItem('user', JSON.stringify(updatedUser));
         this.authService.userSubject.next(updatedUser);
         this.updateInitialProfile();
-        this.router.navigate(['/profile']);
+        this.router.navigate(['/profil']);
       });
   }
 
@@ -299,7 +299,7 @@ export class EditComponent implements OnInit {
       .updateProfile(this.selectedEmployer.name, this.selectedJob.name, this.selectedRdvChoice)
       .subscribe({
         next: () => {
-          this.router.navigate(['/profile']);
+          this.router.navigate(['/profil']);
           this.notificationService.showSuccess('Vos informations ont bien été enregistrées');
         },
         error: () => {
@@ -316,7 +316,7 @@ export class EditComponent implements OnInit {
     this.profileService.updateDescription(this.userProfile.description).subscribe(() => {
       this.notificationService.showSuccess('Vos informations ont bien été enregistrées');
       this.updateInitialProfile();
-      this.router.navigate(['/profile']);
+      this.router.navigate(['/profil']);
     });
   }
 
diff --git a/src/app/profile/personal-offer-edition/personal-offer-edition.component.ts b/src/app/profile/personal-offer-edition/personal-offer-edition.component.ts
index 99e37853a..28461141e 100644
--- a/src/app/profile/personal-offer-edition/personal-offer-edition.component.ts
+++ b/src/app/profile/personal-offer-edition/personal-offer-edition.component.ts
@@ -107,7 +107,7 @@ export class PersonalOfferEditionComponent implements OnInit {
           this.initialPersonalOffer = this.personalOfferForm.value;
           this.personalOfferForm.markAsPristine();
         });
-      this.router.navigateByUrl('/profile');
+      this.router.navigateByUrl('/profil');
     }
   }
 
@@ -137,7 +137,7 @@ export class PersonalOfferEditionComponent implements OnInit {
         this.notificationService.showError(`${err.error.message}`, 'Une erreur est survenue');
       },
     );
-    this.router.navigate(['/profile']);
+    this.router.navigate(['/profil']);
   }
 
   public goBack(): void {
diff --git a/src/app/profile/profile-routing.module.ts b/src/app/profile/profile-routing.module.ts
index ecd292897..9f3dbb5ec 100644
--- a/src/app/profile/profile-routing.module.ts
+++ b/src/app/profile/profile-routing.module.ts
@@ -23,13 +23,13 @@ const footerOutletRoute: Route = {
 
 const routes: Routes = [
   {
-    path: 'edit',
+    path: 'edition',
     canActivate: [AuthGuard],
     canDeactivate: [DeactivateGuard],
     component: EditComponent,
   },
   {
-    path: 'structures-management',
+    path: 'gestion-structures',
     component: StructuresManagementComponent,
   },
   footerOutletRoute,
@@ -41,13 +41,13 @@ const routes: Routes = [
         component: ProfileComponent,
       },
       {
-        path: ':id',
+        path: ':userPermalink',
         component: ProfileComponent,
       },
     ],
   },
   {
-    path: 'edit-structure/:id',
+    path: 'edition-structure/:permalink',
     component: StructureEditionSummaryComponent,
     canActivate: [RoleGuard],
     data: { allowedRoles: [RouteRole.structureAdmin] },
@@ -56,7 +56,7 @@ const routes: Routes = [
     },
   },
   {
-    path: 'edit-personal-offer/:id',
+    path: 'edition-offre-personnelle/:id',
     component: PersonalOfferEditionComponent,
     canActivate: [IsPersonalOfferOwnerGuard],
     resolve: {
@@ -64,7 +64,7 @@ const routes: Routes = [
     },
   },
   {
-    path: 'structure-members-management/:id',
+    path: 'gestion-membres/:permalink',
     component: StructureMembersManagementComponent,
     canActivate: [RoleGuard],
     data: { allowedRoles: [RouteRole.structureAdmin] },
diff --git a/src/app/profile/profile-structure/personal-offer/personal-offer.component.ts b/src/app/profile/profile-structure/personal-offer/personal-offer.component.ts
index 526d64fc4..1fde1ca4c 100644
--- a/src/app/profile/profile-structure/personal-offer/personal-offer.component.ts
+++ b/src/app/profile/profile-structure/personal-offer/personal-offer.component.ts
@@ -15,7 +15,7 @@ export class PersonalOfferComponent {
   constructor(private router: Router) {}
 
   public goToEditPersonalOffer(): void {
-    this.router.navigateByUrl(`/profile/edit-personal-offer/${this.personalOffer._id}`, {
+    this.router.navigateByUrl(`/profil/edition-offre-personnelle/${this.personalOffer._id}`, {
       state: { structureName: this.structureName },
     });
   }
diff --git a/src/app/profile/profile-structure/profile-structure.component.ts b/src/app/profile/profile-structure/profile-structure.component.ts
index cf3673974..6648500aa 100644
--- a/src/app/profile/profile-structure/profile-structure.component.ts
+++ b/src/app/profile/profile-structure/profile-structure.component.ts
@@ -1,6 +1,6 @@
 import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
 import { FormGroup } from '@angular/forms';
-import { ActivatedRoute, Router } from '@angular/router';
+import { Router } from '@angular/router';
 import { DateTime } from 'luxon';
 import { Structure } from '../../models/structure.model';
 import { StructureWithOwners } from '../../models/structureWithOwners.model';
@@ -23,7 +23,7 @@ export class ProfileStructureComponent implements OnInit {
   @Input() public isPublic: boolean;
   @Input() public isPending = false;
   @Input() public joinRequestDate: string | null;
-  @Output() cancelJoin = new EventEmitter<any>();
+  @Output() cancelJoin = new EventEmitter<string>();
 
   public membersWithJobWithPO: User[] = [];
   public structureForm: FormGroup;
@@ -33,7 +33,6 @@ export class ProfileStructureComponent implements OnInit {
   public personalOffer: PersonalOffer;
 
   constructor(
-    private route: ActivatedRoute,
     private router: Router,
     private userService: UserService,
     private searchService: SearchService,
@@ -82,16 +81,16 @@ export class ProfileStructureComponent implements OnInit {
     this.router.navigateByUrl('/home');
   }
   public goToDetail(): void {
-    this.router.navigate(['/profile'], { queryParams: { id: this.structure._id } });
+    this.router.navigate([], { queryParams: { structure: this.structure.permalink } });
   }
   public goToOffer(): void {
-    this.router.navigate(['/form/personaloffer'], { state: { structure: this.structure } });
+    this.router.navigate(['/formulaire/offre-personnelle'], { state: { structure: this.structure } });
   }
   public goToEditStructure(): void {
-    this.router.navigateByUrl(`/profile/edit-structure/${this.structure._id}`);
+    this.router.navigateByUrl(`/profil/edition-structure/${this.structure.permalink}`);
   }
   public goToStructureMembersManagement(): void {
-    this.router.navigateByUrl(`/profile/structure-members-management/${this.structure._id}`);
+    this.router.navigateByUrl(`/profil/gestion-membres/${this.structure.permalink}`);
   }
   public isValid(): boolean {
     return this.structureForm.valid;
diff --git a/src/app/profile/profile.component.ts b/src/app/profile/profile.component.ts
index 86f1a4969..7e899f0c5 100644
--- a/src/app/profile/profile.component.ts
+++ b/src/app/profile/profile.component.ts
@@ -35,11 +35,11 @@ export class ProfileComponent implements OnInit {
 
   ngOnInit(): void {
     this.route.params.subscribe((urlParams) => {
-      const userId = urlParams.id ? urlParams.id : '';
-      if (userId) {
+      const userPermalink = urlParams.userPermalink || '';
+      if (userPermalink) {
         this.isPublic = true;
         this.userService
-          .getUser(userId)
+          .getUserByPermalink(userPermalink)
           .pipe(
             map((res) => res),
             catchError(() => {
@@ -106,20 +106,16 @@ export class ProfileComponent implements OnInit {
   }
   public goToProfileEdit(tabToSelect?: string): void {
     if (tabToSelect) {
-      this.router.navigateByUrl('/profile/edit', { state: { data: tabToSelect } });
+      this.router.navigateByUrl('/profil/edition', { state: { data: tabToSelect } });
     } else {
-      this.router.navigateByUrl('/profile/edit');
+      this.router.navigateByUrl('/profil/edition');
     }
   }
   public goToStructuresManagement(): void {
-    this.router.navigateByUrl('/profile/structures-management');
+    this.router.navigateByUrl('/profil/gestion-structures');
   }
   public goToFormStructure(): void {
-    this.router.navigateByUrl('/form/structure');
-  }
-
-  public addStructure(): void {
-    this.router.navigateByUrl('/form/structure');
+    this.router.navigateByUrl('/formulaire/structure');
   }
   public cancelJoin(idStructure: string): void {
     this.userService.cancelJoin(idStructure, this.userProfile._id).subscribe({
diff --git a/src/app/profile/structure-edition-summary/structure-edition-summary.component.ts b/src/app/profile/structure-edition-summary/structure-edition-summary.component.ts
index 9a9b89aaf..c775ab218 100644
--- a/src/app/profile/structure-edition-summary/structure-edition-summary.component.ts
+++ b/src/app/profile/structure-edition-summary/structure-edition-summary.component.ts
@@ -94,7 +94,7 @@ export class StructureEditionSummaryComponent implements OnInit {
   }
 
   public goToEdit(step: structureFormStep): void {
-    this.router.navigate(['/form/structure', this.structure._id, structureFormStep[step]]);
+    this.router.navigate(['/formulaire/structure', this.structure.permalink, structureFormStep[step]]);
   }
 
   public isFormValid(): boolean {
@@ -181,6 +181,6 @@ export class StructureEditionSummaryComponent implements OnInit {
   }
 
   public goToManageMembers(): void {
-    this.router.navigate([`/profile/structure-members-management/${this.structure._id}`]);
+    this.router.navigate([`/profil/gestion-membres/${this.structure.permalink}`]);
   }
 }
diff --git a/src/app/profile/structures-management/structures-management.component.ts b/src/app/profile/structures-management/structures-management.component.ts
index 193e936fa..7be96b72b 100644
--- a/src/app/profile/structures-management/structures-management.component.ts
+++ b/src/app/profile/structures-management/structures-management.component.ts
@@ -38,12 +38,12 @@ export class StructuresManagementComponent implements OnInit {
     history.back();
   }
   public goToFormStructure(): void {
-    this.router.navigateByUrl('/form/structure');
+    this.router.navigateByUrl('/formulaire/structure');
   }
 
   private shouldRedirect(structures: StructureWithOwners[] | Observable<any>[]): void {
     if (!structures.length) {
-      this.router.navigate(['/profile']);
+      this.router.navigate(['/profil']);
     }
   }
 
diff --git a/src/app/reset-password/forgot-password.component.ts b/src/app/reset-password/forgot-password.component.ts
index 81fd6e5d9..8f3e89dc9 100644
--- a/src/app/reset-password/forgot-password.component.ts
+++ b/src/app/reset-password/forgot-password.component.ts
@@ -54,6 +54,6 @@ export class ForgotPasswordComponent implements OnInit {
   }
 
   public goLogin(): void {
-    this.router.navigateByUrl('/login');
+    this.router.navigateByUrl('/connexion');
   }
 }
diff --git a/src/app/resolvers/structure.resolver.ts b/src/app/resolvers/structure.resolver.ts
index 14fdc214f..fab997a45 100644
--- a/src/app/resolvers/structure.resolver.ts
+++ b/src/app/resolvers/structure.resolver.ts
@@ -20,11 +20,11 @@ export class StructureResolver {
   ) {}
 
   resolve(route: ActivatedRouteSnapshot): Observable<Structure> {
-    const structureId = route.params.id;
+    const structurePermalink = route.params.permalink || route.queryParams.structure;
 
-    if (structureId) {
+    if (structurePermalink) {
       forkJoin({
-        structure: this.structureService.getStructure(structureId).pipe(
+        structure: this.structureService.getStructureByPermalink(structurePermalink).pipe(
           map((res) => res),
           catchError(() => {
             this.router.navigate(['/home']);
diff --git a/src/app/services/auth.service.ts b/src/app/services/auth.service.ts
index d303885a1..6e4382da4 100644
--- a/src/app/services/auth.service.ts
+++ b/src/app/services/auth.service.ts
@@ -36,7 +36,7 @@ export class AuthService {
   public logout(): void {
     localStorage.removeItem('user');
     this.userSubject.next(null);
-    window.location.replace('/home');
+    window.location.replace('/actualites');
   }
 
   public isLoggedIn(): boolean {
diff --git a/src/app/services/structure.service.ts b/src/app/services/structure.service.ts
index 8671c4251..848b1e654 100644
--- a/src/app/services/structure.service.ts
+++ b/src/app/services/structure.service.ts
@@ -40,6 +40,10 @@ export class StructureService {
     return this.http.get<Structure>(`${this.baseUrl}/${id}`);
   }
 
+  public getStructureByPermalink(permalink: string): Observable<Structure> {
+    return this.http.get<Structure>(`${this.baseUrl}/permalink/${permalink}`);
+  }
+
   public delete(id: string): Observable<Structure> {
     return this.http.delete<Structure>(`${this.baseUrl}/${id}`);
   }
diff --git a/src/app/services/user.service.ts b/src/app/services/user.service.ts
index 1bcb892b6..795bd3d31 100644
--- a/src/app/services/user.service.ts
+++ b/src/app/services/user.service.ts
@@ -14,12 +14,15 @@ export class UserService {
   public getUser(userId: string): Observable<User> {
     return this.http.get<User>(`${this.baseUrl}/${userId}`);
   }
+  public getUserByPermalink(permalink: string): Observable<User> {
+    return this.http.get<User>(`${this.baseUrl}/permalink/${permalink}`);
+  }
   public joinStructure(id: string, email: string): Observable<Structure> {
     return this.http.post<any>(`${this.baseUrl}/join-request/${id}`, { email });
   }
 
   public validateJoinStructure(token: string, status: string): Observable<any> {
-    return this.http.get<any>(`${this.baseUrl}/join-validate/${token}/${status}`);
+    return this.http.get<Structure>(`${this.baseUrl}/join-validate/${token}/${status}`);
   }
   public cancelJoin(idStructure: string, idUser: string): Observable<any> {
     return this.http.get<any>(`${this.baseUrl}/join-cancel/${idStructure}/${idUser}
diff --git a/src/app/shared/components/member-card/member-card.component.ts b/src/app/shared/components/member-card/member-card.component.ts
index 07a0849ab..bbc3c7c02 100644
--- a/src/app/shared/components/member-card/member-card.component.ts
+++ b/src/app/shared/components/member-card/member-card.component.ts
@@ -67,7 +67,7 @@ export class MemberCardComponent implements OnInit {
   cardClicked(): void {
     if (this.redirectToProfile) {
       this.windowScrollService.scrollYToPreserve.next(this.windowScrollService.scrollY.value);
-      this.router.navigateByUrl(`/profile/${this.member._id}`);
+      this.router.navigateByUrl(`/profil/${this.member.permalink}`);
     } else if (this.showRadioButton) {
       this.selectedCard.emit(this.member._id);
     }
diff --git a/src/app/structure-list/components/card/card.component.ts b/src/app/structure-list/components/card/card.component.ts
index c1571a72d..22d42859b 100644
--- a/src/app/structure-list/components/card/card.component.ts
+++ b/src/app/structure-list/components/card/card.component.ts
@@ -65,13 +65,12 @@ export class CardComponent implements OnInit {
   public cardClicked(): void {
     if (this.redirectToStructure) {
       this.showDetails.emit(this.structure);
-      const queryString = this.route.snapshot.queryParamMap.get('search');
       this.router.navigate([], {
         relativeTo: this.route,
         queryParams: {
-          id: this.structure._id,
-          ...(queryString && { search: queryString }),
+          structure: this.structure.permalink,
         },
+        queryParamsHandling: 'merge',
         state: { isOrientation: this.isOrientation },
       });
     } else {
diff --git a/src/app/structure-list/components/structure-details/structure-details.component.ts b/src/app/structure-list/components/structure-details/structure-details.component.ts
index d28eabfb8..c42966542 100644
--- a/src/app/structure-list/components/structure-details/structure-details.component.ts
+++ b/src/app/structure-list/components/structure-details/structure-details.component.ts
@@ -73,23 +73,19 @@ export class StructureDetailsComponent implements OnInit {
   ) {}
 
   async ngOnInit(): Promise<void> {
-    this.route.queryParams.subscribe((queryParams) => {
-      if (queryParams.id) {
-        this.structureService.getStructure(queryParams.id).subscribe((structure) => {
-          this.structure = new Structure(structure);
-          this.profileIsLinkedToStructure(this.structure._id);
-          this.isLoading = true;
-          this.initForm();
-        });
+    this.route.data.subscribe((data) => {
+      if (data.structure) {
+        this.structure = new Structure(data.structure);
+        this.profileIsLinkedToStructure(this.structure._id);
+        this.isLoading = true;
+        this.initForm();
       } else {
         this.structure = null;
       }
-      this.showButtons = !history.state.isOrientation;
-    });
-    this.route.data.subscribe((data) => {
       if (data.fullScreen) {
         this.fullScreen = true;
       }
+      this.showButtons = !history.state.isOrientation;
     });
   }
 
@@ -138,7 +134,12 @@ export class StructureDetailsComponent implements OnInit {
   }
 
   public close(): void {
-    this.router.navigate([]);
+    this.router.navigate([], {
+      queryParams: {
+        structure: null,
+      },
+      queryParamsHandling: 'merge',
+    });
   }
 
   public print(): void {
@@ -165,7 +166,9 @@ export class StructureDetailsComponent implements OnInit {
 
   public handleJoin(): void {
     if (!this.userIsLoggedIn()) {
-      this.router.navigate(['login'], { queryParams: { returnUrl: `acteurs?id=${this.structure._id}` } });
+      this.router.navigate(['connexion'], {
+        queryParams: { returnUrl: `acteurs?structure=${this.structure.permalink}` },
+      });
       return;
     }
 
@@ -179,7 +182,7 @@ export class StructureDetailsComponent implements OnInit {
   }
 
   public handleModify(): void {
-    this.router.navigate(['profile', 'edit-structure', this.structure._id]);
+    this.router.navigate(['profil', 'edition-structure', this.structure.permalink]);
   }
 
   public deleteStructure(shouldDelete: boolean): void {
@@ -202,7 +205,9 @@ export class StructureDetailsComponent implements OnInit {
       this.structureService
         .claimStructureWithAccount(this.structure._id, this.authService.userValue.username)
         .subscribe();
-      this.router.navigate(['join-request', this.structure._id], { state: { isClaimed: !this.structure.hasNoUserDN } });
+      this.router.navigate(['join-request', this.structure.permalink], {
+        state: { isClaimed: !this.structure.hasNoUserDN },
+      });
     }
   }
 
@@ -210,7 +215,9 @@ export class StructureDetailsComponent implements OnInit {
     this.toggleJoinModal();
     if (shouldJoin) {
       this.usersService.joinStructure(this.structure._id, this.authService.userValue.username).subscribe();
-      this.router.navigate(['join-request', this.structure._id], { state: { isClaimed: !this.structure.hasNoUserDN } });
+      this.router.navigate(['join-request', this.structure.permalink], {
+        state: { isClaimed: !this.structure.hasNoUserDN },
+      });
     }
   }
 
diff --git a/src/app/structure-list/components/structure-list-search/structure-list-search.component.ts b/src/app/structure-list/components/structure-list-search/structure-list-search.component.ts
index de56f479e..0f136ba8e 100644
--- a/src/app/structure-list/components/structure-list-search/structure-list-search.component.ts
+++ b/src/app/structure-list/components/structure-list-search/structure-list-search.component.ts
@@ -44,7 +44,6 @@ export class StructureListSearchComponent implements OnInit {
   constructor(
     public searchService: SearchService,
     private activatedRoute: ActivatedRoute,
-    private route: ActivatedRoute,
     private router: Router,
     private elementRef: ElementRef,
   ) {}
@@ -98,7 +97,7 @@ export class StructureListSearchComponent implements OnInit {
   public updateUrlParams(filters: Filter[]): void {
     // No url update if the page is displaying structure details, because it must keep the url with the structure id, neither for orientation
     if (
-      (this.activatedRoute.snapshot.queryParams.id && filters.length === 0) ||
+      (this.activatedRoute.snapshot.queryParams.structure && filters.length === 0) ||
       this.router.url.startsWith('/orientation')
     ) {
       return;
@@ -116,7 +115,7 @@ export class StructureListSearchComponent implements OnInit {
     this.checkedModulesFilter = this.utils.convertFiltersToModule(filters);
 
     this.router.navigate(['./'], {
-      relativeTo: this.route,
+      relativeTo: this.activatedRoute,
       queryParams: queryString,
     });
   }
diff --git a/src/app/structure-list/services/search.service.ts b/src/app/structure-list/services/search.service.ts
index f8e23213c..c0a3fd494 100644
--- a/src/app/structure-list/services/search.service.ts
+++ b/src/app/structure-list/services/search.service.ts
@@ -34,13 +34,14 @@ export class SearchService {
     jobsGroup?: string[],
     employers?: string[],
   ): Promise<SearchResults> {
-    return lastValueFrom(
+    const users = await lastValueFrom(
       this.http.post<SearchResults>(`/api/userRegistry/?search=${searchTerm}`, {
         jobsGroup,
         employer: employers,
         page,
       }),
     );
+    return users;
   }
   public getUserRegistryCount(): Observable<number> {
     return this.http.get<any>(`/api/userRegistry/count`).pipe();
diff --git a/src/app/structure-list/structure-list.component.ts b/src/app/structure-list/structure-list.component.ts
index 50f12a4aa..19745a4f3 100644
--- a/src/app/structure-list/structure-list.component.ts
+++ b/src/app/structure-list/structure-list.component.ts
@@ -3,7 +3,6 @@ import { ActivatedRoute, Router } from '@angular/router';
 import { GeoJson } from '../map/models/geojson.model';
 import { Structure } from '../models/structure.model';
 import { AuthService } from '../services/auth.service';
-import { StructureService } from '../services/structure.service';
 import { PrintService } from '../shared/service/print.service';
 
 @Component({
@@ -30,17 +29,12 @@ export class StructureListComponent implements OnChanges, OnInit {
   constructor(
     private route: ActivatedRoute,
     private router: Router,
-    private structureService: StructureService,
     private authService: AuthService,
     private printService: PrintService,
   ) {
-    this.route.queryParams.subscribe((queryParams) => {
-      if (queryParams.id) {
-        if (!this.structure) {
-          this.structureService.getStructure(queryParams.id).subscribe((s) => {
-            this.showDetails(new Structure(s));
-          });
-        }
+    this.route.data.subscribe((data) => {
+      if (data.structure) {
+        this.showDetails(new Structure(data.structure));
       } else {
         this.closeDetails();
       }
@@ -59,8 +53,9 @@ export class StructureListComponent implements OnChanges, OnInit {
       this.router.navigate([], {
         relativeTo: this.route,
         queryParams: {
-          id: this.selectedStructure._id,
+          structure: this.selectedStructure.permalink,
         },
+        queryParamsHandling: 'merge',
       });
     }
     if (changes.structureList) {
@@ -91,9 +86,9 @@ export class StructureListComponent implements OnChanges, OnInit {
 
   public addStructure(): void {
     if (!this.authService.isLoggedIn()) {
-      this.router.navigateByUrl('/login');
+      this.router.navigateByUrl('/connexion');
     } else {
-      this.router.navigateByUrl('/form/structure');
+      this.router.navigateByUrl('/formulaire/structure');
     }
   }
 
diff --git a/src/app/structure/structure-join/structure-join.component.html b/src/app/structure/structure-join/structure-join.component.html
index 825848740..67f2d7894 100644
--- a/src/app/structure/structure-join/structure-join.component.html
+++ b/src/app/structure/structure-join/structure-join.component.html
@@ -20,35 +20,35 @@
   <ng-container *ngIf="!structureName && !isLoading && validationToken">
     <div class="container">
       <div class="page">
-        <img *ngIf="error" src="../../../assets/form/structureNeutral.svg" alt="join error" />
+        <img *ngIf="errorStatus" src="../../../assets/form/structureNeutral.svg" alt="join error" />
         <img
-          *ngIf="!error && isStructureJoinValidated === 'true'"
+          *ngIf="!errorStatus && isStructureJoinValidated === 'true'"
           src="../../../assets/form/structureCreated.svg"
           alt="join accepted"
         />
         <img
-          *ngIf="!error && isStructureJoinValidated === 'false'"
+          *ngIf="!errorStatus && isStructureJoinValidated === 'false'"
           src="../../../assets/form/structureNegatif.svg"
           alt="join refused"
         />
-        <h2 *ngIf="error && error === 404">
+        <h2 *ngIf="errorStatus && errorStatus === 404">
           {{ errorEnum.Other }}
         </h2>
-        <h2 *ngIf="error && error === 403">
+        <h2 *ngIf="errorStatus && errorStatus === 403">
           {{ errorEnum.Expired }}
         </h2>
-        <h2 *ngIf="error && error === 422">
+        <h2 *ngIf="errorStatus && errorStatus === 422">
           {{ errorEnum.AlreadyLinked }}
         </h2>
-        <h2 *ngIf="this.structureJoinedId && !error">
+        <h2 *ngIf="this.structureJoined && !errorStatus">
           L'utilisateur a été {{ isStructureJoinValidated === 'true' ? 'accepté' : 'refusé' }} dans la structure.
         </h2>
-        <div *ngIf="this.structureJoinedId && !error" class="subtitle">
+        <div *ngIf="this.structureJoined && !errorStatus" class="subtitle">
           Vous avez {{ isStructureJoinValidated === 'true' ? 'accepté' : 'refusé' }} la demande d'ajout dans la
           structure
-          {{ structureJoinedName }}
+          {{ structureJoined.structureName }}
         </div>
-        <div *ngIf="error && (error === 403 || error === 422)" class="subtitle">
+        <div *ngIf="errorStatus && (errorStatus === 403 || errorStatus === 422)" class="subtitle">
           Il semblerait que la demande d’adhésion ait déjà été traitée ou que le mail soit expiré.
         </div>
       </div>
diff --git a/src/app/structure/structure-join/structure-join.component.ts b/src/app/structure/structure-join/structure-join.component.ts
index d441729c3..5180bf1c8 100644
--- a/src/app/structure/structure-join/structure-join.component.ts
+++ b/src/app/structure/structure-join/structure-join.component.ts
@@ -20,9 +20,8 @@ export class StructureJoinComponent implements OnInit {
   public isStructureJoinValidated = null;
   public validationToken = null;
   public isLoading: boolean;
-  public structureJoinedId: string;
-  public structureJoinedName: string;
-  public error: any;
+  public structureJoined: Structure;
+  public errorStatus: number;
   public errorEnum = JoinErrors;
 
   constructor(
@@ -52,11 +51,10 @@ export class StructureJoinComponent implements OnInit {
     if (this.isStructureJoinValidated !== null && this.validationToken) {
       this.usersService.validateJoinStructure(this.validationToken, this.isStructureJoinValidated).subscribe({
         next: (res) => {
-          this.structureJoinedId = res.id;
-          this.structureJoinedName = res.name;
+          this.structureJoined = res;
         },
         error: (err) => {
-          this.error = err.status;
+          this.errorStatus = err.status;
           console.error(err);
           this.isLoading = false;
         },
@@ -68,10 +66,10 @@ export class StructureJoinComponent implements OnInit {
   public handleFinish(): void {
     this.routerListener.goToPreviousUrl();
   }
-  public handleCallback(): any {
-    if (this.structureJoinedId) {
-      return this.router.navigateByUrl(`/acteurs?id=${this.structureJoinedId}`);
+  public handleCallback(): void {
+    if (this.structureJoined) {
+      this.router.navigateByUrl(`/acteurs?structure=${this.structureJoined.permalink}`);
     }
-    return this.router.navigateByUrl(`/acteurs`);
+    this.router.navigateByUrl(`/acteurs`);
   }
 }
diff --git a/src/sitemap.xml b/src/sitemap.xml
index 2b2ff2cc9..42905c49d 100644
--- a/src/sitemap.xml
+++ b/src/sitemap.xml
@@ -1,34 +1,45 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<urlset
-      xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
-      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-      xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9
-            http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
-<!-- created with Free Online Sitemap Generator www.xml-sitemaps.com -->
+<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
+  <url>
+    <loc>https://resin.grandlyon.com/</loc>
+    <priority>1.00</priority>
+    <lastmod>2024-05-28T15:47:00+00:00</lastmod>
+  </url>
 
+  <url>
+    <loc>https://resin.grandlyon.com/actualites</loc>
+    <priority>0.80</priority>
+    <lastmod>2024-05-28T15:47:00+00:00</lastmod>
+  </url>
 
-<url>
-  <loc>https://resin.grandlyon.com/</loc>
-  <priority>1.00</priority>
-  <lastmod>2021-05-04T13:28:32+00:00</lastmod>
-</url>
+  <url>
+    <loc>https://resin.grandlyon.com/acteurs</loc>
+    <priority>0.80</priority>
+    <lastmod>2024-05-28T15:47:00+00:00</lastmod>
+  </url>
 
-<url>
-  <loc>https://resin.grandlyon.com/news</loc>
-  <priority>0.80</priority>
-  <lastmod>2021-05-04T13:28:32+00:00</lastmod>
-</url>
+  <url>
+    <loc>https://resin.grandlyon.com/orientation</loc>
+    <priority>0.80</priority>
+    <lastmod>2024-05-28T15:47:00+00:00</lastmod>
+  </url>
 
-<url>
-  <loc>https://resin.grandlyon.com/acteurs</loc>
-  <priority>0.80</priority>
-  <lastmod>2021-05-04T13:28:32+00:00</lastmod>
-</url>
+  <url>
+    <loc>https://resin.grandlyon.com/newsletter</loc>
+    <priority>0.64</priority>
+    <lastmod>2024-05-28T15:47:00+00:00</lastmod>
+  </url>
 
-<url>
-  <loc>https://resin.grandlyon.com/page/qui-sommes-nous</loc>
-  <priority>0.64</priority>
-  <lastmod>2022-01-04T15:28:32+00:00</lastmod>
-</url>
+  <url>
+    <loc>https://resin.grandlyon.com/mentions-legales</loc>
+    <priority>0.64</priority>
+    <lastmod>2024-05-28T15:47:00+00:00</lastmod>
+  </url>
 
-</urlset>
+  <url>
+    <loc>https://resin.grandlyon.com/page/qui-sommes-nous</loc>
+    <priority>0.64</priority>
+    <lastmod>2024-05-28T15:47:00+00:00</lastmod>
+  </url>
+
+</urlset>
\ No newline at end of file
-- 
GitLab