@contember/engine-content-api 1.3.0-alpha.6 → 1.3.0-alpha.7

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.
Files changed (45) hide show
  1. package/dist/src/acl/PermissionFactory.d.ts +5 -4
  2. package/dist/src/acl/PermissionFactory.d.ts.map +1 -1
  3. package/dist/src/acl/PermissionFactory.js +10 -13
  4. package/dist/src/acl/PermissionFactory.js.map +1 -1
  5. package/dist/src/acl/index.d.ts +0 -1
  6. package/dist/src/acl/index.d.ts.map +1 -1
  7. package/dist/src/acl/index.js +0 -1
  8. package/dist/src/acl/index.js.map +1 -1
  9. package/dist/src/tsconfig.tsbuildinfo +1 -1
  10. package/dist/src/types.d.ts +1 -1
  11. package/dist/src/types.d.ts.map +1 -1
  12. package/dist/src/utils/index.d.ts +0 -1
  13. package/dist/src/utils/index.d.ts.map +1 -1
  14. package/dist/src/utils/index.js +0 -1
  15. package/dist/src/utils/index.js.map +1 -1
  16. package/dist/tests/cases/integration/graphQlRequests/query/acl/isNullAcl.test.d.ts +2 -0
  17. package/dist/tests/cases/integration/graphQlRequests/query/acl/isNullAcl.test.d.ts.map +1 -0
  18. package/dist/tests/cases/integration/graphQlRequests/query/acl/isNullAcl.test.js +91 -0
  19. package/dist/tests/cases/integration/graphQlRequests/query/acl/isNullAcl.test.js.map +1 -0
  20. package/dist/tests/cases/integration/graphQlRequests/query/acl/rowPredicateSubset.test.js +1 -1
  21. package/dist/tests/cases/integration/graphQlRequests/query/acl/rowPredicateSubset.test.js.map +1 -1
  22. package/dist/tests/cases/unit/permissionMerger.test.js +8 -3
  23. package/dist/tests/cases/unit/permissionMerger.test.js.map +1 -1
  24. package/dist/tests/cases/unit/predicatesInjector.test.js +1 -1
  25. package/dist/tests/cases/unit/predicatesInjector.test.js.map +1 -1
  26. package/dist/tests/tsconfig.tsbuildinfo +1 -1
  27. package/package.json +11 -11
  28. package/src/acl/PermissionFactory.ts +15 -13
  29. package/src/acl/index.ts +0 -1
  30. package/src/types.ts +1 -1
  31. package/src/utils/index.ts +0 -1
  32. package/tests/cases/integration/graphQlRequests/query/acl/isNullAcl.test.ts +77 -0
  33. package/tests/cases/integration/graphQlRequests/query/acl/rowPredicateSubset.test.ts +1 -1
  34. package/tests/cases/unit/permissionMerger.test.ts +9 -4
  35. package/tests/cases/unit/predicatesInjector.test.ts +1 -1
  36. package/dist/src/acl/PermissionsByIdentityFactory.d.ts +0 -12
  37. package/dist/src/acl/PermissionsByIdentityFactory.d.ts.map +0 -1
  38. package/dist/src/acl/PermissionsByIdentityFactory.js +0 -15
  39. package/dist/src/acl/PermissionsByIdentityFactory.js.map +0 -1
  40. package/dist/src/utils/arrays.d.ts +0 -3
  41. package/dist/src/utils/arrays.d.ts.map +0 -1
  42. package/dist/src/utils/arrays.js +0 -22
  43. package/dist/src/utils/arrays.js.map +0 -1
  44. package/src/acl/PermissionsByIdentityFactory.ts +0 -21
  45. package/src/utils/arrays.ts +0 -19
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contember/engine-content-api",
3
- "version": "1.3.0-alpha.6",
3
+ "version": "1.3.0-alpha.7",
4
4
  "license": "Apache-2.0",
5
5
  "main": "dist/src/index.js",
6
6
  "typings": "dist/src/index.d.ts",
@@ -14,21 +14,21 @@
14
14
  "test": "vitest --no-threads"
15
15
  },
