abilitiesUtils.ts 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. import {$accessProfile} from "@/services/profile/accessProfile"
  2. import {$organizationProfile} from "@/services/profile/organizationProfile"
  3. import {$roleUtils} from "~/services/rights/roleUtils";
  4. import {AbilitiesType, AnyJson, AnyStore} from "~/types/types";
  5. import {Ability} from "@casl/ability";
  6. import {$yamlParser} from "~/services/utils/yamlParser";
  7. import * as _ from "lodash";
  8. /**
  9. * @category Services/droits
  10. * @class AbilitiesUtils
  11. * Classe permettant de mener des opérations sur les abilités
  12. */
  13. class AbilitiesUtils {
  14. private $store: AnyStore = {} as AnyStore
  15. private $ability: Ability = {} as Ability
  16. private factory: AnyJson = {}
  17. /**
  18. * @constructor
  19. */
  20. constructor(store: AnyStore, ability: Ability) {
  21. this.$store = store
  22. this.$ability = ability
  23. }
  24. /**
  25. * Initialise les services factories
  26. */
  27. initFactory() {
  28. this.factory = {
  29. access: $accessProfile(this.$store, this.$ability),
  30. organization: $organizationProfile(this.$store)
  31. }
  32. }
  33. /**
  34. * Set les abilities de l'utilisateur à chaque fois qu'on update son profile
  35. */
  36. setAbilities(){
  37. //Nécessaire pour que l'update des abilité soit correct après la phase SSR
  38. this.$ability.update(this.$store.state.profile.access.abilities);
  39. /**
  40. * Au moment où l'on effectue un SetProfile via le store Organization, il faut aller récupérer
  41. * les différentes abilitées que l'utilisateur peut effectuer. (Tout cela se passe en SSR)
  42. */
  43. const unsubscribe = this.$store.subscribeAction({
  44. after: (action, state) => {
  45. switch (action.type) {
  46. case 'profile/organization/setProfile':
  47. //On récupère les abilités
  48. const abilities = this.getAbilities();
  49. //On les store puis on update le service ability pour le mettre à jour.
  50. this.$store.commit('profile/access/setAbilities', abilities)
  51. this.$ability.update(abilities);
  52. //Unsubscribe pour éviter les memory leaks
  53. unsubscribe()
  54. break;
  55. }
  56. }
  57. })
  58. }
  59. /**
  60. * Récupération de l'ensemble des abilities quelles soient par Roles ou par Config.
  61. * @return {Array<AbilitiesType>}
  62. */
  63. getAbilities():Array<AbilitiesType> {
  64. const abilitiesByRoles = this.getAbilitiesByRoles(this.$store.state.profile.access.roles)
  65. this.$ability.update(abilitiesByRoles);
  66. this.initFactory();
  67. return abilitiesByRoles.concat(this.getAbilitiesByConfig('./config/abilities/config.yaml'))
  68. }
  69. /**
  70. * Adaptation et transformations des roles en abilities
  71. * @param {Array<string>} roles
  72. * @return {Array<AbilitiesType>}
  73. */
  74. getAbilitiesByRoles(roles: Array<string>): Array<AbilitiesType> {
  75. roles = $roleUtils.transformUnderscoreToHyphenBeforeCompleteMigration(roles);
  76. return $roleUtils.transformRoleToAbilities(roles);
  77. }
  78. /**
  79. * - Parcours la config d'abilities en Yaml
  80. * - filtres la config pour ne garder que les abilities autorisées
  81. * - transform la config restante en Object Abilities
  82. * @param {string} configPath
  83. * @return {Array<AbilitiesType>}
  84. */
  85. getAbilitiesByConfig(configPath:string): Array<AbilitiesType> {
  86. let abilitiesByConfig: Array<AbilitiesType> = []
  87. try {
  88. const doc = $yamlParser.parse(configPath);
  89. const abilitiesAvailable = doc['abilities']
  90. const abilitiesFiltered = this.abilitiesAvailableFilter(abilitiesAvailable)
  91. abilitiesByConfig = this.transformAbilitiesConfigToAbility(abilitiesFiltered)
  92. } catch (e) {
  93. console.debug(e)
  94. }
  95. return abilitiesByConfig;
  96. }
  97. /**
  98. * Filtre toutes les abilities possible suivant si l'utilisateur est autorisé ou non à les posséder
  99. * @param {AnyJson} abilitiesAvailable
  100. * @return {AnyJson}
  101. */
  102. abilitiesAvailableFilter(abilitiesAvailable:AnyJson):AnyJson{
  103. return _.pickBy(abilitiesAvailable, (ability:any) =>{
  104. const services = ability['services']
  105. return this.canHaveTheAbility(services)
  106. })
  107. }
  108. /**
  109. * Transform une config d'abilities en un tableau d'Abilities
  110. * @param {AnyJson} abilitiesAvailable
  111. * @return {Array<AbilitiesType>}
  112. */
  113. transformAbilitiesConfigToAbility(abilitiesAvailable:AnyJson):Array<AbilitiesType>{
  114. let abilitiesByConfig: Array<AbilitiesType> = []
  115. _.each(abilitiesAvailable, (ability, subject) => {
  116. let myAbility: AbilitiesType = {
  117. action: ability['action'],
  118. subject: subject
  119. }
  120. abilitiesByConfig.push(myAbility)
  121. })
  122. return abilitiesByConfig;
  123. }
  124. /**
  125. * Parcours les fonctions par services et établit si oui ou non l'abilité est autorisée
  126. * @param {AnyJson} functionByservices
  127. * @return {boolean}
  128. */
  129. canHaveTheAbility(functionByservices: AnyJson) {
  130. let hasAbility = true;
  131. _.each(functionByservices, (functions, service) => {
  132. if (hasAbility) {
  133. const nbFunctions = functions.length
  134. let cmpt = 0
  135. while (hasAbility && nbFunctions > cmpt) {
  136. const f = functions[cmpt]['function'];
  137. const parameters = functions[cmpt]['parameters'] ?? null;
  138. const result = functions[cmpt]['result'] ?? null;
  139. hasAbility = result !== null ? this.factory[service].handler()[f](parameters) == result : this.factory[service].handler()[f](parameters)
  140. cmpt++
  141. }
  142. }
  143. })
  144. return hasAbility;
  145. }
  146. }
  147. export const $abilitiesUtils = (store: AnyStore, ability:Ability) => new AbilitiesUtils(store, ability);