UNPKG

feathers-casl

Version:

Add access control with CASL to your feathers application.

123 lines (103 loc) 7.7 kB
import { HookContext, Application, NextFunction, Id, Service, Query } from '@feathersjs/feathers'; import { AnyAbility, AnyMongoAbility, SubjectRawRule, MongoQuery, ClaimRawRule, Subject } from '@casl/ability'; import { RealTimeConnection, Channel } from '@feathersjs/transport-commons'; import { AdapterBase } from '@feathersjs/adapter-commons'; import { PartialDeep } from 'type-fest'; type AnyData = Record<string, any>; type Adapter = '@feathersjs/memory' | '@feathersjs/knex' | '@feathersjs/mongodb' | 'feathers-sequelize'; interface ServiceCaslOptions { availableFields: string[]; } interface CaslParams<A extends AnyMongoAbility = AnyMongoAbility> { ability?: 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); } 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'> { skipThrow: boolean; } interface UtilCheckCanOptions extends ThrowUnlessCanOptions { checkGeneral?: boolean; useConditionalSelect?: boolean; } declare const authorize: <H extends HookContext = HookContext>(_options?: Partial<AuthorizeHookOptions>) => (context: H, next?: NextFunction) => Promise<any>; declare const checkBasicPermission: <H extends HookContext>(_options?: Partial<CheckBasicPermissionHookOptions>) => ((context: H) => Promise<H>); declare const getChannelsWithReadAbility: (app: Application, data: AnyData, context: HookContext, _options?: Partial<ChannelOptions>) => undefined | Channel | Channel[]; 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; declare const checkBasicPermissionUtil: <H extends HookContext>(context: H, _options?: Partial<CheckBasicPermissionUtilsOptions>) => Promise<H>; declare const checkCan: <S>(ability: AnyAbility, id: Id, method: string, modelName: string, service: Service<S>, providedOptions?: Partial<UtilCheckCanOptions>) => Promise<boolean>; declare const convertRuleToQuery: (rule: SubjectRawRule<any, any, MongoQuery> | ClaimRawRule<any>, options?: GetConditionalQueryOptions) => Query | undefined; declare function couldHaveRestrictingFields(ability: AnyAbility, action: string, subjectType: string): boolean; declare const getAvailableFields: (context: HookContext, options?: Partial<Pick<AuthorizeChannelCommonsOptions, "availableFields">>) => undefined | string[]; declare const getModelName: (modelName: string | ((context: HookContext) => string), context: HookContext) => string; type Rule = ReturnType<AnyAbility['possibleRulesFor']>[0]; declare const hasRestrictingConditions: (ability: AnyAbility, action: string, modelName: string) => Rule[] | false; declare const hasRestrictingFields: (ability: AnyAbility, action: string, subject: Subject, options?: HasRestrictingFieldsOptions) => boolean | string[]; declare const mergeQueryFromAbility: <T>(app: Application, ability: AnyAbility, method: string, modelName: string, originalQuery: Query, service: AdapterBase<T>, options: Pick<AuthorizeHookOptions, "adapter">) => Query; declare const simplifyQuery: <Q extends Query | null>(query: Q, replaceAnd?: boolean, replaceOr?: boolean) => Q; declare const getFieldsForConditions: (ability: AnyAbility, action: string, modelName: string) => string[]; declare const getMinimalFields: (ability: AnyAbility, action: string, subject: Record<string, unknown>, options: GetMinimalFieldsOptions) => string[]; declare const initialize: (options?: PartialDeep<InitOptions>) => ((app: Application) => void); export { type Adapter, type AnyData, type AuthorizeChannelCommonsOptions, type AuthorizeHookOptions, type AuthorizeHookOptionsExclusive, type AvailableFieldsOption, type CaslParams, type ChannelOptions, type CheckBasicPermissionHookOptions, type CheckBasicPermissionHookOptionsExclusive, type CheckBasicPermissionUtilsOptions, type EventName, type GetConditionalQueryOptions, type GetMinimalFieldsOptions, type GetModelName, type HasRestrictingFieldsOptions, type HookBaseOptions, type InitOptions, type Path, type ServiceCaslOptions, type ThrowUnlessCanOptions, type UtilCheckCanOptions, authorize, checkBasicPermission, checkBasicPermissionUtil, checkCan, convertRuleToQuery, couldHaveRestrictingFields, initialize as feathersCasl, getAbility, getAvailableFields, getChannelsWithReadAbility, getEventName, getFieldsForConditions, getMinimalFields, getModelName, hasRestrictingConditions, hasRestrictingFields, makeChannelOptions, makeDefaultOptions, mergeQueryFromAbility, simplifyQuery };