@contember/schema-definition 2.0.0-beta.3 → 2.0.0-beta.4

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 (32) hide show
  1. package/dist/development/src/acl/builder/PermissionOverrider.cjs +7 -1
  2. package/dist/development/src/acl/builder/PermissionOverrider.cjs.map +1 -1
  3. package/dist/development/src/acl/builder/PermissionOverrider.js +7 -1
  4. package/dist/development/src/acl/builder/PermissionOverrider.js.map +1 -1
  5. package/dist/development/src/acl/definition/internal/AclFactory.cjs +22 -0
  6. package/dist/development/src/acl/definition/internal/AclFactory.cjs.map +1 -1
  7. package/dist/development/src/acl/definition/internal/AclFactory.js +22 -0
  8. package/dist/development/src/acl/definition/internal/AclFactory.js.map +1 -1
  9. package/dist/development/src/acl/definition/permissions.cjs.map +1 -1
  10. package/dist/development/src/acl/definition/permissions.js.map +1 -1
  11. package/dist/production/src/acl/builder/PermissionOverrider.cjs +7 -1
  12. package/dist/production/src/acl/builder/PermissionOverrider.cjs.map +1 -1
  13. package/dist/production/src/acl/builder/PermissionOverrider.js +7 -1
  14. package/dist/production/src/acl/builder/PermissionOverrider.js.map +1 -1
  15. package/dist/production/src/acl/definition/internal/AclFactory.cjs +22 -0
  16. package/dist/production/src/acl/definition/internal/AclFactory.cjs.map +1 -1
  17. package/dist/production/src/acl/definition/internal/AclFactory.js +22 -0
  18. package/dist/production/src/acl/definition/internal/AclFactory.js.map +1 -1
  19. package/dist/production/src/acl/definition/permissions.cjs.map +1 -1
  20. package/dist/production/src/acl/definition/permissions.js.map +1 -1
  21. package/dist/tests/tsconfig.tsbuildinfo +1 -1
  22. package/dist/types/acl/builder/PermissionOverrider.d.ts.map +1 -1
  23. package/dist/types/acl/definition/internal/AclFactory.d.ts +1 -0
  24. package/dist/types/acl/definition/internal/AclFactory.d.ts.map +1 -1
  25. package/dist/types/acl/definition/permissions.d.ts +1 -0
  26. package/dist/types/acl/definition/permissions.d.ts.map +1 -1
  27. package/dist/types/tsconfig.tsbuildinfo +1 -1
  28. package/package.json +3 -3
  29. package/src/acl/builder/PermissionOverrider.ts +6 -0
  30. package/src/acl/definition/internal/AclFactory.ts +30 -1
  31. package/src/acl/definition/permissions.ts +1 -0
  32. package/tests/cases/unit/readAclDefinitions.test.ts +76 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contember/schema-definition",
3
- "version": "2.0.0-beta.3",
3
+ "version": "2.0.0-beta.4",
4
4
  "license": "Apache-2.0",
5
5
  "main": "./dist/production/index.js",
6
6
  "typings": "./dist/types/index.d.ts",
@@ -23,8 +23,8 @@
23
23
  }
24
24
  },
25
25
  "dependencies": {
26
- "@contember/schema": "2.0.0-beta.3",
27
- "@contember/schema-utils": "2.0.0-beta.3",
26
+ "@contember/schema": "2.0.0-beta.4",
27
+ "@contember/schema-utils": "2.0.0-beta.4",
28
28
  "reflect-metadata": "^0.2.2",
29
29
  "fast-deep-equal": "^3.1.3"
30
30
  },
@@ -33,6 +33,12 @@ export default class PermissionOverrider {
33
33
  : {
34
34
  customPrimary: overrides.operations.customPrimary ?? original.operations.customPrimary,
35
35
  }),
36
+ ...(original.operations.noRoot || overrides.operations.noRoot ? {
37
+ noRoot: [
38
+ ...(original.operations.noRoot || []),
39
+ ...(overrides.operations.noRoot || []),
40
+ ],
41
+ } : {}),
36
42
  },
37
43
  }
38
44
  }
@@ -53,7 +53,12 @@ export class AclFactory {
53
53
 
54
54
  const predicatesResolver = EntityPredicatesResolver.create(rolePermissions, this.model, entity)
55
55
 
56
- const entityOperations: Writable<Acl.EntityOperations> = {}
56
+ const entityOperations: Writable<Acl.EntityOperations> = {
57
+ }
58
+ const noRootOptions = this.getNoRootOptions(entity, rolePermissions.get(entityName))
59
+ if (noRootOptions?.length) {
60
+ entityOperations.noRoot = noRootOptions
61
+ }
57
62
  for (const op of ['create', 'update', 'read'] as const) {
58
63
  const fieldPermissions: Writable<Acl.FieldPermissions> = {}
59
64
  for (const field of Object.keys(entity.fields)) {
@@ -76,10 +81,34 @@ export class AclFactory {
76
81
  return [entityName, {
77
82
  predicates: predicatesResolver.getUsedPredicates(),
78
83
  operations: entityOperations,
84
+
79
85
  }]
80
86
  }))
81
87
  }
