@casl/prisma
Version:
Allows to query accessible records using Prisma client based on CASL rules
1 lines • 23 kB
Source Map (JSON)
{"version":3,"file":"runtime.mjs","sources":["../../src/errors/ParsingQueryError.ts","../../src/prisma/PrismaQueryParser.ts","../../src/prisma/interpretPrismaQuery.ts","../../src/prisma/prismaQuery.ts","../../src/accessibleByFactory.ts","../../src/createAbilityFactory.ts"],"sourcesContent":["export class ParsingQueryError extends Error {\n static invalidArgument(operatorName: string, value: unknown, expectValueType: string) {\n const valueType = `${typeof value}(${JSON.stringify(value, null, 2)})`;\n return new this(\n `\"${operatorName}\" expects to receive ${expectValueType} but instead got \"${valueType}\"`\n );\n }\n}\n","import {\n buildAnd,\n Comparable,\n CompoundCondition,\n CompoundInstruction,\n Condition,\n FieldCondition,\n FieldInstruction,\n FieldParsingContext,\n NULL_CONDITION,\n ObjectQueryFieldParsingContext,\n ObjectQueryParser\n} from '@ucast/core';\nimport { ParsingQueryError } from '../errors/ParsingQueryError';\n\nconst isPlainObject = (value: any) => {\n return value && (value.constructor === Object || !value.constructor);\n};\n\nconst equals: FieldInstruction = {\n type: 'field',\n validate(instruction, value) {\n if (Array.isArray(value) || isPlainObject(value)) {\n throw new ParsingQueryError(`\"${instruction.name}\" does not supports comparison of arrays and objects`);\n }\n }\n};\n\nconst not: FieldInstruction<unknown, ObjectQueryFieldParsingContext> = {\n type: 'field',\n parse(instruction, value, { hasOperators, field, parse }) {\n if (isPlainObject(value) && !hasOperators(value) || Array.isArray(value)) {\n throw new ParsingQueryError(`\"${instruction.name}\" does not supports comparison of arrays and objects`);\n }\n\n if (!isPlainObject(value)) {\n return new FieldCondition('notEquals', field, value);\n }\n\n return new CompoundCondition('NOT', [parse(value, { field })]);\n }\n};\n\nconst within: FieldInstruction<unknown[]> = {\n type: 'field',\n validate(instruction, value) {\n if (!Array.isArray(value)) {\n throw ParsingQueryError.invalidArgument(instruction.name, value, 'an array');\n }\n }\n};\n\nconst lt: FieldInstruction<Comparable> = {\n type: 'field',\n validate(instruction, value) {\n const type = typeof value;\n const isComparable = type === 'string'\n || type === 'number' && Number.isFinite(value)\n || value instanceof Date;\n\n if (!isComparable) {\n throw ParsingQueryError.invalidArgument(instruction.name, value, 'comparable value');\n }\n }\n};\n\nconst POSSIBLE_MODES = new Set(['insensitive', 'default']);\nconst mode: FieldInstruction<string> = {\n type: 'field',\n validate(instruction, value) {\n if (!POSSIBLE_MODES.has(value)) {\n throw ParsingQueryError.invalidArgument(\n instruction.name,\n value,\n `one of ${Array.from(POSSIBLE_MODES).join(', ')}`\n );\n }\n },\n parse: () => NULL_CONDITION\n};\n\ninterface StringFieldContext extends FieldParsingContext {\n query: {\n mode?: 'insensitive'\n }\n}\n\nconst compareString: FieldInstruction<string, StringFieldContext> = {\n type: 'field',\n validate(instruction, value) {\n if (typeof value !== 'string') {\n throw ParsingQueryError.invalidArgument(instruction.name, value, 'string');\n }\n },\n parse(instruction, value, { query, field }) {\n const name = query.mode === 'insensitive' ? `i${instruction.name}` : instruction.name;\n return new FieldCondition(name, field, value);\n }\n};\n\nconst compound: CompoundInstruction = {\n type: 'compound',\n validate(instruction, value) {\n if (!value || typeof value !== 'object') {\n throw ParsingQueryError.invalidArgument(instruction.name, value, 'an array or object');\n }\n },\n parse(instruction, arrayOrObject, { parse }) {\n const value = Array.isArray(arrayOrObject) ? arrayOrObject : [arrayOrObject];\n const conditions = value.map(v => parse(v));\n return new CompoundCondition(instruction.name, conditions);\n }\n};\n\nconst booleanField: FieldInstruction<boolean> = {\n type: 'field',\n validate(instruction, value) {\n if (typeof value !== 'boolean') {\n throw ParsingQueryError.invalidArgument(instruction.name, value, 'a boolean');\n }\n }\n};\n\nconst has: FieldInstruction<unknown> = {\n type: 'field'\n};\n\nconst hasSome: FieldInstruction<unknown[]> = {\n type: 'field',\n validate(instruction, value) {\n if (!Array.isArray(value)) {\n throw ParsingQueryError.invalidArgument(instruction.name, value, 'an array');\n }\n }\n};\n\nconst relation: FieldInstruction<Record<string, unknown>, ObjectQueryFieldParsingContext> = {\n type: 'field',\n parse(instruction, value, { field, parse }) {\n if (!isPlainObject(value)) {\n throw ParsingQueryError.invalidArgument(instruction.name, value, 'a query for nested relation');\n }\n\n return new FieldCondition(instruction.name, field, parse(value));\n }\n};\n\nconst inverted = (name: string, baseInstruction: FieldInstruction): FieldInstruction => {\n const parse = baseInstruction.parse;\n\n if (!parse) {\n return {\n ...baseInstruction,\n parse(_, value, ctx) {\n return new CompoundCondition('NOT', [new FieldCondition(name, ctx.field, value)]);\n }\n };\n }\n\n return {\n ...baseInstruction,\n parse(instruction, value, ctx) {\n const condition = parse(instruction, value, ctx);\n if (condition.operator !== instruction.name) {\n throw new Error(`Cannot invert \"${name}\" operator parser because it returns a complex Condition`);\n }\n (condition as Mutable<Condition>).operator = name;\n return new CompoundCondition('NOT', [condition]);\n }\n };\n};\n\nconst instructions = {\n equals,\n not,\n in: within,\n notIn: inverted('in', within),\n lt,\n lte: lt,\n gt: lt,\n gte: lt,\n mode,\n startsWith: compareString,\n endsWith: compareString,\n contains: compareString,\n isEmpty: booleanField,\n has,\n hasSome,\n hasEvery: hasSome,\n NOT: compound,\n AND: compound,\n OR: compound,\n every: relation,\n some: relation,\n none: inverted('some', relation),\n is: relation,\n isNot: inverted('is', relation),\n isSet: booleanField\n};\n\nexport interface ParseOptions {\n field: string\n}\n\ntype Query = Record<string, any>;\nexport class PrismaQueryParser extends ObjectQueryParser<Query> {\n constructor() {\n super(instructions, {\n defaultOperatorName: 'equals',\n });\n }\n\n parse(query: Query, options?: ParseOptions): Condition {\n if (options && options.field) {\n return buildAnd(this.parseFieldOperators(options.field, query));\n }\n\n return super.parse(query);\n }\n}\n\ntype Mutable<T> = { -readonly [K in keyof T]: T[K] };\n","import { CompoundCondition, Condition, FieldCondition } from '@ucast/core';\nimport {\n JsInterpreter,\n createJsInterpreter,\n eq,\n ne,\n and,\n or,\n within,\n lt,\n lte,\n gt,\n gte,\n compare\n} from '@ucast/js';\n\ntype StringInterpreter = JsInterpreter<FieldCondition<string>, Record<string, string>>;\nconst startsWith: StringInterpreter = (condition, object, { get }) => {\n return get(object, condition.field).startsWith(condition.value);\n};\nconst istartsWith: StringInterpreter = (condition, object, { get }) => {\n return get(object, condition.field).toLowerCase().startsWith(condition.value.toLowerCase());\n};\n\nconst endsWith: StringInterpreter = (condition, object, { get }) => {\n return get(object, condition.field).endsWith(condition.value);\n};\nconst iendsWith: StringInterpreter = (condition, object, { get }) => {\n return get(object, condition.field).toLowerCase().endsWith(condition.value.toLowerCase());\n};\n\nconst contains: StringInterpreter = (condition, object, { get }) => {\n return get(object, condition.field).includes(condition.value);\n};\nconst icontains: StringInterpreter = (condition, object, { get }) => {\n return get(object, condition.field).toLowerCase().includes(condition.value.toLowerCase());\n};\n\ntype ArrayInterpreter<\n TConditionValue,\n TValue extends Record<string, unknown[]> = Record<string, unknown[]>\n> = JsInterpreter<FieldCondition<TConditionValue>, TValue>;\nconst isEmpty: ArrayInterpreter<boolean> = (condition, object, { get }) => {\n const value = get(object, condition.field);\n const empty = Array.isArray(value) && value.length === 0;\n return empty === condition.value;\n};\nconst has: ArrayInterpreter<unknown> = (condition, object, { get }) => {\n const value = get(object, condition.field);\n return Array.isArray(value) && value.includes(condition.value);\n};\nconst hasSome: ArrayInterpreter<unknown[]> = (condition, object, { get }) => {\n const value = get(object, condition.field);\n return Array.isArray(value) && condition.value.some(v => value.includes(v));\n};\nconst hasEvery: ArrayInterpreter<unknown[]> = (condition, object, { get }) => {\n const value = get(object, condition.field);\n return Array.isArray(value) && condition.value.every(v => value.includes(v));\n};\n\nconst every: JsInterpreter<FieldCondition<Condition>> = (condition, object, { get, interpret }) => {\n const items = get(object, condition.field) as Record<string, unknown>[];\n return Array.isArray(items)\n && items.length > 0\n && items.every(item => interpret(condition.value, item));\n};\n\nconst some: JsInterpreter<FieldCondition<Condition>> = (condition, object, { get, interpret }) => {\n const items = get(object, condition.field) as Record<string, unknown>[];\n return Array.isArray(items) && items.some(item => interpret(condition.value, item));\n};\n\nconst is: JsInterpreter<FieldCondition<Condition>> = (condition, object, { get, interpret }) => {\n const item = get(object, condition.field) as Record<string, unknown>;\n return item && typeof item === 'object' && interpret(condition.value, item);\n};\n\nconst not: JsInterpreter<CompoundCondition> = (condition, object, { interpret }) => {\n return condition.value.every(subCondition => !interpret(subCondition, object));\n};\n\nconst isSet: JsInterpreter<FieldCondition<Condition>> = (condition, object, { get }) => {\n const item = get(object, condition.field);\n return item !== undefined;\n}\n\nfunction toComparable(value: unknown) {\n return value && typeof value === 'object' ? value.valueOf() : value;\n}\n\nconst compareValues: typeof compare = (a, b) => compare(toComparable(a), toComparable(b));\n\nexport const interpretPrismaQuery = createJsInterpreter({\n // TODO: support arrays and objects comparison\n equals: eq,\n notEquals: ne,\n in: within,\n lt,\n lte,\n gt,\n gte,\n startsWith,\n istartsWith,\n endsWith,\n iendsWith,\n contains,\n icontains,\n isEmpty,\n has,\n hasSome,\n hasEvery,\n and,\n or,\n AND: and,\n OR: or,\n NOT: not,\n every,\n some,\n is,\n isSet,\n}, {\n get: (object, field) => object[field],\n compare: compareValues,\n});\n","import { AnyInterpreter, createTranslatorFactory } from '@ucast/core';\nimport { ForcedSubject } from '@casl/ability';\nimport { PrismaQueryParser } from './PrismaQueryParser';\nimport { interpretPrismaQuery } from './interpretPrismaQuery';\n\nconst parser = new PrismaQueryParser();\nexport const prismaQuery = createTranslatorFactory(\n parser.parse,\n interpretPrismaQuery as AnyInterpreter\n);\n\nexport type Model<T, TName extends string> = T & ForcedSubject<TName>;\nexport type Subjects<T extends Partial<Record<string, Record<string, unknown>>>> =\n | keyof T\n | { [K in keyof T]: Model<T[K], K & string> }[keyof T];\n\n/**\n * Extracts Prisma model name from given object and possible list of all subjects\n */\nexport type ExtractModelName<\n TObject,\n TModelName extends PropertyKey\n> = TObject extends { kind: TModelName }\n ? TObject['kind']\n : TObject extends ForcedSubject<TModelName>\n ? TObject['__caslSubjectType__']\n : TObject extends { __typename: TModelName }\n ? TObject['__typename']\n : TModelName;\n","import { rulesToQuery } from '@casl/ability/extra';\nimport { AnyAbility, ForbiddenError, Generics, PureAbility } from '@casl/ability';\nimport { BasePrismaQuery, InferPrismaTypes } from './types';\n\nfunction convertToPrismaQuery(rule: AnyAbility['rules'][number]) {\n return rule.inverted ? { NOT: rule.conditions } : rule.conditions;\n}\n\nconst proxyHandlers: ProxyHandler<{ _ability: AnyAbility, _action: string }> = {\n get(target, subjectType) {\n const query = rulesToQuery(target._ability, target._action, subjectType, convertToPrismaQuery);\n\n if (query === null) {\n const error = ForbiddenError.from(target._ability)\n .setMessage(`It's not allowed to run \"${target._action}\" on \"${subjectType as string}\"`);\n error.action = target._action;\n error.subjectType = error.subject = subjectType as string;\n throw error;\n }\n\n const prismaQuery = Object.create(null);\n\n if (query.$or) {\n prismaQuery.OR = query.$or;\n }\n\n if (query.$and) {\n prismaQuery.AND = query.$and;\n }\n\n return prismaQuery;\n }\n};\n\n/**\n * @deprecated use accessibleBy directly instead. It will infer the types from passed Ability instance.\n */\nexport const createAccessibleByFactory = <\n TResult extends Record<string, unknown>,\n TPrismaQuery\n>() => {\n return function accessibleBy<TAbility extends PureAbility<any, TPrismaQuery>>(ability: TAbility, action: TAbility[\"rules\"][number][\"action\"] = \"read\"): TResult {\n return new Proxy({\n _ability: ability,\n _action: action,\n }, proxyHandlers) as unknown as TResult;\n };\n};\n\nexport function accessibleBy<TAbility extends PureAbility<any, BasePrismaQuery>>(\n ability: TAbility,\n action: TAbility[\"rules\"][number][\"action\"] = \"read\"\n): InferPrismaTypes<Generics<TAbility>['conditions']>['WhereInput'] {\n return new Proxy({\n _ability: ability,\n _action: action,\n }, proxyHandlers) as Record<string, any>;\n};\n","import {\n AbilityOptions,\n AbilityOptionsOf,\n AbilityTuple,\n fieldPatternMatcher,\n PureAbility,\n RawRuleFrom,\n RawRuleOf\n} from '@casl/ability';\nimport { prismaQuery } from './prisma/prismaQuery';\n\nexport function createAbilityFactory<\n TModelName extends string,\n TPrismaQuery extends Record<string, any>\n>() {\n function createAbility<\n T extends PureAbility<any, TPrismaQuery>\n >(rules?: RawRuleOf<T>[], options?: AbilityOptionsOf<T>): T;\n function createAbility<\n A extends AbilityTuple = [string, TModelName],\n C extends TPrismaQuery = TPrismaQuery\n >(\n rules?: RawRuleFrom<A, C>[],\n options?: AbilityOptions<A, C>\n ): PureAbility<A, C>;\n function createAbility(rules: any[] = [], options = {}): PureAbility<any, any> {\n return new PureAbility(rules, {\n ...options,\n conditionsMatcher: prismaQuery,\n fieldMatcher: fieldPatternMatcher,\n });\n }\n\n return createAbility;\n}\n"],"names":["ParsingQueryError","Error","invalidArgument","operatorName","value","expectValueType","valueType","JSON","stringify","this","isPlainObject","constructor","Object","equals","type","validate","instruction","Array","isArray","name","not","parse","hasOperators","field","FieldCondition","CompoundCondition","within","lt","isComparable","Number","isFinite","Date","POSSIBLE_MODES","Set","mode","has","from","join","NULL_CONDITION","compareString","query","compound","arrayOrObject","conditions","map","v","booleanField","hasSome","relation","inverted","baseInstruction","assign","_","ctx","condition","operator","instructions","in","notIn","lte","gt","gte","startsWith","endsWith","contains","isEmpty","hasEvery","NOT","AND","OR","every","some","none","is","isNot","isSet","PrismaQueryParser","ObjectQueryParser","super","defaultOperatorName","options","buildAnd","parseFieldOperators","object","get","istartsWith","toLowerCase","iendsWith","includes","icontains","empty","length","interpret","items","item","subCondition","undefined","toComparable","valueOf","compareValues","a","b","compare","interpretPrismaQuery","createJsInterpreter","eq","notEquals","ne","and","or","parser","prismaQuery","createTranslatorFactory","convertToPrismaQuery","rule","proxyHandlers","target","subjectType","rulesToQuery","_ability","_action","error","ForbiddenError","setMessage","action","subject","create","$or","$and","createAccessibleByFactory","accessibleBy","ability","Proxy","createAbilityFactory","createAbility","rules","PureAbility","conditionsMatcher","fieldMatcher","fieldPatternMatcher"],"mappings":"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"}