Kaynağa Gözat

revision of the abilityUtils service

Olivier Massot 2 yıl önce
ebeveyn
işleme
0088bd2935
2 değiştirilmiş dosya ile 78 ekleme ve 50 silme
  1. 10 5
      pages/subscription.vue
  2. 68 45
      services/rights/abilityUtils.ts

+ 10 - 5
pages/subscription.vue

@@ -277,15 +277,20 @@ Page 'Mon abonnement'
   import {DolibarrAccount} from "~/models/Organization/DolibarrAccount";
   import {MobytUserStatus} from "~/models/Organization/MobytUserStatus";
   import {Ref} from "@vue/reactivity";
+  import {useAbilityUtils} from "~/composables/utils/useAbilityUtils";
+  import {useAccessProfileStore} from "~/stores/accessProfile";
 
-  const { can } = useAbility()
+  const ability = useAbility()
 
-  // onBeforeMount(() => {
-  //   if(!can('display', 'subscription_page'))
-  //     return navigateTo('/error')
-  // })
+  onBeforeMount(() => {
+    if(!ability.can('display', 'subscription_page'))
+      return navigateTo('/error')
+  })
 
   const showDolibarrPanel = computed(() => !dolibarrPending.value && dolibarrAccount.value && dolibarrAccount.value.bills.length > 0)
+
+  // On ouvre les panneaux dans le onMounted en attendant la résolution du bug : https://github.com/vuetifyjs/vuetify/issues/16427#issuecomment-1380927133
+  // TODO: quand le bug ci dessus est résolu, remplacer par `const openedPanels: Ref<Array<string>> = ref(['informations', 'bills', 'more_features'])`
   const openedPanels: Ref<Array<string>> = ref([])
   onMounted(() => {
     openedPanels.value = ['informations', 'bills', 'more_features']

+ 68 - 45
services/rights/abilityUtils.ts

@@ -102,7 +102,6 @@ class AbilityUtils {
                 abilities.push({ action, subject })
             }
         })
-
         return abilities
     }
 
