@semantic-api/access-control
Types
Global API
Role
ts
export type Role<
TCollections extends Record<string, CollectionStructure>,
TAlgorithms extends Record<string, AlgorithmStructure>,
TAccessControl extends AccessControl<TCollections, TAlgorithms>=any
> = {
inherit?: Array<keyof TAccessControl['roles'] | keyof typeof baseRoles>
grantEverything?: boolean
forbidEverything?: boolean
capabilities?: {
[P in keyof (TCollections & TAlgorithms)]?: {
grantEverything?: boolean
forbidEverything?: boolean
functions?: 'functions' extends keyof (TCollections & TAlgorithms)[P]
? Array<keyof (TCollections & TAlgorithms)[P]['functions']>
: never
blacklist?: 'functions' extends keyof (TCollections & TAlgorithms)[P]
? Array<keyof (TCollections & TAlgorithms)[P]['functions']>
: never
}
}
}
AccessControl
ts
export type InternalAccessControl<
TCollections extends Record<string, CollectionStructure>,
TAlgorithms extends Record<string, AlgorithmStructure>,
TAccessControl extends AccessControl<TCollections, TAlgorithms>=any
> = {
roles?: Roles<TCollections, TAlgorithms, TAccessControl>
availableRoles?: keyof TAccessControl['roles']
parent?: TAccessControl['roles']
}
export type AccessControl<
TCollections extends Record<string, CollectionStructure>,
TAlgorithms extends Record<string, AlgorithmStructure>,
TAccessControl extends AccessControl<TCollections, TAlgorithms>=any
> = InternalAccessControl<TCollections, TAlgorithms, TAccessControl> & {
layers?: Partial<Record<ValidAccessControlLayer, AccessControlLayer<TCollections, TAlgorithms, TAccessControl>>>
}
AccessControlLayer
ts
export type AccessControlLayerProps<TPayload extends Record<string, any>=any> = {
propertyName?: string
parentId?: string
childId?: string
payload: TPayload
}
export type AccessControlLayer<
TCollections extends Record<string, CollectionStructure>,
TAlgorithms extends Record<string, Awaited<ReturnType<Algorithm>>>,
TAccessControl extends AccessControl<TCollections, TAlgorithms>=any
> = (context: Context<any, TCollections, TAlgorithms, TAccessControl>, props: AccessControlLayerProps) => Promise<Either<
ACErrors,
ReadPayload | WritePayload
>>
ValidAccessControlLayer
ts
export type ValidAccessControlLayer =
'read'
| 'write'
| 'call'
defineAccessControl
Defines a AccessControl
object while providing strong typing.
ts
export const defineAccessControl = <
TCollections extends Record<string, CollectionStructure>,
TAlgorithms extends Record<string, AlgorithmStructure>,
>() => <const TAccessControl extends AccessControl<TCollections, TAlgorithms, TAccessControl>>(accessControl: TAccessControl) =>
(layers?: Partial<Record<ValidAccessControlLayer, AccessControlLayer<TCollections, TAlgorithms, TAccessControl>>>) => {
const roles = {}
Object.assign(roles, baseRoles)
Object.assign(roles, accessControl.roles)
accessControl.roles = roles
accessControl.layers = layers
return accessControl
}
Example
typescript
import { defineAccessControl } from '@semantic-api/access-control'
export const accessControl = defineAccessControl<Collections, Algorithms>()({
roles: {
guest: {
inherit: [
'unauthenticated',
// will produce TS diagnostics since there's no 'non_existent' role to inherit
// 'non_existent'
],
capabilities: {
someResource: {
grantEverything: true
}
}
}
}
})({
read: async (context, { payload }) => {
// will produce TS diagnostics since 'non_existent' role wasn't provided
// if( context.token.user.roles.includes('non_existent') ) {
// context.log('oh no!')
// }
}
})