@jperezmart/nest-casl-testing 0.1.2 → 0.2.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.
- package/README.md +7 -1
- package/dist/index.cjs +4 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -7
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +12 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -23,9 +23,15 @@ would have built:
|
|
|
23
23
|
|
|
24
24
|
```ts
|
|
25
25
|
import { buildAbilityForTest } from '@jperezmart/nest-casl-testing';
|
|
26
|
+
import type { RolePermissions } from '@jperezmart/nest-casl';
|
|
26
27
|
import { subject } from '@casl/ability';
|
|
27
28
|
|
|
28
|
-
|
|
29
|
+
interface AppUser {
|
|
30
|
+
id: string;
|
|
31
|
+
roles: string[];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const permissions: RolePermissions<'author', AppUser> = {
|
|
29
35
|
author: (user, { can }) => {
|
|
30
36
|
can('read', 'Article');
|
|
31
37
|
can('update', 'Article', { authorId: user.id });
|
package/dist/index.cjs
CHANGED
|
@@ -2,9 +2,11 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
2
2
|
let _casl_ability = require("@casl/ability");
|
|
3
3
|
//#region src/index.ts
|
|
4
4
|
/**
|
|
5
|
-
* Build a CASL ability directly from
|
|
5
|
+
* Build a CASL ability directly from Role permissions and a user, without
|
|
6
6
|
* booting a Nest application. Intended for unit-testing permission definitions
|
|
7
|
-
* in projects that consume `@jperezmart/nest-casl`.
|
|
7
|
+
* in projects that consume `@jperezmart/nest-casl`. The role union, user and
|
|
8
|
+
* ability types are inferred from `permissions`; the user may carry roles the
|
|
9
|
+
* map does not declare.
|
|
8
10
|
*
|
|
9
11
|
* @example
|
|
10
12
|
* ```ts
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["AbilityBuilder","createMongoAbility"],"sources":["../src/index.ts"],"sourcesContent":["import type { AnyAbility, MongoAbility } from '@casl/ability';\nimport { AbilityBuilder, createMongoAbility } from '@casl/ability';\nimport type {\n AuthorizableUser,\n
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["AbilityBuilder","createMongoAbility"],"sources":["../src/index.ts"],"sourcesContent":["import type { AnyAbility, MongoAbility } from '@casl/ability';\nimport { AbilityBuilder, createMongoAbility } from '@casl/ability';\nimport type {\n AuthorizableUser,\n DefineRolePermissions,\n RolePermissions,\n} from '@jperezmart/nest-casl';\n\n/** Extra options accepted by {@link buildAbilityForTest}. */\nexport interface BuildAbilityForTestOptions {\n /**\n * Role that bypasses all checks (mirrors `CaslModule.forRoot`). Any string:\n * the superuser role usually has no entry in the Role permissions.\n */\n superuserRole?: string;\n\n /** Custom subject-type detection (mirrors `CaslModule.forRoot`). */\n detectSubjectType?: (subject: object) => string;\n}\n\n/**\n * Build a CASL ability directly from Role permissions and a user, without\n * booting a Nest application. Intended for unit-testing permission definitions\n * in projects that consume `@jperezmart/nest-casl`. The role union, user and\n * ability types are inferred from `permissions`; the user may carry roles the\n * map does not declare.\n *\n * @example\n * ```ts\n * const ability = buildAbilityForTest(permissions, { id: \"1\", roles: [\"author\"] });\n * expect(ability.can(\"update\", subject(\"Article\", { authorId: \"1\" }))).toBe(true);\n * ```\n */\nexport function buildAbilityForTest<\n Roles extends string = string,\n TUser extends AuthorizableUser = AuthorizableUser,\n TAbility extends AnyAbility = AnyAbility,\n>(\n permissions: RolePermissions<Roles, TUser, TAbility>,\n user: TUser,\n options: BuildAbilityForTestOptions = {},\n): TAbility {\n const builder = new AbilityBuilder<MongoAbility>(createMongoAbility);\n const buildOptions = options.detectSubjectType\n ? { detectSubjectType: options.detectSubjectType }\n : undefined;\n\n // Mirror AbilityFactory: a missing / non-array `roles` means \"no roles\".\n const roles: readonly string[] = Array.isArray(user.roles) ? user.roles : [];\n\n if (\n options.superuserRole !== undefined &&\n roles.includes(options.superuserRole)\n ) {\n builder.can('manage', 'all');\n return builder.build(buildOptions) as unknown as TAbility;\n }\n\n for (const role of roles) {\n const definition = (permissions as Record<string, unknown>)[role];\n if (definition === true) {\n builder.can('manage', 'all');\n } else if (typeof definition === 'function') {\n (definition as DefineRolePermissions<TUser, AnyAbility>)(\n user,\n builder as unknown as AbilityBuilder<AnyAbility>,\n );\n }\n }\n\n return builder.build(buildOptions) as unknown as TAbility;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAiCA,SAAgB,oBAKd,aACA,MACA,UAAsC,CAAC,GAC7B;CACV,MAAM,UAAU,IAAIA,cAAAA,eAA6BC,cAAAA,kBAAkB;CACnE,MAAM,eAAe,QAAQ,oBACzB,EAAE,mBAAmB,QAAQ,kBAAkB,IAC/C,KAAA;CAGJ,MAAM,QAA2B,MAAM,QAAQ,KAAK,KAAK,IAAI,KAAK,QAAQ,CAAC;CAE3E,IACE,QAAQ,kBAAkB,KAAA,KAC1B,MAAM,SAAS,QAAQ,aAAa,GACpC;EACA,QAAQ,IAAI,UAAU,KAAK;EAC3B,OAAO,QAAQ,MAAM,YAAY;CACnC;CAEA,KAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,aAAc,YAAwC;EAC5D,IAAI,eAAe,MACjB,QAAQ,IAAI,UAAU,KAAK;OACtB,IAAI,OAAO,eAAe,YAC/B,WACE,MACA,OACF;CAEJ;CAEA,OAAO,QAAQ,MAAM,YAAY;AACnC"}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,18 +1,23 @@
|
|
|
1
1
|
import { AnyAbility } from "@casl/ability";
|
|
2
|
-
import { AuthorizableUser,
|
|
2
|
+
import { AuthorizableUser, RolePermissions } from "@jperezmart/nest-casl";
|
|
3
3
|
|
|
4
4
|
//#region src/index.d.ts
|
|
5
5
|
/** Extra options accepted by {@link buildAbilityForTest}. */
|
|
6
|
-
interface BuildAbilityForTestOptions
|
|
7
|
-
/**
|
|
8
|
-
|
|
6
|
+
interface BuildAbilityForTestOptions {
|
|
7
|
+
/**
|
|
8
|
+
* Role that bypasses all checks (mirrors `CaslModule.forRoot`). Any string:
|
|
9
|
+
* the superuser role usually has no entry in the Role permissions.
|
|
10
|
+
*/
|
|
11
|
+
superuserRole?: string;
|
|
9
12
|
/** Custom subject-type detection (mirrors `CaslModule.forRoot`). */
|
|
10
13
|
detectSubjectType?: (subject: object) => string;
|
|
11
14
|
}
|
|
12
15
|
/**
|
|
13
|
-
* Build a CASL ability directly from
|
|
16
|
+
* Build a CASL ability directly from Role permissions and a user, without
|
|
14
17
|
* booting a Nest application. Intended for unit-testing permission definitions
|
|
15
|
-
* in projects that consume `@jperezmart/nest-casl`.
|
|
18
|
+
* in projects that consume `@jperezmart/nest-casl`. The role union, user and
|
|
19
|
+
* ability types are inferred from `permissions`; the user may carry roles the
|
|
20
|
+
* map does not declare.
|
|
16
21
|
*
|
|
17
22
|
* @example
|
|
18
23
|
* ```ts
|
|
@@ -20,7 +25,7 @@ interface BuildAbilityForTestOptions<Roles extends string = string> {
|
|
|
20
25
|
* expect(ability.can("update", subject("Article", { authorId: "1" }))).toBe(true);
|
|
21
26
|
* ```
|
|
22
27
|
*/
|
|
23
|
-
declare function buildAbilityForTest<Roles extends string = string, TUser extends AuthorizableUser
|
|
28
|
+
declare function buildAbilityForTest<Roles extends string = string, TUser extends AuthorizableUser = AuthorizableUser, TAbility extends AnyAbility = AnyAbility>(permissions: RolePermissions<Roles, TUser, TAbility>, user: TUser, options?: BuildAbilityForTestOptions): TAbility;
|
|
24
29
|
//#endregion
|
|
25
30
|
export { BuildAbilityForTestOptions, buildAbilityForTest };
|
|
26
31
|
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/index.ts"],"mappings":";;;;;UASiB,0BAAA;EAAA
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/index.ts"],"mappings":";;;;;UASiB,0BAAA;EAAA;;;;EAKf,aAAA;EAGA;EAAA,iBAAA,IAAqB,OAAA;AAAA;AAAe;AAgBtC;;;;;;;;;;;;AAhBsC,iBAgBtB,mBAAA,8CAEA,gBAAA,GAAmB,gBAAA,mBAChB,UAAA,GAAa,UAAA,EAE9B,WAAA,EAAa,eAAA,CAAgB,KAAA,EAAO,KAAA,EAAO,QAAA,GAC3C,IAAA,EAAM,KAAA,EACN,OAAA,GAAS,0BAAA,GACR,QAAA"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,18 +1,23 @@
|
|
|
1
1
|
import { AnyAbility } from "@casl/ability";
|
|
2
|
-
import { AuthorizableUser,
|
|
2
|
+
import { AuthorizableUser, RolePermissions } from "@jperezmart/nest-casl";
|
|
3
3
|
|
|
4
4
|
//#region src/index.d.ts
|
|
5
5
|
/** Extra options accepted by {@link buildAbilityForTest}. */
|
|
6
|
-
interface BuildAbilityForTestOptions
|
|
7
|
-
/**
|
|
8
|
-
|
|
6
|
+
interface BuildAbilityForTestOptions {
|
|
7
|
+
/**
|
|
8
|
+
* Role that bypasses all checks (mirrors `CaslModule.forRoot`). Any string:
|
|
9
|
+
* the superuser role usually has no entry in the Role permissions.
|
|
10
|
+
*/
|
|
11
|
+
superuserRole?: string;
|
|
9
12
|
/** Custom subject-type detection (mirrors `CaslModule.forRoot`). */
|
|
10
13
|
detectSubjectType?: (subject: object) => string;
|
|
11
14
|
}
|
|
12
15
|
/**
|
|
13
|
-
* Build a CASL ability directly from
|
|
16
|
+
* Build a CASL ability directly from Role permissions and a user, without
|
|
14
17
|
* booting a Nest application. Intended for unit-testing permission definitions
|
|
15
|
-
* in projects that consume `@jperezmart/nest-casl`.
|
|
18
|
+
* in projects that consume `@jperezmart/nest-casl`. The role union, user and
|
|
19
|
+
* ability types are inferred from `permissions`; the user may carry roles the
|
|
20
|
+
* map does not declare.
|
|
16
21
|
*
|
|
17
22
|
* @example
|
|
18
23
|
* ```ts
|
|
@@ -20,7 +25,7 @@ interface BuildAbilityForTestOptions<Roles extends string = string> {
|
|
|
20
25
|
* expect(ability.can("update", subject("Article", { authorId: "1" }))).toBe(true);
|
|
21
26
|
* ```
|
|
22
27
|
*/
|
|
23
|
-
declare function buildAbilityForTest<Roles extends string = string, TUser extends AuthorizableUser
|
|
28
|
+
declare function buildAbilityForTest<Roles extends string = string, TUser extends AuthorizableUser = AuthorizableUser, TAbility extends AnyAbility = AnyAbility>(permissions: RolePermissions<Roles, TUser, TAbility>, user: TUser, options?: BuildAbilityForTestOptions): TAbility;
|
|
24
29
|
//#endregion
|
|
25
30
|
export { BuildAbilityForTestOptions, buildAbilityForTest };
|
|
26
31
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"mappings":";;;;;UASiB,0BAAA;EAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"mappings":";;;;;UASiB,0BAAA;EAAA;;;;EAKf,aAAA;EAGA;EAAA,iBAAA,IAAqB,OAAA;AAAA;AAAe;AAgBtC;;;;;;;;;;;;AAhBsC,iBAgBtB,mBAAA,8CAEA,gBAAA,GAAmB,gBAAA,mBAChB,UAAA,GAAa,UAAA,EAE9B,WAAA,EAAa,eAAA,CAAgB,KAAA,EAAO,KAAA,EAAO,QAAA,GAC3C,IAAA,EAAM,KAAA,EACN,OAAA,GAAS,0BAAA,GACR,QAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { AbilityBuilder, createMongoAbility } from "@casl/ability";
|
|
2
2
|
//#region src/index.ts
|
|
3
3
|
/**
|
|
4
|
-
* Build a CASL ability directly from
|
|
4
|
+
* Build a CASL ability directly from Role permissions and a user, without
|
|
5
5
|
* booting a Nest application. Intended for unit-testing permission definitions
|
|
6
|
-
* in projects that consume `@jperezmart/nest-casl`.
|
|
6
|
+
* in projects that consume `@jperezmart/nest-casl`. The role union, user and
|
|
7
|
+
* ability types are inferred from `permissions`; the user may carry roles the
|
|
8
|
+
* map does not declare.
|
|
7
9
|
*
|
|
8
10
|
* @example
|
|
9
11
|
* ```ts
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import type { AnyAbility, MongoAbility } from '@casl/ability';\nimport { AbilityBuilder, createMongoAbility } from '@casl/ability';\nimport type {\n AuthorizableUser,\n
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import type { AnyAbility, MongoAbility } from '@casl/ability';\nimport { AbilityBuilder, createMongoAbility } from '@casl/ability';\nimport type {\n AuthorizableUser,\n DefineRolePermissions,\n RolePermissions,\n} from '@jperezmart/nest-casl';\n\n/** Extra options accepted by {@link buildAbilityForTest}. */\nexport interface BuildAbilityForTestOptions {\n /**\n * Role that bypasses all checks (mirrors `CaslModule.forRoot`). Any string:\n * the superuser role usually has no entry in the Role permissions.\n */\n superuserRole?: string;\n\n /** Custom subject-type detection (mirrors `CaslModule.forRoot`). */\n detectSubjectType?: (subject: object) => string;\n}\n\n/**\n * Build a CASL ability directly from Role permissions and a user, without\n * booting a Nest application. Intended for unit-testing permission definitions\n * in projects that consume `@jperezmart/nest-casl`. The role union, user and\n * ability types are inferred from `permissions`; the user may carry roles the\n * map does not declare.\n *\n * @example\n * ```ts\n * const ability = buildAbilityForTest(permissions, { id: \"1\", roles: [\"author\"] });\n * expect(ability.can(\"update\", subject(\"Article\", { authorId: \"1\" }))).toBe(true);\n * ```\n */\nexport function buildAbilityForTest<\n Roles extends string = string,\n TUser extends AuthorizableUser = AuthorizableUser,\n TAbility extends AnyAbility = AnyAbility,\n>(\n permissions: RolePermissions<Roles, TUser, TAbility>,\n user: TUser,\n options: BuildAbilityForTestOptions = {},\n): TAbility {\n const builder = new AbilityBuilder<MongoAbility>(createMongoAbility);\n const buildOptions = options.detectSubjectType\n ? { detectSubjectType: options.detectSubjectType }\n : undefined;\n\n // Mirror AbilityFactory: a missing / non-array `roles` means \"no roles\".\n const roles: readonly string[] = Array.isArray(user.roles) ? user.roles : [];\n\n if (\n options.superuserRole !== undefined &&\n roles.includes(options.superuserRole)\n ) {\n builder.can('manage', 'all');\n return builder.build(buildOptions) as unknown as TAbility;\n }\n\n for (const role of roles) {\n const definition = (permissions as Record<string, unknown>)[role];\n if (definition === true) {\n builder.can('manage', 'all');\n } else if (typeof definition === 'function') {\n (definition as DefineRolePermissions<TUser, AnyAbility>)(\n user,\n builder as unknown as AbilityBuilder<AnyAbility>,\n );\n }\n }\n\n return builder.build(buildOptions) as unknown as TAbility;\n}\n"],"mappings":";;;;;;;;;;;;;;;AAiCA,SAAgB,oBAKd,aACA,MACA,UAAsC,CAAC,GAC7B;CACV,MAAM,UAAU,IAAI,eAA6B,kBAAkB;CACnE,MAAM,eAAe,QAAQ,oBACzB,EAAE,mBAAmB,QAAQ,kBAAkB,IAC/C,KAAA;CAGJ,MAAM,QAA2B,MAAM,QAAQ,KAAK,KAAK,IAAI,KAAK,QAAQ,CAAC;CAE3E,IACE,QAAQ,kBAAkB,KAAA,KAC1B,MAAM,SAAS,QAAQ,aAAa,GACpC;EACA,QAAQ,IAAI,UAAU,KAAK;EAC3B,OAAO,QAAQ,MAAM,YAAY;CACnC;CAEA,KAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,aAAc,YAAwC;EAC5D,IAAI,eAAe,MACjB,QAAQ,IAAI,UAAU,KAAK;OACtB,IAAI,OAAO,eAAe,YAC/B,WACE,MACA,OACF;CAEJ;CAEA,OAAO,QAAQ,MAAM,YAAY;AACnC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jperezmart/nest-casl-testing",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Testing utilities for @jperezmart/nest-casl — build and assert abilities without booting Nest.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@casl/ability": "^7.0.0",
|
|
37
37
|
"@jperezmart/eslint-config": "^1.0.0",
|
|
38
|
-
"@jperezmart/nest-casl": "0.
|
|
38
|
+
"@jperezmart/nest-casl": "0.2.0",
|
|
39
39
|
"@jperezmart/typescript-config": "^1.0.0",
|
|
40
40
|
"eslint": "^10.3.0",
|
|
41
41
|
"tsdown": "^0.22.2",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
},
|
|
45
45
|
"peerDependencies": {
|
|
46
46
|
"@casl/ability": "^7.0.0",
|
|
47
|
-
"@jperezmart/nest-casl": "^0.
|
|
47
|
+
"@jperezmart/nest-casl": "^0.2.0"
|
|
48
48
|
},
|
|
49
49
|
"publishConfig": {
|
|
50
50
|
"access": "public"
|