first steps of implementing permissions
This commit is contained in:
parent
1adbcf9a44
commit
f0b2e9a818
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"USERADMIN": {
|
||||
"size": 8,
|
||||
"permissions": {
|
||||
"VIEW": 0,
|
||||
"ADD": 1,
|
||||
"DELETE": 2,
|
||||
"EDIT": 3,
|
||||
"EDIT_PASSWORD": 4
|
||||
},
|
||||
"meta_permissions": {
|
||||
"MANAGE": ["VIEW", "ADD", "DELETE", "EDIT"]
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
|
||||
type GroupPermissionsDef = Record<string, number>
|
||||
|
||||
interface GroupDef {
|
||||
size: number
|
||||
permissions: GroupPermissionsDef
|
||||
meta_permissions?: Record<string, Array<string>>
|
||||
}
|
||||
|
||||
type PermissionDef = Record<string, GroupDef>
|
||||
|
||||
|
||||
|
||||
|
||||
import raw from "./permissions.config.json"
|
||||
const config = raw as const
|
||||
|
||||
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)
|
||||
throw error(`definition for ${group} is null`)
|
||||
|
||||
if (typeof definition.size !== "number")
|
||||
throw error(`type of size in group ${group} is not number (is ${typeof definition.size})`)
|
||||
|
||||
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)
|
||||
throw error(`position ${position} of permission ${name} in group ${group} is out of bounds (size is ${definition.size})`)
|
||||
}
|
||||
|
||||
if (definition.meta_permissions !== undefined) {
|
||||
const permissions = Object.keys(definition.permissions)
|
||||
|
||||
if (typeof definition.meta_permissions !== "object")
|
||||
throw error(`meta_permissions of group ${group} is not an object (is ${typeof definition.meta_permissions})`)
|
||||
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 (!permissions.includes(partial))
|
||||
throw error(`permission ${partial} of definition of meta permission ${name} in group ${group} is not a permission of this group`)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
type PermissionGroups = keyof typeof config
|
||||
|
||||
function toPermissionObj(config: PermissionDef): Record<PermissionGroups, Record<string, number>> {
|
||||
let curr_pos = 0
|
||||
const obj: Record<string, Record<string, number>> = {}
|
||||
|
||||
for (const [name, definition] of Object.entries(config)) {
|
||||
obj[name] = {}
|
||||
for (const [permission, value] of Object.entries(definition.permissions)) {
|
||||
obj[name][permission] = 1 << (curr_pos + value)
|
||||
}
|
||||
for (const [meta, permissions] of Object.entries(definition?.meta_permissions ?? {})) {
|
||||
let mask = 0;
|
||||
for (const permission in permissions) {
|
||||
mask |= 1 << definition.permissions[permission]
|
||||
}
|
||||
|
||||
obj[name][meta] = mask << curr_pos
|
||||
}
|
||||
|
||||
curr_pos += definition.size
|
||||
}
|
||||
return obj
|
||||
}
|
||||
|
||||
__validate_config(config)
|
||||
|
||||
|
||||
export default {
|
||||
...toPermissionObj(config),
|
||||
|
||||
has: (user_permissions: number, permission: number): boolean => (user_permissions & permission) > 0
|
||||
}
|
||||
Loading…
Reference in New Issue