| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- import {$accessProfile} from '~/services/profile/accessProfile'
- import {$organizationProfile} from '~/services/profile/organizationProfile'
- import {$roleUtils} from '~/services/rights/roleUtils'
- import {AbilitiesType} from '~/types/interfaces'
- import {useAccessProfileStore} from "~/store/profile/access";
- import {useProfileOrganizationStore} from "~/store/profile/organization";
- import YamlDenormalizer from "~/services/data/serializer/denormalizer/yamlDenormalizer";
- import {MongoAbility} from "@casl/ability/dist/types/Ability";
- import {AnyJson} from "~/types/data";
- /**
- * Classe permettant de mener des opérations sur les habilités
- */
- class AbilitiesUtils {
- private readonly $ability: MongoAbility = {} as MongoAbility
- private factory: AnyJson = {}
- /**
- * @constructor
- */
- constructor(ability: MongoAbility) {
- this.$ability = ability
- }
- /**
- * Retourne la factory des services
- *
- * @return {AnyJson} factory
- */
- getFactory() {
- return this.factory
- }
- /**
- * Initialise les services factories
- */
- initFactory() {
- this.factory = {
- access: $accessProfile,
- organization: $organizationProfile()
- }
- this.setAbilitiesAndStore()
- }
- /**
- * Initialise les Abilities pour le service AccessProfile
- */
- setAbilitiesAndStore() {
- this.factory.access.setAbility(this.$ability)
- this.factory.access.setPinia()
- }
- /**
- * Définit les abilities de l'utilisateur à chaque fois qu'on met à jour son profile
- */
- setAbilities() {
- const accessProfileStore = useAccessProfileStore()
- const organizationProfileStore = useProfileOrganizationStore()
- // Nécessaire pour que l'update des habilités soit correcte après la phase SSR
- this.$ability.update(accessProfileStore.abilities)
- // // Au moment où l'on effectue un SetProfile, il faut aller récupérer
- // // les différentes abilitées que l'utilisateur peut effectuer. (Tout cela se passe en SSR)
- const unsubscribe = organizationProfileStore.$onAction(({
- name, // name of the action
- store, // store instance, same as `someStore`
- args, // array of parameters passed to the action
- after, // hook after the action returns or resolves
- onError, // hook if the action throws or rejects
- }) => {
- after((result)=>{
- if(name === 'setProfile'){
- //On récupère les abilités
- const abilities: Array<AbilitiesType> = this.getAbilities();
- //On les store puis on update le service ability pour le mettre à jour.
- accessProfileStore.abilities = abilities
- this.$ability.update(abilities)
- // Unsubscribe pour éviter les memory leaks
- unsubscribe()
- }
- })
- })
- }
- /**
- * Récupération de l'ensemble des abilities, qu'elles soient par Roles ou par Config
- *
- * @return {Array<AbilitiesType>}
- */
- getAbilities(): Array<AbilitiesType> {
- const accessProfileStore = useAccessProfileStore()
- const abilitiesByRoles: Array<AbilitiesType> = this.getAbilitiesByRoles(accessProfileStore.roles)
- this.$ability.update(abilitiesByRoles)
- this.initFactory()
- return abilitiesByRoles.concat(this.getAbilitiesByConfig('./config/abilities/config.yaml'))
- }
- /**
- * Adaptation et transformations des roles en abilities
- *
- * @param {Array<string>} roles
- * @return {Array<AbilitiesType>}
- */
- getAbilitiesByRoles(roles: Array<string>): Array<AbilitiesType> {
- roles = $roleUtils.transformUnderscoreToHyphenBeforeCompleteMigration(roles)
- return $roleUtils.transformRoleToAbilities(roles)
- }
- /**
- * - Parcourt la config d'abilities en Yaml
- * - filtres la config pour ne garder que les abilities autorisées
- * - transform la config restante en Object Abilities
- * @param {string} configPath
- * @return {Array<AbilitiesType>}
- */
- getAbilitiesByConfig(configPath: string): Array<AbilitiesType> {
- let abilitiesByConfig: Array<AbilitiesType> = []
- try {
- const doc = YamlDenormalizer.denormalize({path: configPath})
- const abilitiesAvailable = doc.abilities
- const abilitiesFiltered = this.abilitiesAvailableFilter(abilitiesAvailable)
- abilitiesByConfig = this.transformAbilitiesConfigToAbility(abilitiesFiltered)
- } catch (e: any) {
- throw new Error(e.message)
- }
- return abilitiesByConfig
- }
- /**
- * Filtre toutes les abilities possible suivant si l'utilisateur est autorisé ou non à les posséder
- *
- * @param {AnyJson} abilitiesAvailable
- * @return {AnyJson}
- */
- abilitiesAvailableFilter(abilitiesAvailable: AnyJson): AnyJson {
- return usePickBy(abilitiesAvailable, (ability: any) => {
- const services = ability.services
- return this.canHaveTheAbility(services)
- })
- }
- /**
- * Transform une config d'abilities en un tableau d'Abilities
- *
- * @param {AnyJson} abilitiesAvailable
- * @return {Array<AbilitiesType>}
- */
- transformAbilitiesConfigToAbility(abilitiesAvailable: AnyJson): Array<AbilitiesType> {
- const abilitiesByConfig: Array<AbilitiesType> = []
- useEach(abilitiesAvailable, (ability, subject) => {
- const myAbility: AbilitiesType = {
- action: ability.action,
- subject
- }
- abilitiesByConfig.push(myAbility)
- })
- return abilitiesByConfig
- }
- /**
- * Parcourt les fonctions par services et établit si oui ou non l'habilité est autorisée
- *
- * @return {boolean}
- * @param functionByservices
- */
- canHaveTheAbility(functionByservices: AnyJson) {
- let hasAbility: boolean = true;
- useEach(functionByservices, (functions, service) => {
- if (hasAbility) {
- const nbFunctions: number = functions.length
- let cmpt: number = 0
- while (hasAbility && nbFunctions > cmpt) {
- const f: string = functions[cmpt]['function'];
- const parameters: any = functions[cmpt]['parameters'] ?? null;
- const result: boolean = functions[cmpt]['result'] ?? true;
- hasAbility = result !== null ? this.factory[service].handler()[f](parameters) == result : this.factory[service].handler()[f](parameters)
- cmpt++
- }
- }
- })
- return hasAbility
- }
- }
- export const $abilitiesUtils = (ability: MongoAbility) => new AbilitiesUtils(ability)
|