added display name to config

This commit is contained in:
Patrick 2025-08-22 13:54:27 +02:00
parent b2e6f059a6
commit 9093ddaeb5
2 changed files with 80 additions and 23 deletions

View File

@ -2,14 +2,32 @@
"USERADMIN": {
"size": 8,
"permissions": {
"VIEW": 0,
"ADD": 1,
"DELETE": 2,
"EDIT": 3,
"EDIT_PASSWORD": 4
"VIEW": {
"position": 0,
"name": "Anzeigen"
},
"ADD": {
"position": 1,
"name": "Anlegen"
},
"DELETE": {
"position": 2,
"name": "Entfernen"
},
"EDIT": {
"position": 3,
"name": "Bearbeiten"
},
"EDIT_PASSWORD": {
"position": 4,
"name": "Administration"
}
},
"meta_permissions": {
"MANAGE": ["VIEW", "ADD", "DELETE", "EDIT"]
"MANAGE": {
"permissions": ["VIEW", "ADD", "DELETE", "EDIT"],
"name": "Verwalten"
}
}
}
}

View File

@ -1,15 +1,27 @@
type GroupPermissionsDef = Record<string, number>
interface GroupPermissionDetail {
position: number
name: string
}
interface GroupMetaPermissionDetail {
permissions: Array<string>
name: string
}
type GroupPermissionsDef = Record<string, GroupPermissionDetail>
type GroupMetaPermissionsDef = Record<string, GroupMetaPermissionDetail>
interface GroupDef {
size: number
permissions: GroupPermissionsDef
meta_permissions?: Record<string, Array<string>>
meta_permissions?: GroupMetaPermissionsDef
}
type PermissionDef = Record<string, GroupDef>
const _display_names = new Map<number, string>()
import raw from "./permissions.config.json"
@ -19,11 +31,11 @@ const __validate_config = (config: unknown): config is PermissionDef => {
const error = (message: string) => new Error("Failed to parse permissions.config.json: " + message)
if (typeof config !== "object" || config === null) throw error("configuration is not an object or null.")
for (const [group, definition] of Object.entries(config)) {
if (typeof definition !== "object")
throw error(`definition for ${group} is not an object (is ${typeof definition})`)
if (definition === null)
if (definition == null)
throw error(`definition for ${group} is null`)
if (typeof definition.size !== "number")
@ -31,10 +43,14 @@ const __validate_config = (config: unknown): config is PermissionDef => {
if (typeof definition.permissions !== "object")
throw error(`definition of permissions for group ${group} is not an object`)
for (const [name, position] of Object.entries(definition.permissions)) {
if (typeof position !== "number")
throw error(`position of ${name} in group ${group} is not a number (is ${typeof position})`)
if (position >= definition.size)
for (const [name, detail] of Object.entries(definition.permissions)) {
if (typeof detail !== "object" || detail == null)
throw error(`definition for permission ${name} has to be an object`)
if (typeof detail.position !== "number")
throw error(`position of ${name} in group ${group} is not a number (is ${typeof detail.position})`)
if (detail.position >= definition.size)
throw error(`position ${position} of permission ${name} in group ${group} is out of bounds (size is ${definition.size})`)
}
@ -46,9 +62,11 @@ const __validate_config = (config: unknown): config is PermissionDef => {
for (const [name, parts] of Object.entries(definition.meta_permissions)) {
if (Object.keys(definition.permissions).includes(name))
throw error(`meta permission ${name} uses the same name as the permission`)
if (typeof parts !== "object" && !(parts instanceof Array) || parts === null)
throw error(`definition of meta permission ${name} in group ${group} is not an array`)
for (const partial of (parts as Array<any>)) {
if (typeof parts !== "object" || parts == null)
throw error(`definition of meta permission ${name} in group ${group} is not an object`)
if (typeof parts.permissions !== "object" || !(parts.permissions instanceof Array))
throw error(`definition of meta permission ${name} has to include a key "permissions" with a value of type Array<string>`)
for (const partial of (parts.permissions as Array<any>)) {
if (!permissions.includes(partial))
throw error(`permission ${partial} of definition of meta permission ${name} in group ${group} is not a permission of this group`)
}
@ -68,20 +86,23 @@ function toPermissionObj(config: PermissionDef): Record<PermissionGroups, Record
for (const [name, definition] of Object.entries(config)) {
obj[name] = {}
obj[name]["ALL"] = 0;
for (const [permission, value] of Object.entries(definition.permissions)) {
for (const [permission, detail] of Object.entries(definition.permissions)) {
if (permission == "ALL") {
throw new Error(`permission must not be called ALL in group ${name}`)
}
obj[name][permission] = 1 << (curr_pos + value)
obj[name]["ALL"] |= obj[name][permission]
const mask = 1 << (curr_pos + detail.position)
obj[name][permission] = mask
obj[name]["ALL"] |= mask
_display_names.set(mask, detail.name)
}
for (const [meta, permissions] of Object.entries(definition?.meta_permissions ?? {})) {
for (const [meta, detail] of Object.entries(definition?.meta_permissions ?? {})) {
let mask = 0;
for (const permission in permissions) {
mask |= 1 << definition.permissions[permission]
for (const permission of detail.permissions) {
mask |= 1 << definition.permissions[permission].position
}
obj[name][meta] = mask << curr_pos
_display_names.set(mask, detail.name)
}
curr_pos += definition.size
@ -97,4 +118,22 @@ export default {
has: (user_permissions: number, permissions: number): boolean => (user_permissions & permissions) == permissions,
any: (user_permissions: number, permissions: number): boolean => (user_permissions & permissions) > 0,
display_name: (permission: number): string|undefined => {
const name = _display_names.get(permission)
if (name != undefined) return name
const names: Array<string> = []
let mask = 1
while (permission >= mask) {
const current_perm = permission & mask
const current_name = _display_names.get(current_perm)
if (current_name != undefined) names.push(current_name)
mask <<= 1
}
return names.join(" | ")
}
}