roleUtils.ts 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. import { AbilitiesType } from '~/types/interfaces'
  2. import {AnyJson} from "~/types/data"
  3. import _ from "lodash"
  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 actionMap: AnyJson = {
  43. '': 'manage',
  44. _VIEW: 'read'
  45. }
  46. /**
  47. * Classe permettant de mener des opérations sur les rôles
  48. */
  49. class RoleUtils {
  50. /**
  51. * Teste si une personne possède un profil suivant ses rôles
  52. *
  53. * @param {string} profileName
  54. * @param {Array<string>} roles
  55. * @return {boolean}
  56. */
  57. static isA (profileName: string, roles: Array<string>): boolean {
  58. profileName = profileName.toUpperCase()
  59. if (!profileName.match(/^[A-Z_]+$/)) {
  60. throw new Error('invalid role name')
  61. }
  62. // TODO: actuellement, passer un profil ne corresondant à aucun rôle ne lèvera aucune erreur, et se contentera de
  63. // retourner false; ce serait pas mal de lever une erreur, ce ne serait pas normal de demander un rôle inexistant
  64. return roles.includes('ROLE_' + profileName + '_CORE')
  65. }
  66. /**
  67. * Filtre les rôles afin d'en exclure les "Roles fonctions"
  68. *
  69. * @param {Array<string>} roles
  70. * @return {Array<string>}
  71. */
  72. static filterFunctionRoles (roles: Array<string>): Array<string> {
  73. return roles.filter((role) => {
  74. return !rolesByFunction.includes(role)
  75. })
  76. }
  77. /**
  78. * Fix en attendant la migration complète, quelques rôles disposent d'underscore en trop, on corrige cela...
  79. *
  80. * TODO: remove after complete migration
  81. *
  82. * @param {Array<string>} roles
  83. * @return {Array<string>}
  84. */
  85. static transformUnderscoreToHyphen (roles: Array<string>): Array<string> {
  86. // 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?
  87. const regex = /(ROLE_)([A-Z]*_[A-Z]*)([A-Z_]*)*/i
  88. let match
  89. roles = roles.map((role) => {
  90. if (rolesToChange.includes(role)) {
  91. if ((match = regex.exec(role)) !== null) {
  92. const role = match[1]
  93. const subject = match[2].replace('_', '-')
  94. const action = match[3]
  95. return role + subject + (action || '')
  96. }
  97. }
  98. return role
  99. })
  100. return roles
  101. }
  102. /**
  103. * On transforme les ROLES Symfony en Abilities
  104. *
  105. * Ex:
  106. *
  107. * "ROLE_ORGANIZATION" => { subject: 'organization', action: 'manage'}
  108. * "ROLE_PLACE_VIEW" => { subject: 'place', action: 'read'}
  109. *
  110. * @param {Array<string>} roles
  111. * @return {Array<AbilitiesType>}
  112. */
  113. static rolesToAbilities (roles: Array<string>): [] | Array<AbilitiesType> {
  114. const abilities:Array<AbilitiesType> = []
  115. roles = RoleUtils.transformUnderscoreToHyphen(roles)
  116. // TODO: on pourrait peut-être faciliter la lecture en réécrivant la regex en `ROLE_([A-Z-]*)(_[A-Z]+)?`, ou
  117. // même en faisant un simple split sur le '_'
  118. const regex = /(ROLE_)([A-Z-]*)([_A-Z]*)/i
  119. let match
  120. _.each(roles, (role) => {
  121. if ((match = regex.exec(role)) !== null) {
  122. const subject = match[2]
  123. const actionName = match[3] ?? ''
  124. const action = actionMap[actionName]
  125. if (subject && typeof action !== 'undefined') {
  126. abilities.push({
  127. action: action,
  128. subject: subject.toLowerCase()
  129. })
  130. }
  131. }
  132. })
  133. return abilities
  134. }
  135. }
  136. export default RoleUtils