@contember/engine-content-api 1.0.0-rc.9 → 1.1.0-alpha.2

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 (68) hide show
  1. package/dist/src/acl/Authorizator.d.ts +7 -3
  2. package/dist/src/acl/Authorizator.d.ts.map +1 -1
  3. package/dist/src/acl/Authorizator.js +43 -0
  4. package/dist/src/acl/Authorizator.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/introspection/IntrospectionSchemaFactory.js +2 -2
  10. package/dist/src/introspection/IntrospectionSchemaFactory.js.map +1 -1
  11. package/dist/src/schema/EntityTypeProvider.js +3 -3
  12. package/dist/src/schema/EntityTypeProvider.js.map +1 -1
  13. package/dist/src/schema/FieldAccessVisitor.js +2 -2
  14. package/dist/src/schema/FieldAccessVisitor.js.map +1 -1
  15. package/dist/src/schema/MutationProvider.js +2 -2
  16. package/dist/src/schema/MutationProvider.js.map +1 -1
  17. package/dist/src/schema/QueryProvider.js +1 -1
  18. package/dist/src/schema/QueryProvider.js.map +1 -1
  19. package/dist/src/schema/WhereTypeProvider.js +2 -2
  20. package/dist/src/schema/WhereTypeProvider.js.map +1 -1
  21. package/dist/src/schema/entities/FieldTypeVisitor.d.ts +5 -3
  22. package/dist/src/schema/entities/FieldTypeVisitor.d.ts.map +1 -1
  23. package/dist/src/schema/entities/FieldTypeVisitor.js +5 -2
  24. package/dist/src/schema/entities/FieldTypeVisitor.js.map +1 -1
  25. package/dist/src/schema/mutations/CreateEntityInputFieldVisitor.js +1 -1
  26. package/dist/src/schema/mutations/CreateEntityInputFieldVisitor.js.map +1 -1
  27. package/dist/src/schema/mutations/CreateEntityRelationAllowedOperationsVisitor.js +3 -3
  28. package/dist/src/schema/mutations/CreateEntityRelationAllowedOperationsVisitor.js.map +1 -1
  29. package/dist/src/schema/mutations/EntityInputProvider.js +1 -1
  30. package/dist/src/schema/mutations/EntityInputProvider.js.map +1 -1
  31. package/dist/src/schema/mutations/UpdateEntityInputFieldVisitor.js +1 -1
  32. package/dist/src/schema/mutations/UpdateEntityInputFieldVisitor.js.map +1 -1
  33. package/dist/src/schema/mutations/UpdateEntityRelationAllowedOperationsVisitor.d.ts.map +1 -1
  34. package/dist/src/schema/mutations/UpdateEntityRelationAllowedOperationsVisitor.js +5 -5
  35. package/dist/src/schema/mutations/UpdateEntityRelationAllowedOperationsVisitor.js.map +1 -1
  36. package/dist/src/schema/mutations/UpdateEntityRelationInputFieldVisitor.js +1 -1
  37. package/dist/src/schema/mutations/UpdateEntityRelationInputFieldVisitor.js.map +1 -1
  38. package/dist/src/tsconfig.tsbuildinfo +1 -1
  39. package/dist/tests/cases/integration/graphQlSchema/graphQlSchemaBuilder.test.js +23 -1
  40. package/dist/tests/cases/integration/graphQlSchema/graphQlSchemaBuilder.test.js.map +1 -1
  41. package/dist/tests/cases/integration/graphQlSchema/schema-acl-predicate.gql +110 -0
  42. package/dist/tests/src/test.js +1 -1
  43. package/dist/tests/src/test.js.map +1 -1
  44. package/dist/tests/tsconfig.tsbuildinfo +1 -1
  45. package/package.json +10 -10
  46. package/src/acl/Authorizator.ts +44 -4
  47. package/src/acl/index.ts +0 -1
  48. package/src/introspection/IntrospectionSchemaFactory.ts +2 -2
  49. package/src/schema/EntityTypeProvider.ts +3 -3
  50. package/src/schema/FieldAccessVisitor.ts +2 -2
  51. package/src/schema/MutationProvider.ts +2 -2
  52. package/src/schema/QueryProvider.ts +1 -1
  53. package/src/schema/WhereTypeProvider.ts +2 -2
  54. package/src/schema/entities/FieldTypeVisitor.ts +9 -8
  55. package/src/schema/mutations/CreateEntityInputFieldVisitor.ts +1 -1
  56. package/src/schema/mutations/CreateEntityRelationAllowedOperationsVisitor.ts +3 -3
  57. package/src/schema/mutations/EntityInputProvider.ts +1 -1
  58. package/src/schema/mutations/UpdateEntityInputFieldVisitor.ts +1 -1
  59. package/src/schema/mutations/UpdateEntityRelationAllowedOperationsVisitor.ts +5 -9
  60. package/src/schema/mutations/UpdateEntityRelationInputFieldVisitor.ts +1 -1
  61. package/tests/cases/integration/graphQlSchema/graphQlSchemaBuilder.test.ts +30 -2
  62. package/tests/cases/integration/graphQlSchema/schema-acl-predicate.gql +110 -0
  63. package/tests/src/test.ts +2 -2
  64. package/dist/src/acl/StaticAuthorizator.d.ts +0 -9
  65. package/dist/src/acl/StaticAuthorizator.d.ts.map +0 -1
  66. package/dist/src/acl/StaticAuthorizator.js +0 -32
  67. package/dist/src/acl/StaticAuthorizator.js.map +0 -1
  68. package/src/acl/StaticAuthorizator.ts +0 -29
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contember/engine-content-api",
3
- "version": "1.0.0-rc.9",
3
+ "version": "1.1.0-alpha.2",
4
4
  "license": "Apache-2.0",
