roleUtils.ts 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. import { AbilitiesType } from '~/types/interfaces'
  2. import {AnyJson} from "~/types/data"
  3. import * as _ from 'lodash-es'
  4. // TODO: peut-être passer ces constantes dans la config?
  5. const rolesByFunction: Array<string> = [
  6. 'ROLE_SUPER_ADMIN',
  7. 'ROLE_ADMIN',
  8. 'ROLE_ADMIN_CORE',
  9. 'ROLE_ADMINISTRATIF_MANAGER',
  10. 'ROLE_ADMINISTRATIF_MANAGER_CORE',
  11. 'ROLE_PEDAGOGICS_MANAGER',
  12. 'ROLE_PEDAGOGICS_MANAGER_CORE',
  13. 'ROLE_FINANCIAL_MANAGER',
  14. 'ROLE_FINANCIAL_MANAGER_CORE',
  15. 'ROLE_CA',
  16. 'ROLE_CA_CORE',
  17. 'ROLE_STUDENT',
  18. 'ROLE_STUDENT_CORE',
  19. 'ROLE_TEACHER',
  20. 'ROLE_TEACHER_CORE',
  21. 'ROLE_MEMBER',
  22. 'ROLE_MEMBER_CORE',
  23. 'ROLE_OTHER',
  24. 'ROLE_OTHER_CORE'
  25. ]
  26. const rolesToChange: Array<string> = [
  27. 'ROLE_GENERAL_CONFIG',
  28. 'ROLE_GENERAL_CONFIG_VIEW',
  29. 'ROLE_TAGG_ADVANCED',
  30. 'ROLE_TAGG_ADVANCED_VIEW',
  31. 'ROLE_PEDAGOGICS_ADMINISTRATION',
  32. 'ROLE_PEDAGOGICS_ADMINISTRATION_VIEW',
  33. 'ROLE_PEDAGOGICS_SEIZURE',
  34. 'ROLE_PEDAGOGICS_SEIZURE_VIEW',
  35. 'ROLE_BILLINGS_ADMINISTRATION',
  36. 'ROLE_BILLINGS_ADMINISTRATION_VIEW',
  37. 'ROLE_BILLINGS_SEIZURE',
  38. 'ROLE_BILLINGS_SEIZURE_VIEW',
  39. 'ROLE_ONLINEREGISTRATION_ADMINISTRATION',
  40. 'ROLE_ONLINEREGISTRATION_ADMINISTRATION_VIEW'
  41. ]
  42. const actions = ['VIEW', 'REFERENCE', 'CORE']
  43. const actionMap: AnyJson = {
  44. '': 'manage',
  45. 'VIEW': 'read',
  46. 'REFERENCE': null,
  47. 'CORE': null,
  48. }
  49. interface Role {
  50. subject: string
  51. action: 'VIEW' | 'CORE' | 'REFERENCE' | ''
  52. }
  53. /**
  54. * Classe permettant de mener des opérations sur les rôles
  55. */
  56. class RoleUtils {
  57. /**
  58. * Teste si une personne possède un profil suivant ses rôles
  59. *
  60. * @param {string} profileName
  61. * @param {Array<string>} roles
  62. * @return {boolean}
  63. */
  64. static isA (profileName: string, roles: Array<string>): boolean {
  65. profileName = profileName.toUpperCase()
  66. if (!profileName.match(/^[A-Z_]+$/)) {
  67. throw new Error('invalid role name')
  68. }
  69. // TODO: actuellement, passer un profil ne correspondant à aucun rôle ne lèvera aucune erreur, et se contentera de
  70. // retourner false; ce serait pas mal de lever une erreur, ce ne serait pas normal de demander un rôle inexistant
  71. return roles.includes('ROLE_' + profileName + '_CORE')
  72. }
  73. /**
  74. * Filtre les rôles afin d'en exclure les "Roles fonctions"
  75. *
  76. * @param {Array<string>} roles
  77. * @return {Array<string>}
  78. */
  79. static filterFunctionRoles (roles: Array<string>): Array<string> {
  80. return roles.filter((role) => {
  81. return !rolesByFunction.includes(role)
  82. })
  83. }
  84. /**
  85. * Parse une chaine de caractère décrivant un rôle applicatif
  86. *
  87. * @param role
  88. */
  89. static parseRole(role: string): Role {
  90. const parts = role.split('_')
  91. if (parts[0] !== 'ROLE') {
  92. throw new Error('can not parse role')
  93. }
  94. parts.shift()
  95. let action: 'VIEW' | 'CORE' | 'REFERENCE' | '' = ''
  96. if (actions.includes(parts.at(-1) ?? '')) {
  97. // @ts-ignore
  98. action = parts.pop() ?? ''
  99. }
  100. const subject = parts.join('-')
  101. return { subject, action }
  102. }
  103. static roleToString(role: Role) {
  104. // TODO: est-ce qu'il faut retransformer les - en _ ? (si oui, attention à maj les tests)
  105. return ['ROLE', role.subject, role.action].filter((s: string) => s !== null && s.length > 0).join('_')
  106. }
  107. /**
  108. * Construit une habilité à partir du rôle en paramètre.
  109. * Retourne null si le role ne donne droit à aucune habilité
  110. * @param role
  111. */
  112. static roleToAbility(role: Role): AbilitiesType | null {
  113. const mappedAction = actionMap[role.action]
  114. if (mappedAction === null) {
  115. return null
  116. }
  117. return {
  118. action: mappedAction,
  119. subject: role.subject.toLowerCase()
  120. }
  121. }
  122. /**
  123. * On transforme les ROLES Symfony en Abilities
  124. *
  125. * Ex:
  126. *
  127. * "ROLE_ORGANIZATION" => { subject: 'organization', action: 'manage'}
  128. * "ROLE_PLACE_VIEW" => { subject: 'place', action: 'read'}
  129. *
  130. * @param {Array<string>} roles
  131. * @return {Array<AbilitiesType>}
  132. */
  133. static rolesToAbilities (roles: Array<string>): [] | Array<AbilitiesType> {
  134. const abilities:Array<AbilitiesType> = []
  135. _.each(roles, (role: string) => {
  136. const parsed: Role | null= RoleUtils.parseRole(role)
  137. const ability = RoleUtils.roleToAbility(parsed)
  138. // @ts-ignore
  139. if (ability !== null && ability.subject && typeof ability.action !== 'undefined') {
  140. abilities.push(ability)
  141. }
  142. })
  143. return abilities
  144. }
  145. }
  146. export default RoleUtils