82
88
 
89
+
90
+ getNoRootOptions(entity: Model.Entity, permissions?: EntityPermissions): Acl.EntityOperations['noRoot'] {
91
+ const allowedRoot = new Set<Acl.Operation>()
92
+ const disallowedRoot = new Set<Acl.Operation>()
93
+ for (const def of permissions?.definitions ?? []) {
94
+ const noRoot = def.through === true
95
+ for (const op of ['create', 'read', 'update', 'delete'] as const) {
96
+ if (def[op]) {
97
+ const currentSet = noRoot ? disallowedRoot : allowedRoot
98
+ currentSet.add(op as Acl.Operation)
99
+
100
+ const otherSet = noRoot ? allowedRoot : disallowedRoot
101
+
102
+ if (otherSet.has(op as Acl.Operation)) {
103
+ throw new Error(`Operation ${op} cannot be both allowed and disallowed on root on entity ${entity.name}`)
104
+ }
105
+ }
106
+ }
107
+
108
+ }
109
+ return [...disallowedRoot.values()]
110
+ }
111
+
83
112
  private createVariables(role: Role, variables: VariableDefinition[]): Acl.Variables {
84
113
  const roleVariables = variables.filter(it => it.roles.includes(role))
85
114
  return Object.fromEntries(roleVariables.map((variable): [string, Acl.Variable] => {
@@ -10,6 +10,7 @@ export type WhenDefinition = Acl.PredicateDefinition<PredicateExtra>
10
10
 
11
11
  export interface AllowDefinition<E> {
12
12
  when?: WhenDefinition
13
+ through?: true
13
14
  name?: string
14
15
  create?: true | ('id' | keyof E)[]
15
16
  update?: true | ('id' | keyof E)[]
@@ -566,3 +566,79 @@ test('explicit ID predicate', () => {
566
566
  'predicates': {},
567
567
  })
568
568
  })
569
+
570
+ namespace NoRoot {
571
+ export const publicRole = c.createRole('public')
572
+
573
+ @c.Allow(publicRole, {
574
+ read: ['id'],
575
+ })
576
+ @c.Allow(publicRole, {
577
+ when: { foo: { eq: 2 } },
578
+ through: true,
579
+ update: ['id'],
580
+ })
581
+ @c.Allow(publicRole, {
582
+ when: { foo: { eq: 1 } },
583
+ through: true,
584
+ update: ['id'],
585
+ })
586
+ export class Book {
587
+ title = c.stringColumn()
588
+ foo = c.intColumn()
589
+ }
590
+ }
591
+
592
+ test('no root - valid', () => {
593
+ const schema = createSchema(NoRoot)
594
+ expect(schema.acl.roles.public.entities.Book).toStrictEqual({
595
+ operations: {
596
+ noRoot: [Acl.Operation.update],
597
+ read: {
598
+ id: true,
599
+ },
600
+ update: {
601
+ id: 'or_foo_eq_1_foo_eq_2',
602
+ },
603
+ },
604
+ predicates: {
605
+ or_foo_eq_1_foo_eq_2: {
606
+ or: [
607
+ {
608
+ foo: {
609
+ eq: 1,
610
+ },
611
+ },
612
+ {
613
+ foo: {
614
+ eq: 2,
615
+ },
616
+ },
617
+ ],
618
+ },
619
+ },
620
+ })
621
+ })
622
+
623
+
624
+ namespace NoRootInvalid {
625
+ export const publicRole = c.createRole('public')
626
+
627
+ @c.Allow(publicRole, {
628
+ when: { foo: { eq: 2 } },
629
+ through: true,
630
+ update: ['id'],
631
+ })
632
+ @c.Allow(publicRole, {
633
+ when: { foo: { eq: 1 } },
634
+ update: ['id'],
635
+ })
636
+ export class Book {
637
+ title = c.stringColumn()
638
+ foo = c.intColumn()
639
+ }
640
+ }
641
+
642
+ test('no root - invalid combo', () => {
643
+ expect(() => createSchema(NoRootInvalid)).toThrow('Operation update cannot be both allowed and disallowed on root on entity Book')
644
+ })