5
5
  "main": "dist/src/index.js",
6
6
  "typings": "dist/src/index.d.ts",
@@ -10,19 +10,19 @@
10
10
  "test": "uvu dist/tests/cases/ \\.js$"
11
11
  },
12
12
  "dependencies": {
13
- "@contember/database": "^1.0.0-rc.9",
14
- "@contember/dic": "^1.0.0-rc.9",
15
- "@contember/engine-common": "^1.0.0-rc.9",
16
- "@contember/graphql-utils": "^1.0.0-rc.9",
17
- "@contember/schema": "^1.0.0-rc.9",
18
- "@contember/schema-utils": "^1.0.0-rc.9",
13
+ "@contember/database": "^1.1.0-alpha.2",
14
+ "@contember/dic": "^1.1.0-alpha.2",
15
+ "@contember/engine-common": "^1.1.0-alpha.2",
16
+ "@contember/graphql-utils": "^1.1.0-alpha.2",
17
+ "@contember/schema": "^1.1.0-alpha.2",
18
+ "@contember/schema-utils": "^1.1.0-alpha.2",
19
19
  "@graphql-tools/schema": "^7.1.5",
20
20
  "graphql-tag": "^2.12.5"
21
21
  },
22
22
  "devDependencies": {
23
- "@contember/database-tester": "^1.0.0-rc.9",
24
- "@contember/engine-api-tester": "^1.0.0-rc.9",
25
- "@contember/schema-definition": "^1.0.0-rc.9",
23
+ "@contember/database-tester": "^1.1.0-alpha.2",
24
+ "@contember/engine-api-tester": "^1.1.0-alpha.2",
25
+ "@contember/schema-definition": "^1.1.0-alpha.2",
26
26
  "@graphql-codegen/cli": "^1.15.2",
27
27
  "@graphql-codegen/typescript": "^1.15.2",
28
28
  "@graphql-codegen/typescript-operations": "^1.15.2",
@@ -1,8 +1,48 @@
1
1
  import { Acl } from '@contember/schema'
2
2
 
3
- export interface Authorizator {
4
- isAllowed(operation: Acl.Operation, entity: string): boolean
5
- isAllowed(operation: Acl.Operation.create | Acl.Operation.read | Acl.Operation.update, entity: string, field: string,): boolean
6
3
 
7
- isCustomPrimaryAllowed(entity: string): boolean
4
+ export type AuthorizationResult = 'yes' | 'no' | 'maybe'
5
+
6
+ export class Authorizator {
7
+ constructor(private readonly permissions: Acl.Permissions) {
8
+ }
9
+
10
+ getEntityPermission(operation: Acl.Operation, entity: string): AuthorizationResult {
11
+ if (!this.permissions[entity]) {
12
+ return 'no'
13
+ }
14
+ const entityPermissions: Acl.EntityPermissions = this.permissions[entity]
15
+
16
+ if (operation === Acl.Operation.delete) {
17
+ return this.predicateToResult(entityPermissions.operations.delete)
18
+ }
19
+ const fieldPermissions = entityPermissions.operations[operation]
20
+ if (!fieldPermissions) {
21
+ return 'no'
22
+ }
23
+ return Object.values(fieldPermissions).filter(it => !!it).length > 0 ? 'yes' : 'no'
24
+ }
25
+
26
+ getFieldPermissions(operation: Acl.Operation.create | Acl.Operation.read | Acl.Operation.update, entity: string, field: string): AuthorizationResult {
27
+ const fieldPermissions = this.permissions[entity]?.operations[operation]?.[field]
28
+ if (!fieldPermissions) {
29
+ return 'no'
30
+ }
31
+ return this.predicateToResult(fieldPermissions)
32
+ }
33
+
34
+ private predicateToResult(predicate: Acl.Predicate | undefined): AuthorizationResult {
35
+ if (!predicate) {
36
+ return 'no'
37
+ }
38
+ if (predicate === true) {
39
+ return 'yes'
40
+ }
41
+ return 'maybe'
42
+ }
43
+
44
+
45
+ isCustomPrimaryAllowed(entity: string): boolean {
46
+ return this.permissions?.[entity]?.operations?.customPrimary || false
47
+ }
8
48
  }
package/src/acl/index.ts CHANGED
@@ -3,6 +3,5 @@ export * from './PermissionFactory'
3
3
  export * from './PermissionsByIdentityFactory'
4
4
  export * from './PredicateFactory'
5
5
  export * from './PredicatesInjector'
6
- export * from './StaticAuthorizator'
7
6
  export * from './VariableInjector'
8
7
  export * from './VariableUtils'
@@ -107,7 +107,7 @@ export class IntrospectionSchemaFactory {
107
107
  },
108
108
  })
