feat: roles SPA foundations
This commit is contained in:
1 parent
80f7037d3a
commit
907949aa12
180 files changed
+4308
-835
No files matched your search
@@ -0,0 +1,70 @@
|
||||
export type Scope = 'none' | 'own' | 'all'
|
||||
|
||||
export interface Grant {
|
||||
key: string
|
||||
scope: Scope
|
||||
}
|
||||
|
||||
export interface RoleRef {
|
||||
id: number
|
||||
name: string
|
||||
built_in: boolean
|
||||
locked: boolean
|
||||
}
|
||||
|
||||
export interface Access {
|
||||
role: RoleRef
|
||||
permissions: Grant[]
|
||||
}
|
||||
|
||||
export interface CanOptions {
|
||||
ownerId?: number
|
||||
typeKey?: string
|
||||
scope?: 'own' | 'all'
|
||||
}
|
||||
|
||||
export interface ScopeOptions {
|
||||
typeKey?: string
|
||||
}
|
||||
|
||||
const TYPE_SEPARATOR = ':'
|
||||
|
||||
function scopeOfGrant(grants: readonly Grant[], key: string): Scope | undefined {
|
||||
return grants.find((grant) => grant.key === key)?.scope
|
||||
}
|
||||
|
||||
export function effectiveScope(
|
||||
grants: readonly Grant[],
|
||||
key: string,
|
||||
options: ScopeOptions = {},
|
||||
): Scope {
|
||||
if (options.typeKey) {
|
||||
const typed = scopeOfGrant(grants, `${key}${TYPE_SEPARATOR}${options.typeKey}`)
|
||||
if (typed !== undefined) {
|
||||
return typed
|
||||
}
|
||||
}
|
||||
return scopeOfGrant(grants, key) ?? 'none'
|
||||
}
|
||||
|
||||
export function allows(
|
||||
grants: readonly Grant[],
|
||||
userId: number | undefined,
|
||||
key: string,
|
||||
options: CanOptions = {},
|
||||
): boolean {
|
||||
const scope = effectiveScope(grants, key, options)
|
||||
if (scope === 'none') {
|
||||
return false
|
||||
}
|
||||
if (scope === 'all') {
|
||||
return true
|
||||
}
|
||||
if (options.scope === 'all') {
|
||||
return false
|
||||
}
|
||||
if (options.ownerId === undefined) {
|
||||
return true
|
||||
}
|
||||
return userId !== undefined && options.ownerId !== 0 && options.ownerId === userId
|
||||
}
|
||||
Reference in new issue
Block a user