@casl/mongoose 4.0.2 → 6.0.1

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.
package/README.md CHANGED
@@ -22,7 +22,7 @@ pnpm add @casl/mongoose @casl/ability
22
22
 
23
23
  ### Accessible Records plugin
24
24
 
25
- `accessibleRecordsPlugin` is a plugin which adds `accessibleBy` method to query and static methods of your models. You can add this plugin globally:
25
+ `accessibleRecordsPlugin` is a plugin which adds `accessibleBy` method to query and static methods of mongoose models. We can add this plugin globally:
26
26
 
27
27
  ```js
28
28
  const { accessibleRecordsPlugin } = require('@casl/mongoose');
@@ -31,7 +31,7 @@ const mongoose = require('mongoose');
31
31
  mongoose.plugin(accessibleRecordsPlugin);
32
32
  ```
33
33
 
34
- > Make sure you add the plugin before calling `mongoose.model(...)` method. Mongoose won't add global plugins to models that where created before calling `mongoose.plugin()`.
34
+ > Make sure to add the plugin before calling `mongoose.model(...)` method. Mongoose won't add global plugins to models that where created before calling `mongoose.plugin()`.
35
35
 
36
36
  or to a particular model:
37
37
 
@@ -49,7 +49,7 @@ Post.plugin(accessibleRecordsPlugin)
49
49
  module.exports = mongoose.model('Post', Post)
50
50
  ```
51
51
 
52
- Afterwards you can fetch accessible records by calling `accessibleBy` method on `Post`:
52
+ Afterwards, we can fetch accessible records using `accessibleBy` method on `Post`:
53
53
 
54
54
  ```js
55
55
  const Post = require('./Post')
@@ -77,7 +77,7 @@ async function main() {
77
77
  }
78
78
  ```
79
79
 
80
- `accessibleBy` returns an instance of `mongoose.Query` and that means you can chain it with any `mongoose.Query`'s method (e.g., `select`, `limit`, `sort`). By default, `accessibleBy` constructs query based on the list of rules for `read` action but you can change this by providing the 2nd optional argument:
80
+ `accessibleBy` returns an instance of `mongoose.Query` and that means you can chain it with any `mongoose.Query`'s method (e.g., `select`, `limit`, `sort`). By default, `accessibleBy` constructs a query based on the list of rules for `read` action but we can change this by providing the 2nd optional argument:
81
81
 
82
82
  ```js
83
83
  const Post = require('./Post');