109
109
  return Object.values(getEntity(this.model, entityName).fields)
110
- .filter(it => this.authorizator.isAllowed(Acl.Operation.read, entityName, it.name))
110
+ .filter(it => this.authorizator.getFieldPermissions(Acl.Operation.read, entityName, it.name) !== 'no')
111
111
  .map((it): ContentSchema._Column | ContentSchema._Relation => ({
112
112
  ...additionalInfo[it.name],
113
113
  name: it.name,
@@ -154,7 +154,7 @@ export class IntrospectionSchemaFactory {
154
154
 
155
155
  public create(): ContentSchema._Schema {
156
156
  const entities = Object.values(this.model.entities)
157
- .filter(it => this.authorizator.isAllowed(Acl.Operation.read, it.name))
157
+ .filter(it => this.authorizator.getEntityPermission(Acl.Operation.read, it.name) !== 'no')
158
158
  .map(entity => ({
159
159
  name: entity.name,
160
160
  customPrimaryAllowed: this.authorizator.isCustomPrimaryAllowed(entity.name),
@@ -53,14 +53,14 @@ export class EntityTypeProvider {
53
53
  }
54
54
 
55
55
  public getEntity(entityName: string): GraphQLObjectType {
56
- if (!this.authorizator.isAllowed(Acl.Operation.read, entityName)) {
56
+ if (this.authorizator.getEntityPermission(Acl.Operation.read, entityName) === 'no') {
57
57
  throw new ImplementationException()
58
58
  }
59
59
  return this.entities(entityName)
60
60
  }
61
61
 
62
62
  public getConnection(entityName: string): GraphQLObjectType {
63
- if (!this.authorizator.isAllowed(Acl.Operation.read, entityName)) {
63
+ if (this.authorizator.getEntityPermission(Acl.Operation.read, entityName) === 'no') {
64
64
  throw new ImplementationException()
65
65
  }
66
66
  return this.connections(entityName)
@@ -100,7 +100,7 @@ export class EntityTypeProvider {
100
100
 
101
101
  const fields: { [field: string]: GraphQLFieldConfig<any, any> } = accessibleFields.reduce(
102
102
  (result, fieldName) => {
103
- const fieldTypeVisitor = new FieldTypeVisitor(this.columnTypeResolver, this)
103
+ const fieldTypeVisitor = new FieldTypeVisitor(this.columnTypeResolver, this, this.authorizator)
104
104
  const type: GraphQLOutputType = acceptFieldVisitor(this.schema, entity, fieldName, fieldTypeVisitor)
105
105
 
106
106
  const fieldArgsVisitor = new FieldArgsVisitor(this.whereTypeProvider, this.orderByTypeProvider)
@@ -8,10 +8,10 @@ export class FieldAccessVisitor implements Model.ColumnVisitor<boolean>, Model.R
8
8
  ) {}
9
9
 
10
10
  visitColumn(entity: Model.Entity, column: Model.AnyColumn) {
11
- return this.authorizator.isAllowed(this.operation, entity.name, column.name)
11
+ return this.authorizator.getFieldPermissions(this.operation, entity.name, column.name) !== 'no'
12
12
  }
13
13
 
14
14
  visitRelation({}, {}, targetEntity: Model.Entity) {
15
- return this.authorizator.isAllowed(this.operation, targetEntity.name)
15
+ return this.authorizator.getEntityPermission(this.operation, targetEntity.name) !== 'no'
16
16
  }
17
17
  }
@@ -69,7 +69,7 @@ export class MutationProvider {
69
69
  if (entity.view) {
70
70
  return undefined
71
71
  }
72
- if (!this.authorizator.isAllowed(Acl.Operation.delete, entityName)) {
72
+ if (this.authorizator.getEntityPermission(Acl.Operation.delete, entityName) === 'no') {
73
73
  return undefined
74
74
  }
75
75
  const uniqueWhere = this.whereTypeProvider.getEntityUniqueWhereType(entityName)
@@ -180,7 +180,7 @@ export class MutationProvider {
180
180
  errorMessage: { type: GraphQLString },
181
181
  errors: { type: this.resultSchemaTypeProvider.errorListResultType },
182
182
  }
183
- if (this.authorizator.isAllowed(Acl.Operation.read, entityName)) {
183
+ if (this.authorizator.getEntityPermission(Acl.Operation.read, entityName) !== 'no') {
184
184
  const nodeType = this.entityTypeProvider.getEntity(entityName)
185
185
  fields.node = { type: nodeType, resolve: aliasAwareResolver }
186
186
  }
@@ -19,7 +19,7 @@ export class QueryProvider {
19
19
  ) {}
20
20
 
21
21
  public getQueries(entity: Model.Entity): { [fieldName: string]: GraphQLFieldConfig<any, Context, any> } {
22
- if (!this.authorizator.isAllowed(Acl.Operation.read, entity.name)) {
22
+ if (this.authorizator.getEntityPermission(Acl.Operation.read, entity.name) === 'no') {
23
23
  return {}
24
24
  }
25
25
  return {
@@ -22,14 +22,14 @@ export class WhereTypeProvider {
22
22
  ) {}
23
23
 
24
24
  public getEntityWhereType(entityName: string): GraphQLInputObjectType {
25
- if (!this.authorizator.isAllowed(Acl.Operation.read, entityName)) {
25
+ if (this.authorizator.getEntityPermission(Acl.Operation.read, entityName) === 'no') {
26
26
  throw new ImplementationException()
27
27
  }
28
28
  return this.whereSingleton(entityName)
29
29
  }
30
30
 
31
31
  public getEntityUniqueWhereType(entityName: string): undefined | GraphQLInputObjectType {
32
- if (!this.authorizator.isAllowed(Acl.Operation.read, entityName)) {
32
+ if (this.authorizator.getEntityPermission(Acl.Operation.read, entityName) === 'no') {
33
33
  return undefined
34
34
  }
35
35
  return this.uniqueWhereSingleton(entityName)
@@ -1,20 +1,21 @@
1
1
  import { GraphQLList, GraphQLNonNull, GraphQLOutputType } from 'graphql'
2
- import { Model } from '@contember/schema'
2
+ import { Acl, Model } from '@contember/schema'
3
3
  import { ColumnTypeResolver } from '../ColumnTypeResolver'
4
4
  import { EntityTypeProvider } from '../EntityTypeProvider'
5
+ import { Authorizator } from '../../acl'
5
6
 
6
7
  export class FieldTypeVisitor implements Model.ColumnVisitor<GraphQLOutputType>, Model.RelationByGenericTypeVisitor<GraphQLOutputType> {
7
- private columnTypeResolver: ColumnTypeResolver
8
- private entityTypeProvider: EntityTypeProvider
9
-
10
- constructor(columnTypeResolver: ColumnTypeResolver, entityTypeProvider: EntityTypeProvider) {
11
- this.columnTypeResolver = columnTypeResolver
12
- this.entityTypeProvider = entityTypeProvider
8
+ constructor(
9
+ private readonly columnTypeResolver: ColumnTypeResolver,
10
+ private readonly entityTypeProvider: EntityTypeProvider,
11
+ private readonly authorizator: Authorizator,
12
+ ) {
13
13
  }
14
14
 
15
15
  public visitColumn(entity: Model.Entity, column: Model.AnyColumn): GraphQLOutputType {
16
16
  const basicType = this.columnTypeResolver.getType(column)
17
- return column.nullable ? basicType : new GraphQLNonNull(basicType)
17
+ const permissions = this.authorizator.getFieldPermissions(Acl.Operation.read, entity.name, column.name)
18
+ return column.nullable || permissions === 'maybe' ? basicType : new GraphQLNonNull(basicType)
18
19
  }
19
20
 
20
21
  public visitHasMany(entity: Model.Entity, relation: Model.Relation): GraphQLOutputType {
@@ -19,7 +19,7 @@ export class CreateEntityInputFieldVisitor implements
19
19
  if (entity.primary === column.name && !this.authorizator.isCustomPrimaryAllowed(entity.name)) {
20
20
  return undefined
21
21
  }
22
- if (!this.authorizator.isAllowed(Acl.Operation.create, entity.name, column.name)) {
22
+ if (this.authorizator.getFieldPermissions(Acl.Operation.create, entity.name, column.name) === 'no') {
23
23
  return undefined
24
24
  }
25
25
  const type = this.columnTypeResolver.getType(column)
@@ -65,9 +65,9 @@ export class CreateEntityRelationAllowedOperationsVisitor implements
65
65
  ): Input.CreateRelationOperation[] {
66
66
  const result: Input.CreateRelationOperation[] = []
67
67
 
68
- const canReadTargetEntity = this.authorizator.isAllowed(Acl.Operation.read, targetEntity.name)
69
- const canCreateTargetEntity = this.authorizator.isAllowed(Acl.Operation.create, targetEntity.name)
70
- const canCreateOwning = this.authorizator.isAllowed(Acl.Operation.create, owningEntity.name, owningRelation.name)
68
+ const canReadTargetEntity = this.authorizator.getEntityPermission(Acl.Operation.read, targetEntity.name) !== 'no'
69
+ const canCreateTargetEntity = this.authorizator.getEntityPermission(Acl.Operation.create, targetEntity.name) !== 'no'
70
+ const canCreateOwning = this.authorizator.getFieldPermissions(Acl.Operation.create, owningEntity.name, owningRelation.name) !== 'no'
71
71
 
72
72
  if (canReadTargetEntity && canCreateOwning) {
73
73
  result.push(Input.CreateRelationOperation.connect)
@@ -51,7 +51,7 @@ export class EntityInputProvider<Operation extends EntityInputType> {
51
51
  throw new ImplementationException(`EntityInputProvider: Invalid operation ${this.operation}`)
52
52
  }
53
53
  })()
54
- if (!this.authorizator.isAllowed(operation, entity.name)) {
54
+ if (this.authorizator.getEntityPermission(operation, entity.name) === 'no') {
55
55
  return undefined
56
56
  }
57
57
 
@@ -18,7 +18,7 @@ export class UpdateEntityInputFieldVisitor implements
18
18
  if (entity.primary === column.name) {
19
19
  return undefined
20
20
  }
21
- if (!this.authorizator.isAllowed(Acl.Operation.update, entity.name, column.name)) {
21
+ if (this.authorizator.getFieldPermissions(Acl.Operation.update, entity.name, column.name) === 'no') {
22
22
  return undefined
23
23
  }
24
24
  const type = this.columnTypeResolver.getType(column)
@@ -76,15 +76,11 @@ export class UpdateEntityRelationAllowedOperationsVisitor implements
76
76
  ): Input.UpdateRelationOperation[] {
77
77
  const result: Input.UpdateRelationOperation[] = []
78
78
 
79
- const canReadTargetEntity = this.authorizator.isAllowed(Acl.Operation.read, targetEntity.name)
80
- const canCreateTargetEntity = this.authorizator.isAllowed(Acl.Operation.create, targetEntity.name)
81
- const canUpdateTargetEntity = this.authorizator.isAllowed(Acl.Operation.update, targetEntity.name)
82
- const canDeleteTargetEntity = this.authorizator.isAllowed(Acl.Operation.delete, targetEntity.name)
83
- const canUpdateOwningRelation = this.authorizator.isAllowed(
84
- Acl.Operation.update,
85
- owningEntity.name,
86
- owningRelation.name,
87
- )
79
+ const canReadTargetEntity = this.authorizator.getEntityPermission(Acl.Operation.read, targetEntity.name) !== 'no'
80
+ const canCreateTargetEntity = this.authorizator.getEntityPermission(Acl.Operation.create, targetEntity.name) !== 'no'
81
+ const canUpdateTargetEntity = this.authorizator.getEntityPermission(Acl.Operation.update, targetEntity.name) !== 'no'
82
+ const canDeleteTargetEntity = this.authorizator.getEntityPermission(Acl.Operation.delete, targetEntity.name) !== 'no'
83
+ const canUpdateOwningRelation = this.authorizator.getFieldPermissions(Acl.Operation.update, owningEntity.name, owningRelation.name) !== 'no'
88
84
 
89
85
  if (canReadTargetEntity && canUpdateOwningRelation) {
90
86
  result.push(Input.UpdateRelationOperation.connect)
@@ -174,7 +174,7 @@ export class UpdateEntityRelationInputFieldVisitor implements
174
174
  }
175
175
 
176
176
  private createWhereInput(targetEntity: Model.Entity): GraphQLInputFieldConfig | undefined {
177
- if (!this.authorizator.isAllowed(Acl.Operation.read, targetEntity.name)) {
177
+ if (this.authorizator.getEntityPermission(Acl.Operation.read, targetEntity.name) === 'no') {
178
178
  return undefined
179
179
  }
180
180
  const uniqueWhere = this.whereTypeBuilder.getEntityUniqueWhereType(targetEntity.name)
@@ -3,7 +3,7 @@ import { Acl, Model } from '@contember/schema'
3
3
  import * as path from 'path'
4
4
 
5
5
  import { AllowAllPermissionFactory, SchemaBuilder, SchemaDefinition } from '@contember/schema-definition'
6
- import { GraphQlSchemaBuilderFactory, StaticAuthorizator } from '../../../../src'
6
+ import { GraphQlSchemaBuilderFactory, Authorizator } from '../../../../src'
7
7
  import * as model from './model'
8
8
  import { promises as fs } from 'fs'
9
9
  import * as assert from 'uvu/assert'
@@ -23,7 +23,7 @@ const testSchema = async (test: Test) => {
23
23
  const schema = schemaResult instanceof SchemaBuilder ? schemaResult.buildSchema() : schemaResult
24
24
  const schemaWithAcl = { ...schema, acl: { roles: {}, variables: {} } }
25
25
  const permissions = test.permissions(schemaWithAcl)
26
- const authorizator = new StaticAuthorizator(permissions)
26
+ const authorizator = new Authorizator(permissions)
27
27
  const graphQlSchemaBuilder = schemaFactory.create(schemaWithAcl, authorizator)
28
28
  const graphQlSchema = graphQlSchemaBuilder.build()
29
29
 
@@ -110,6 +110,34 @@ graphqlSchemaBuilderTest('restricted access to fields by permissions', async ()
110
110
  graphQlSchemaFile: 'schema-acl.gql',
111
111
  })
112
112
  })
113
+
114
+
115
+ graphqlSchemaBuilderTest('conditionally restricted read', async () => {
116
+ await testSchema({
117
+ schema: builder =>
118
+ builder.entity('Test', e =>
119
+ e
120
+ .column('a', c => c.type(Model.ColumnType.String).notNull()),
121
+ ),
122
+ permissions: () => ({
123
+ Test: {
124
+ predicates: {
125
+ testPredicate: {
126
+ a: { eq: 'Foo' },
127
+ },
128
+ },
129
+ operations: {
130
+ read: {
131
+ id: true,
132
+ a: 'testPredicate',
133
+ },
134
+ },
135
+ },
136
+ }),
137
+ graphQlSchemaFile: 'schema-acl-predicate.gql',
138
+ })
139
+ })
140
+
113
141
  const oneHasManySchema = (builder: SchemaBuilder) =>
114
142
  builder.entity('Root', e =>
115
143
  e
@@ -0,0 +1,110 @@
1
+ type Query {
2
+ getTest(by: TestUniqueWhere!, filter: TestWhere): Test
3
+ listTest(filter: TestWhere, orderBy: [TestOrderBy!], offset: Int, limit: Int): [Test!]!
4
+ paginateTest(filter: TestWhere, orderBy: [TestOrderBy!], skip: Int, first: Int): TestConnection!
5
+ transaction: QueryTransaction
6
+ _info: Info
7
+ }
8
+
9
+ type Test {
10
+ _meta: TestMeta
11
+ id: UUID!
12
+ a: String
13
+ }
14
+
15
+ type TestMeta {
16
+ id: FieldMeta
17
+ a: FieldMeta
18
+ }
19
+
20
+ type FieldMeta {
21
+ readable: Boolean
22
+ updatable: Boolean
23
+ }
24
+
25
+ scalar UUID
26
+
27
+ input TestUniqueWhere {
28
+ id: UUID
29
+ }
30
+
31
+ input TestWhere {
32
+ id: UUIDCondition
33
+ a: StringCondition
34
+ and: [TestWhere]
35
+ or: [TestWhere]
36
+ not: TestWhere
37
+ }
38
+
39
+ input UUIDCondition {
40
+ and: [UUIDCondition!]
41
+ or: [UUIDCondition!]
42
+ not: UUIDCondition
43
+ null: Boolean
44
+ isNull: Boolean
45
+ eq: UUID
46
+ notEq: UUID
47
+ in: [UUID!]
48
+ notIn: [UUID!]
49
+ lt: UUID
50
+ lte: UUID
51
+ gt: UUID
52
+ gte: UUID
53
+ }
54
+
55
+ input StringCondition {
56
+ and: [StringCondition!]
57
+ or: [StringCondition!]
58
+ not: StringCondition
59
+ null: Boolean
60
+ isNull: Boolean
61
+ eq: String
62
+ notEq: String
63
+ in: [String!]
64
+ notIn: [String!]
65
+ lt: String
66
+ lte: String
67
+ gt: String
68
+ gte: String
69
+ contains: String
70
+ startsWith: String
71
+ endsWith: String
72
+ containsCI: String
73
+ startsWithCI: String
74
+ endsWithCI: String
75
+ }
76
+
77
+ input TestOrderBy {
78
+ _random: Boolean
79
+ _randomSeeded: Int
80
+ id: OrderDirection
81
+ a: OrderDirection
82
+ }
83
+
84
+ enum OrderDirection {
85
+ asc
86
+ desc
87
+ }
88
+
89
+ type TestConnection {
90
+ pageInfo: PageInfo!
91
+ edges: [TestEdge!]!
92
+ }
93
+
94
+ type PageInfo {
95
+ totalCount: Int!
96
+ }
97
+
98
+ type TestEdge {
99
+ node: Test!
100
+ }
101
+
102
+ type QueryTransaction {
103
+ getTest(by: TestUniqueWhere!, filter: TestWhere): Test
104
+ listTest(filter: TestWhere, orderBy: [TestOrderBy!], offset: Int, limit: Int): [Test!]!
105
+ paginateTest(filter: TestWhere, orderBy: [TestOrderBy!], skip: Int, first: Int): TestConnection!
106
+ }
107
+
108
+ type Info {
109
+ description: String
110
+ }
package/tests/src/test.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Acl, Model, Schema, Validation } from '@contember/schema'
2
- import { ExecutionContainerFactory, GraphQlSchemaBuilderFactory, StaticAuthorizator } from '../../src'
2
+ import { ExecutionContainerFactory, GraphQlSchemaBuilderFactory, Authorizator } from '../../src'
3
3
  import { AllowAllPermissionFactory, emptySchema } from '@contember/schema-utils'
4
4
  import { executeGraphQlTest } from './testGraphql'
5
5
  import { Client } from '@contember/database'
@@ -89,7 +89,7 @@ export const failedTransaction = (executes: SqlQuery[]): SqlQuery[] => {
89
89
 
90
90
  export const execute = async (test: Test) => {
91
91
  const permissions: Acl.Permissions = test.permissions || new AllowAllPermissionFactory().create(test.schema)
92
- const authorizator = new StaticAuthorizator(permissions)
92
+ const authorizator = new Authorizator(permissions)
93
93
  const builder = new GraphQlSchemaBuilderFactory().create(test.schema, authorizator)
94
94
  const graphQLSchema = builder.build()
95
95
 
@@ -1,9 +0,0 @@
1
- import { Acl } from '@contember/schema';
2
- import { Authorizator } from './Authorizator';
3
- export declare class StaticAuthorizator implements Authorizator {
4
- private readonly permissions;
5
- constructor(permissions: Acl.Permissions);
6
- isAllowed(operation: Acl.Operation, entity: string, field?: string): boolean;
7
- isCustomPrimaryAllowed(entity: string): boolean;
8
- }
9
- //# sourceMappingURL=StaticAuthorizator.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"StaticAuthorizator.d.ts","sourceRoot":"","sources":["../../../src/acl/StaticAuthorizator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAA;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAE7C,qBAAa,kBAAmB,YAAW,YAAY;IAC1C,OAAO,CAAC,QAAQ,CAAC,WAAW;gBAAX,WAAW,EAAE,GAAG,CAAC,WAAW;IAEzD,SAAS,CAAC,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO;IAmB5E,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;CAG/C"}
@@ -1,32 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.StaticAuthorizator = void 0;
4
- const schema_1 = require("@contember/schema");
5
- class StaticAuthorizator {
6
- constructor(permissions) {
7
- this.permissions = permissions;
8
- }
9
- isAllowed(operation, entity, field) {
10
- if (!this.permissions[entity]) {
11
- return false;
12
- }
13
- const entityPermissions = this.permissions[entity];
14
- if (operation === schema_1.Acl.Operation.delete) {
15
- return !!entityPermissions.operations.delete;
16
- }
17
- const fieldPermissions = entityPermissions.operations[operation];
18
- if (!fieldPermissions) {
19
- return false;
20
- }
21
- if (field) {
22
- return !!fieldPermissions[field];
23
- }
24
- return Object.values(fieldPermissions).filter(it => !!it).length > 0;
25
- }
26
- isCustomPrimaryAllowed(entity) {
27
- var _a, _b, _c;
28
- return ((_c = (_b = (_a = this.permissions) === null || _a === void 0 ? void 0 : _a[entity]) === null || _b === void 0 ? void 0 : _b.operations) === null || _c === void 0 ? void 0 : _c.customPrimary) || false;
29
- }
30
- }
31
- exports.StaticAuthorizator = StaticAuthorizator;
32
- //# sourceMappingURL=StaticAuthorizator.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"StaticAuthorizator.js","sourceRoot":"","sources":["../../../src/acl/StaticAuthorizator.ts"],"names":[],"mappings":";;;AAAA,8CAAuC;AAGvC,MAAa,kBAAkB;IAC9B,YAA6B,WAA4B;QAA5B,gBAAW,GAAX,WAAW,CAAiB;IAAG,CAAC;IAE7D,SAAS,CAAC,SAAwB,EAAE,MAAc,EAAE,KAAc;QACjE,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE;YAC9B,OAAO,KAAK,CAAA;SACZ;QACD,MAAM,iBAAiB,GAA0B,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;QAEzE,IAAI,SAAS,KAAK,YAAG,CAAC,SAAS,CAAC,MAAM,EAAE;YACvC,OAAO,CAAC,CAAC,iBAAiB,CAAC,UAAU,CAAC,MAAM,CAAA;SAC5C;QACD,MAAM,gBAAgB,GAAG,iBAAiB,CAAC,UAAU,CAAC,SAAS,CAAC,CAAA;QAChE,IAAI,CAAC,gBAAgB,EAAE;YACtB,OAAO,KAAK,CAAA;SACZ;QACD,IAAI,KAAK,EAAE;YACV,OAAO,CAAC,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAA;SAChC;QACD,OAAO,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,CAAA;IACrE,CAAC;IAED,sBAAsB,CAAC,MAAc;;QACpC,OAAO,CAAA,MAAA,MAAA,MAAA,IAAI,CAAC,WAAW,0CAAG,MAAM,CAAC,0CAAE,UAAU,0CAAE,aAAa,KAAI,KAAK,CAAA;IACtE,CAAC;CACD;AAzBD,gDAyBC"}
@@ -1,29 +0,0 @@
1
- import { Acl } from '@contember/schema'
2
- import { Authorizator } from './Authorizator'
3
-
4
- export class StaticAuthorizator implements Authorizator {
5
- constructor(private readonly permissions: Acl.Permissions) {}
6
-
7
- isAllowed(operation: Acl.Operation, entity: string, field?: string): boolean {
8
- if (!this.permissions[entity]) {
9
- return false
10
- }
11
- const entityPermissions: Acl.EntityPermissions = this.permissions[entity]
12
-
13
- if (operation === Acl.Operation.delete) {
14
- return !!entityPermissions.operations.delete
15
- }
16
- const fieldPermissions = entityPermissions.operations[operation]
17
- if (!fieldPermissions) {
18
- return false
19
- }
20
- if (field) {
21
- return !!fieldPermissions[field]
22
- }
23
- return Object.values(fieldPermissions).filter(it => !!it).length > 0
24
- }
25
-
26
- isCustomPrimaryAllowed(entity: string): boolean {
27
- return this.permissions?.[entity]?.operations?.customPrimary || false
28
- }
29
- }