@@ -114,11 +113,10 @@ class AbilityUtils {
      */
     hasConfigAbility(services: AnyJson) {
         const handlerMap: any = {
-            hasRole: (parameters: any) => this.hasRoles(parameters),
-            hasAbility: (parameters: any) => this.hasAbilities(parameters),
-            hasProfile: (parameters: any) => this.hasProfileAmong(parameters),
-            isAdminAccount: (parameters: any) => this.accessProfile.isAdminAccount,
+            hasAbility: (parameters: any) => this.hasAllAbilities(parameters),
+            hasProfile: (parameters: any) => parameters === null || this.hasAnyProfile(parameters),
             hasModule: (parameters: any) => this.hasModule(parameters),
+            isAdminAccount: (parameters: any) => this.accessProfile.isAdminAccount,
             isSchool: (parameters: any) => this.organizationProfile.isSchool,
             isArtist: (parameters: any) => this.organizationProfile.isArtist,
             isManagerProduct: (parameters: any) => this.organizationProfile.isManagerProduct,
@@ -129,6 +127,13 @@ class AbilityUtils {
             getWebsite: (parameters: any) => this.organizationProfile.getWebsite,
         }
 
+        // TODO: renommer les fonctions du handlerMap de la même façon que les fonctions hasAnyXxx, hasAllXxx, etc.
+        // TODO: revoir les fichiers yaml en fonction
+        // TODO: clarifier le fonctionnement du hasAbility (c'est très bizarre de tester des habilités alors qu'on est en train de les construire)
+        // TODO: extraire l'intérieur du useEach dans une méthode séparée pour clarifier l'algo
+        // TODO: voir pourquoi on a besoin d'accepter un param null pour le hasProfile?
+        // TODO: créer un outil pour simplifier le déboguage des droits
+
         let hasAbility = true
 
         useEach(services, (handlers: Array<{ function: string, parameters?: Array<any>, result?: any }>, service: string) => {
@@ -136,17 +141,14 @@ class AbilityUtils {
             useEach(handlers, (handler: { function: string, parameters?: Array<any>, result?: any }) => {
 
                 const expectedResult: boolean = handler.result ?? true;
-                const parametersArray = handler.parameters ?? []
+                const parameters = handler.parameters ?? []
 
-                useEach(parametersArray, (parameters: any) => {
-                    const actualResult = handlerMap[handler.function](parameters ?? null)
+                const actualResult = handlerMap[handler.function](parameters ?? null)
 
-                    if (actualResult !== expectedResult) {
-                        hasAbility = false
-                        return false
-                    }
-                })
-                if (!hasAbility) { return false }
+                if (actualResult !== expectedResult) {
+                    hasAbility = false
+                    return false
+                }
             })
             if (!hasAbility) { return false }
         })
@@ -154,28 +156,22 @@ class AbilityUtils {
     }
 
     /**
-     * Est-ce que l'utilisateur possède la ou les habilités
+     * Est-ce que l'utilisateur possède toutes les habilités passées en paramètre
      *
      * @param {Array<AbilitiesType>} abilities Habilités à tester
      * @return {boolean}
      */
-    hasAbilities(abilities: Array<AbilitiesType>|null): boolean{
-        useEach(abilities ?? [], (ability) => {
-            if (!this.ability.can(ability.action, ability.subject)) {
-                return false
-            }
-        })
-        return true
+    hasAllAbilities(abilities: Array<AbilitiesType>): boolean {
+        return abilities.every(ability => this.ability.can(ability.action, ability.subject))
     }
 
-
     /**
-     * Teste le profil d'un utilisateur
+     * Teste si l'utilisateur possède le profil donné
      *
-     * @param {string} profile : profile à tester
+     * @param {string} profile Profil à tester
      * @return {boolean}
      */
-    private testProfile(profile: string): boolean {
+    hasProfile(profile: string): boolean {
         const factory: {[key: string]: boolean|null} = {
             'admin': this.accessProfile.isAdmin,
             'administratifManager': this.accessProfile.isAdministratifManager,
@@ -198,16 +194,18 @@ class AbilityUtils {
      * @param {Array<string>} profiles Profils à tester
      * @return {boolean}
      */
-    hasProfileAmong (profiles: Array<string>|null): boolean {
-        if (null === profiles)
-            return true;
+    hasAnyProfile (profiles: Array<string>): boolean {
+        return profiles.some(p => this.hasProfile(p))
+    }
 
-        useEach(profiles, (profile) => {
-            if (this.testProfile(profile)) {
-                return true
-            }
-        })
-        return false
+    /**
+     * Retourne vrai si l'utilisateur connecté possède tous les profils passés en paramètre
+     *
+     * @param {Array<string>} profiles Profils à tester
+     * @return {boolean}
+     */
+    hasAllProfiles (profiles: Array<string>): boolean {
+        return profiles.every(p => this.hasProfile(p))
     }
 
     /**
@@ -216,23 +214,28 @@ class AbilityUtils {
      * @return {boolean}
      * @param role
      */
-    hasRole(role: string|null): boolean {
-        return role === null || this.accessProfile.roles.includes(role)
+    hasRole(role: string): boolean {
+        return this.accessProfile.roles.includes(role)
     }
 
     /**
-     * Est-ce que l'utilisateur possède tous les rôles donnés ?
+     * L'utilisateur possède-t-il au moins l'un des rôles donnés
      *
      * @return {boolean}
      * @param roles
      */
-    hasRoles(roles: Array<string>): boolean {
-        useEach(roles, (r: string) =>  {
-            if (!this.accessProfile.roles.includes(r)) {
-                return false
-            }
-        })
-        return true
+    hasAnyRole(roles: Array<string>): boolean {
+        return roles.some(r => this.hasRole(r))
+    }
+
+    /**
+     * L'utilisateur possède-t-il tous les rôles donnés
+     *
+     * @return {boolean}
+     * @param roles
+     */
+    hasAllRoles(roles: Array<string>): boolean {
+        return roles.every(r => this.hasRole(r))
     }
 
     /**
@@ -244,6 +247,26 @@ class AbilityUtils {
     hasModule(module: string): boolean {
         return this.organizationProfile.modules.includes(module)
     }
+
+    /**
+     * Est-ce que l'organisation possède au moins un des modules donnés
+     *
+     * @param modules
+     * @return {boolean}
+     */
+    hasAnyModule(modules: Array<string>): boolean {
+        return modules.some(r => this.hasModule(r))
+    }
+
+    /**
+     * Est-ce que l'organisation possède-t-il tous les modules donnés
+     *
+     * @param modules
+     * @return {boolean}
+     */
+    hasAllModules(modules: Array<string>): boolean {
+        return modules.every(r => this.hasModule(r))
+    }
 }
 
 export default AbilityUtils