|
@@ -42,11 +42,18 @@ const rolesToChange: Array<string> = [
|
|
|
'ROLE_ONLINEREGISTRATION_ADMINISTRATION_VIEW'
|
|
'ROLE_ONLINEREGISTRATION_ADMINISTRATION_VIEW'
|
|
|
]
|
|
]
|
|
|
|
|
|
|
|
|
|
+const actions = ['VIEW', 'MANAGE', 'REFERENCE']
|
|
|
|
|
+
|
|
|
const actionMap: AnyJson = {
|
|
const actionMap: AnyJson = {
|
|
|
'': 'manage',
|
|
'': 'manage',
|
|
|
_VIEW: 'read'
|
|
_VIEW: 'read'
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+interface Role {
|
|
|
|
|
+ subject: string
|
|
|
|
|
+ action: 'VIEW' | 'MANAGE' | 'REFERENCE' | ''
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* Classe permettant de mener des opérations sur les rôles
|
|
* Classe permettant de mener des opérations sur les rôles
|
|
|
*/
|
|
*/
|
|
@@ -63,7 +70,7 @@ class RoleUtils {
|
|
|
if (!profileName.match(/^[A-Z_]+$/)) {
|
|
if (!profileName.match(/^[A-Z_]+$/)) {
|
|
|
throw new Error('invalid role name')
|
|
throw new Error('invalid role name')
|
|
|
}
|
|
}
|
|
|
- // TODO: actuellement, passer un profil ne corresondant à aucun rôle ne lèvera aucune erreur, et se contentera de
|
|
|
|
|
|
|
+ // TODO: actuellement, passer un profil ne correspondant à aucun rôle ne lèvera aucune erreur, et se contentera de
|
|
|
// retourner false; ce serait pas mal de lever une erreur, ce ne serait pas normal de demander un rôle inexistant
|
|
// retourner false; ce serait pas mal de lever une erreur, ce ne serait pas normal de demander un rôle inexistant
|
|
|
return roles.includes('ROLE_' + profileName + '_CORE')
|
|
return roles.includes('ROLE_' + profileName + '_CORE')
|
|
|
}
|
|
}
|
|
@@ -81,30 +88,38 @@ class RoleUtils {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * Fix en attendant la migration complète, quelques rôles disposent d'underscore en trop, on corrige cela...
|
|
|
|
|
|
|
+ * Parse une chaine de caractère décrivant un rôle applicatif
|
|
|
*
|
|
*
|
|
|
- * TODO: remove after complete migration
|
|
|
|
|
- *
|
|
|
|
|
- * @param {Array<string>} roles
|
|
|
|
|
- * @return {Array<string>}
|
|
|
|
|
|
|
+ * @param role
|
|
|
*/
|
|
*/
|
|
|
- static transformUnderscoreToHyphen (roles: Array<string>): Array<string> {
|
|
|
|
|
- // 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?
|
|
|
|
|
- const regex = /(ROLE_)([A-Z]*_[A-Z]*)([A-Z_]*)*/i
|
|
|
|
|
-
|
|
|
|
|
- let match
|
|
|
|
|
- roles = roles.map((role) => {
|
|
|
|
|
- if (rolesToChange.includes(role)) {
|
|
|
|
|
- if ((match = regex.exec(role)) !== null) {
|
|
|
|
|
- const role = match[1]
|
|
|
|
|
- const subject = match[2].replace('_', '-')
|
|
|
|
|
- const action = match[3]
|
|
|
|
|
- return role + subject + (action || '')
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- return role
|
|
|
|
|
- })
|
|
|
|
|
- return roles
|
|
|
|
|
|
|
+ static parseRole(role: string): Role {
|
|
|
|
|
+ const parts = role.split('_')
|
|
|
|
|
+
|
|
|
|
|
+ if (parts[0] !== 'ROLE') {
|
|
|
|
|
+ throw new Error('can not parse role')
|
|
|
|
|
+ }
|
|
|
|
|
+ parts.shift()
|
|
|
|
|
+
|
|
|
|
|
+ let action: 'VIEW' | 'MANAGE' | 'REFERENCE' | '' = ''
|
|
|
|
|
+ if (actions.includes(parts[-1])) {
|
|
|
|
|
+ // @ts-ignore
|
|
|
|
|
+ action = parts.pop() ?? ''
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const subject = parts.join('-')
|
|
|
|
|
+
|
|
|
|
|
+ return { subject, action }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ static roleToString(role: Role) {
|
|
|
|
|
+ return ['ROLE', role.subject, role.action].filter((s: string) => s.length > 0).join('_')
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ static roleToAbility(role: Role): AbilitiesType {
|
|
|
|
|
+ return {
|
|
|
|
|
+ action: actionMap[role.action],
|
|
|
|
|
+ subject: role.subject.toLowerCase()
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -121,25 +136,11 @@ class RoleUtils {
|
|
|
static rolesToAbilities (roles: Array<string>): [] | Array<AbilitiesType> {
|
|
static rolesToAbilities (roles: Array<string>): [] | Array<AbilitiesType> {
|
|
|
const abilities:Array<AbilitiesType> = []
|
|
const abilities:Array<AbilitiesType> = []
|
|
|
|
|
|
|
|
- roles = RoleUtils.transformUnderscoreToHyphen(roles)
|
|
|
|
|
-
|
|
|
|
|
- // TODO: on pourrait peut-être faciliter la lecture en réécrivant la regex en `ROLE_([A-Z-]*)(_[A-Z]+)?`, ou
|
|
|
|
|
- // même en faisant un simple split sur le '_'
|
|
|
|
|
- const regex = /(ROLE_)([A-Z-]*)([_A-Z]*)/i
|
|
|
|
|
- let match
|
|
|
|
|
-
|
|
|
|
|
- _.each(roles, (role) => {
|
|
|
|
|
- if ((match = regex.exec(role)) !== null) {
|
|
|
|
|
- const subject = match[2]
|
|
|
|
|
- const actionName = match[3] ?? ''
|
|
|
|
|
- const action = actionMap[actionName]
|
|
|
|
|
-
|
|
|
|
|
- if (subject && typeof action !== 'undefined') {
|
|
|
|
|
- abilities.push({
|
|
|
|
|
- action: action,
|
|
|
|
|
- subject: subject.toLowerCase()
|
|
|
|
|
- })
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ _.each(roles, (role: string) => {
|
|
|
|
|
+ const parsed: Role | null= RoleUtils.parseRole(role)
|
|
|
|
|
+
|
|
|
|
|
+ if (parsed.subject && typeof parsed.action !== 'undefined') {
|
|
|
|
|
+ abilities.push(RoleUtils.roleToAbility(parsed))
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
|
|
|