UNPKG

feathers-casl

Version:

Add access control with CASL to your feathers application.

139 lines (138 loc) 8.6 kB
import { AnyAbility, AnyMongoAbility, ClaimRawRule, MongoQuery, Subject, SubjectRawRule } from "@casl/ability"; import { Channel, RealTimeConnection } from "@feathersjs/transport-commons"; import { Application, HookContext, Id, NextFunction, Query, Service } from "@feathersjs/feathers"; import { AdapterBase } from "@feathersjs/adapter-commons"; import { PartialDeep } from "type-fest"; //#region src/types.d.ts type AnyData = Record<string, any>; type Adapter = '@feathersjs/memory' | '@feathersjs/knex' | '@feathersjs/mongodb' | 'feathers-sequelize' | 'feathers-kysely'; interface ServiceCaslOptions { availableFields: string[]; } interface CaslParams<A extends AnyMongoAbility = AnyMongoAbility> { ability?: A | ((context: HookContext) => A | Promise<A>); casl?: { ability: A | (() => A); }; } interface HookBaseOptions<H extends HookContext = HookContext> { ability: AnyAbility | ((context: H) => AnyAbility | Promise<AnyAbility>); actionOnForbidden: undefined | (() => void); checkAbilityForInternal: boolean; checkMultiActions: boolean; modelName: GetModelName; notSkippable: boolean; method?: string | ((context: H) => string); debug?: boolean; } interface CheckBasicPermissionHookOptions<H extends HookContext = HookContext> extends HookBaseOptions<H> { checkCreateForData: boolean | ((context: H) => boolean); storeAbilityForAuthorize: boolean; } type CheckBasicPermissionUtilsOptions<H extends HookContext = HookContext> = Omit<CheckBasicPermissionHookOptions<H>, 'notSkippable'>; type CheckBasicPermissionHookOptionsExclusive<H extends HookContext = HookContext> = Pick<CheckBasicPermissionHookOptions<H>, Exclude<keyof CheckBasicPermissionHookOptions, keyof HookBaseOptions>>; type AvailableFieldsOption<H extends HookContext = HookContext> = string[] | ((context: H) => string[] | undefined) | undefined; interface AuthorizeChannelCommonsOptions<H extends HookContext = HookContext> { availableFields: AvailableFieldsOption<H>; } interface AuthorizeHookOptions<H extends HookContext = HookContext> extends HookBaseOptions<H>, AuthorizeChannelCommonsOptions<H> { adapter: Adapter; useUpdateData: boolean; usePatchData: boolean; } type AuthorizeHookOptionsExclusive<H extends HookContext = HookContext> = Pick<AuthorizeHookOptions<H>, Exclude<keyof AuthorizeHookOptions<H>, keyof HookBaseOptions<H>>>; type GetModelName<H extends HookContext = HookContext> = string | ((context: H) => string); type EventName = 'created' | 'updated' | 'patched' | 'removed'; interface ChannelOptions extends AuthorizeChannelCommonsOptions { ability: AnyAbility | ((app: Application, connection: RealTimeConnection, data: unknown, context: HookContext) => AnyAbility); /** Easy way to disable filtering, default: `false` */ activated: boolean; /** Channel that's used when there occurs an error, default: `['authenticated']` */ channelOnError: string[]; /** Prefiltered channels, default: `app.channel(app.channels)` */ channels?: Channel | Channel[]; modelName: GetModelName; restrictFields: boolean; /** change action to use for events. For example: `'receive'`, default: `'get'` */ useActionName: string | { [e in EventName]?: string }; } interface GetConditionalQueryOptions { actionOnForbidden?(): void; } interface HasRestrictingFieldsOptions { availableFields: string[] | undefined; } interface InitOptions<H extends HookContext = HookContext> { defaultAdapter: Adapter; authorizeHook: AuthorizeHookOptions<H>; channels: ChannelOptions; } interface GetMinimalFieldsOptions { availableFields?: string[]; checkCan?: boolean; } type Path = string | Array<string | number>; interface ThrowUnlessCanOptions extends Pick<HookBaseOptions, 'actionOnForbidden' | 'debug'> { skipThrow: boolean; } interface UtilCheckCanOptions extends ThrowUnlessCanOptions { checkGeneral?: boolean; useConditionalSelect?: boolean; } //#endregion //#region src/hooks/authorize/authorize.hook.d.ts declare const authorize: <H extends HookContext = HookContext>(_options?: Partial<AuthorizeHookOptions>) => (context: H, next?: NextFunction) => Promise<any>; //#endregion //#region src/hooks/checkBasicPermission.hook.d.ts declare const checkBasicPermission: <H extends HookContext>(_options?: Partial<CheckBasicPermissionHookOptions>) => ((context: H) => Promise<H>); //#endregion //#region src/channels/getChannelsWithReadAbility.d.ts declare const getChannelsWithReadAbility: (app: Application, data: AnyData, context: HookContext, _options?: Partial<ChannelOptions>) => undefined | Channel | Channel[]; //#endregion //#region src/channels/channels.utils.d.ts declare const makeChannelOptions: (app: Application, options?: Partial<ChannelOptions>) => ChannelOptions; declare const makeDefaultOptions: (options?: Partial<ChannelOptions>) => ChannelOptions; declare const getAbility: (app: Application, data: Record<string, unknown>, connection: RealTimeConnection, context: HookContext, options: Partial<ChannelOptions>) => undefined | AnyAbility; declare const getEventName: (method: string) => EventName | undefined; //#endregion //#region src/utils/checkBasicPermission.d.ts declare const checkBasicPermissionUtil: <H extends HookContext>(context: H, _options?: Partial<CheckBasicPermissionUtilsOptions>) => Promise<H>; //#endregion //#region src/utils/checkCan.d.ts declare const checkCan: <S>(ability: AnyAbility, id: Id, method: string, modelName: string, service: Service<S>, providedOptions?: Partial<UtilCheckCanOptions>) => Promise<boolean>; //#endregion //#region src/utils/convertRuleToQuery.d.ts declare const convertRuleToQuery: (rule: SubjectRawRule<any, any, MongoQuery> | ClaimRawRule<any>, options?: GetConditionalQueryOptions) => Query | undefined; //#endregion //#region src/utils/couldHaveRestrictingFields.d.ts declare function couldHaveRestrictingFields(ability: AnyAbility, action: string, subjectType: string): boolean; //#endregion //#region src/utils/getAvailableFields.d.ts declare const getAvailableFields: (context: HookContext, options?: Partial<Pick<AuthorizeChannelCommonsOptions, "availableFields">>) => undefined | string[]; //#endregion //#region src/utils/getModelName.d.ts declare const getModelName: (modelName: string | ((context: HookContext) => string) | undefined, context: HookContext) => string; //#endregion //#region src/utils/hasRestrictingConditions.d.ts type Rule = ReturnType<AnyAbility['possibleRulesFor']>[0]; declare const hasRestrictingConditions: (ability: AnyAbility, action: string, modelName: string) => Rule[] | false; //#endregion //#region src/utils/hasRestrictingFields.d.ts declare const hasRestrictingFields: (ability: AnyAbility, action: string, subject: Subject, options?: HasRestrictingFieldsOptions) => boolean | string[]; //#endregion //#region src/utils/mergeQueryFromAbility.d.ts declare const mergeQueryFromAbility: <T>(app: Application, ability: AnyAbility, method: string, modelName: string, originalQuery: Query, service: AdapterBase<T>, options: Pick<AuthorizeHookOptions, "adapter">) => Query; //#endregion //#region src/utils/simplifyQuery.d.ts declare const simplifyQuery: <Q extends Query | null>(query: Q, replaceAnd?: boolean, replaceOr?: boolean) => Q; //#endregion //#region src/utils/getFieldsForConditions.d.ts declare const getFieldsForConditions: (ability: AnyAbility, action: string, modelName: string) => string[]; //#endregion //#region src/utils/getMinimalFields.d.ts declare const getMinimalFields: (ability: AnyAbility, action: string, subject: Record<string, unknown>, options: GetMinimalFieldsOptions) => string[]; //#endregion //#region src/initialize.d.ts declare const initialize: (options?: PartialDeep<InitOptions>) => ((app: Application) => void); //#endregion export { Adapter, AnyData, AuthorizeChannelCommonsOptions, AuthorizeHookOptions, AuthorizeHookOptionsExclusive, AvailableFieldsOption, CaslParams, ChannelOptions, CheckBasicPermissionHookOptions, CheckBasicPermissionHookOptionsExclusive, CheckBasicPermissionUtilsOptions, EventName, GetConditionalQueryOptions, GetMinimalFieldsOptions, GetModelName, HasRestrictingFieldsOptions, HookBaseOptions, InitOptions, Path, ServiceCaslOptions, ThrowUnlessCanOptions, UtilCheckCanOptions, authorize, checkBasicPermission, checkBasicPermissionUtil, checkCan, convertRuleToQuery, couldHaveRestrictingFields, initialize as feathersCasl, getAbility, getAvailableFields, getChannelsWithReadAbility, getEventName, getFieldsForConditions, getMinimalFields, getModelName, hasRestrictingConditions, hasRestrictingFields, makeChannelOptions, makeDefaultOptions, mergeQueryFromAbility, simplifyQuery };