abilitiesUtils.ts 6.0 KB

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