@@ -91,7 +91,7 @@ async function main() {
91
91
 
92
92
  > `accessibleBy` is built on top of `rulesToQuery` function from `@casl/ability/extra`. Read [Ability to database query](https://casl.js.org/v5/en/advanced/ability-to-database-query) to get insights of how it works.
93
93
 
94
- In case when user doesn’t have permission to do a particular action, CASL will not even send request to MongoDB and instead will force Query to return empty result set. CASL patches native mongodb collection's methods in such case to return predefine value (empty array for `find`, `null` for `findOne` and `0` for `count`). It also adds `__forbiddenByCasl__: 1` condition which will enforce mongodb to return empty set in case if you use one of methods that are not patched, so users who is not allowed to get particular records won't get them!
94
+ In case user doesn’t have permission to do a particular action, CASL will throw `ForbiddenError` and will not send request to MongoDB. It also adds `__forbiddenByCasl__: 1` condition for additional safety.
95
95
 
96
96
  For example, lets find all posts which user can delete (we haven’t defined abilities for delete):
97
97
 
@@ -105,12 +105,15 @@ mongoose.set('debug', true);
105
105
  const ability = defineAbility(can => can('read', 'Post', { private: false }));
106
106
 
107
107
  async function main() {
108
- const posts = await Post.accessibleBy(ability, 'delete');
109
- console.log(posts) // [];
108
+ try {
109
+ const posts = await Post.accessibleBy(ability, 'delete');
110
+ } catch (error) {
111
+ console.log(error) // ForbiddenError;
112
+ }
110
113
  }
111
114
  ```
112
115
 
113
- You can also use the resulting conditions in [aggregation pipeline](https://mongoosejs.com/docs/api.html#aggregate_Aggregate):
116
+ We can also use the resulting conditions in [aggregation pipeline](https://mongoosejs.com/docs/api.html#aggregate_Aggregate):
114
117
 
115
118
  ```js
116
119
  const Post = require('./Post');
@@ -161,7 +164,7 @@ async function main() {
161
164
 
162
165
  ### Accessible Fields plugin
163
166
 
164
- `accessibleFieldsPlugin` is a plugin that adds `accessibleFieldsBy` method to instance and static methods of a model and allows to retrieve all accessible fields. This is useful when you need send only accessible part of a model in response:
167
+ `accessibleFieldsPlugin` is a plugin that adds `accessibleFieldsBy` method to instance and static methods of a model and allows to retrieve all accessible fields. This is useful when we need to send only accessible part of a model in response:
165
168
 
166
169
  ```js
167
170
  const { accessibleFieldsPlugin } = require('@casl/mongoose');
@@ -198,7 +201,7 @@ post.accessibleFieldsBy(ability); // ['title']
198
201
 
199
202
  As you can see, a static method returns all fields that can be read for all posts. At the same time, an instance method returns fields that can be read from this particular `post` instance. That's why there is no much sense (except you want to reduce traffic between app and database) to pass the result of static method into `mongoose.Query`'s `select` method because eventually you will need to call `accessibleFieldsBy` on every instance.
200
203
 
201
- ## Integration with any MongoDB library
204
+ ## Integration with other MongoDB libraries
202
205
 
203
206
  In case you don't use mongoose, this package provides `toMongoQuery` function which can convert CASL rules into [MongoDB] query. Lets see an example of how to fetch accessible records using raw [MongoDB adapter][mongo-adapter]
204
207
 
@@ -229,14 +232,14 @@ async function main() {
229
232
 
230
233
  ## TypeScript support
231
234
 
232
- The package is written in TypeScript, this makes it easier to work with plugins and `toMongoQuery` helper because IDE will hint you about you can pass inside arguments and TypeScript will warn you about wrong usage. Let's see it in action!
235
+ The package is written in TypeScript, this makes it easier to work with plugins and `toMongoQuery` helper because IDE provides useful hints. Let's see it in action!
233
236
 
234
237
  Suppose we have `Post` entity which can be described as:
235
238
 
236
239
  ```ts
237
- import * as mongoose from 'mongoose';
240
+ import mongoose from 'mongoose';
238
241
 
239
- export interface Post {
242
+ export interface Post extends mongoose.Document {
240
243
  title: string
241
244
  content: string
242
245
  published: boolean
@@ -295,7 +298,7 @@ const post = new Post();
295
298
  post.accessibleFieldsBy(/* parameters */);
296
299
  ```
297
300
 
298
- And we want to include both plugins, we can use `AccessibleModel` type that includes methods from both plugins:
301
+ And if we want to include both plugins, we can use `AccessibleModel` type that provides methods from both plugins:
299
302
 
300
303
  ```ts
301
304
  import {
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:true});var t=require("@casl/ability");var n=require("mongoose");var e=require("@casl/ability/extra");function r(t){return t&&"object"===typeof t&&"default"in t?t:{default:t}}var o=r(n);function i(t){const n=t.conditions;return t.inverted?{$nor:[n]}:n}function s(t,n,r){return e.rulesToQuery(t,r||"read",n,i)}function c(n,e,r,o){const i=t.ForbiddenError.from(n);i.action=e;i.subjectType=r;i.setMessage(t.getDefaultErrorMessage(i));o.where({__forbiddenByCasl__:1});o.exec=function t(...n){const e="function"===typeof n[0]?n[0]:n[1];if("function"===typeof e){process.nextTick((()=>e(i)));return}return Promise.reject(i)};return o}function u(t,n){let e=this.modelName;if(!e)e="model"in this?this.model.modelName:null;if(!e)throw new TypeError("Cannot detect model name to return accessible records");const r=s(t,e,n);if(null===r)return c(t,n||"read",e,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(n,e){const r=e.getFields(n);if(!e||!("except"in e))return r;const o=t.wrapArray(e.except);return r.filter((t=>-1===o.indexOf(t)))}function d(){let n;return(e,r)=>{if(!n){const o=r&&"only"in r?t.wrapArray(r.only):a(e,r);n=t=>t.fields||o}return n}}function p(t,n){const r=Object.assign({getFields:l},n);const o=d();function i(n,i){const s="function"===typeof this?this.modelName:this;return e.permittedFieldsOf(n,i||"read",s,{fieldsFrom:o(t,r)})}t.statics.accessibleFieldsBy=i;t.method("accessibleFieldsBy",i)}exports.accessibleFieldsPlugin=p;exports.accessibleRecordsPlugin=f;exports.getSchemaPaths=l;exports.toMongoQuery=s;
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;
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]\n) {\n return rulesToQuery(ability, action || 'read', subjectType, convertToMongoQuery);\n}\n","import { Normalize, AnyMongoAbility, Generics, ForbiddenError, getDefaultErrorMessage } from '@casl/ability';\nimport type { Schema, DocumentQuery, 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: DocumentQuery<Document, Document>\n) {\n const error = ForbiddenError.from(ability);\n error.action = action;\n error.subjectType = modelName;\n error.setMessage(getDefaultErrorMessage(error));\n\n query.where({ __forbiddenByCasl__: 1 }); // eslint-disable-line\n query.exec = function patchedExecByCasl(...args: any[]) {\n const cb = typeof args[0] === 'function' ? args[0] : args[1];\n if (typeof cb === 'function') {\n process.nextTick(() => cb(error));\n return;\n }\n // eslint-disable-next-line consistent-return\n return Promise.reject(error);\n } as typeof query['exec'];\n\n return query;\n}\n\ntype GetAccessibleRecords<T extends Document> = <U extends AnyMongoAbility>(\n ability: U,\n action?: Normalize<Generics<U>['abilities']>[0]\n) => DocumentQuery<T, T>;\n\nfunction accessibleBy<T extends AnyMongoAbility>(\n this: any,\n ability: T,\n action?: Normalize<Generics<T>['abilities']>[0]\n): DocumentQuery<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\nexport interface AccessibleRecordModel<T extends Document, K = {}> extends Model<T, K & {\n accessibleBy: GetAccessibleRecords<T>\n}> {\n accessibleBy: GetAccessibleRecords<T>\n}\n\nexport function accessibleRecordsPlugin(schema: Schema<Document>) {\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<Document>, 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<AccessibleFieldsDocument>,\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","error","ForbiddenError","from","setMessage","getDefaultErrorMessage","where","__forbiddenByCasl__","exec","patchedExecByCasl","args","cb","process","nextTick","Promise","reject","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,UAEOC,eAAaH,EAASE,GAAU,OAAQD,EAAaP,GCR9D,SAASU,EACPJ,EACAE,EACAG,EACAC,SAEMC,EAAQC,iBAAeC,KAAKT,GAClCO,EAAML,OAASA,EACfK,EAAMN,YAAcI,EACpBE,EAAMG,WAAWC,yBAAuBJ,IAExCD,EAAMM,MAAM,CAAEC,oBAAqB,IACnCP,EAAMQ,KAAO,SAASC,KAAqBC,SACnCC,EAAwB,oBAAZD,EAAK,GAAoBA,EAAK,GAAKA,EAAK,MACxC,oBAAPC,EAAmB,CAC5BC,QAAQC,UAAS,IAAMF,EAAGV,mBAIrBa,QAAQC,OAAOd,WAGjBD,EAQT,SAASgB,EAEPtB,EACAE,OAEIG,EAAgCkB,KAAKlB,cAEpCA,EACHA,EAAY,UAAWkB,KAAOA,KAAKC,MAAMnB,UAAY,SAGlDA,QACG,IAAIoB,UAAU,+DAGhBnB,EAAQP,EAAaC,EAASK,EAAWH,MAEjC,OAAVI,SACKF,EAAYJ,EAASE,GAAU,OAAQG,EAAWkB,KAAKX,gBAGzDW,gBAAgBG,aAASC,MAAQJ,KAAKK,IAAI,CAACtB,IAAUiB,KAAKX,MAAM,CAAEiB,KAAM,CAACvB,KAS3E,SAASwB,EAAwBC,GACtCA,EAAOzB,MAAMgB,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,EAA0BO,SAC3BU,EAAY,OACTC,EAAaX,GAAW,SAAUA,EACpCI,YAAUJ,EAAQY,MAClBb,EAASN,EAAQO,GACrBU,EAAarD,GAAQA,EAAK4C,QAAUU,SAG/BD,GAIJ,SAASG,EACdpB,EACAqB,SAEMd,iBAAYE,UAAWP,GAAmBmB,SAC1CJ,EAAaD,aAGVM,EAAqCrD,EAA0BE,SAChEoD,EAA0B,oBAAT/B,KAAsBA,KAAKlB,UAAYkB,YACvDgC,oBAAkBvD,EAASE,GAAU,OAAQoD,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 { 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,2 +1,2 @@
1
- import{ForbiddenError as t,getDefaultErrorMessage as n,wrapArray as o}from"@casl/ability";import e from"mongoose";import{rulesToQuery as r,permittedFieldsOf as i}from"@casl/ability/extra";function c(t){const n=t.conditions;return t.inverted?{$nor:[n]}:n}function s(t,n,o){return r(t,o||"read",n,c)}function f(o,e,r,i){const c=t.from(o);c.action=e;c.subjectType=r;c.setMessage(n(c));i.where({__forbiddenByCasl__:1});i.exec=function t(...n){const o="function"===typeof n[0]?n[0]:n[1];if("function"===typeof o){process.nextTick((()=>o(c)));return}return Promise.reject(c)};return i}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 r=s(t,o,n);if(null===r)return f(t,n||"read",o,this.where());return this instanceof e.Query?this.and([r]):this.where({$and:[r]})}function l(t){t.query.accessibleBy=u;t.statics.accessibleBy=u}const a=t=>Object.keys(t.paths);function d(t,n){const e=n.getFields(t);if(!n||!("except"in n))return e;const r=o(n.except);return e.filter((t=>-1===r.indexOf(t)))}function m(){let t;return(n,e)=>{if(!t){const r=e&&"only"in e?o(e.only):d(n,e);t=t=>t.fields||r}return t}}function h(t,n){const o=Object.assign({getFields:a},n);const e=m();function r(n,r){const c="function"===typeof this?this.modelName:this;return i(n,r||"read",c,{fieldsFrom:e(t,o)})}t.statics.accessibleFieldsBy=r;t.method("accessibleFieldsBy",r)}export{h as accessibleFieldsPlugin,l as accessibleRecordsPlugin,a as getSchemaPaths,s as toMongoQuery};
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};
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]\n) {\n return rulesToQuery(ability, action || 'read', subjectType, convertToMongoQuery);\n}\n","import { Normalize, AnyMongoAbility, Generics, ForbiddenError, getDefaultErrorMessage } from '@casl/ability';\nimport type { Schema, DocumentQuery, 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: DocumentQuery<Document, Document>\n) {\n const error = ForbiddenError.from(ability);\n error.action = action;\n error.subjectType = modelName;\n error.setMessage(getDefaultErrorMessage(error));\n\n query.where({ __forbiddenByCasl__: 1 }); // eslint-disable-line\n query.exec = function patchedExecByCasl(...args: any[]) {\n const cb = typeof args[0] === 'function' ? args[0] : args[1];\n if (typeof cb === 'function') {\n process.nextTick(() => cb(error));\n return;\n }\n // eslint-disable-next-line consistent-return\n return Promise.reject(error);\n } as typeof query['exec'];\n\n return query;\n}\n\ntype GetAccessibleRecords<T extends Document> = <U extends AnyMongoAbility>(\n ability: U,\n action?: Normalize<Generics<U>['abilities']>[0]\n) => DocumentQuery<T, T>;\n\nfunction accessibleBy<T extends AnyMongoAbility>(\n this: any,\n ability: T,\n action?: Normalize<Generics<T>['abilities']>[0]\n): DocumentQuery<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\nexport interface AccessibleRecordModel<T extends Document, K = {}> extends Model<T, K & {\n accessibleBy: GetAccessibleRecords<T>\n}> {\n accessibleBy: GetAccessibleRecords<T>\n}\n\nexport function accessibleRecordsPlugin(schema: Schema<Document>) {\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<Document>, 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<AccessibleFieldsDocument>,\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","error","ForbiddenError","from","setMessage","getDefaultErrorMessage","where","__forbiddenByCasl__","exec","patchedExecByCasl","args","cb","process","nextTick","Promise","reject","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,UAEOC,EAAaH,EAASE,GAAU,OAAQD,EAAaP,GCR9D,SAASU,EACPJ,EACAE,EACAG,EACAC,SAEMC,EAAQC,EAAeC,KAAKT,GAClCO,EAAML,OAASA,EACfK,EAAMN,YAAcI,EACpBE,EAAMG,WAAWC,EAAuBJ,IAExCD,EAAMM,MAAM,CAAEC,oBAAqB,IACnCP,EAAMQ,KAAO,SAASC,KAAqBC,SACnCC,EAAwB,oBAAZD,EAAK,GAAoBA,EAAK,GAAKA,EAAK,MACxC,oBAAPC,EAAmB,CAC5BC,QAAQC,UAAS,IAAMF,EAAGV,mBAIrBa,QAAQC,OAAOd,WAGjBD,EAQT,SAASgB,EAEPtB,EACAE,OAEIG,EAAgCkB,KAAKlB,cAEpCA,EACHA,EAAY,UAAWkB,KAAOA,KAAKC,MAAMnB,UAAY,SAGlDA,QACG,IAAIoB,UAAU,+DAGhBnB,EAAQP,EAAaC,EAASK,EAAWH,MAEjC,OAAVI,SACKF,EAAYJ,EAASE,GAAU,OAAQG,EAAWkB,KAAKX,gBAGzDW,gBAAgBG,EAASC,MAAQJ,KAAKK,IAAI,CAACtB,IAAUiB,KAAKX,MAAM,CAAEiB,KAAM,CAACvB,KAS3E,SAASwB,EAAwBC,GACtCA,EAAOzB,MAAMgB,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,EAA0BO,SAC3BU,EAAY,OACTC,EAAaX,GAAW,SAAUA,EACpCI,EAAUJ,EAAQY,MAClBb,EAASN,EAAQO,GACrBU,EAAarD,GAAQA,EAAK4C,QAAUU,SAG/BD,GAIJ,SAASG,EACdpB,EACAqB,SAEMd,iBAAYE,UAAWP,GAAmBmB,SAC1CJ,EAAaD,aAGVM,EAAqCrD,EAA0BE,SAChEoD,EAA0B,oBAAT/B,KAAsBA,KAAKlB,UAAYkB,YACvDgC,EAAkBvD,EAASE,GAAU,OAAQoD,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 { 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"}
@@ -15,5 +15,5 @@ export interface AccessibleFieldsModel<T extends AccessibleFieldsDocument> exten
15
15
  export interface AccessibleFieldsDocument extends Document {
16
16
  accessibleFieldsBy: GetAccessibleFields<AccessibleFieldsDocument>;
17
17
  }
18
- export declare function accessibleFieldsPlugin(schema: Schema<AccessibleFieldsDocument>, rawOptions?: Partial<AccessibleFieldsOptions>): void;
18
+ export declare function accessibleFieldsPlugin(schema: Schema<any>, rawOptions?: Partial<AccessibleFieldsOptions>): void;
19
19
  export {};
@@ -1,10 +1,11 @@
1
1
  import { Normalize, AnyMongoAbility, Generics } from '@casl/ability';
2
- import type { Schema, DocumentQuery, Model, Document } from 'mongoose';
3
- declare type GetAccessibleRecords<T extends Document> = <U extends AnyMongoAbility>(ability: U, action?: Normalize<Generics<U>['abilities']>[0]) => DocumentQuery<T, T>;
4
- export interface AccessibleRecordModel<T extends Document, K = {}> extends Model<T, K & {
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
5
  accessibleBy: GetAccessibleRecords<T>;
6
- }> {
6
+ };
7
+ export interface AccessibleRecordModel<T extends Document, K = unknown> extends Model<T, K & QueryHelpers<T>> {
7
8
  accessibleBy: GetAccessibleRecords<T>;
8
9
  }
9
- export declare function accessibleRecordsPlugin(schema: Schema<Document>): void;
10
+ export declare function accessibleRecordsPlugin(schema: Schema<any>): void;
10
11
  export {};
@@ -1,2 +1,2 @@
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
+ 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;
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@casl/mongoose",
3
- "version": "4.0.2",
3
+ "version": "6.0.1",
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
- "typings": "index.d.ts",
7
+ "typings": "dist/types/index.d.ts",
8
8
  "exports": {
9
9
  ".": {
10
10
  "import": "./dist/es6m/index.mjs",
@@ -13,7 +13,8 @@
13
13
  },
14
14
  "repository": {
15
15
  "type": "git",
16
- "url": "https://github.com/stalniy/casl.git"
16
+ "url": "https://github.com/stalniy/casl.git",
17
+ "directory": "packages/casl-mongoose"
17
18
  },
18
19
  "publishConfig": {
19
20
  "access": "public"
@@ -21,54 +22,33 @@
21
22
  "homepage": "https://casl.js.org",
22
23
  "scripts": {
23
24
  "prebuild": "rm -rf dist/* && npm run build.types",
24
- "build": "BUILD_TYPES=es6m,es6c rollup -c ../../rollup.config.js -e @casl/ability/extra,@casl/ability,mongoose",
25
- "build.types": "tsc -p tsconfig.build.json",
26
- "lint": "eslint --ext .ts,.js src/ spec/",
27
- "test": "NODE_ENV=test jest --config ../../tools/jest.config.js --env node --runInBand",
25
+ "build": "BUILD_TYPES=es6m,es6c dx rollup -e @casl/ability/extra,@casl/ability,mongoose",
26
+ "build.types": "dx tsc",
27
+ "lint": "dx eslint src/ spec/",
28
+ "test": "dx jest",
28
29
  "prerelease": "npm run lint && npm test && NODE_ENV=production npm run build",
29
- "release": "semantic-release -e ../../tools/semantic-release"
30
+ "release": "dx semantic-release"
30
31
  },
31
32
  "keywords": [
33
+ "casl",
32
34
  "mongo",
33
- "access control",
34
35
  "authorization",
35
36
  "acl",
36
- "security",
37
37
  "permissions"
38
38
  ],
39
39
  "author": "Sergii Stotskyi <sergiy.stotskiy@gmail.com>",
40
40
  "license": "MIT",
41
41
  "peerDependencies": {
42
- "@casl/ability": "^3.0.0 || ^4.0.0 || ^5.1.0",
43
- "mongoose": "^4.0.0 || <= 5.10.0"
42
+ "@casl/ability": "^3.0.0 || ^4.0.0 || ^5.1.0 || ^6.0.0",
43
+ "mongoose": "^6.0.0"
44
44
  },
45
45
  "devDependencies": {
46
- "@babel/core": "^7.8.4",
47
- "@babel/plugin-proposal-class-properties": "^7.8.3",
48
- "@babel/plugin-proposal-object-rest-spread": "^7.10.0",
49
- "@babel/plugin-transform-typescript": "^7.10.0",
50
- "@babel/preset-env": "^7.8.4",
51
- "@casl/ability": "^5.1.0",
52
- "@rollup/plugin-babel": "^5.0.2",
53
- "@rollup/plugin-node-resolve": "^11.0.0",
54
- "@semantic-release/changelog": "^5.0.1",
55
- "@semantic-release/git": "^9.0.0",
56
- "@types/mongoose": "^5.7.0",
57
- "@typescript-eslint/eslint-plugin": "4.21.0",
46
+ "@casl/ability": "^6.0.0",
47
+ "@casl/dx": "workspace:^1.0.0",
48
+ "@types/jest": "^26.0.22",
58
49
  "chai": "^4.1.0",
59
50
  "chai-spies": "^1.0.0",
60
- "eslint": "^7.1.0",
61
- "eslint-config-airbnb-base": "^14.1.0",
62
- "eslint-config-airbnb-typescript": "^12.0.0",
63
- "eslint-plugin-import": "^2.20.2",
64
- "jest": "^26.0.0",
65
- "mongoose": "~5.10.0",
66
- "rollup": "^2.10.9",
67
- "rollup-plugin-sourcemaps": "^0.6.2",
68
- "rollup-plugin-terser": "^7.0.0",
69
- "semantic-release": "17.3.2",
70
- "ts-jest": "^26.4.4",
71
- "typescript": "~4.0.0"
51
+ "mongoose": "^6.0.0"
72
52
  },
73
53
  "files": [
74
54
  "dist",
package/CHANGELOG.md DELETED
@@ -1,240 +0,0 @@
1
- # Change Log
2
-
3
- All notable changes to this project will be documented in this file.
4
-
5
- ## [4.0.2](https://github.com/stalniy/casl/compare/@casl/mongoose@4.0.1...@casl/mongoose@4.0.2) (2021-04-12)
6
-
7
-
8
- ### Bug Fixes
9
-
10
- * **mongoose:** uses `mongoose` as commonjs module ([c98506b](https://github.com/stalniy/casl/commit/c98506b77ebd6b3068040f512012e12891749b87))
11
-
12
- ## [4.0.1](https://github.com/stalniy/casl/compare/@casl/mongoose@4.0.0...@casl/mongoose@4.0.1) (2021-02-12)
13
-
14
-
15
- ### Bug Fixes
16
-
17
- * **changelog:** removes unrelated entries from changelog ([5437622](https://github.com/stalniy/casl/commit/543762224e329cda02f786c585998217581c2f3b))
18
-
19
- # [4.0.0](https://github.com/stalniy/casl/compare/@casl/mongoose@3.2.2...@casl/mongoose@4.0.0) (2021-02-12)
20
-
21
- ### Features
22
-
23
- * **mongoose:** throws `ForbiddenError` instead of returning a hard-coded value when user has not permissions to do some action ([917dd01](https://github.com/stalniy/casl/commit/917dd017bd95627f2550fc8f34b4ccf03fea94c5)), closes [#404](https://github.com/stalniy/casl/issues/404)
24
-
25
-
26
- ### BREAKING CHANGES
27
-
28
- * **mongoose:** `accessibleBy` eventually throws `ForbiddenError` instead of returning a hard-coded value
29
-
30
- **Before**:
31
-
32
- ```ts
33
- // ability doesn't allow to read Post
34
- const ability = defineAbility(can => can('manage', 'Comment'));
35
-
36
- try {
37
- const items = await Post.accessibleBy(ability, 'read');
38
- console.log(items); // []
39
- } catch (error) {
40
- console.error(error); // no error thrown
41
- }
42
- ```
43
-
44
- **After**:
45
-
46
- ```ts
47
- // ability doesn't allow to read Post
48
- const ability = defineAbility(can => can('manage', 'Comment'));
49
-
50
- try {
51
- const items = await Post.accessibleBy(ability, 'read');
52
- console.log(items); // not reached, because query fails with error
53
- } catch (error) {
54
- console.error(error); // ForbiddenError thrown
55
- }
56
- ```
57
-
58
- ## [3.2.2](https://github.com/stalniy/casl/compare/@casl/mongoose@3.2.1...@casl/mongoose@3.2.2) (2021-01-05)
59
-
60
-
61
- ### Bug Fixes
62
-
63
- * **mongoose:** simplifies types for `toMongoQuery` helper ([1615f4b](https://github.com/stalniy/casl/commit/1615f4b9ba870cddc190bdf4a504822760a21add))
64
-
65
- ## [3.2.1](https://github.com/stalniy/casl/compare/@casl/mongoose@3.2.0...@casl/mongoose@3.2.1) (2020-12-28)
66
-
67
-
68
- ### Bug Fixes
69
-
70
- * **dist:** adds separate `tsconfig.build.json` to every completementary project ([87742ce](https://github.com/stalniy/casl/commit/87742cec518a8a68d5fc29be2bbc9561cbc7da6c)), closes [#419](https://github.com/stalniy/casl/issues/419)
71
-
72
- # [3.2.0](https://github.com/stalniy/casl/compare/@casl/mongoose@3.1.0...@casl/mongoose@3.2.0) (2020-12-26)
73
-
74
-
75
- ### Bug Fixes
76
-
77
- * **angular:** fixes sourcemap generation for the code built by ngc ([7715263](https://github.com/stalniy/casl/commit/771526379ff8203170a433d71b68644a48ff44eb)), closes [#387](https://github.com/stalniy/casl/issues/387) [#382](https://github.com/stalniy/casl/issues/382)
78
- * **package:** removes `engine` section that points to npm@6 ([eecd12a](https://github.com/stalniy/casl/commit/eecd12ac49f56d6a0f57d1a57fb37487335b5f03)), closes [#417](https://github.com/stalniy/casl/issues/417)
79
-
80
-
81
- ### Features
82
-
83
- * **esm:** adds ESM support for latest Node.js through `exports` prop in package.json ([cac2506](https://github.com/stalniy/casl/commit/cac2506a80c18f194210c2d89108d1d094751fa4)), closes [#331](https://github.com/stalniy/casl/issues/331)
84
-
85
- # [3.1.0](https://github.com/stalniy/casl/compare/@casl/mongoose@3.0.3...@casl/mongoose@3.1.0) (2020-08-20)
86
-
87
-
88
- ### Features
89
-
90
- * **mongoose:** adds `getFields` option to `accessibleFieldsPlugin` ([a93037c](https://github.com/stalniy/casl/commit/a93037cc423649b6ea45347166adc8ea7eeffe9e))
91
-
92
- ## [3.0.3](https://github.com/stalniy/casl/compare/@casl/mongoose@3.0.2...@casl/mongoose@3.0.3) (2020-06-09)
93
-
94
-
95
- ### Bug Fixes
96
-
97
- * **docs:** ensure README and docs for all packages are in sync ([8df3684](https://github.com/stalniy/casl/commit/8df3684b139de0af60c9c37f284a5028ffbf2224)), closes [#338](https://github.com/stalniy/casl/issues/338)
98
-
99
- ## [3.0.2](https://github.com/stalniy/casl/compare/@casl/mongoose@3.0.1...@casl/mongoose@3.0.2) (2020-04-10)
100
-
101
-
102
- ### Bug Fixes
103
-
104
- * **mongoose:** ensure that terser doesn't mangle reserved required props ([83f1d32](https://github.com/stalniy/casl/commit/83f1d32d47cb99335c26fb2ba4aa4e6920cb761c))
105
-
106
- ## [3.0.1](https://github.com/stalniy/casl/compare/@casl/mongoose@3.0.0...@casl/mongoose@3.0.1) (2020-04-09)
107
-
108
-
109
- ### Bug Fixes
110
-
111
- * **mongoose:** adds support for casl/ability@4 in package.json ([ffb887c](https://github.com/stalniy/casl/commit/ffb887c57b7839e0239d59bbcb859b4469782fbd))
112
-
113
- # [3.0.0](https://github.com/stalniy/casl/compare/@casl/mongoose@2.3.3...@casl/mongoose@3.0.0) (2020-04-09)
114
-
115
-
116
- ### Bug Fixes
117
-
118
- * **mongoose:** ensures mongoose works with MongoQuery conditions ([f92b7df](https://github.com/stalniy/casl/commit/f92b7df532ecca24ee05d02cf9388b21f8d242fa)), closes [#249](https://github.com/stalniy/casl/issues/249)
119
- * **mongoose:** fixes mongoose typings ([d320eba](https://github.com/stalniy/casl/commit/d320eba70c14c7fc6700aba3e38fee062fdd9c3a)), closes [#248](https://github.com/stalniy/casl/issues/248)
120
-
121
-
122
- ### Features
123
-
124
- * **mongoose:** adds generics to mongoose types ([6cdf82e](https://github.com/stalniy/casl/commit/6cdf82ee2f547fdb6c5dcd9cb51cef1c4b4c542d)), closes [#256](https://github.com/stalniy/casl/issues/256)
125
- * **mongoose:** simplifies generics for mongoose ([7ff65f7](https://github.com/stalniy/casl/commit/7ff65f75cf715ca9428dda2fe6e0c91715646979)), closes [#107](https://github.com/stalniy/casl/issues/107)
126
-
127
-
128
- ### BREAKING CHANGES
129
-
130
- * **mongoose:** removes deprecated `permittedFieldsPlugin` use `accessibleFieldsPlugin` instead
131
- * **typescript:** weak hand written declaration files are removed as `@casl/mongoose` has been completely rewritten to TypeScript.
132
-
133
- ## [2.3.3](https://github.com/stalniy/casl/compare/@casl/mongoose@2.3.2...@casl/mongoose@2.3.3) (2020-03-13)
134
-
135
-
136
- ### Bug Fixes
137
-
138
- * **mongoose:** adds missing `index.js` file ([804c0dd](https://github.com/stalniy/casl/commit/804c0dd9aeaa5a0a2753cba0677c8150c362d671))
139
- * **mongoose:** makes sure abilityConditions does not override existing `$and` conditions ([#273](https://github.com/stalniy/casl/issues/273)) ([c13300f](https://github.com/stalniy/casl/commit/c13300f37d218d2c0754133557e3795887c6ef3b)), closes [#272](https://github.com/stalniy/casl/issues/272)
140
-
141
- # [@casl/mongoose-v2.3.2](https://github.com/stalniy/casl/compare/@casl/mongoose@2.3.1...@casl/mongoose@2.3.2) (2019-09-14)
142
-
143
-
144
- ### Bug Fixes
145
-
146
- * **mongoose:** mock query result on collection level ([1e8c241](https://github.com/stalniy/casl/commit/1e8c241)), closes [#218](https://github.com/stalniy/casl/issues/218)
147
-
148
- # [@casl/mongoose-v2.3.1](https://github.com/stalniy/casl/compare/@casl/mongoose@2.3.0...@casl/mongoose@2.3.1) (2019-02-10)
149
-
150
-
151
- ### Bug Fixes
152
-
153
- * **packages:** increases peerDependency of [@casl](https://github.com/casl)/ability ([9f6a7b8](https://github.com/stalniy/casl/commit/9f6a7b8)), closes [#119](https://github.com/stalniy/casl/issues/119)
154
-
155
- # [@casl/mongoose-v2.3.0](https://github.com/stalniy/casl/compare/@casl/mongoose@2.2.2...@casl/mongoose@2.3.0) (2018-12-28)
156
-
157
-
158
- ### Features
159
-
160
- * **mongoose:** wraps resulting query into additional `$and` ([1af1c54](https://github.com/stalniy/casl/commit/1af1c54)), closes [#140](https://github.com/stalniy/casl/issues/140)
161
-
162
- # [@casl/mongoose-v2.2.2](https://github.com/stalniy/casl/compare/@casl/mongoose@2.2.1...@casl/mongoose@2.2.2) (2018-11-07)
163
-
164
-
165
- ### Bug Fixes
166
-
167
- * **mongoose:** adds optional options as null type ([#127](https://github.com/stalniy/casl/issues/127)) ([ac3c262](https://github.com/stalniy/casl/commit/ac3c262))
168
-
169
- # [@casl/mongoose-v2.2.1](https://github.com/stalniy/casl/compare/@casl/mongoose@2.2.0...@casl/mongoose@2.2.1) (2018-10-14)
170
-
171
-
172
- ### Bug Fixes
173
-
174
- * **mongoose:** sets the correct `this` for deprecated methods ([488a227](https://github.com/stalniy/casl/commit/488a227)), closes [#116](https://github.com/stalniy/casl/issues/116)
175
-
176
- # [@casl/mongoose-v2.2.0](https://github.com/stalniy/casl/compare/@casl/mongoose@2.1.2...@casl/mongoose@2.2.0) (2018-10-10)
177
-
178
-
179
- ### Bug Fixes
180
-
181
- * **angular:** adding type definitions for accessibleFields ([#117](https://github.com/stalniy/casl/issues/117)) ([a00c02b](https://github.com/stalniy/casl/commit/a00c02b))
182
- * **README:** changes links to [@casl](https://github.com/casl)/ability to point to npm package instead to git root [skip ci] ([a74086b](https://github.com/stalniy/casl/commit/a74086b)), closes [#102](https://github.com/stalniy/casl/issues/102)
183
-
184
-
185
- ### Features
186
-
187
- * **react:can:** updates typescript declarations ([213dcde](https://github.com/stalniy/casl/commit/213dcde))
188
-
189
- <a name="@casl/mongoose-v2.1.2"></a>
190
- # [@casl/mongoose-v2.1.2](https://github.com/stalniy/casl/compare/@casl/mongoose@2.1.1...@casl/mongoose@2.1.2) (2018-07-02)
191
-
192
-
193
- ### Bug Fixes
194
-
195
- * **mongoose:** `accessibleBy` now doesn't change query type ([da7ed74](https://github.com/stalniy/casl/commit/da7ed74)), closes [#87](https://github.com/stalniy/casl/issues/87)
196
-
197
- <a name="2.1.1"></a>
198
- ## [2.1.1](https://github.com/stalniy/casl/compare/@casl/mongoose@2.1.0...@casl/mongoose@2.1.1) (2018-05-06)
199
-
200
-
201
- ### Bug Fixes
202
-
203
- * **mongoose:** fixes d.ts ([9be9989](https://github.com/stalniy/casl/commit/9be9989)), closes [#57](https://github.com/stalniy/casl/issues/57)
204
-
205
-
206
-
207
-
208
- <a name="2.1.0"></a>
209
- # 2.1.0 (2018-04-17)
210
-
211
-
212
- ### Bug Fixes
213
-
214
- * **mongoose:** returns empty result set for Query#count ([f89dfb9](https://github.com/stalniy/casl/commit/f89dfb9)), closes [#52](https://github.com/stalniy/casl/issues/52)
215
- * **typescript:** fixes typings ([d5fc51c](https://github.com/stalniy/casl/commit/d5fc51c)), relates to [#18](https://github.com/stalniy/casl/issues/18)
216
-
217
-
218
- ### Features
219
-
220
- * **mongoose:** adds `permittedFieldsBy` to [@casl](https://github.com/casl)/mongoose ([17bcf9e](https://github.com/stalniy/casl/commit/17bcf9e)), closes [#49](https://github.com/stalniy/casl/issues/49)
221
-
222
-
223
- <a name="2.0.2"></a>
224
- ## 2.0.2 (2018-04-16)
225
-
226
-
227
- ### Bug Fixes
228
-
229
- * **mongoose:** returns empty result set for Query#count ([f89dfb9](https://github.com/stalniy/casl/commit/f89dfb9)), closes [#52](https://github.com/stalniy/casl/issues/52)
230
- * **typescript:** updates d.ts files ([d5fc51c](https://github.com/stalniy/casl/commit/d5fc51c)), closes [#18](https://github.com/stalniy/casl/issues/18)
231
-
232
-
233
- <a name="2.0.1"></a>
234
- # 2.0.1 (2018-03-23)
235
-
236
-
237
- ### Features
238
-
239
- * **package:** adds mongoose plugin
240
- * **package:** adds MongoDB query builder
package/index.d.ts DELETED
@@ -1 +0,0 @@
1
- export * from './dist/types';
package/index.js DELETED
@@ -1 +0,0 @@
1
- module.exports = require('./dist/umd');