Ver código fonte

v8-5075_fixes_after_tests_2

Olivier Massot 2 anos atrás
pai
commit
58424a85e7

+ 4 - 0
components/Layout/Header/Menu.vue

@@ -125,6 +125,10 @@ const btn = ref(null)
     padding: 0;
   }
 
+  .v-list-item {
+    width: 100%;
+  }
+
   .header-menu .v-list .v-list-item:last-child {
     border-bottom: none;
   }

+ 13 - 6
components/Layout/Header/Notification.vue

@@ -251,14 +251,21 @@ const download = (link: string) => {
   if (accessProfileStore.id === null) {
     throw new Error('Current access id is null')
   }
-  const url_parts: Array<string> = link.split('/api');
+  // TODO: passer cette logique dans un service ; tester ; voir si possible de réunir avec composables/utils/useDownloadFile.ts
 
-  if(accessProfileStore.originalAccess)
-    url_parts[0] = UrlUtils.join('api', String(accessProfileStore.originalAccess.id), String(accessProfileStore.id))
-  else
-    url_parts[0] = UrlUtils.join('api', String(accessProfileStore.id))
+  const path: string = link.split('/api')[1];
 
-  window.open(UrlUtils.join(runtimeConfig.baseUrlLegacy, url_parts.join('')));
+  // En switch : https://api.test5.opentalent.fr/api/{accessId}/{switchId}/files/{fileId}/download
+  // Sans switch : https://local.api.opentalent.fr/api/{accessId}/files/{fileId}/download
+  const url = UrlUtils.join(
+      runtimeConfig.baseUrlLegacy,
+      'api',
+      String(accessProfileStore.id),
+      String(accessProfileStore.switchId || ''),
+      path
+  )
+
+  window.open(url);
 }
 
 

+ 1 - 1
config/abilities/pages/myAccount.yaml

@@ -68,7 +68,7 @@
     action: 'display'
     conditions:
       - { function: organizationHasAnyModule, parameters: ['GeneralConfig'] }
-      - { function: accessHasAnyProfile, parameters: ['admin', 'administratifManager', 'pedagogicManager', 'financialManager'] }
+      - { function: accessHasAnyProfile, parameters: ['admin', 'administratifManager', 'pedagogicManager', 'financialManager', 'caMember'] }
 
   my_bills_page:
     action: 'display'

+ 82 - 0
doc/abilities.md

@@ -0,0 +1,82 @@
+# Abilities
+
+### Principe de base
+
+La gestion des droits se base sur la librairie [@casl/ability](https://casl.js.org/v6/en/) et génère un ensemble de 
+droits (abilities), par exemple le droit d'afficher une page.
+
+Ces droits dépendent de deux choses :
+
+- Les modules du logiciel possédés par l'organisation
+- Les rôles de l'utilisateur dans cette organisation (y compris d'éventuels droits personnalisés)
+
+Par la suite, on pourra tester les droits d'un utilisateur à effectuer une action en faisant par exemple : 
+
+      if(!ability.can('display', 'subscription_page')) {
+          throw new Error('Forbidden')
+      }
+
+
+### Fonctionnement
+
+#### Les rôles de l'utilisateur
+
+Les rôles de l'utilisateur sont récupérés auprès de l'API. Ils peuvent être de deux natures :
+
+- rôle en tant que fonction (`ROLE_CA`, `ROLE_MEMBER`, ...)
+- rôle lié à un droit particulier (`ROLE_GENERAL_CONFIG`, `ROLE_USERS`, ...)
+
+#### Les fichiers de configuration
+
+L'ensemble des droits est défini dans les fichiers de configuration `./config/abilities`
+
+Chaque entrée est constituée : 
+
+- d'un nom
+- d'une action associée (`display` ou `manage`)
+- et éventuellement d'une ou plusieurs conditions
+
+Exemple :
+
+    adherent_list_page:
+        action: 'display'
+        conditions:
+        - { function: organizationHasAnyModule, parameters: ['Users'] }
+        - { function: organizationIsShowAdherentList }
+        - { function: accessHasAnyProfile, parameters: ['member'] }
+
+
+#### Le plugin ability.ts
+
+Le plugin `plugins/ability.ts` :
+
+1. récupère les profils de l'access et de l'organisation
+2. instancie le service AbilityBuilder
+3. lui injecte les deux profils récupérés plus haut
+4. puis créé un listener qui appellera la méthode `buildAbilities` de ce service à chaque mise à jour du profil de l'organisation
+
+
+#### Le service AbilityBuilder
+
+Ce service fait appel tour à tour à deux méthodes `buildAbilitiesFromRoles` et `buildAbilitiesFromConfig`
+
+La première fait appel à son tour au service `RoleUtils` pour convertir tous les rôles (hors rôles liés à une fonction,
+par ex "Membre du CA") en droits. Ainsi un rôle `ROLE_EXAMENS` deviendra un droit `{subject: 'examen', action: 'manage'}`
+et un rôle deviendra un droits `{subject: 'billing_administration', action: 'display'}`
+
+La seconde construit les droits à partir des fichiers de configuration qui définissent les conditions d'accès aux 
+différents droits (voir plus haut). Ces conditions sont testées de diverses manières selon leur nature. Par exemple, 
+la condition `accessIsAdminAccount` deviendra un test sur `accessProfile.isAdminAccount`.
+
+Une fois construit, ces droits sont passés au service MongoAbility de la librairie Casl.
+
+#### Utilisation
+
+A partir de là, on pourra tester les droits d'un utilisateur dans une page ou un composable à l'aide de la commande 
+`ability.can(action, subject)`. 
+
+Cette méthode sera ainsi appelée en en-tête de la section script de chaque page, et pour chaque entrée des menus.
+
+
+
+

+ 0 - 2
models/Core/Notification.ts

@@ -30,6 +30,4 @@ export default class Notification extends ApiModel {
 
   @Attr({})
   declare notificationUsers: Array<string>
-
-
 }

+ 2 - 0
stores/accessProfile.ts

@@ -108,6 +108,8 @@ export const useAccessProfileStore = defineStore('accessProfile', () => {
     historical.value = profile.historical
     isAdminAccess.value = profile.isAdminAccess
 
+    // TODO: pqoi est-ce qu'on ne conserve pas les roles fonction et qu'on ne fait pas de ces méthodes des computed?
+    //       est-ce que ce ne serait pas plus intuitif? si on fait ça, attention à maj l'abilityBuilder
     isAdmin.value = RoleUtils.isA('ADMIN', profileRoles)
     isAdministratifManager.value = RoleUtils.isA('ADMINISTRATIF_MANAGER', profileRoles)
     isPedagogicManager.value = RoleUtils.isA('PEDAGOGICS_MANAGER', profileRoles)