Olivier Massot 2 лет назад
Родитель
Сommit
78c85ca1d3
1 измененных файлов с 43 добавлено и 42 удалено
  1. 43 42
      services/rights/roleUtils.ts

+ 43 - 42
services/rights/roleUtils.ts

@@ -42,11 +42,18 @@ const rolesToChange: Array<string> = [
   'ROLE_ONLINEREGISTRATION_ADMINISTRATION_VIEW'
 ]
 
+const actions = ['VIEW', 'MANAGE', 'REFERENCE']
+
 const actionMap: AnyJson = {
   '': 'manage',
   _VIEW: 'read'
 }
 
+interface Role {
+  subject: string
+  action: 'VIEW' | 'MANAGE' | 'REFERENCE' | ''
+}
+
 /**
  * Classe permettant de mener des opérations sur les rôles
  */
@@ -63,7 +70,7 @@ class RoleUtils {
     if (!profileName.match(/^[A-Z_]+$/)) {
       throw new Error('invalid role name')
     }
-    // TODO: actuellement, passer un profil ne corresondant à aucun rôle ne lèvera aucune erreur, et se contentera de
+    // TODO: actuellement, passer un profil ne correspondant à aucun rôle ne lèvera aucune erreur, et se contentera de
     //       retourner false; ce serait pas mal de lever une erreur, ce ne serait pas normal de demander un rôle inexistant
     return roles.includes('ROLE_' + profileName + '_CORE')
   }
@@ -81,30 +88,38 @@ class RoleUtils {
   }
 
   /**
-   * Fix en attendant la migration complète, quelques rôles disposent d'underscore en trop, on corrige cela...
+   * Parse une chaine de caractère décrivant un rôle applicatif
    *
-   * TODO: remove after complete migration
-   *
-   * @param {Array<string>} roles
-   * @return {Array<string>}
+   * @param role
    */
-  static transformUnderscoreToHyphen (roles: Array<string>): Array<string> {
-    // TODO: clarifier le fonctionnement de cette méthode et de la regex, qu'est-ce qui sépare le groupe 2 et 3 au final?
-    const regex = /(ROLE_)([A-Z]*_[A-Z]*)([A-Z_]*)*/i
-
-    let match
-    roles = roles.map((role) => {
-      if (rolesToChange.includes(role)) {
-        if ((match = regex.exec(role)) !== null) {
-          const role = match[1]
-          const subject = match[2].replace('_', '-')
-          const action = match[3]
-          return role + subject + (action || '')
-        }
-      }
-      return role
-    })
-    return roles
+  static parseRole(role: string): Role {
+    const parts = role.split('_')
+
+    if (parts[0] !== 'ROLE') {
+      throw new Error('can not parse role')
+    }
+    parts.shift()
+
+    let action: 'VIEW' | 'MANAGE' | 'REFERENCE' | '' = ''
+    if (actions.includes(parts[-1])) {
+      // @ts-ignore
+      action = parts.pop() ?? ''
+    }
+
+    const subject = parts.join('-')
+
+    return { subject, action }
+  }
+
+  static roleToString(role: Role) {
+    return ['ROLE', role.subject, role.action].filter((s: string) => s.length > 0).join('_')
+  }
+
+  static roleToAbility(role: Role): AbilitiesType {
+    return {
+      action: actionMap[role.action],
+      subject: role.subject.toLowerCase()
+    }
   }
 
   /**
@@ -121,25 +136,11 @@ class RoleUtils {
   static rolesToAbilities (roles: Array<string>): [] | Array<AbilitiesType> {
     const abilities:Array<AbilitiesType> = []
 
-    roles = RoleUtils.transformUnderscoreToHyphen(roles)
-
-    // TODO: on pourrait peut-être faciliter la lecture en réécrivant la regex en `ROLE_([A-Z-]*)(_[A-Z]+)?`, ou
-    //       même en faisant un simple split sur le '_'
-    const regex = /(ROLE_)([A-Z-]*)([_A-Z]*)/i
-    let match
-
-    _.each(roles, (role) => {
-      if ((match = regex.exec(role)) !== null) {
-        const subject = match[2]
-        const actionName = match[3] ?? ''
-        const action = actionMap[actionName]
-
-        if (subject && typeof action !== 'undefined') {
-          abilities.push({
-            action: action,
-            subject: subject.toLowerCase()
-          })
-        }
+    _.each(roles, (role: string) => {
+      const parsed: Role | null= RoleUtils.parseRole(role)
+
+      if (parsed.subject && typeof parsed.action !== 'undefined') {
+        abilities.push(RoleUtils.roleToAbility(parsed))
       }
     })