@casl/mongoose 6.0.0 → 7.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:true});var t=require("@casl/ability");var e=require("mongoose");var n=require("@casl/ability/extra");function r(t){return t&&"object"===typeof t&&"default"in t?t:{default:t}}var o=r(e);function i(t){const e=t.conditions;return t.inverted?{$nor:[e]}:e}function s(t,e,r="read"){return n.rulesToQuery(t,r,e,i)}function c(e,n,r,o){o.where({__forbiddenByCasl__:1});const i=o;if("function"===typeof i.pre)i.pre((o=>{const i=t.ForbiddenError.from(e);i.action=n;i.subjectType=r;i.setMessage(t.getDefaultErrorMessage(i));o(i)}));return o}function u(t,e){let n=this.modelName;if(!n)n="model"in this?this.model.modelName:null;if(!n)throw new TypeError("Cannot detect model name to return accessible records");const r=s(t,n,e);if(null===r)return c(t,e||"read",n,this.where());return this instanceof o["default"].Query?this.and([r]):this.where({$and:[r]})}function f(t){t.query.accessibleBy=u;t.statics.accessibleBy=u}const l=t=>Object.keys(t.paths);function a(e,n){const r=n.getFields(e);if(!n||!("except"in n))return r;const o=t.wrapArray(n.except);return r.filter((t=>-1===o.indexOf(t)))}function d(){let e;return(n,r)=>{if(!e){const o=r&&"only"in r?t.wrapArray(r.only):a(n,r);e=t=>t.fields||o}return e}}function h(t,e){const r=Object.assign({getFields:l},e);const o=d();function i(e,i){const s="function"===typeof this?this.modelName:this;return n.permittedFieldsOf(e,i||"read",s,{fieldsFrom:o(t,r)})}t.statics.accessibleFieldsBy=i;t.method("accessibleFieldsBy",i)}exports.accessibleFieldsPlugin=h;exports.accessibleRecordsPlugin=f;exports.getSchemaPaths=l;exports.toMongoQuery=s;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});var t=require("@casl/ability");var n=require("@casl/ability/extra");function r(t){const n=t.conditions;return t.inverted?{$nor:[n]}:n}function e(t,e,o="read"){return n.rulesToQuery(t,o,e,r)}function o(n,r,e,o){o.where({__forbiddenByCasl__:1});const c=o;if("function"===typeof c.pre)c.pre((o=>{const c=t.ForbiddenError.from(n);c.action=r;c.subjectType=e;c.setMessage(t.getDefaultErrorMessage(c));o(c)}));return o}function c(t,n,r){const c=n.detectSubjectType({constructor:t.model});if(!c)throw new TypeError(`Cannot detect subjec type of "${t.model.modelName}" to return accessible records`);const s=e(n,c,r);if(null===s)return o(n,r||"read",c,t.where());return t.and([s])}function s(t,n){return c(this.where(),t,n)}function i(t,n){return c(this,t,n)}function u(t){t.query.accessibleBy=i;t.statics.accessibleBy=s}const f=t=>Object.keys(t.paths);function l(n,r){const e=r.getFields(n);if(!r||!("except"in r))return e;const o=t.wrapArray(r.except);return e.filter((t=>-1===o.indexOf(t)))}function a(){let n;return(r,e)=>{if(!n){const o=e&&"only"in e?t.wrapArray(e.only):l(r,e);n=t=>t.fields||o}return n}}function d(t,r){const e=Object.assign({getFields:f},r);const o=a();function c(r,c){return n.permittedFieldsOf(r,c||"read",this,{fieldsFrom:o(t,e)})}function s(r,c){const s={constructor:this};return n.permittedFieldsOf(r,c||"read",s,{fieldsFrom:o(t,e)})}t.statics.accessibleFieldsBy=s;t.method("accessibleFieldsBy",c)}exports.accessibleFieldsPlugin=d;exports.accessibleRecordsPlugin=u;exports.getSchemaPaths=f;exports.toMongoQuery=e;
2
2
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/mongo.ts","../../src/accessible_records.ts","../../src/accessible_fields.ts"],"sourcesContent":["import { AnyMongoAbility } from '@casl/ability';\nimport { rulesToQuery } from '@casl/ability/extra';\n\nfunction convertToMongoQuery(rule: AnyMongoAbility['rules'][number]) {\n const conditions = rule.conditions!;\n return rule.inverted ? { $nor: [conditions] } : conditions;\n}\n\nexport function toMongoQuery<T extends AnyMongoAbility>(\n ability: T,\n subjectType: Parameters<T['rulesFor']>[1],\n action: Parameters<T['rulesFor']>[0] = 'read'\n) {\n return rulesToQuery(ability, action, subjectType, convertToMongoQuery);\n}\n","import { Normalize, AnyMongoAbility, Generics, ForbiddenError, getDefaultErrorMessage } from '@casl/ability';\nimport type { Schema, QueryWithHelpers, Model, Document } from 'mongoose';\nimport mongoose from 'mongoose';\nimport { toMongoQuery } from './mongo';\n\nfunction failedQuery(\n ability: AnyMongoAbility,\n action: string,\n modelName: string,\n query: QueryWithHelpers<Document, Document>\n) {\n query.where({ __forbiddenByCasl__: 1 }); // eslint-disable-line\n const anyQuery: any = query;\n\n if (typeof anyQuery.pre === 'function') {\n anyQuery.pre((cb: (error?: Error) => void) => {\n const error = ForbiddenError.from(ability);\n error.action = action;\n error.subjectType = modelName;\n error.setMessage(getDefaultErrorMessage(error));\n cb(error);\n });\n }\n\n return query;\n}\n\nfunction accessibleBy<T extends AnyMongoAbility>(\n this: any,\n ability: T,\n action?: Normalize<Generics<T>['abilities']>[0]\n): QueryWithHelpers<Document, Document> {\n let modelName: string | undefined = this.modelName;\n\n if (!modelName) {\n modelName = 'model' in this ? this.model.modelName : null;\n }\n\n if (!modelName) {\n throw new TypeError('Cannot detect model name to return accessible records');\n }\n\n const query = toMongoQuery(ability, modelName, action);\n\n if (query === null) {\n return failedQuery(ability, action || 'read', modelName, this.where());\n }\n\n return this instanceof mongoose.Query ? this.and([query]) : this.where({ $and: [query] });\n}\n\ntype GetAccessibleRecords<T extends Document> = <U extends AnyMongoAbility>(\n ability: U,\n action?: Normalize<Generics<U>['abilities']>[0]\n) => QueryWithHelpers<T, T, QueryHelpers<T>>;\n\ntype QueryHelpers<T extends Document> = {\n accessibleBy: GetAccessibleRecords<T>\n};\nexport interface AccessibleRecordModel<\n T extends Document, K = unknown\n> extends Model<T, K & QueryHelpers<T>> {\n accessibleBy: GetAccessibleRecords<T>\n}\n\nexport function accessibleRecordsPlugin(schema: Schema<any>) {\n schema.query.accessibleBy = accessibleBy;\n schema.statics.accessibleBy = accessibleBy;\n}\n","import { wrapArray, Normalize, AnyMongoAbility, Generics } from '@casl/ability';\nimport { permittedFieldsOf, PermittedFieldsOptions } from '@casl/ability/extra';\nimport type { Schema, Model, Document } from 'mongoose';\n\nexport type AccessibleFieldsOptions =\n {\n getFields(schema: Schema<Document>): string[]\n } &\n ({ only: string | string[] } | { except: string | string[] });\n\nexport const getSchemaPaths: AccessibleFieldsOptions['getFields'] = schema => Object.keys((schema as { paths: object }).paths);\n\nfunction fieldsOf(schema: Schema<Document>, options: Partial<AccessibleFieldsOptions>) {\n const fields = options.getFields!(schema);\n\n if (!options || !('except' in options)) {\n return fields;\n }\n\n const excludedFields = wrapArray(options.except);\n return fields.filter(field => excludedFields.indexOf(field) === -1);\n}\n\ntype GetAccessibleFields<T extends AccessibleFieldsDocument> = <U extends AnyMongoAbility>(\n this: Model<T> | T,\n ability: U,\n action?: Normalize<Generics<U>['abilities']>[0]\n) => string[];\n\nexport interface AccessibleFieldsModel<T extends AccessibleFieldsDocument> extends Model<T> {\n accessibleFieldsBy: GetAccessibleFields<T>\n}\n\nexport interface AccessibleFieldsDocument extends Document {\n accessibleFieldsBy: GetAccessibleFields<AccessibleFieldsDocument>\n}\n\nfunction modelFieldsGetter() {\n let fieldsFrom: PermittedFieldsOptions<AnyMongoAbility>['fieldsFrom'];\n return (schema: Schema<any>, options: Partial<AccessibleFieldsOptions>) => {\n if (!fieldsFrom) {\n const ALL_FIELDS = options && 'only' in options\n ? wrapArray(options.only as string[])\n : fieldsOf(schema, options);\n fieldsFrom = rule => rule.fields || ALL_FIELDS;\n }\n\n return fieldsFrom;\n };\n}\n\nexport function accessibleFieldsPlugin(\n schema: Schema<any>,\n rawOptions?: Partial<AccessibleFieldsOptions>\n) {\n const options = { getFields: getSchemaPaths, ...rawOptions };\n const fieldsFrom = modelFieldsGetter();\n type ModelOrDoc = Model<AccessibleFieldsDocument> | AccessibleFieldsDocument;\n\n function accessibleFieldsBy(this: ModelOrDoc, ability: AnyMongoAbility, action?: string) {\n const subject = typeof this === 'function' ? this.modelName : this;\n return permittedFieldsOf(ability, action || 'read', subject, {\n fieldsFrom: fieldsFrom(schema, options)\n });\n }\n\n schema.statics.accessibleFieldsBy = accessibleFieldsBy;\n schema.method('accessibleFieldsBy', accessibleFieldsBy);\n}\n"],"names":["convertToMongoQuery","rule","conditions","inverted","$nor","toMongoQuery","ability","subjectType","action","rulesToQuery","failedQuery","modelName","query","where","__forbiddenByCasl__","anyQuery","pre","cb","error","ForbiddenError","from","setMessage","getDefaultErrorMessage","accessibleBy","this","model","TypeError","mongoose","Query","and","$and","accessibleRecordsPlugin","schema","statics","getSchemaPaths","Object","keys","paths","fieldsOf","options","fields","getFields","excludedFields","wrapArray","except","filter","field","indexOf","modelFieldsGetter","fieldsFrom","ALL_FIELDS","only","accessibleFieldsPlugin","rawOptions","accessibleFieldsBy","subject","permittedFieldsOf","method"],"mappings":"wPAGA,SAASA,EAAoBC,SACrBC,EAAaD,EAAKC,kBACjBD,EAAKE,SAAW,CAAEC,KAAM,CAACF,IAAgBA,EAG3C,SAASG,EACdC,EACAC,EACAC,EAAuC,eAEhCC,eAAaH,EAASE,EAAQD,EAAaP,GCRpD,SAASU,EACPJ,EACAE,EACAG,EACAC,GAEAA,EAAMC,MAAM,CAAEC,oBAAqB,UAC7BC,EAAgBH,KAEM,oBAAjBG,EAASC,IAClBD,EAASC,KAAKC,UACNC,EAAQC,iBAAeC,KAAKd,GAClCY,EAAMV,OAASA,EACfU,EAAMX,YAAcI,EACpBO,EAAMG,WAAWC,yBAAuBJ,IACxCD,EAAGC,aAIAN,EAGT,SAASW,EAEPjB,EACAE,OAEIG,EAAgCa,KAAKb,cAEpCA,EACHA,EAAY,UAAWa,KAAOA,KAAKC,MAAMd,UAAY,SAGlDA,QACG,IAAIe,UAAU,+DAGhBd,EAAQP,EAAaC,EAASK,EAAWH,MAEjC,OAAVI,SACKF,EAAYJ,EAASE,GAAU,OAAQG,EAAWa,KAAKX,gBAGzDW,gBAAgBG,aAASC,MAAQJ,KAAKK,IAAI,CAACjB,IAAUY,KAAKX,MAAM,CAAEiB,KAAM,CAAClB,KAiB3E,SAASmB,EAAwBC,GACtCA,EAAOpB,MAAMW,aAAeA,EAC5BS,EAAOC,QAAQV,aAAeA,QCzDnBW,EAAuDF,GAAUG,OAAOC,KAAMJ,EAA6BK,OAExH,SAASC,EAASN,EAA0BO,SACpCC,EAASD,EAAQE,UAAWT,OAE7BO,KAAa,WAAYA,UACrBC,QAGHE,EAAiBC,YAAUJ,EAAQK,eAClCJ,EAAOK,QAAOC,IAA4C,IAAnCJ,EAAeK,QAAQD,KAiBvD,SAASE,QACHC,QACG,CAACjB,EAAqBO,SACtBU,EAAY,OACTC,EAAaX,GAAW,SAAUA,EACpCI,YAAUJ,EAAQY,MAClBb,EAASN,EAAQO,GACrBU,EAAahD,GAAQA,EAAKuC,QAAUU,SAG/BD,GAIJ,SAASG,EACdpB,EACAqB,SAEMd,iBAAYE,UAAWP,GAAmBmB,SAC1CJ,EAAaD,aAGVM,EAAqChD,EAA0BE,SAChE+C,EAA0B,oBAAT/B,KAAsBA,KAAKb,UAAYa,YACvDgC,oBAAkBlD,EAASE,GAAU,OAAQ+C,EAAS,CAC3DN,WAAYA,EAAWjB,EAAQO,KAInCP,EAAOC,QAAQqB,mBAAqBA,EACpCtB,EAAOyB,OAAO,qBAAsBH"}
1
+ {"version":3,"file":"index.js","sources":["../../src/mongo.ts","../../src/accessible_records.ts","../../src/accessible_fields.ts"],"sourcesContent":["import { AnyMongoAbility } from '@casl/ability';\nimport { AbilityQuery, rulesToQuery } from '@casl/ability/extra';\n\nfunction convertToMongoQuery(rule: AnyMongoAbility['rules'][number]) {\n const conditions = rule.conditions!;\n return rule.inverted ? { $nor: [conditions] } : conditions;\n}\n\nexport function toMongoQuery<T extends AnyMongoAbility>(\n ability: T,\n subjectType: Parameters<T['rulesFor']>[1],\n action: Parameters<T['rulesFor']>[0] = 'read'\n): AbilityQuery | null {\n return rulesToQuery(ability, action, subjectType, convertToMongoQuery);\n}\n","import { Normalize, AnyMongoAbility, Generics, ForbiddenError, getDefaultErrorMessage } from '@casl/ability';\nimport { Schema, QueryWithHelpers, Model, Document, HydratedDocument, Query } from 'mongoose';\nimport { toMongoQuery } from './mongo';\n\nfunction failedQuery(\n ability: AnyMongoAbility,\n action: string,\n modelName: string,\n query: QueryWithHelpers<Document, Document>\n) {\n query.where({ __forbiddenByCasl__: 1 }); // eslint-disable-line\n const anyQuery: any = query;\n\n if (typeof anyQuery.pre === 'function') {\n anyQuery.pre((cb: (error?: Error) => void) => {\n const error = ForbiddenError.from(ability);\n error.action = action;\n error.subjectType = modelName;\n error.setMessage(getDefaultErrorMessage(error));\n cb(error);\n });\n }\n\n return query;\n}\n\nfunction accessibleBy<T extends AnyMongoAbility>(\n baseQuery: Query<any, any>,\n ability: T,\n action?: Normalize<Generics<T>['abilities']>[0]\n): QueryWithHelpers<Document, Document> {\n const subjectType = ability.detectSubjectType({\n constructor: baseQuery.model\n });\n\n if (!subjectType) {\n throw new TypeError(`Cannot detect subjec type of \"${baseQuery.model.modelName}\" to return accessible records`);\n }\n\n const query = toMongoQuery(ability, subjectType, action);\n\n if (query === null) {\n return failedQuery(ability, action || 'read', subjectType, baseQuery.where());\n }\n\n return baseQuery.and([query]);\n}\n\ntype GetAccessibleRecords<T, TQueryHelpers, TMethods, TVirtuals> = <U extends AnyMongoAbility>(\n ability: U,\n action?: Normalize<Generics<U>['abilities']>[0]\n) => QueryWithHelpers<\nArray<T>,\nT,\nAccessibleRecordQueryHelpers<T, TQueryHelpers, TMethods, TVirtuals>\n>;\n\nexport type AccessibleRecordQueryHelpers<T, TQueryHelpers = {}, TMethods = {}, TVirtuals = {}> = {\n accessibleBy: GetAccessibleRecords<\n HydratedDocument<T, TMethods, TVirtuals>,\n TQueryHelpers,\n TMethods,\n TVirtuals\n >\n};\nexport interface AccessibleRecordModel<\n T,\n TQueryHelpers = {},\n TMethods = {},\n TVirtuals = {}\n> extends Model<T,\n TQueryHelpers & AccessibleRecordQueryHelpers<T, TQueryHelpers, TMethods, TVirtuals>,\n TMethods,\n TVirtuals> {\n accessibleBy: GetAccessibleRecords<\n HydratedDocument<T, TMethods, TVirtuals>,\n TQueryHelpers,\n TMethods,\n TVirtuals\n >\n}\n\nfunction modelAccessibleBy(this: Model<unknown>, ability: AnyMongoAbility, action?: string) {\n return accessibleBy(this.where(), ability, action);\n}\n\nfunction queryAccessibleBy(\n this: Query<unknown, unknown>,\n ability: AnyMongoAbility,\n action?: string\n) {\n return accessibleBy(this, ability, action);\n}\n\nexport function accessibleRecordsPlugin(schema: Schema<any>): void {\n (schema.query as Record<string, unknown>).accessibleBy = queryAccessibleBy;\n schema.statics.accessibleBy = modelAccessibleBy;\n}\n","import { wrapArray, Normalize, AnyMongoAbility, Generics } from '@casl/ability';\nimport { permittedFieldsOf, PermittedFieldsOptions } from '@casl/ability/extra';\nimport type { Schema, Model, Document } from 'mongoose';\n\nexport type AccessibleFieldsOptions =\n {\n getFields(schema: Schema<Document>): string[]\n } &\n ({ only: string | string[] } | { except: string | string[] });\n\nexport const getSchemaPaths: AccessibleFieldsOptions['getFields'] = schema => Object.keys((schema as { paths: object }).paths);\n\nfunction fieldsOf(schema: Schema<Document>, options: Partial<AccessibleFieldsOptions>) {\n const fields = options.getFields!(schema);\n\n if (!options || !('except' in options)) {\n return fields;\n }\n\n const excludedFields = wrapArray(options.except);\n return fields.filter(field => excludedFields.indexOf(field) === -1);\n}\n\ntype GetAccessibleFields<T> = <U extends AnyMongoAbility>(\n this: Model<T> | T,\n ability: U,\n action?: Normalize<Generics<U>['abilities']>[0]\n) => string[];\n\nexport interface AccessibleFieldsModel<\n T,\n TQueryHelpers = {},\n TMethods = {},\n TVirtuals = {}\n> extends Model<T, TQueryHelpers, TMethods & AccessibleFieldDocumentMethods<T>, TVirtuals> {\n accessibleFieldsBy: GetAccessibleFields<T>\n}\n\nexport interface AccessibleFieldDocumentMethods<T = Document> {\n accessibleFieldsBy: GetAccessibleFields<T>\n}\n\n/**\n * @deprecated Mongoose recommends against `extends Document`, prefer to use `AccessibleFieldsModel` instead.\n * See here: https://mongoosejs.com/docs/typescript.html#using-extends-document\n */\nexport interface AccessibleFieldsDocument extends Document, AccessibleFieldDocumentMethods {}\n\nfunction modelFieldsGetter() {\n let fieldsFrom: PermittedFieldsOptions<AnyMongoAbility>['fieldsFrom'];\n return (schema: Schema<any>, options: Partial<AccessibleFieldsOptions>) => {\n if (!fieldsFrom) {\n const ALL_FIELDS = options && 'only' in options\n ? wrapArray(options.only as string[])\n : fieldsOf(schema, options);\n fieldsFrom = rule => rule.fields || ALL_FIELDS;\n }\n\n return fieldsFrom;\n };\n}\n\nexport function accessibleFieldsPlugin(\n schema: Schema<any>,\n rawOptions?: Partial<AccessibleFieldsOptions>\n): void {\n const options = { getFields: getSchemaPaths, ...rawOptions };\n const fieldsFrom = modelFieldsGetter();\n\n function istanceAccessibleFields(this: Document, ability: AnyMongoAbility, action?: string) {\n return permittedFieldsOf(ability, action || 'read', this, {\n fieldsFrom: fieldsFrom(schema, options)\n });\n }\n\n function modelAccessibleFields(this: Model<unknown>, ability: AnyMongoAbility, action?: string) {\n const document = { constructor: this };\n return permittedFieldsOf(ability, action || 'read', document, {\n fieldsFrom: fieldsFrom(schema, options)\n });\n }\n\n schema.statics.accessibleFieldsBy = modelAccessibleFields;\n schema.method('accessibleFieldsBy', istanceAccessibleFields);\n}\n"],"names":["convertToMongoQuery","rule","conditions","inverted","$nor","toMongoQuery","ability","subjectType","action","rulesToQuery","failedQuery","modelName","query","where","__forbiddenByCasl__","anyQuery","pre","cb","error","ForbiddenError","from","setMessage","getDefaultErrorMessage","accessibleBy","baseQuery","detectSubjectType","constructor","model","TypeError","and","modelAccessibleBy","this","queryAccessibleBy","accessibleRecordsPlugin","schema","statics","getSchemaPaths","Object","keys","paths","fieldsOf","options","fields","getFields","excludedFields","wrapArray","except","filter","field","indexOf","modelFieldsGetter","fieldsFrom","ALL_FIELDS","only","accessibleFieldsPlugin","rawOptions","istanceAccessibleFields","permittedFieldsOf","modelAccessibleFields","document","accessibleFieldsBy","method"],"mappings":"0IAGA,SAASA,EAAoBC,SACrBC,EAAaD,EAAKC,kBACjBD,EAAKE,SAAW,CAAEC,KAAM,CAACF,IAAgBA,EAG3C,SAASG,EACdC,EACAC,EACAC,EAAuC,eAEhCC,eAAaH,EAASE,EAAQD,EAAaP,GCTpD,SAASU,EACPJ,EACAE,EACAG,EACAC,GAEAA,EAAMC,MAAM,CAAEC,oBAAqB,UAC7BC,EAAgBH,KAEM,oBAAjBG,EAASC,IAClBD,EAASC,KAAKC,UACNC,EAAQC,iBAAeC,KAAKd,GAClCY,EAAMV,OAASA,EACfU,EAAMX,YAAcI,EACpBO,EAAMG,WAAWC,yBAAuBJ,IACxCD,EAAGC,aAIAN,EAGT,SAASW,EACPC,EACAlB,EACAE,SAEMD,EAAcD,EAAQmB,kBAAkB,CAC5CC,YAAaF,EAAUG,YAGpBpB,QACG,IAAIqB,UAAW,iCAAgCJ,EAAUG,MAAMhB,iDAGjEC,EAAQP,EAAaC,EAASC,EAAaC,MAEnC,OAAVI,SACKF,EAAYJ,EAASE,GAAU,OAAQD,EAAaiB,EAAUX,gBAGhEW,EAAUK,IAAI,CAACjB,IAqCxB,SAASkB,EAAwCxB,EAA0BE,UAClEe,EAAaQ,KAAKlB,QAASP,EAASE,GAG7C,SAASwB,EAEP1B,EACAE,UAEOe,EAAaQ,KAAMzB,EAASE,GAG9B,SAASyB,EAAwBC,GACrCA,EAAOtB,MAAkCW,aAAeS,EACzDE,EAAOC,QAAQZ,aAAeO,QCtFnBM,EAAuDF,GAAUG,OAAOC,KAAMJ,EAA6BK,OAExH,SAASC,EAASN,EAA0BO,SACpCC,EAASD,EAAQE,UAAWT,OAE7BO,KAAa,WAAYA,UACrBC,QAGHE,EAAiBC,YAAUJ,EAAQK,eAClCJ,EAAOK,QAAOC,IAA4C,IAAnCJ,EAAeK,QAAQD,KA4BvD,SAASE,QACHC,QACG,CAACjB,EAAqBO,SACtBU,EAAY,OACTC,EAAaX,GAAW,SAAUA,EACpCI,YAAUJ,EAAQY,MAClBb,EAASN,EAAQO,GACrBU,EAAalD,GAAQA,EAAKyC,QAAUU,SAG/BD,GAIJ,SAASG,EACdpB,EACAqB,SAEMd,iBAAYE,UAAWP,GAAmBmB,SAC1CJ,EAAaD,aAEVM,EAAwClD,EAA0BE,UAClEiD,oBAAkBnD,EAASE,GAAU,OAAQuB,KAAM,CACxDoB,WAAYA,EAAWjB,EAAQO,cAI1BiB,EAA4CpD,EAA0BE,SACvEmD,EAAW,CAAEjC,YAAaK,aACzB0B,oBAAkBnD,EAASE,GAAU,OAAQmD,EAAU,CAC5DR,WAAYA,EAAWjB,EAAQO,KAInCP,EAAOC,QAAQyB,mBAAqBF,EACpCxB,EAAO2B,OAAO,qBAAsBL"}
@@ -1,2 +1,2 @@
1
- import{ForbiddenError as t,getDefaultErrorMessage as n,wrapArray as o}from"@casl/ability";import i from"mongoose";import{rulesToQuery as e,permittedFieldsOf as r}from"@casl/ability/extra";function c(t){const n=t.conditions;return t.inverted?{$nor:[n]}:n}function s(t,n,o="read"){return e(t,o,n,c)}function f(o,i,e,r){r.where({__forbiddenByCasl__:1});const c=r;if("function"===typeof c.pre)c.pre((r=>{const c=t.from(o);c.action=i;c.subjectType=e;c.setMessage(n(c));r(c)}));return r}function u(t,n){let o=this.modelName;if(!o)o="model"in this?this.model.modelName:null;if(!o)throw new TypeError("Cannot detect model name to return accessible records");const e=s(t,o,n);if(null===e)return f(t,n||"read",o,this.where());return this instanceof i.Query?this.and([e]):this.where({$and:[e]})}function l(t){t.query.accessibleBy=u;t.statics.accessibleBy=u}const a=t=>Object.keys(t.paths);function d(t,n){const i=n.getFields(t);if(!n||!("except"in n))return i;const e=o(n.except);return i.filter((t=>-1===e.indexOf(t)))}function h(){let t;return(n,i)=>{if(!t){const e=i&&"only"in i?o(i.only):d(n,i);t=t=>t.fields||e}return t}}function m(t,n){const o=Object.assign({getFields:a},n);const i=h();function e(n,e){const c="function"===typeof this?this.modelName:this;return r(n,e||"read",c,{fieldsFrom:i(t,o)})}t.statics.accessibleFieldsBy=e;t.method("accessibleFieldsBy",e)}export{m as accessibleFieldsPlugin,l as accessibleRecordsPlugin,a as getSchemaPaths,s as toMongoQuery};
1
+ import{ForbiddenError as t,getDefaultErrorMessage as n,wrapArray as r}from"@casl/ability";import{rulesToQuery as o,permittedFieldsOf as e}from"@casl/ability/extra";function c(t){const n=t.conditions;return t.inverted?{$nor:[n]}:n}function i(t,n,r="read"){return o(t,r,n,c)}function s(r,o,e,c){c.where({__forbiddenByCasl__:1});const i=c;if("function"===typeof i.pre)i.pre((c=>{const i=t.from(r);i.action=o;i.subjectType=e;i.setMessage(n(i));c(i)}));return c}function u(t,n,r){const o=n.detectSubjectType({constructor:t.model});if(!o)throw new TypeError(`Cannot detect subjec type of "${t.model.modelName}" to return accessible records`);const e=i(n,o,r);if(null===e)return s(n,r||"read",o,t.where());return t.and([e])}function f(t,n){return u(this.where(),t,n)}function l(t,n){return u(this,t,n)}function a(t){t.query.accessibleBy=l;t.statics.accessibleBy=f}const d=t=>Object.keys(t.paths);function b(t,n){const o=n.getFields(t);if(!n||!("except"in n))return o;const e=r(n.except);return o.filter((t=>-1===e.indexOf(t)))}function y(){let t;return(n,o)=>{if(!t){const e=o&&"only"in o?r(o.only):b(n,o);t=t=>t.fields||e}return t}}function p(t,n){const r=Object.assign({getFields:d},n);const o=y();function c(n,c){return e(n,c||"read",this,{fieldsFrom:o(t,r)})}function i(n,c){const i={constructor:this};return e(n,c||"read",i,{fieldsFrom:o(t,r)})}t.statics.accessibleFieldsBy=i;t.method("accessibleFieldsBy",c)}export{p as accessibleFieldsPlugin,a as accessibleRecordsPlugin,d as getSchemaPaths,i as toMongoQuery};
2
2
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../../src/mongo.ts","../../src/accessible_records.ts","../../src/accessible_fields.ts"],"sourcesContent":["import { AnyMongoAbility } from '@casl/ability';\nimport { rulesToQuery } from '@casl/ability/extra';\n\nfunction convertToMongoQuery(rule: AnyMongoAbility['rules'][number]) {\n const conditions = rule.conditions!;\n return rule.inverted ? { $nor: [conditions] } : conditions;\n}\n\nexport function toMongoQuery<T extends AnyMongoAbility>(\n ability: T,\n subjectType: Parameters<T['rulesFor']>[1],\n action: Parameters<T['rulesFor']>[0] = 'read'\n) {\n return rulesToQuery(ability, action, subjectType, convertToMongoQuery);\n}\n","import { Normalize, AnyMongoAbility, Generics, ForbiddenError, getDefaultErrorMessage } from '@casl/ability';\nimport type { Schema, QueryWithHelpers, Model, Document } from 'mongoose';\nimport mongoose from 'mongoose';\nimport { toMongoQuery } from './mongo';\n\nfunction failedQuery(\n ability: AnyMongoAbility,\n action: string,\n modelName: string,\n query: QueryWithHelpers<Document, Document>\n) {\n query.where({ __forbiddenByCasl__: 1 }); // eslint-disable-line\n const anyQuery: any = query;\n\n if (typeof anyQuery.pre === 'function') {\n anyQuery.pre((cb: (error?: Error) => void) => {\n const error = ForbiddenError.from(ability);\n error.action = action;\n error.subjectType = modelName;\n error.setMessage(getDefaultErrorMessage(error));\n cb(error);\n });\n }\n\n return query;\n}\n\nfunction accessibleBy<T extends AnyMongoAbility>(\n this: any,\n ability: T,\n action?: Normalize<Generics<T>['abilities']>[0]\n): QueryWithHelpers<Document, Document> {\n let modelName: string | undefined = this.modelName;\n\n if (!modelName) {\n modelName = 'model' in this ? this.model.modelName : null;\n }\n\n if (!modelName) {\n throw new TypeError('Cannot detect model name to return accessible records');\n }\n\n const query = toMongoQuery(ability, modelName, action);\n\n if (query === null) {\n return failedQuery(ability, action || 'read', modelName, this.where());\n }\n\n return this instanceof mongoose.Query ? this.and([query]) : this.where({ $and: [query] });\n}\n\ntype GetAccessibleRecords<T extends Document> = <U extends AnyMongoAbility>(\n ability: U,\n action?: Normalize<Generics<U>['abilities']>[0]\n) => QueryWithHelpers<T, T, QueryHelpers<T>>;\n\ntype QueryHelpers<T extends Document> = {\n accessibleBy: GetAccessibleRecords<T>\n};\nexport interface AccessibleRecordModel<\n T extends Document, K = unknown\n> extends Model<T, K & QueryHelpers<T>> {\n accessibleBy: GetAccessibleRecords<T>\n}\n\nexport function accessibleRecordsPlugin(schema: Schema<any>) {\n schema.query.accessibleBy = accessibleBy;\n schema.statics.accessibleBy = accessibleBy;\n}\n","import { wrapArray, Normalize, AnyMongoAbility, Generics } from '@casl/ability';\nimport { permittedFieldsOf, PermittedFieldsOptions } from '@casl/ability/extra';\nimport type { Schema, Model, Document } from 'mongoose';\n\nexport type AccessibleFieldsOptions =\n {\n getFields(schema: Schema<Document>): string[]\n } &\n ({ only: string | string[] } | { except: string | string[] });\n\nexport const getSchemaPaths: AccessibleFieldsOptions['getFields'] = schema => Object.keys((schema as { paths: object }).paths);\n\nfunction fieldsOf(schema: Schema<Document>, options: Partial<AccessibleFieldsOptions>) {\n const fields = options.getFields!(schema);\n\n if (!options || !('except' in options)) {\n return fields;\n }\n\n const excludedFields = wrapArray(options.except);\n return fields.filter(field => excludedFields.indexOf(field) === -1);\n}\n\ntype GetAccessibleFields<T extends AccessibleFieldsDocument> = <U extends AnyMongoAbility>(\n this: Model<T> | T,\n ability: U,\n action?: Normalize<Generics<U>['abilities']>[0]\n) => string[];\n\nexport interface AccessibleFieldsModel<T extends AccessibleFieldsDocument> extends Model<T> {\n accessibleFieldsBy: GetAccessibleFields<T>\n}\n\nexport interface AccessibleFieldsDocument extends Document {\n accessibleFieldsBy: GetAccessibleFields<AccessibleFieldsDocument>\n}\n\nfunction modelFieldsGetter() {\n let fieldsFrom: PermittedFieldsOptions<AnyMongoAbility>['fieldsFrom'];\n return (schema: Schema<any>, options: Partial<AccessibleFieldsOptions>) => {\n if (!fieldsFrom) {\n const ALL_FIELDS = options && 'only' in options\n ? wrapArray(options.only as string[])\n : fieldsOf(schema, options);\n fieldsFrom = rule => rule.fields || ALL_FIELDS;\n }\n\n return fieldsFrom;\n };\n}\n\nexport function accessibleFieldsPlugin(\n schema: Schema<any>,\n rawOptions?: Partial<AccessibleFieldsOptions>\n) {\n const options = { getFields: getSchemaPaths, ...rawOptions };\n const fieldsFrom = modelFieldsGetter();\n type ModelOrDoc = Model<AccessibleFieldsDocument> | AccessibleFieldsDocument;\n\n function accessibleFieldsBy(this: ModelOrDoc, ability: AnyMongoAbility, action?: string) {\n const subject = typeof this === 'function' ? this.modelName : this;\n return permittedFieldsOf(ability, action || 'read', subject, {\n fieldsFrom: fieldsFrom(schema, options)\n });\n }\n\n schema.statics.accessibleFieldsBy = accessibleFieldsBy;\n schema.method('accessibleFieldsBy', accessibleFieldsBy);\n}\n"],"names":["convertToMongoQuery","rule","conditions","inverted","$nor","toMongoQuery","ability","subjectType","action","rulesToQuery","failedQuery","modelName","query","where","__forbiddenByCasl__","anyQuery","pre","cb","error","ForbiddenError","from","setMessage","getDefaultErrorMessage","accessibleBy","this","model","TypeError","mongoose","Query","and","$and","accessibleRecordsPlugin","schema","statics","getSchemaPaths","Object","keys","paths","fieldsOf","options","fields","getFields","excludedFields","wrapArray","except","filter","field","indexOf","modelFieldsGetter","fieldsFrom","ALL_FIELDS","only","accessibleFieldsPlugin","rawOptions","accessibleFieldsBy","subject","permittedFieldsOf","method"],"mappings":"4LAGA,SAASA,EAAoBC,SACrBC,EAAaD,EAAKC,kBACjBD,EAAKE,SAAW,CAAEC,KAAM,CAACF,IAAgBA,EAG3C,SAASG,EACdC,EACAC,EACAC,EAAuC,eAEhCC,EAAaH,EAASE,EAAQD,EAAaP,GCRpD,SAASU,EACPJ,EACAE,EACAG,EACAC,GAEAA,EAAMC,MAAM,CAAEC,oBAAqB,UAC7BC,EAAgBH,KAEM,oBAAjBG,EAASC,IAClBD,EAASC,KAAKC,UACNC,EAAQC,EAAeC,KAAKd,GAClCY,EAAMV,OAASA,EACfU,EAAMX,YAAcI,EACpBO,EAAMG,WAAWC,EAAuBJ,IACxCD,EAAGC,aAIAN,EAGT,SAASW,EAEPjB,EACAE,OAEIG,EAAgCa,KAAKb,cAEpCA,EACHA,EAAY,UAAWa,KAAOA,KAAKC,MAAMd,UAAY,SAGlDA,QACG,IAAIe,UAAU,+DAGhBd,EAAQP,EAAaC,EAASK,EAAWH,MAEjC,OAAVI,SACKF,EAAYJ,EAASE,GAAU,OAAQG,EAAWa,KAAKX,gBAGzDW,gBAAgBG,EAASC,MAAQJ,KAAKK,IAAI,CAACjB,IAAUY,KAAKX,MAAM,CAAEiB,KAAM,CAAClB,KAiB3E,SAASmB,EAAwBC,GACtCA,EAAOpB,MAAMW,aAAeA,EAC5BS,EAAOC,QAAQV,aAAeA,QCzDnBW,EAAuDF,GAAUG,OAAOC,KAAMJ,EAA6BK,OAExH,SAASC,EAASN,EAA0BO,SACpCC,EAASD,EAAQE,UAAWT,OAE7BO,KAAa,WAAYA,UACrBC,QAGHE,EAAiBC,EAAUJ,EAAQK,eAClCJ,EAAOK,QAAOC,IAA4C,IAAnCJ,EAAeK,QAAQD,KAiBvD,SAASE,QACHC,QACG,CAACjB,EAAqBO,SACtBU,EAAY,OACTC,EAAaX,GAAW,SAAUA,EACpCI,EAAUJ,EAAQY,MAClBb,EAASN,EAAQO,GACrBU,EAAahD,GAAQA,EAAKuC,QAAUU,SAG/BD,GAIJ,SAASG,EACdpB,EACAqB,SAEMd,iBAAYE,UAAWP,GAAmBmB,SAC1CJ,EAAaD,aAGVM,EAAqChD,EAA0BE,SAChE+C,EAA0B,oBAAT/B,KAAsBA,KAAKb,UAAYa,YACvDgC,EAAkBlD,EAASE,GAAU,OAAQ+C,EAAS,CAC3DN,WAAYA,EAAWjB,EAAQO,KAInCP,EAAOC,QAAQqB,mBAAqBA,EACpCtB,EAAOyB,OAAO,qBAAsBH"}
1
+ {"version":3,"file":"index.mjs","sources":["../../src/mongo.ts","../../src/accessible_records.ts","../../src/accessible_fields.ts"],"sourcesContent":["import { AnyMongoAbility } from '@casl/ability';\nimport { AbilityQuery, rulesToQuery } from '@casl/ability/extra';\n\nfunction convertToMongoQuery(rule: AnyMongoAbility['rules'][number]) {\n const conditions = rule.conditions!;\n return rule.inverted ? { $nor: [conditions] } : conditions;\n}\n\nexport function toMongoQuery<T extends AnyMongoAbility>(\n ability: T,\n subjectType: Parameters<T['rulesFor']>[1],\n action: Parameters<T['rulesFor']>[0] = 'read'\n): AbilityQuery | null {\n return rulesToQuery(ability, action, subjectType, convertToMongoQuery);\n}\n","import { Normalize, AnyMongoAbility, Generics, ForbiddenError, getDefaultErrorMessage } from '@casl/ability';\nimport { Schema, QueryWithHelpers, Model, Document, HydratedDocument, Query } from 'mongoose';\nimport { toMongoQuery } from './mongo';\n\nfunction failedQuery(\n ability: AnyMongoAbility,\n action: string,\n modelName: string,\n query: QueryWithHelpers<Document, Document>\n) {\n query.where({ __forbiddenByCasl__: 1 }); // eslint-disable-line\n const anyQuery: any = query;\n\n if (typeof anyQuery.pre === 'function') {\n anyQuery.pre((cb: (error?: Error) => void) => {\n const error = ForbiddenError.from(ability);\n error.action = action;\n error.subjectType = modelName;\n error.setMessage(getDefaultErrorMessage(error));\n cb(error);\n });\n }\n\n return query;\n}\n\nfunction accessibleBy<T extends AnyMongoAbility>(\n baseQuery: Query<any, any>,\n ability: T,\n action?: Normalize<Generics<T>['abilities']>[0]\n): QueryWithHelpers<Document, Document> {\n const subjectType = ability.detectSubjectType({\n constructor: baseQuery.model\n });\n\n if (!subjectType) {\n throw new TypeError(`Cannot detect subjec type of \"${baseQuery.model.modelName}\" to return accessible records`);\n }\n\n const query = toMongoQuery(ability, subjectType, action);\n\n if (query === null) {\n return failedQuery(ability, action || 'read', subjectType, baseQuery.where());\n }\n\n return baseQuery.and([query]);\n}\n\ntype GetAccessibleRecords<T, TQueryHelpers, TMethods, TVirtuals> = <U extends AnyMongoAbility>(\n ability: U,\n action?: Normalize<Generics<U>['abilities']>[0]\n) => QueryWithHelpers<\nArray<T>,\nT,\nAccessibleRecordQueryHelpers<T, TQueryHelpers, TMethods, TVirtuals>\n>;\n\nexport type AccessibleRecordQueryHelpers<T, TQueryHelpers = {}, TMethods = {}, TVirtuals = {}> = {\n accessibleBy: GetAccessibleRecords<\n HydratedDocument<T, TMethods, TVirtuals>,\n TQueryHelpers,\n TMethods,\n TVirtuals\n >\n};\nexport interface AccessibleRecordModel<\n T,\n TQueryHelpers = {},\n TMethods = {},\n TVirtuals = {}\n> extends Model<T,\n TQueryHelpers & AccessibleRecordQueryHelpers<T, TQueryHelpers, TMethods, TVirtuals>,\n TMethods,\n TVirtuals> {\n accessibleBy: GetAccessibleRecords<\n HydratedDocument<T, TMethods, TVirtuals>,\n TQueryHelpers,\n TMethods,\n TVirtuals\n >\n}\n\nfunction modelAccessibleBy(this: Model<unknown>, ability: AnyMongoAbility, action?: string) {\n return accessibleBy(this.where(), ability, action);\n}\n\nfunction queryAccessibleBy(\n this: Query<unknown, unknown>,\n ability: AnyMongoAbility,\n action?: string\n) {\n return accessibleBy(this, ability, action);\n}\n\nexport function accessibleRecordsPlugin(schema: Schema<any>): void {\n (schema.query as Record<string, unknown>).accessibleBy = queryAccessibleBy;\n schema.statics.accessibleBy = modelAccessibleBy;\n}\n","import { wrapArray, Normalize, AnyMongoAbility, Generics } from '@casl/ability';\nimport { permittedFieldsOf, PermittedFieldsOptions } from '@casl/ability/extra';\nimport type { Schema, Model, Document } from 'mongoose';\n\nexport type AccessibleFieldsOptions =\n {\n getFields(schema: Schema<Document>): string[]\n } &\n ({ only: string | string[] } | { except: string | string[] });\n\nexport const getSchemaPaths: AccessibleFieldsOptions['getFields'] = schema => Object.keys((schema as { paths: object }).paths);\n\nfunction fieldsOf(schema: Schema<Document>, options: Partial<AccessibleFieldsOptions>) {\n const fields = options.getFields!(schema);\n\n if (!options || !('except' in options)) {\n return fields;\n }\n\n const excludedFields = wrapArray(options.except);\n return fields.filter(field => excludedFields.indexOf(field) === -1);\n}\n\ntype GetAccessibleFields<T> = <U extends AnyMongoAbility>(\n this: Model<T> | T,\n ability: U,\n action?: Normalize<Generics<U>['abilities']>[0]\n) => string[];\n\nexport interface AccessibleFieldsModel<\n T,\n TQueryHelpers = {},\n TMethods = {},\n TVirtuals = {}\n> extends Model<T, TQueryHelpers, TMethods & AccessibleFieldDocumentMethods<T>, TVirtuals> {\n accessibleFieldsBy: GetAccessibleFields<T>\n}\n\nexport interface AccessibleFieldDocumentMethods<T = Document> {\n accessibleFieldsBy: GetAccessibleFields<T>\n}\n\n/**\n * @deprecated Mongoose recommends against `extends Document`, prefer to use `AccessibleFieldsModel` instead.\n * See here: https://mongoosejs.com/docs/typescript.html#using-extends-document\n */\nexport interface AccessibleFieldsDocument extends Document, AccessibleFieldDocumentMethods {}\n\nfunction modelFieldsGetter() {\n let fieldsFrom: PermittedFieldsOptions<AnyMongoAbility>['fieldsFrom'];\n return (schema: Schema<any>, options: Partial<AccessibleFieldsOptions>) => {\n if (!fieldsFrom) {\n const ALL_FIELDS = options && 'only' in options\n ? wrapArray(options.only as string[])\n : fieldsOf(schema, options);\n fieldsFrom = rule => rule.fields || ALL_FIELDS;\n }\n\n return fieldsFrom;\n };\n}\n\nexport function accessibleFieldsPlugin(\n schema: Schema<any>,\n rawOptions?: Partial<AccessibleFieldsOptions>\n): void {\n const options = { getFields: getSchemaPaths, ...rawOptions };\n const fieldsFrom = modelFieldsGetter();\n\n function istanceAccessibleFields(this: Document, ability: AnyMongoAbility, action?: string) {\n return permittedFieldsOf(ability, action || 'read', this, {\n fieldsFrom: fieldsFrom(schema, options)\n });\n }\n\n function modelAccessibleFields(this: Model<unknown>, ability: AnyMongoAbility, action?: string) {\n const document = { constructor: this };\n return permittedFieldsOf(ability, action || 'read', document, {\n fieldsFrom: fieldsFrom(schema, options)\n });\n }\n\n schema.statics.accessibleFieldsBy = modelAccessibleFields;\n schema.method('accessibleFieldsBy', istanceAccessibleFields);\n}\n"],"names":["convertToMongoQuery","rule","conditions","inverted","$nor","toMongoQuery","ability","subjectType","action","rulesToQuery","failedQuery","modelName","query","where","__forbiddenByCasl__","anyQuery","pre","cb","error","ForbiddenError","from","setMessage","getDefaultErrorMessage","accessibleBy","baseQuery","detectSubjectType","constructor","model","TypeError","and","modelAccessibleBy","this","queryAccessibleBy","accessibleRecordsPlugin","schema","statics","getSchemaPaths","Object","keys","paths","fieldsOf","options","fields","getFields","excludedFields","wrapArray","except","filter","field","indexOf","modelFieldsGetter","fieldsFrom","ALL_FIELDS","only","accessibleFieldsPlugin","rawOptions","istanceAccessibleFields","permittedFieldsOf","modelAccessibleFields","document","accessibleFieldsBy","method"],"mappings":"oKAGA,SAASA,EAAoBC,SACrBC,EAAaD,EAAKC,kBACjBD,EAAKE,SAAW,CAAEC,KAAM,CAACF,IAAgBA,EAG3C,SAASG,EACdC,EACAC,EACAC,EAAuC,eAEhCC,EAAaH,EAASE,EAAQD,EAAaP,GCTpD,SAASU,EACPJ,EACAE,EACAG,EACAC,GAEAA,EAAMC,MAAM,CAAEC,oBAAqB,UAC7BC,EAAgBH,KAEM,oBAAjBG,EAASC,IAClBD,EAASC,KAAKC,UACNC,EAAQC,EAAeC,KAAKd,GAClCY,EAAMV,OAASA,EACfU,EAAMX,YAAcI,EACpBO,EAAMG,WAAWC,EAAuBJ,IACxCD,EAAGC,aAIAN,EAGT,SAASW,EACPC,EACAlB,EACAE,SAEMD,EAAcD,EAAQmB,kBAAkB,CAC5CC,YAAaF,EAAUG,YAGpBpB,QACG,IAAIqB,UAAW,iCAAgCJ,EAAUG,MAAMhB,iDAGjEC,EAAQP,EAAaC,EAASC,EAAaC,MAEnC,OAAVI,SACKF,EAAYJ,EAASE,GAAU,OAAQD,EAAaiB,EAAUX,gBAGhEW,EAAUK,IAAI,CAACjB,IAqCxB,SAASkB,EAAwCxB,EAA0BE,UAClEe,EAAaQ,KAAKlB,QAASP,EAASE,GAG7C,SAASwB,EAEP1B,EACAE,UAEOe,EAAaQ,KAAMzB,EAASE,GAG9B,SAASyB,EAAwBC,GACrCA,EAAOtB,MAAkCW,aAAeS,EACzDE,EAAOC,QAAQZ,aAAeO,QCtFnBM,EAAuDF,GAAUG,OAAOC,KAAMJ,EAA6BK,OAExH,SAASC,EAASN,EAA0BO,SACpCC,EAASD,EAAQE,UAAWT,OAE7BO,KAAa,WAAYA,UACrBC,QAGHE,EAAiBC,EAAUJ,EAAQK,eAClCJ,EAAOK,QAAOC,IAA4C,IAAnCJ,EAAeK,QAAQD,KA4BvD,SAASE,QACHC,QACG,CAACjB,EAAqBO,SACtBU,EAAY,OACTC,EAAaX,GAAW,SAAUA,EACpCI,EAAUJ,EAAQY,MAClBb,EAASN,EAAQO,GACrBU,EAAalD,GAAQA,EAAKyC,QAAUU,SAG/BD,GAIJ,SAASG,EACdpB,EACAqB,SAEMd,iBAAYE,UAAWP,GAAmBmB,SAC1CJ,EAAaD,aAEVM,EAAwClD,EAA0BE,UAClEiD,EAAkBnD,EAASE,GAAU,OAAQuB,KAAM,CACxDoB,WAAYA,EAAWjB,EAAQO,cAI1BiB,EAA4CpD,EAA0BE,SACvEmD,EAAW,CAAEjC,YAAaK,aACzB0B,EAAkBnD,EAASE,GAAU,OAAQmD,EAAU,CAC5DR,WAAYA,EAAWjB,EAAQO,KAInCP,EAAOC,QAAQyB,mBAAqBF,EACpCxB,EAAO2B,OAAO,qBAAsBL"}
@@ -8,12 +8,18 @@ export declare type AccessibleFieldsOptions = {
8
8
  except: string | string[];
9
9
  });
10
10
  export declare const getSchemaPaths: AccessibleFieldsOptions['getFields'];
11
- declare type GetAccessibleFields<T extends AccessibleFieldsDocument> = <U extends AnyMongoAbility>(this: Model<T> | T, ability: U, action?: Normalize<Generics<U>['abilities']>[0]) => string[];
12
- export interface AccessibleFieldsModel<T extends AccessibleFieldsDocument> extends Model<T> {
11
+ declare type GetAccessibleFields<T> = <U extends AnyMongoAbility>(this: Model<T> | T, ability: U, action?: Normalize<Generics<U>['abilities']>[0]) => string[];
12
+ export interface AccessibleFieldsModel<T, TQueryHelpers = {}, TMethods = {}, TVirtuals = {}> extends Model<T, TQueryHelpers, TMethods & AccessibleFieldDocumentMethods<T>, TVirtuals> {
13
13
  accessibleFieldsBy: GetAccessibleFields<T>;
14
14
  }
15
- export interface AccessibleFieldsDocument extends Document {
16
- accessibleFieldsBy: GetAccessibleFields<AccessibleFieldsDocument>;
15
+ export interface AccessibleFieldDocumentMethods<T = Document> {
16
+ accessibleFieldsBy: GetAccessibleFields<T>;
17
+ }
18
+ /**
19
+ * @deprecated Mongoose recommends against `extends Document`, prefer to use `AccessibleFieldsModel` instead.
20
+ * See here: https://mongoosejs.com/docs/typescript.html#using-extends-document
21
+ */
22
+ export interface AccessibleFieldsDocument extends Document, AccessibleFieldDocumentMethods {
17
23
  }
18
24
  export declare function accessibleFieldsPlugin(schema: Schema<any>, rawOptions?: Partial<AccessibleFieldsOptions>): void;
19
25
  export {};
@@ -1,11 +1,11 @@
1
1
  import { Normalize, AnyMongoAbility, Generics } from '@casl/ability';
2
- import type { Schema, QueryWithHelpers, Model, Document } from 'mongoose';
3
- declare type GetAccessibleRecords<T extends Document> = <U extends AnyMongoAbility>(ability: U, action?: Normalize<Generics<U>['abilities']>[0]) => QueryWithHelpers<T, T, QueryHelpers<T>>;
4
- declare type QueryHelpers<T extends Document> = {
5
- accessibleBy: GetAccessibleRecords<T>;
2
+ import { Schema, QueryWithHelpers, Model, HydratedDocument } from 'mongoose';
3
+ declare type GetAccessibleRecords<T, TQueryHelpers, TMethods, TVirtuals> = <U extends AnyMongoAbility>(ability: U, action?: Normalize<Generics<U>['abilities']>[0]) => QueryWithHelpers<Array<T>, T, AccessibleRecordQueryHelpers<T, TQueryHelpers, TMethods, TVirtuals>>;
4
+ export declare type AccessibleRecordQueryHelpers<T, TQueryHelpers = {}, TMethods = {}, TVirtuals = {}> = {
5
+ accessibleBy: GetAccessibleRecords<HydratedDocument<T, TMethods, TVirtuals>, TQueryHelpers, TMethods, TVirtuals>;
6
6
  };
7
- export interface AccessibleRecordModel<T extends Document, K = unknown> extends Model<T, K & QueryHelpers<T>> {
8
- accessibleBy: GetAccessibleRecords<T>;
7
+ export interface AccessibleRecordModel<T, TQueryHelpers = {}, TMethods = {}, TVirtuals = {}> extends Model<T, TQueryHelpers & AccessibleRecordQueryHelpers<T, TQueryHelpers, TMethods, TVirtuals>, TMethods, TVirtuals> {
8
+ accessibleBy: GetAccessibleRecords<HydratedDocument<T, TMethods, TVirtuals>, TQueryHelpers, TMethods, TVirtuals>;
9
9
  }
10
10
  export declare function accessibleRecordsPlugin(schema: Schema<any>): void;
11
11
  export {};
@@ -1,6 +1,9 @@
1
- import { AccessibleFieldsModel, AccessibleFieldsDocument } from './accessible_fields';
2
- import { AccessibleRecordModel } from './accessible_records';
3
- export declare type AccessibleModel<T extends AccessibleFieldsDocument> = AccessibleRecordModel<T> & AccessibleFieldsModel<T>;
4
- export * from './accessible_records';
5
- export * from './accessible_fields';
6
- export * from './mongo';
1
+ import { AccessibleFieldDocumentMethods, AccessibleFieldsModel } from './accessible_fields';
2
+ import { AccessibleRecordModel, AccessibleRecordQueryHelpers } from './accessible_records';
3
+ export interface AccessibleModel<T, TQueryHelpers = unknown, TMethods = unknown, TVirtuals = unknown> extends AccessibleRecordModel<T, TQueryHelpers, TMethods & AccessibleFieldDocumentMethods<T>, TVirtuals>, AccessibleFieldsModel<T, TQueryHelpers & AccessibleRecordQueryHelpers<T, TQueryHelpers, TMethods & AccessibleFieldDocumentMethods<T>, TVirtuals>, TMethods, TVirtuals> {
4
+ }
5
+ export { accessibleRecordsPlugin } from './accessible_records';
6
+ export type { AccessibleRecordModel } from './accessible_records';
7
+ export { getSchemaPaths, accessibleFieldsPlugin } from './accessible_fields';
8
+ export type { AccessibleFieldsModel, AccessibleFieldsDocument, AccessibleFieldsOptions } from './accessible_fields';
9
+ export { toMongoQuery } from './mongo';
@@ -1,2 +1,3 @@
1
1
  import { AnyMongoAbility } from '@casl/ability';
2
- export declare function toMongoQuery<T extends AnyMongoAbility>(ability: T, subjectType: Parameters<T['rulesFor']>[1], action?: Parameters<T['rulesFor']>[0]): import("@casl/ability/extra").AbilityQuery<object> | null;
2
+ import { AbilityQuery } from '@casl/ability/extra';
3
+ export declare function toMongoQuery<T extends AnyMongoAbility>(ability: T, subjectType: Parameters<T['rulesFor']>[1], action?: Parameters<T['rulesFor']>[0]): AbilityQuery | null;
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "@casl/mongoose",
3
- "version": "6.0.0",
3
+ "version": "7.1.0",
4
4
  "description": "Allows to query accessible records from MongoDB based on CASL rules",
5
5
  "main": "dist/es6c/index.js",
6
6
  "es2015": "dist/es6m/index.mjs",
7
7
  "typings": "dist/types/index.d.ts",
8
8
  "exports": {
9
9
  ".": {
10
+ "types": "./dist/types/index.d.ts",
10
11
  "import": "./dist/es6m/index.mjs",
11
12
  "require": "./dist/es6c/index.js"
12
13
  }
@@ -39,15 +40,16 @@
39
40
  "author": "Sergii Stotskyi <sergiy.stotskiy@gmail.com>",
40
41
  "license": "MIT",
41
42
  "peerDependencies": {
42
- "@casl/ability": "^3.0.0 || ^4.0.0 || ^5.1.0",
43
- "mongoose": "^6.0.0"
43
+ "@casl/ability": "^3.0.0 || ^4.0.0 || ^5.1.0 || ^6.0.0",
44
+ "mongoose": "^6.0.13"
44
45
  },
45
46
  "devDependencies": {
46
- "@casl/ability": "^5.1.0",
47
+ "@casl/ability": "^6.0.0",
47
48
  "@casl/dx": "workspace:^1.0.0",
49
+ "@types/jest": "^28.0.0",
48
50
  "chai": "^4.1.0",
49
51
  "chai-spies": "^1.0.0",
50
- "mongoose": "^6.0.0"
52
+ "mongoose": "^6.0.13"
51
53
  },
52
54
  "files": [
53
55
  "dist",