16
16
  "dependencies": {
17
- "@contember/database": "^1.3.0-alpha.6",
18
- "@contember/dic": "^1.3.0-alpha.6",
19
- "@contember/logger": "^1.3.0-alpha.6",
20
- "@contember/graphql-utils": "^1.3.0-alpha.6",
21
- "@contember/schema": "^1.3.0-alpha.6",
22
- "@contember/schema-definition": "^1.3.0-alpha.6",
23
- "@contember/schema-utils": "^1.3.0-alpha.6",
17
+ "@contember/database": "^1.3.0-alpha.7",
18
+ "@contember/dic": "^1.3.0-alpha.7",
19
+ "@contember/logger": "^1.3.0-alpha.7",
20
+ "@contember/graphql-utils": "^1.3.0-alpha.7",
21
+ "@contember/schema": "^1.3.0-alpha.7",
22
+ "@contember/schema-definition": "^1.3.0-alpha.7",
23
+ "@contember/schema-utils": "^1.3.0-alpha.7",
24
24
  "@graphql-tools/schema": "^8.3.5",
25
25
  "fast-deep-equal": "^3.1.3",
26
26
  "graphql-tag": "^2.12.5"
27
27
  },
28
28
  "devDependencies": {
29
- "@contember/database-tester": "^1.3.0-alpha.6",
30
- "@contember/engine-api-tester": "^1.3.0-alpha.6",
31
- "@contember/schema-definition": "^1.3.0-alpha.6",
29
+ "@contember/database-tester": "^1.3.0-alpha.7",
30
+ "@contember/engine-api-tester": "^1.3.0-alpha.7",
31
+ "@contember/schema-definition": "^1.3.0-alpha.7",
32
32
  "@graphql-codegen/cli": "^2.6.2",
33
33
  "@graphql-codegen/typescript": "^2.5.1",
34
34
  "@graphql-codegen/typescript-operations": "^2.4.2",
@@ -1,33 +1,35 @@
1
- import { Acl, Model, Writable } from '@contember/schema'
1
+ import { Acl, Model, Schema, Writable } from '@contember/schema'
2
2
  import { getEntity, PredicateDefinitionProcessor } from '@contember/schema-utils'
3
3
  import { mapObject } from '../utils'
4
4
  import { prefixVariable } from './VariableUtils'
5
5
 
6
- export class PermissionFactory {
7
- constructor(private readonly schema: Model.Schema) {}
6
+ export interface Identity {
7
+ projectRoles: readonly string[]
8
+ }
8
9
 
9
- public create(acl: Acl.Schema, roles: readonly string[], prefix?: string): Acl.Permissions {
10
+ export class PermissionFactory {
11
+ public create(schema: Schema, roles: readonly string[], prefix?: string): Acl.Permissions {
10
12
  let result: Acl.Permissions = {}
11
13
  for (let role of roles) {
12
- const roleDefinition = acl.roles[role] || { entities: {} }
13
- let rolePermissions: Acl.Permissions = this.prefixPredicatesWithRole(roleDefinition.entities, prefix || role)
14
+ const roleDefinition = schema.acl.roles[role] || { entities: {} }
15
+ let rolePermissions: Acl.Permissions = this.prefixPredicatesWithRole(schema.model, roleDefinition.entities, prefix || role)
14
16
  if (roleDefinition.inherits) {
15
- const inheritedPermissions = this.create(acl, roleDefinition.inherits, prefix || role)
17
+ const inheritedPermissions = this.create(schema, roleDefinition.inherits, prefix || role)
16
18
  rolePermissions = this.mergePermissions(inheritedPermissions, rolePermissions)
17
19
  }
18
20
  result = this.mergePermissions(result, rolePermissions)
19
21
  }
20
- result = this.makePrimaryPredicatesUnionOfAllFields(result)
22
+ result = this.makePrimaryPredicatesUnionOfAllFields(schema.model, result)
21
23
 
22
24
  return result
23
25
  }
24
26
 
25
- private prefixPredicatesWithRole(permissions: Acl.Permissions, role: string): Acl.Permissions {
27
+ private prefixPredicatesWithRole(model: Model.Schema, permissions: Acl.Permissions, role: string): Acl.Permissions {
26
28
  return mapObject(permissions, ({ operations, predicates }, entityName) => ({
27
29
  operations,
28
30
  predicates: mapObject(predicates, predicate => {
29
- const predicateDefinitionProcessor = new PredicateDefinitionProcessor(this.schema)
30
- return predicateDefinitionProcessor.process(getEntity(this.schema, entityName), predicate, {
31
+ const predicateDefinitionProcessor = new PredicateDefinitionProcessor(model)
32
+ return predicateDefinitionProcessor.process(getEntity(model, entityName), predicate, {
31
33
  handleColumn: ({ value }) => {
32
34
  if (typeof value === 'string') {
33
35
  return prefixVariable(role, value)
@@ -45,9 +47,9 @@ export class PermissionFactory {
45
47
  }))
46
48
  }
47
49
 
48
- private makePrimaryPredicatesUnionOfAllFields(permissions: Acl.Permissions): Acl.Permissions {
50
+ private makePrimaryPredicatesUnionOfAllFields(model: Model.Schema, permissions: Acl.Permissions): Acl.Permissions {
49
51
  return mapObject(permissions, (permission, entityName): Acl.EntityPermissions => {
50
- const entity = getEntity(this.schema, entityName)
52
+ const entity = getEntity(model, entityName)
51
53
  const entityPredicates: Writable<Acl.PredicateMap> = { ...permission.predicates }
52
54
  const entityOperations: Writable<Acl.EntityOperations> = { ...permission.operations }
53
55
 
package/src/acl/index.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  export * from './Authorizator'
2
2
  export * from './PermissionFactory'
3
- export * from './PermissionsByIdentityFactory'
4
3
  export * from './PredicateFactory'
5
4
  export * from './PredicatesInjector'
6
5
  export * from './VariableInjector'
package/src/types.ts CHANGED
@@ -6,5 +6,5 @@ export interface Context {
6
6
  db: Client
7
7
  identityVariables: Acl.VariablesMap
8
8
  executionContainer: ExecutionContainer
9
- timer: <T>(event: string, cb?: () => T) => Promise<T>
9
+ timer: <T>(event: string, cb: () => T) => T
10
10
  }
@@ -1,5 +1,4 @@
1
1
  export * from './accessor'
2
- export * from './arrays'
3
2
  export * from './assertNever'
4
3
  export * from './Interface'
5
4
  export * from './isIt'
@@ -0,0 +1,77 @@
1
+ import { AclDefinition as acl, createSchema, SchemaDefinition as def } from '@contember/schema-definition'
2
+ import { test } from 'vitest'
3
+ import { execute } from '../../../../../src/test'
4
+ import { GQL, SQL } from '../../../../../src/tags'
5
+ import { PermissionFactory } from '../../../../../../src'
6
+ import { testUuid } from '@contember/engine-api-tester'
7
+
8
+
9
+ namespace RowPredicateSubset {
10
+ export const ownerRole = acl.createRole('owner')
11
+ export const personIdVariable = acl.createPredefinedVariable('personId', 'personID', ownerRole)
12
+
13
+ @acl.allow(ownerRole, {
14
+ read: true,
15
+ when: { resource: acl.canRead('item') },
16
+ })
17
+ export class Item {
18
+ resource = def.oneHasOne(Resource, 'item')
19
+ }
20
+
21
+ @acl.allow(ownerRole, {
22
+ read: true,
23
+ when: { owner: acl.canRead('resources') },
24
+ })
25
+ export class Resource {
26
+ item = def.oneHasOneInverse(Item, 'resource')
27
+ owner = def.manyHasOne(Person, 'resources')
28
+ }
29
+
30
+ @acl.allow(ownerRole, {
31
+ read: true,
32
+ when: { personId: personIdVariable },
33
+ })
34
+ export class Person {
35
+ personId = def.uuidColumn().notNull()
36
+ resources = def.oneHasMany(Resource, 'owner')
37
+ }
38
+ }
39
+
40
+
41
+ test('owner predicate with isNull', async () => {
42
+ const schema = createSchema(RowPredicateSubset)
43
+
44
+ const permissions = new PermissionFactory().create(schema, ['owner'])
45
+
46
+ await execute({
47
+ schema: schema.model,
48
+ permissions: permissions,
49
+ variables: {
50
+ owner__personId: { eq: testUuid(0) },
51
+ },
52
+ query: GQL`
53
+ query {
54
+ listItem(filter: {resource: {id: {isNull: true}}}) {
55
+ id
56
+ }
57
+ }`,
58
+ executes: [
59
+ {
60
+ sql: SQL`select "root_"."id" as "root_id" from "public"."item" as "root_"
61
+ left join "public"."resource" as "root_resource" on "root_"."resource_id" = "root_resource"."id"
62
+ left join "public"."person" as "root_resource_owner" on "root_resource"."owner_id" = "root_resource_owner"."id"
63
+ where "root_resource"."id" is null and "root_resource_owner"."person_id" = ? and "root_resource_owner"."person_id" = ?`,
64
+ response: {
65
+ rows: [],
66
+ },
67
+ },
68
+ ],
69
+ return: {
70
+ data: {
71
+ listItem: [],
72
+ },
73
+ },
74
+ })
75
+ })
76
+
77
+
@@ -37,7 +37,7 @@ namespace RowPredicateSubset {
37
37
  test('row level predicate includes main predicate', async () => {
38
38
  const schema = createSchema(RowPredicateSubset)
39
39
 
40
- const permissions = new PermissionFactory(schema.model).create(schema.acl, ['reader'])
40
+ const permissions = new PermissionFactory().create(schema, ['reader'])
41
41
 
42
42
  await execute({
43
43
  schema: schema.model,
@@ -1,7 +1,8 @@
1
1
  import { Acl, Model } from '@contember/schema'
2
2
  import { PermissionFactory } from '../../../src/acl'
3
3
  import { SchemaBuilder } from '@contember/schema-definition'
4
- import { describe, it, assert } from 'vitest'
4
+ import { assert, describe, it } from 'vitest'
5
+ import { emptySchema } from '@contember/schema-utils'
5
6
 
6
7
  interface Test {
7
8
  acl: Acl.Schema
@@ -10,13 +11,17 @@ interface Test {
10
11
  }
11
12
 
12
13
  const execute = (test: Test) => {
13
- const schema: Model.Schema = new SchemaBuilder()
14
+ const model: Model.Schema = new SchemaBuilder()
14
15
  .entity('Entity1', e => e.column('lorem').column('bar'))
15
16
  .entity('Entity2', e => e.oneHasOne('xyz', r => r.target('Entity1')))
16
17
  .buildSchema()
17
- const merger = new PermissionFactory(schema)
18
+ const merger = new PermissionFactory()
18
19
  const initialAcl = JSON.parse(JSON.stringify(test.acl))
19
- const result = merger.create(test.acl, test.roles)
20
+ const result = merger.create({
21
+ ...emptySchema,
22
+ model,
23
+ acl: test.acl,
24
+ }, test.roles)
20
25
  assert.deepStrictEqual(result, test.result)
21
26
  assert.deepStrictEqual(test.acl, initialAcl)
22
27
  }
@@ -160,7 +160,7 @@ namespace DeepFilterModel {
160
160
 
161
161
  describe('predicates injector elimination', () => {
162
162
  const schema = createSchema(DeepFilterModel)
163
- const permissions = new PermissionFactory(schema.model).create(schema.acl, ['reader'])
163
+ const permissions = new PermissionFactory().create(schema, ['reader'])
164
164
 
165
165
  const injector = new PredicatesInjector(
166
166
  schema.model,
@@ -1,12 +0,0 @@
1
- import { Acl, Schema } from '@contember/schema';
2
- export declare class PermissionsByIdentityFactory {
3
- createPermissions(schema: Schema, identity: Identity): PermissionResult;
4
- }
5
- export interface Identity {
6
- projectRoles: string[];
7
- }
8
- export interface PermissionResult {
9
- permissions: Acl.Permissions;
10
- verifier: (identity: Identity) => boolean;
11
- }
12
- //# sourceMappingURL=PermissionsByIdentityFactory.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"PermissionsByIdentityFactory.d.ts","sourceRoot":"","sources":["../../../src/acl/PermissionsByIdentityFactory.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAE/C,qBAAa,4BAA4B;IACjC,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,gBAAgB;CAM9E;AAED,MAAM,WAAW,QAAQ;IACxB,YAAY,EAAE,MAAM,EAAE,CAAA;CACtB;AAED,MAAM,WAAW,gBAAgB;IAChC,WAAW,EAAE,GAAG,CAAC,WAAW,CAAA;IAC5B,QAAQ,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,OAAO,CAAA;CACzC"}
@@ -1,15 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.PermissionsByIdentityFactory = void 0;
4
- const PermissionFactory_1 = require("./PermissionFactory");
5
- const utils_1 = require("../utils");
6
- class PermissionsByIdentityFactory {
7
- createPermissions(schema, identity) {
8
- return {
9
- permissions: new PermissionFactory_1.PermissionFactory(schema.model).create(schema.acl, identity.projectRoles),
10
- verifier: otherIdentity => (0, utils_1.arrayEquals)(identity.projectRoles, otherIdentity.projectRoles),
11
- };
12
- }
13
- }
14
- exports.PermissionsByIdentityFactory = PermissionsByIdentityFactory;
15
- //# sourceMappingURL=PermissionsByIdentityFactory.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"PermissionsByIdentityFactory.js","sourceRoot":"","sources":["../../../src/acl/PermissionsByIdentityFactory.ts"],"names":[],"mappings":";;;AAAA,2DAAuD;AACvD,oCAAsC;AAGtC,MAAa,4BAA4B;IACjC,iBAAiB,CAAC,MAAc,EAAE,QAAkB;QAC1D,OAAO;YACN,WAAW,EAAE,IAAI,qCAAiB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,YAAY,CAAC;YAC1F,QAAQ,EAAE,aAAa,CAAC,EAAE,CAAC,IAAA,mBAAW,EAAC,QAAQ,CAAC,YAAY,EAAE,aAAa,CAAC,YAAY,CAAC;SACzF,CAAA;IACF,CAAC;CACD;AAPD,oEAOC"}
@@ -1,3 +0,0 @@
1
- declare const arrayEquals: (a: unknown[] | null, b: unknown[] | null) => boolean;
2
- export { arrayEquals };
3
- //# sourceMappingURL=arrays.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"arrays.d.ts","sourceRoot":"","sources":["../../../src/utils/arrays.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,WAAW,MAAO,OAAO,EAAE,GAAG,IAAI,KAAK,OAAO,EAAE,GAAG,IAAI,KAAG,OAgB/D,CAAA;AAED,OAAO,EAAE,WAAW,EAAE,CAAA"}
@@ -1,22 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.arrayEquals = void 0;
4
- const arrayEquals = (a, b) => {
5
- if (a === b) {
6
- return true;
7
- }
8
- if (a === null || b === null) {
9
- return false;
10
- }
11
- if (a.length !== b.length) {
12
- return false;
13
- }
14
- for (let i = 0; i < a.length; ++i) {
15
- if (a[i] !== b[i]) {
16
- return false;
17
- }
18
- }
19
- return true;
20
- };
21
- exports.arrayEquals = arrayEquals;
22
- //# sourceMappingURL=arrays.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"arrays.js","sourceRoot":"","sources":["../../../src/utils/arrays.ts"],"names":[],"mappings":";;;AAAA,MAAM,WAAW,GAAG,CAAC,CAAmB,EAAE,CAAmB,EAAW,EAAE;IACzE,IAAI,CAAC,KAAK,CAAC,EAAE;QACZ,OAAO,IAAI,CAAA;KACX;IACD,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,IAAI,EAAE;QAC7B,OAAO,KAAK,CAAA;KACZ;IACD,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,EAAE;QAC1B,OAAO,KAAK,CAAA;KACZ;IACD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE;QAClC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE;YAClB,OAAO,KAAK,CAAA;SACZ;KACD;IACD,OAAO,IAAI,CAAA;AACZ,CAAC,CAAA;AAEQ,kCAAW"}
@@ -1,21 +0,0 @@
1
- import { PermissionFactory } from './PermissionFactory'
2
- import { arrayEquals } from '../utils'
3
- import { Acl, Schema } from '@contember/schema'
4
-
5
- export class PermissionsByIdentityFactory {
6
- public createPermissions(schema: Schema, identity: Identity): PermissionResult {
7
- return {
8
- permissions: new PermissionFactory(schema.model).create(schema.acl, identity.projectRoles),
9
- verifier: otherIdentity => arrayEquals(identity.projectRoles, otherIdentity.projectRoles),
10
- }
11
- }
12
- }
13
-
14
- export interface Identity {
15
- projectRoles: string[]
16
- }
17
-
18
- export interface PermissionResult {
19
- permissions: Acl.Permissions
20
- verifier: (identity: Identity) => boolean
21
- }
@@ -1,19 +0,0 @@
1
- const arrayEquals = (a: unknown[] | null, b: unknown[] | null): boolean => {
2
- if (a === b) {
3
- return true
4
- }
5
- if (a === null || b === null) {
6
- return false
7
- }
8
- if (a.length !== b.length) {
9
- return false
10
- }
11
- for (let i = 0; i < a.length; ++i) {
12
- if (a[i] !== b[i]) {
13
- return false
14
- }
15
- }
16
- return true
17
- }
18
-
19
- export { arrayEquals }