@contember/engine-content-api 1.1.1 → 1.2.0-alpha.10
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/dist/src/acl/EvaluatedPredicateReplacer.d.ts +9 -0
- package/dist/src/acl/EvaluatedPredicateReplacer.d.ts.map +1 -0
- package/dist/src/acl/EvaluatedPredicateReplacer.js +31 -0
- package/dist/src/acl/EvaluatedPredicateReplacer.js.map +1 -0
- package/dist/src/acl/PermissionFactory.d.ts.map +1 -1
- package/dist/src/acl/PermissionFactory.js +15 -11
- package/dist/src/acl/PermissionFactory.js.map +1 -1
- package/dist/src/acl/PredicateFactory.d.ts +4 -2
- package/dist/src/acl/PredicateFactory.d.ts.map +1 -1
- package/dist/src/acl/PredicateFactory.js +24 -6
- package/dist/src/acl/PredicateFactory.js.map +1 -1
- package/dist/src/acl/PredicatesInjector.d.ts +1 -1
- package/dist/src/acl/PredicatesInjector.d.ts.map +1 -1
- package/dist/src/acl/PredicatesInjector.js +18 -14
- package/dist/src/acl/PredicatesInjector.js.map +1 -1
- package/dist/src/acl/VariableInjector.d.ts +0 -1
- package/dist/src/acl/VariableInjector.d.ts.map +1 -1
- package/dist/src/acl/VariableInjector.js +4 -14
- package/dist/src/acl/VariableInjector.js.map +1 -1
- package/dist/src/acl/VariableUtils.d.ts +2 -13
- package/dist/src/acl/VariableUtils.d.ts.map +1 -1
- package/dist/src/acl/VariableUtils.js +5 -16
- package/dist/src/acl/VariableUtils.js.map +1 -1
- package/dist/src/extensions/hasManyToHasOneReducer/HasManyToHasOneReducerExecutionHandler.js +1 -1
- package/dist/src/extensions/hasManyToHasOneReducer/HasManyToHasOneReducerExecutionHandler.js.map +1 -1
- package/dist/src/extensions/paginatedHasMany/PaginatedHasManyCountVisitor.d.ts.map +1 -1
- package/dist/src/extensions/paginatedHasMany/PaginatedHasManyCountVisitor.js +25 -13
- package/dist/src/extensions/paginatedHasMany/PaginatedHasManyCountVisitor.js.map +1 -1
- package/dist/src/extensions/paginatedHasMany/PaginatedHasManyNodesVisitor.d.ts.map +1 -1
- package/dist/src/extensions/paginatedHasMany/PaginatedHasManyNodesVisitor.js +26 -13
- package/dist/src/extensions/paginatedHasMany/PaginatedHasManyNodesVisitor.js.map +1 -1
- package/dist/src/input-validation/ValidationContext.d.ts +2 -2
- package/dist/src/input-validation/ValidationContext.d.ts.map +1 -1
- package/dist/src/input-validation/ValidationContext.js.map +1 -1
- package/dist/src/input-validation/ValidationDataSelector.d.ts.map +1 -1
- package/dist/src/input-validation/ValidationDataSelector.js +1 -1
- package/dist/src/input-validation/ValidationDataSelector.js.map +1 -1
- package/dist/src/introspection/content-schema.types.d.ts +19 -223
- package/dist/src/introspection/content-schema.types.d.ts.map +1 -1
- package/dist/src/introspection/content-schema.types.js +2 -2
- package/dist/src/introspection/content-schema.types.js.map +1 -1
- package/dist/src/mapper/Mapper.d.ts +4 -4
- package/dist/src/mapper/Mapper.d.ts.map +1 -1
- package/dist/src/mapper/Mapper.js +7 -7
- package/dist/src/mapper/Mapper.js.map +1 -1
- package/dist/src/mapper/MapperContainer.d.ts.map +1 -1
- package/dist/src/mapper/MapperContainer.js +5 -2
- package/dist/src/mapper/MapperContainer.js.map +1 -1
- package/dist/src/mapper/select/RelationFetcher.d.ts +40 -5
- package/dist/src/mapper/select/RelationFetcher.d.ts.map +1 -1
- package/dist/src/mapper/select/RelationFetcher.js +19 -6
- package/dist/src/mapper/select/RelationFetcher.js.map +1 -1
- package/dist/src/mapper/select/WhereBuilder.d.ts +3 -1
- package/dist/src/mapper/select/WhereBuilder.d.ts.map +1 -1
- package/dist/src/mapper/select/WhereBuilder.js +4 -2
- package/dist/src/mapper/select/WhereBuilder.js.map +1 -1
- package/dist/src/mapper/select/handlers/FieldsVisitor.d.ts +2 -2
- package/dist/src/mapper/select/handlers/FieldsVisitor.d.ts.map +1 -1
- package/dist/src/mapper/select/handlers/FieldsVisitor.js +31 -18
- package/dist/src/mapper/select/handlers/FieldsVisitor.js.map +1 -1
- package/dist/src/mapper/select/optimizer/ConditionOptimizer.d.ts +5 -0
- package/dist/src/mapper/select/optimizer/ConditionOptimizer.d.ts.map +1 -0
- package/dist/src/mapper/select/optimizer/ConditionOptimizer.js +33 -0
- package/dist/src/mapper/select/optimizer/ConditionOptimizer.js.map +1 -0
- package/dist/src/mapper/select/optimizer/WhereOptimizer.d.ts +14 -0
- package/dist/src/mapper/select/optimizer/WhereOptimizer.d.ts.map +1 -0
- package/dist/src/mapper/select/optimizer/WhereOptimizer.js +86 -0
- package/dist/src/mapper/select/optimizer/WhereOptimizer.js.map +1 -0
- package/dist/src/mapper/select/optimizer/WhereReplacer.d.ts +3 -0
- package/dist/src/mapper/select/optimizer/WhereReplacer.d.ts.map +1 -0
- package/dist/src/mapper/select/optimizer/WhereReplacer.js +27 -0
- package/dist/src/mapper/select/optimizer/WhereReplacer.js.map +1 -0
- package/dist/src/mapper/select/optimizer/helpers.d.ts +10 -0
- package/dist/src/mapper/select/optimizer/helpers.d.ts.map +1 -0
- package/dist/src/mapper/select/optimizer/helpers.js +72 -0
- package/dist/src/mapper/select/optimizer/helpers.js.map +1 -0
- package/dist/src/resolvers/GraphQlQueryAstFactory.js +2 -2
- package/dist/src/resolvers/GraphQlQueryAstFactory.js.map +1 -1
- package/dist/src/resolvers/MutationResolver.js +15 -15
- package/dist/src/resolvers/MutationResolver.js.map +1 -1
- package/dist/src/resolvers/ReadHelpers.js +10 -10
- package/dist/src/resolvers/ReadHelpers.js.map +1 -1
- package/dist/src/resolvers/ReadResolver.js +2 -2
- package/dist/src/resolvers/ReadResolver.js.map +1 -1
- package/dist/src/schema/MutationProvider.js +4 -4
- package/dist/src/schema/MutationProvider.js.map +1 -1
- package/dist/src/schema/QueryProvider.js +3 -3
- package/dist/src/schema/QueryProvider.js.map +1 -1
- package/dist/src/schema/ResultSchemaTypeProvider.d.ts +2 -2
- package/dist/src/schema/ResultSchemaTypeProvider.d.ts.map +1 -1
- package/dist/src/schema/entities/FieldArgsVisitor.d.ts +4 -4
- package/dist/src/schema/entities/FieldArgsVisitor.d.ts.map +1 -1
- package/dist/src/tsconfig.tsbuildinfo +1 -1
- package/dist/src/utils/object.d.ts.map +1 -1
- package/dist/src/utils/object.js +3 -4
- package/dist/src/utils/object.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/delete/aclDelete.test.js +1 -1
- package/dist/tests/cases/integration/graphQlRequests/delete/aclDelete.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/insert/acl/setField.test.js +2 -2
- package/dist/tests/cases/integration/graphQlRequests/insert/acl/setField.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/insert/aclInsert.test.js +1 -1
- package/dist/tests/cases/integration/graphQlRequests/insert/aclInsert.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/query/acl/fieldRestrictedByLocale.test.js +7 -6
- package/dist/tests/cases/integration/graphQlRequests/query/acl/fieldRestrictedByLocale.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/query/acl/nestedPredicate.test.js +1 -1
- package/dist/tests/cases/integration/graphQlRequests/query/acl/nestedPredicate.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/query/acl/predicateElimination.test.d.ts +2 -0
- package/dist/tests/cases/integration/graphQlRequests/query/acl/predicateElimination.test.d.ts.map +1 -0
- package/dist/tests/cases/integration/graphQlRequests/query/acl/predicateElimination.test.js +137 -0
- package/dist/tests/cases/integration/graphQlRequests/query/acl/predicateElimination.test.js.map +1 -0
- package/dist/tests/cases/integration/graphQlRequests/query/filter/complexCondition.test.js +1 -1
- package/dist/tests/cases/integration/graphQlRequests/query/filter/composedFilter.test.js +1 -1
- package/dist/tests/cases/integration/graphQlRequests/query/filter/composedFilter.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/query/relations/manyHasManyInverse.test.js +73 -0
- package/dist/tests/cases/integration/graphQlRequests/query/relations/manyHasManyInverse.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/query/relations/manyHasManyOwning.test.js +73 -0
- package/dist/tests/cases/integration/graphQlRequests/query/relations/manyHasManyOwning.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlRequests/update/acl/aclUpdate.test.js +6 -6
- package/dist/tests/cases/integration/graphQlRequests/update/acl/aclUpdate.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlSchema/graphQlSchemaBuilder.test.js +6 -3
- package/dist/tests/cases/integration/graphQlSchema/graphQlSchemaBuilder.test.js.map +1 -1
- package/dist/tests/cases/integration/graphQlSchema/model.js.map +1 -1
- package/dist/tests/cases/unit/aclVariablesFactory.test.js +7 -33
- package/dist/tests/cases/unit/aclVariablesFactory.test.js.map +1 -1
- package/dist/tests/cases/unit/conditionOptimizer.test.d.ts +2 -0
- package/dist/tests/cases/unit/conditionOptimizer.test.d.ts.map +1 -0
- package/dist/tests/cases/unit/conditionOptimizer.test.js +118 -0
- package/dist/tests/cases/unit/conditionOptimizer.test.js.map +1 -0
- package/dist/tests/cases/unit/orderbyHelper.test.js +1 -0
- package/dist/tests/cases/unit/orderbyHelper.test.js.map +1 -1
- package/dist/tests/cases/unit/permissionMerger.test.js +2 -0
- package/dist/tests/cases/unit/permissionMerger.test.js.map +1 -1
- package/dist/tests/cases/unit/predicatesFactory.test.d.ts +2 -0
- package/dist/tests/cases/unit/predicatesFactory.test.d.ts.map +1 -0
- package/dist/tests/cases/unit/predicatesFactory.test.js +103 -0
- package/dist/tests/cases/unit/predicatesFactory.test.js.map +1 -0
- package/dist/tests/cases/unit/predicatesInjector.test.js +88 -14
- package/dist/tests/cases/unit/predicatesInjector.test.js.map +1 -1
- package/dist/tests/cases/unit/variableInjector.test.js +4 -3
- package/dist/tests/cases/unit/variableInjector.test.js.map +1 -1
- package/dist/tests/cases/unit/whereOptimizer.test.d.ts +2 -0
- package/dist/tests/cases/unit/whereOptimizer.test.d.ts.map +1 -0
- package/dist/tests/cases/unit/whereOptimizer.test.js +183 -0
- package/dist/tests/cases/unit/whereOptimizer.test.js.map +1 -0
- package/dist/tests/src/testGraphql.d.ts.map +1 -1
- package/dist/tests/src/testGraphql.js +10 -2
- package/dist/tests/src/testGraphql.js.map +1 -1
- package/dist/tests/tsconfig.tsbuildinfo +1 -1
- package/graphql.codegen.yml +0 -3
- package/package.json +16 -16
- package/src/acl/EvaluatedPredicateReplacer.ts +32 -0
- package/src/acl/PermissionFactory.ts +18 -13
- package/src/acl/PredicateFactory.ts +39 -8
- package/src/acl/PredicatesInjector.ts +26 -13
- package/src/acl/VariableInjector.ts +2 -15
- package/src/acl/VariableUtils.ts +7 -23
- package/src/extensions/hasManyToHasOneReducer/HasManyToHasOneReducerExecutionHandler.ts +3 -3
- package/src/extensions/paginatedHasMany/PaginatedHasManyCountVisitor.ts +26 -28
- package/src/extensions/paginatedHasMany/PaginatedHasManyNodesVisitor.ts +27 -31
- package/src/input-validation/ValidationContext.ts +2 -2
- package/src/input-validation/ValidationDataSelector.ts +2 -2
- package/src/introspection/content-schema.types.ts +19 -286
- package/src/mapper/Mapper.ts +10 -6
- package/src/mapper/MapperContainer.ts +7 -3
- package/src/mapper/select/RelationFetcher.ts +95 -34
- package/src/mapper/select/WhereBuilder.ts +5 -2
- package/src/mapper/select/handlers/FieldsVisitor.ts +31 -24
- package/src/mapper/select/optimizer/ConditionOptimizer.ts +35 -0
- package/src/mapper/select/optimizer/WhereOptimizer.ts +100 -0
- package/src/mapper/select/optimizer/WhereReplacer.ts +22 -0
- package/src/mapper/select/optimizer/helpers.ts +58 -0
- package/src/resolvers/GraphQlQueryAstFactory.ts +3 -3
- package/src/resolvers/MutationResolver.ts +1 -1
- package/src/resolvers/ReadHelpers.ts +3 -3
- package/src/resolvers/ReadResolver.ts +2 -2
- package/src/utils/object.ts +6 -6
- package/tests/cases/integration/graphQlRequests/delete/aclDelete.test.ts +2 -2
- package/tests/cases/integration/graphQlRequests/insert/acl/setField.test.ts +3 -3
- package/tests/cases/integration/graphQlRequests/insert/aclInsert.test.ts +2 -2
- package/tests/cases/integration/graphQlRequests/query/acl/fieldRestrictedByLocale.test.ts +7 -6
- package/tests/cases/integration/graphQlRequests/query/acl/nestedPredicate.test.ts +1 -1
- package/tests/cases/integration/graphQlRequests/query/acl/predicateElimination.test.ts +130 -0
- package/tests/cases/integration/graphQlRequests/query/filter/complexCondition.test.ts +1 -1
- package/tests/cases/integration/graphQlRequests/query/filter/composedFilter.test.ts +1 -1
- package/tests/cases/integration/graphQlRequests/query/relations/manyHasManyInverse.test.ts +74 -0
- package/tests/cases/integration/graphQlRequests/query/relations/manyHasManyOwning.test.ts +77 -0
- package/tests/cases/integration/graphQlRequests/update/acl/aclUpdate.test.ts +7 -7
- package/tests/cases/integration/graphQlSchema/graphQlSchemaBuilder.test.ts +5 -5
- package/tests/cases/unit/aclVariablesFactory.test.ts +8 -35
- package/tests/cases/unit/conditionOptimizer.test.ts +135 -0
- package/tests/cases/unit/orderbyHelper.test.ts +1 -0
- package/tests/cases/unit/permissionMerger.test.ts +2 -0
- package/tests/cases/unit/predicatesFactory.test.ts +97 -0
- package/tests/cases/unit/predicatesInjector.test.ts +78 -16
- package/tests/cases/unit/variableInjector.test.ts +6 -5
- package/tests/cases/unit/whereOptimizer.test.ts +195 -0
- package/tests/src/testGraphql.ts +9 -2
- package/jasmine.json +0 -7
package/graphql.codegen.yml
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contember/engine-content-api",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0-alpha.10",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"main": "dist/src/index.js",
|
|
6
6
|
"typings": "dist/src/index.d.ts",
|
|
@@ -10,25 +10,25 @@
|
|
|
10
10
|
"test": "vitest --no-threads"
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@contember/database": "^1.
|
|
14
|
-
"@contember/dic": "^1.
|
|
15
|
-
"@contember/engine-common": "^1.
|
|
16
|
-
"@contember/graphql-utils": "^1.
|
|
17
|
-
"@contember/schema": "^1.
|
|
18
|
-
"@contember/schema-utils": "^1.
|
|
13
|
+
"@contember/database": "^1.2.0-alpha.10",
|
|
14
|
+
"@contember/dic": "^1.2.0-alpha.10",
|
|
15
|
+
"@contember/engine-common": "^1.2.0-alpha.10",
|
|
16
|
+
"@contember/graphql-utils": "^1.2.0-alpha.10",
|
|
17
|
+
"@contember/schema": "^1.2.0-alpha.10",
|
|
18
|
+
"@contember/schema-utils": "^1.2.0-alpha.10",
|
|
19
19
|
"@graphql-tools/schema": "^8.3.5",
|
|
20
20
|
"graphql-tag": "^2.12.5"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
|
-
"@contember/database-tester": "^1.
|
|
24
|
-
"@contember/engine-api-tester": "^1.
|
|
25
|
-
"@contember/schema-definition": "^1.
|
|
26
|
-
"@graphql-codegen/cli": "^
|
|
27
|
-
"@graphql-codegen/typescript": "^
|
|
28
|
-
"@graphql-codegen/typescript-operations": "^
|
|
29
|
-
"@graphql-codegen/typescript-resolvers": "^
|
|
30
|
-
"@types/node": "^
|
|
31
|
-
"graphql": "^
|
|
23
|
+
"@contember/database-tester": "^1.2.0-alpha.10",
|
|
24
|
+
"@contember/engine-api-tester": "^1.2.0-alpha.10",
|
|
25
|
+
"@contember/schema-definition": "^1.2.0-alpha.10",
|
|
26
|
+
"@graphql-codegen/cli": "^2.6.2",
|
|
27
|
+
"@graphql-codegen/typescript": "^2.5.1",
|
|
28
|
+
"@graphql-codegen/typescript-operations": "^2.4.2",
|
|
29
|
+
"@graphql-codegen/typescript-resolvers": "^2.6.6",
|
|
30
|
+
"@types/node": "^18",
|
|
31
|
+
"graphql": "^16.5.0",
|
|
32
32
|
"pg": "^8.5.0"
|
|
33
33
|
},
|
|
34
34
|
"peerDependencies": {
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Input, Model, Writable } from '@contember/schema'
|
|
2
|
+
import { replaceWhere } from '../mapper/select/optimizer/WhereReplacer'
|
|
3
|
+
|
|
4
|
+
export class EvaluatedPredicateReplacer {
|
|
5
|
+
constructor(
|
|
6
|
+
private readonly evaluatedPredicate: Input.Where,
|
|
7
|
+
private readonly sourceEntity: Model.Entity,
|
|
8
|
+
private readonly relation: Model.AnyRelation,
|
|
9
|
+
) {
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
public replace(where: Input.Where): Input.Where {
|
|
13
|
+
const result: Writable<Input.Where> = {}
|
|
14
|
+
for (const [key, value] of Object.entries(where)) {
|
|
15
|
+
if (key === 'not') {
|
|
16
|
+
result['not'] = this.replace(value as Input.Where)
|
|
17
|
+
|
|
18
|
+
} else if (key === 'and' || key === 'or') {
|
|
19
|
+
result[key] = (value as Input.Where[]).map(it => this.replace(it))
|
|
20
|
+
|
|
21
|
+
} else if (key === this.relation.name) {
|
|
22
|
+
result[key] = replaceWhere(value as Input.Where, this.evaluatedPredicate, { [this.sourceEntity.primary]: { always: true } })
|
|
23
|
+
|
|
24
|
+
} else {
|
|
25
|
+
result[key] = value
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
}
|
|
29
|
+
return result
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
}
|
|
@@ -17,7 +17,7 @@ export class PermissionFactory {
|
|
|
17
17
|
}
|
|
18
18
|
result = this.mergePermissions(result, rolePermissions)
|
|
19
19
|
}
|
|
20
|
-
this.makePrimaryPredicatesUnionOfAllFields(result)
|
|
20
|
+
result = this.makePrimaryPredicatesUnionOfAllFields(result)
|
|
21
21
|
|
|
22
22
|
return result
|
|
23
23
|
}
|
|
@@ -45,18 +45,20 @@ export class PermissionFactory {
|
|
|
45
45
|
}))
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
private makePrimaryPredicatesUnionOfAllFields(permissions: Acl.Permissions):
|
|
49
|
-
|
|
48
|
+
private makePrimaryPredicatesUnionOfAllFields(permissions: Acl.Permissions): Acl.Permissions {
|
|
49
|
+
return mapObject(permissions, (permission, entityName): Acl.EntityPermissions => {
|
|
50
50
|
const entity = getEntity(this.schema, entityName)
|
|
51
|
-
const
|
|
52
|
-
const
|
|
51
|
+
const entityPredicates: Writable<Acl.PredicateMap> = { ...permission.predicates }
|
|
52
|
+
const entityOperations: Writable<Acl.EntityOperations> = { ...permission.operations }
|
|
53
53
|
|
|
54
54
|
const operationNames = ['read', 'create', 'update'] as const
|
|
55
55
|
for (let operation of operationNames) {
|
|
56
|
-
|
|
57
|
-
if (fieldPermissions === undefined) {
|
|
56
|
+
if (!entityOperations[operation]) {
|
|
58
57
|
continue
|
|
59
58
|
}
|
|
59
|
+
const fieldPermissions: Writable<Acl.FieldPermissions> = { ...entityOperations[operation] }
|
|
60
|
+
entityOperations[operation] = fieldPermissions
|
|
61
|
+
|
|
60
62
|
if (Object.values(fieldPermissions).some(it => it === true)) {
|
|
61
63
|
fieldPermissions[entity.primary] = true
|
|
62
64
|
}
|
|
@@ -70,25 +72,28 @@ export class PermissionFactory {
|
|
|
70
72
|
.filter((value, index, array): value is string => array.indexOf(value) === index)
|
|
71
73
|
|
|
72
74
|
let idPermissions: Acl.Predicate = fieldPermissions[entity.primary] || false
|
|
73
|
-
const predicates = { ...entityPermissions.predicates }
|
|
74
75
|
|
|
75
76
|
for (let predicateReference of predicateReferences) {
|
|
76
77
|
const [predicateDefinition, predicate] = this.mergePredicates(
|
|
77
|
-
|
|
78
|
+
entityPredicates,
|
|
78
79
|
idPermissions,
|
|
79
|
-
|
|
80
|
+
entityPredicates,
|
|
80
81
|
predicateReference,
|
|
81
82
|
)
|
|
82
83
|
if (typeof predicate !== 'string' || predicateDefinition === undefined) {
|
|
83
84
|
throw new Error('should not happen')
|
|
84
85
|
}
|
|
85
86
|
idPermissions = predicate
|
|
86
|
-
|
|
87
|
+
entityPredicates[predicate] = predicateDefinition
|
|
87
88
|
}
|
|
88
89
|
fieldPermissions[entity.primary] = idPermissions
|
|
89
|
-
entityPredicates[idPermissions as Acl.PredicateReference] =
|
|
90
|
+
entityPredicates[idPermissions as Acl.PredicateReference] = entityPredicates[idPermissions as Acl.PredicateReference]
|
|
90
91
|
}
|
|
91
|
-
|
|
92
|
+
return {
|
|
93
|
+
operations: entityOperations,
|
|
94
|
+
predicates: entityPredicates,
|
|
95
|
+
}
|
|
96
|
+
})
|
|
92
97
|
}
|
|
93
98
|
|
|
94
99
|
private mergePermissions(left: Acl.Permissions, right: Acl.Permissions): Acl.Permissions {
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import { Acl, Input, Model } from '@contember/schema'
|
|
2
2
|
import { VariableInjector } from './VariableInjector'
|
|
3
|
+
import { isOwningRelation } from '@contember/schema-utils'
|
|
4
|
+
import { ImplementationException } from '../exception'
|
|
5
|
+
import { EvaluatedPredicateReplacer } from './EvaluatedPredicateReplacer'
|
|
3
6
|
|
|
4
7
|
const getRowLevelPredicatePseudoField = (entity: Model.Entity) => entity.primary
|
|
5
8
|
|
|
6
9
|
export class PredicateFactory {
|
|
7
|
-
constructor(
|
|
10
|
+
constructor(
|
|
11
|
+
private readonly permissions: Acl.Permissions,
|
|
12
|
+
private readonly model: Model.Schema,
|
|
13
|
+
private readonly variableInjector: VariableInjector,
|
|
14
|
+
) {}
|
|
8
15
|
|
|
9
16
|
public shouldApplyCellLevelPredicate(
|
|
10
17
|
entity: Model.Entity,
|
|
@@ -16,13 +23,22 @@ export class PredicateFactory {
|
|
|
16
23
|
return permissions?.[fieldName] !== permissions?.[rowLevelField]
|
|
17
24
|
}
|
|
18
25
|
|
|
19
|
-
public create(
|
|
26
|
+
public create(
|
|
27
|
+
entity: Model.Entity,
|
|
28
|
+
operation: Acl.Operation.delete,
|
|
29
|
+
): Input.Where
|
|
20
30
|
public create(
|
|
21
31
|
entity: Model.Entity,
|
|
22
32
|
operation: Acl.Operation.update | Acl.Operation.read | Acl.Operation.create,
|
|
23
33
|
fieldNames?: string[],
|
|
34
|
+
overRelation?: Model.AnyRelation,
|
|
24
35
|
): Input.Where
|
|
25
|
-
public create(
|
|
36
|
+
public create(
|
|
37
|
+
entity: Model.Entity,
|
|
38
|
+
operation: Acl.Operation,
|
|
39
|
+
fieldNames?: string[],
|
|
40
|
+
overRelation?: Model.AnyRelation,
|
|
41
|
+
): Input.Where {
|
|
26
42
|
const entityPermissions: Acl.EntityPermissions = this.permissions[entity.name]
|
|
27
43
|
const neverCondition: Input.Where = { [entity.primary]: { never: true } }
|
|
28
44
|
|
|
@@ -68,11 +84,8 @@ export class PredicateFactory {
|
|
|
68
84
|
if (predicatesWhere.length === 0) {
|
|
69
85
|
return {}
|
|
70
86
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return { and: predicatesWhere }
|
|
87
|
+
const where: Input.Where = predicatesWhere.length === 1 ? predicatesWhere[0] : { and: predicatesWhere }
|
|
88
|
+
return this.optimizePredicates(where, overRelation)
|
|
76
89
|
}
|
|
77
90
|
|
|
78
91
|
private getRequiredPredicates(
|
|
@@ -94,4 +107,22 @@ export class PredicateFactory {
|
|
|
94
107
|
}
|
|
95
108
|
return predicates
|
|
96
109
|
}
|
|
110
|
+
|
|
111
|
+
private optimizePredicates(where: Input.Where, overRelation?: Model.AnyRelation) {
|
|
112
|
+
if (!overRelation) {
|
|
113
|
+
return where
|
|
114
|
+
}
|
|
115
|
+
const otherSide = isOwningRelation(overRelation) ? overRelation.inversedBy : overRelation.ownedBy
|
|
116
|
+
if (!otherSide) {
|
|
117
|
+
throw new ImplementationException()
|
|
118
|
+
}
|
|
119
|
+
const sourceEntity = this.model.entities[overRelation.target]
|
|
120
|
+
const sourcePredicate = this.create(sourceEntity, Acl.Operation.read, [otherSide])
|
|
121
|
+
if (Object.keys(sourcePredicate).length === 0) {
|
|
122
|
+
return where
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const replacer = new EvaluatedPredicateReplacer(sourcePredicate, sourceEntity, overRelation)
|
|
126
|
+
return replacer.replace(where)
|
|
127
|
+
}
|
|
97
128
|
}
|
|
@@ -5,17 +5,18 @@ import { PredicateFactory } from './PredicateFactory'
|
|
|
5
5
|
export class PredicatesInjector {
|
|
6
6
|
constructor(private readonly schema: Model.Schema, private readonly predicateFactory: PredicateFactory) {}
|
|
7
7
|
|
|
8
|
-
public inject(entity: Model.Entity, where: Input.OptionalWhere): Input.OptionalWhere {
|
|
9
|
-
const restrictedWhere = this.injectToWhere(where, entity)
|
|
10
|
-
return this.createWhere(entity, undefined, restrictedWhere)
|
|
8
|
+
public inject(entity: Model.Entity, where: Input.OptionalWhere, overRelation?: Model.AnyRelation): Input.OptionalWhere {
|
|
9
|
+
const restrictedWhere = this.injectToWhere(where, entity, true)
|
|
10
|
+
return this.createWhere(entity, undefined, restrictedWhere, overRelation)
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
private createWhere(
|
|
14
14
|
entity: Model.Entity,
|
|
15
15
|
fieldNames: string[] | undefined,
|
|
16
16
|
where: Input.OptionalWhere,
|
|
17
|
+
overRelation?: Model.AnyRelation,
|
|
17
18
|
): Input.OptionalWhere {
|
|
18
|
-
const predicatesWhere: Input.Where = this.predicateFactory.create(entity, Acl.Operation.read, fieldNames)
|
|
19
|
+
const predicatesWhere: Input.Where = this.predicateFactory.create(entity, Acl.Operation.read, fieldNames, overRelation)
|
|
19
20
|
|
|
20
21
|
const and = [where, predicatesWhere].filter(it => Object.keys(it).length > 0)
|
|
21
22
|
if (and.length === 0) {
|
|
@@ -27,32 +28,44 @@ export class PredicatesInjector {
|
|
|
27
28
|
return { and: and }
|
|
28
29
|
}
|
|
29
30
|
|
|
30
|
-
private injectToWhere(
|
|
31
|
+
private injectToWhere(
|
|
32
|
+
where: Input.OptionalWhere,
|
|
33
|
+
entity: Model.Entity,
|
|
34
|
+
isRoot: boolean,
|
|
35
|
+
overRelation?: Model.AnyRelation,
|
|
36
|
+
): Input.OptionalWhere {
|
|
31
37
|
const resultWhere: Writable<Input.OptionalWhere> = {}
|
|
32
38
|
if (where.and) {
|
|
33
|
-
resultWhere.and = where.and.filter((it): it is Input.Where => !!it).map(it => this.injectToWhere(it, entity))
|
|
39
|
+
resultWhere.and = where.and.filter((it): it is Input.Where => !!it).map(it => this.injectToWhere(it, entity, isRoot, overRelation))
|
|
34
40
|
}
|
|
35
41
|
if (where.or) {
|
|
36
|
-
resultWhere.or = where.or.filter((it): it is Input.Where => !!it).map(it => this.injectToWhere(it, entity))
|
|
42
|
+
resultWhere.or = where.or.filter((it): it is Input.Where => !!it).map(it => this.injectToWhere(it, entity, isRoot, overRelation))
|
|
37
43
|
}
|
|
38
44
|
if (where.not) {
|
|
39
|
-
resultWhere.not = this.injectToWhere(where.not, entity)
|
|
45
|
+
resultWhere.not = this.injectToWhere(where.not, entity, isRoot, overRelation)
|
|
40
46
|
}
|
|
47
|
+
|
|
41
48
|
const fields = Object.keys(where).filter(it => !['and', 'or', 'not'].includes(it))
|
|
49
|
+
|
|
42
50
|
if (fields.length === 0) {
|
|
43
51
|
return resultWhere
|
|
44
52
|
}
|
|
45
53
|
for (let field of fields) {
|
|
46
|
-
const targetEntity = acceptFieldVisitor(this.schema, entity, field, {
|
|
54
|
+
const [targetEntity, targetRelation] = acceptFieldVisitor(this.schema, entity, field, {
|
|
47
55
|
visitColumn: () => null,
|
|
48
|
-
visitRelation: (_a, _b, targetEntity) => targetEntity,
|
|
49
|
-
})
|
|
56
|
+
visitRelation: (_a, _b, targetEntity, targetRelation) => [targetEntity, targetRelation ?? undefined],
|
|
57
|
+
}) ?? []
|
|
50
58
|
if (targetEntity) {
|
|
51
|
-
resultWhere[field] = this.injectToWhere(where[field] as Input.Where, targetEntity)
|
|
59
|
+
resultWhere[field] = this.injectToWhere(where[field] as Input.Where, targetEntity, false, targetRelation)
|
|
52
60
|
} else {
|
|
53
61
|
resultWhere[field] = where[field]
|
|
54
62
|
}
|
|
55
63
|
}
|
|
56
|
-
|
|
64
|
+
const fieldsForPredicate = !isRoot
|
|
65
|
+
? fields
|
|
66
|
+
: fields.filter(it => this.predicateFactory.shouldApplyCellLevelPredicate(entity, Acl.Operation.read, it))
|
|
67
|
+
|
|
68
|
+
return this.createWhere(entity, fieldsForPredicate, resultWhere, overRelation)
|
|
57
69
|
}
|
|
70
|
+
|
|
58
71
|
}
|
|
@@ -10,29 +10,16 @@ export class VariableInjector {
|
|
|
10
10
|
return predicateDefinitionProcessor.process(entity, where, {
|
|
11
11
|
handleColumn: ({ value }) => {
|
|
12
12
|
if (typeof value === 'string') {
|
|
13
|
-
return this.
|
|
13
|
+
return this.variables[value] ?? { never: true }
|
|
14
14
|
}
|
|
15
15
|
return value as Input.Condition
|
|
16
16
|
},
|
|
17
17
|
handleRelation: ({ value, targetEntity }) => {
|
|
18
18
|
if (typeof value === 'string') {
|
|
19
|
-
return { [targetEntity.primary]: this.
|
|
19
|
+
return { [targetEntity.primary]: this.variables[value] ?? { never: true } }
|
|
20
20
|
}
|
|
21
21
|
return value
|
|
22
22
|
},
|
|
23
23
|
})
|
|
24
24
|
}
|
|
25
|
-
|
|
26
|
-
private createCondition(variable: Acl.VariableValue | undefined): Input.Condition {
|
|
27
|
-
if (variable === undefined) {
|
|
28
|
-
return { never: true }
|
|
29
|
-
}
|
|
30
|
-
if (Array.isArray(variable)) {
|
|
31
|
-
return { in: variable }
|
|
32
|
-
}
|
|
33
|
-
if (typeof variable === 'string' || typeof variable === 'number') {
|
|
34
|
-
return { eq: variable }
|
|
35
|
-
}
|
|
36
|
-
throw new Error('not implemented')
|
|
37
|
-
}
|
|
38
25
|
}
|
package/src/acl/VariableUtils.ts
CHANGED
|
@@ -1,36 +1,20 @@
|
|
|
1
|
-
import { Acl } from '@contember/schema'
|
|
2
|
-
import { getRoleVariables } from '@contember/schema-utils'
|
|
1
|
+
import { Acl, Input } from '@contember/schema'
|
|
2
|
+
import { getRoleVariables, ParsedMembership } from '@contember/schema-utils'
|
|
3
3
|
|
|
4
|
-
type Memberships = readonly { role: string; variables: readonly { name: string; values: readonly string[] }[] }[]
|
|
5
4
|
|
|
6
5
|
export const createAclVariables = (
|
|
7
6
|
aclSchema: Acl.Schema,
|
|
8
|
-
|
|
9
|
-
identityId: string
|
|
10
|
-
personId: string | null
|
|
11
|
-
memberships: Memberships
|
|
12
|
-
},
|
|
7
|
+
memberships: readonly ParsedMembership[],
|
|
13
8
|
): Acl.VariablesMap => {
|
|
14
9
|
|
|
15
|
-
const variablesEntries =
|
|
10
|
+
const variablesEntries = memberships.flatMap(
|
|
16
11
|
membership => {
|
|
17
12
|
const roleVariables = getRoleVariables(membership.role, aclSchema)
|
|
18
|
-
const membershipVariablesMap = Object.fromEntries(membership.variables.map(it => [it.name, it.
|
|
13
|
+
const membershipVariablesMap = Object.fromEntries(membership.variables.map(it => [it.name, it.condition]))
|
|
19
14
|
|
|
20
|
-
return Object.
|
|
15
|
+
return Object.keys(roleVariables).map((name): [string, Input.Condition] => {
|
|
21
16
|
const prefixed = prefixVariable(membership.role, name)
|
|
22
|
-
|
|
23
|
-
switch (def.type) {
|
|
24
|
-
case Acl.VariableType.entity:
|
|
25
|
-
return [prefixed, membershipVariablesMap[name] ?? []]
|
|
26
|
-
case Acl.VariableType.predefined:
|
|
27
|
-
switch (def.value) {
|
|
28
|
-
case 'identityID':
|
|
29
|
-
return [prefixed, [identity.identityId]]
|
|
30
|
-
case 'personID':
|
|
31
|
-
return [prefixed, identity.personId ? [identity.personId] : []]
|
|
32
|
-
}
|
|
33
|
-
}
|
|
17
|
+
return [prefixed, membershipVariablesMap[name] ?? { never: true }]
|
|
34
18
|
})
|
|
35
19
|
},
|
|
36
20
|
)
|
|
@@ -31,7 +31,7 @@ export class HasManyToHasOneReducerExecutionHandler implements SelectExecutionHa
|
|
|
31
31
|
}
|
|
32
32
|
const newObjectNode = objectNode.withArgs<Input.ListQueryInput>({ filter: whereWithParentId })
|
|
33
33
|
|
|
34
|
-
return context.mapper.select(targetEntity, newObjectNode, targetRelation.name)
|
|
34
|
+
return context.mapper.select(targetEntity, newObjectNode, targetRelation, targetRelation.name)
|
|
35
35
|
},
|
|
36
36
|
null,
|
|
37
37
|
)
|
|
@@ -40,7 +40,7 @@ export class HasManyToHasOneReducerExecutionHandler implements SelectExecutionHa
|
|
|
40
40
|
private getRelationTarget(
|
|
41
41
|
entity: Model.Entity,
|
|
42
42
|
relationName: string,
|
|
43
|
-
): [Model.Entity, Model.
|
|
43
|
+
): [Model.Entity, Model.AnyRelation & Model.JoiningColumnRelation] {
|
|
44
44
|
return acceptFieldVisitor(this.schema, entity, relationName, {
|
|
45
45
|
visitColumn: (): never => {
|
|
46
46
|
throw new ImplementationException('HasManyToHasOneReducerExecutionHandler: Not applicable for a column')
|
|
@@ -50,7 +50,7 @@ export class HasManyToHasOneReducerExecutionHandler implements SelectExecutionHa
|
|
|
50
50
|
relation,
|
|
51
51
|
targetEntity,
|
|
52
52
|
targetRelation,
|
|
53
|
-
): [Model.Entity, Model.
|
|
53
|
+
): [Model.Entity, Model.AnyRelation & Model.JoiningColumnRelation] => {
|
|
54
54
|
if (!targetRelation || !isIt<Model.JoiningColumnRelation>(targetRelation, 'joiningColumn')) {
|
|
55
55
|
throw new Error('HasManyToHasOneReducerExecutionHandler: only applicable for relations with joiningColumn')
|
|
56
56
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Input, Model } from '@contember/schema'
|
|
2
|
-
import { GroupedCounts,
|
|
2
|
+
import { GroupedCounts, Mapper, RelationFetcher } from '../../mapper'
|
|
3
3
|
import { ObjectNode } from '../../inputProcessing'
|
|
4
4
|
|
|
5
5
|
export class PaginatedHasManyCountVisitor implements
|
|
@@ -20,11 +20,13 @@ export class PaginatedHasManyCountVisitor implements
|
|
|
20
20
|
targetRelation: Model.ManyHasOneRelation,
|
|
21
21
|
): Promise<GroupedCounts> {
|
|
22
22
|
return await this.relationFetcher.countOneHasManyGroups(
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
{
|
|
24
|
+
mapper: this.mapper,
|
|
25
|
+
filter: this.objectNode.args.filter,
|
|
26
|
+
targetEntity: targetEntity,
|
|
27
|
+
targetRelation: targetRelation,
|
|
28
|
+
ids: this.ids,
|
|
29
|
+
},
|
|
28
30
|
)
|
|
29
31
|
}
|
|
30
32
|
|
|
@@ -34,18 +36,16 @@ export class PaginatedHasManyCountVisitor implements
|
|
|
34
36
|
targetEntity: Model.Entity,
|
|
35
37
|
targetRelation: Model.ManyHasManyInverseRelation | null,
|
|
36
38
|
): Promise<GroupedCounts> {
|
|
37
|
-
const joiningTable = relation.joiningTable
|
|
38
|
-
const columns: JoiningColumns = {
|
|
39
|
-
sourceColumn: joiningTable.joiningColumn,
|
|
40
|
-
targetColumn: joiningTable.inverseJoiningColumn,
|
|
41
|
-
}
|
|
42
39
|
return await this.relationFetcher.countManyHasManyGroups(
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
40
|
+
{
|
|
41
|
+
mapper: this.mapper,
|
|
42
|
+
filter: this.objectNode.args.filter,
|
|
43
|
+
targetEntity: targetEntity,
|
|
44
|
+
sourceRelation: relation,
|
|
45
|
+
targetRelation,
|
|
46
|
+
directionFrom: 'owning',
|
|
47
|
+
ids: this.ids,
|
|
48
|
+
},
|
|
49
49
|
)
|
|
50
50
|
}
|
|
51
51
|
|
|
@@ -55,18 +55,16 @@ export class PaginatedHasManyCountVisitor implements
|
|
|
55
55
|
targetEntity: Model.Entity,
|
|
56
56
|
targetRelation: Model.ManyHasManyOwningRelation,
|
|
57
57
|
): Promise<GroupedCounts> {
|
|
58
|
-
const joiningTable = targetRelation.joiningTable
|
|
59
|
-
const columns: JoiningColumns = {
|
|
60
|
-
targetColumn: joiningTable.joiningColumn,
|
|
61
|
-
sourceColumn: joiningTable.inverseJoiningColumn,
|
|
62
|
-
}
|
|
63
58
|
return await this.relationFetcher.countManyHasManyGroups(
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
59
|
+
{
|
|
60
|
+
mapper: this.mapper,
|
|
61
|
+
filter: this.objectNode.args.filter,
|
|
62
|
+
targetEntity: targetEntity,
|
|
63
|
+
sourceRelation: relation,
|
|
64
|
+
targetRelation,
|
|
65
|
+
directionFrom: 'inverse',
|
|
66
|
+
ids: this.ids,
|
|
67
|
+
},
|
|
70
68
|
)
|
|
71
69
|
}
|
|
72
70
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Input, Model } from '@contember/schema'
|
|
2
|
-
import {
|
|
2
|
+
import { Mapper, RelationFetcher, SelectGroupedObjects } from '../../mapper'
|
|
3
3
|
import { ObjectNode } from '../../inputProcessing'
|
|
4
4
|
|
|
5
5
|
export class PaginatedHasManyNodesVisitor implements
|
|
@@ -20,12 +20,14 @@ export class PaginatedHasManyNodesVisitor implements
|
|
|
20
20
|
targetRelation: Model.ManyHasOneRelation,
|
|
21
21
|
): Promise<SelectGroupedObjects> {
|
|
22
22
|
return await this.relationFetcher.fetchOneHasManyGroups(
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
{
|
|
24
|
+
mapper: this.mapper,
|
|
25
|
+
objectNode: this.objectNode,
|
|
26
|
+
targetEntity: targetEntity,
|
|
27
|
+
relation: relation,
|
|
28
|
+
targetRelation: targetRelation,
|
|
29
|
+
ids: this.ids,
|
|
30
|
+
},
|
|
29
31
|
)
|
|
30
32
|
}
|
|
31
33
|
|
|
@@ -35,19 +37,16 @@ export class PaginatedHasManyNodesVisitor implements
|
|
|
35
37
|
targetEntity: Model.Entity,
|
|
36
38
|
targetRelation: Model.ManyHasManyInverseRelation | null,
|
|
37
39
|
): Promise<SelectGroupedObjects> {
|
|
38
|
-
const joiningTable = relation.joiningTable
|
|
39
|
-
const columns: JoiningColumns = {
|
|
40
|
-
sourceColumn: joiningTable.joiningColumn,
|
|
41
|
-
targetColumn: joiningTable.inverseJoiningColumn,
|
|
42
|
-
}
|
|
43
40
|
return await this.relationFetcher.fetchManyHasManyGroups(
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
41
|
+
{
|
|
42
|
+
mapper: this.mapper,
|
|
43
|
+
field: this.objectNode,
|
|
44
|
+
targetEntity: targetEntity,
|
|
45
|
+
sourceRelation: relation,
|
|
46
|
+
targetRelation,
|
|
47
|
+
directionFrom: 'owning',
|
|
48
|
+
ids: this.ids,
|
|
49
|
+
},
|
|
51
50
|
)
|
|
52
51
|
}
|
|
53
52
|
|
|
@@ -57,19 +56,16 @@ export class PaginatedHasManyNodesVisitor implements
|
|
|
57
56
|
targetEntity: Model.Entity,
|
|
58
57
|
targetRelation: Model.ManyHasManyOwningRelation,
|
|
59
58
|
): Promise<SelectGroupedObjects> {
|
|
60
|
-
const joiningTable = targetRelation.joiningTable
|
|
61
|
-
const columns: JoiningColumns = {
|
|
62
|
-
targetColumn: joiningTable.joiningColumn,
|
|
63
|
-
sourceColumn: joiningTable.inverseJoiningColumn,
|
|
64
|
-
}
|
|
65
59
|
return await this.relationFetcher.fetchManyHasManyGroups(
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
60
|
+
{
|
|
61
|
+
mapper: this.mapper,
|
|
62
|
+
field: this.objectNode,
|
|
63
|
+
targetEntity: targetEntity,
|
|
64
|
+
sourceRelation: relation,
|
|
65
|
+
targetRelation,
|
|
66
|
+
directionFrom: 'inverse',
|
|
67
|
+
ids: this.ids,
|
|
68
|
+
},
|
|
73
69
|
)
|
|
74
70
|
}
|
|
75
71
|
|
|
@@ -10,7 +10,7 @@ namespace ValidationContext {
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
export type NodeType = Value.Object
|
|
13
|
-
export type ValueType = Value.FieldValue
|
|
13
|
+
export type ValueType = Value.FieldValue | undefined
|
|
14
14
|
|
|
15
15
|
export enum NodeContextType {
|
|
16
16
|
value = 'value',
|
|
@@ -69,7 +69,7 @@ namespace ValidationContext {
|
|
|
69
69
|
|
|
70
70
|
export const createSingleNodeContext = (
|
|
71
71
|
parent: NodeContext | ValueContext,
|
|
72
|
-
value:
|
|
72
|
+
value: ValueType,
|
|
73
73
|
): NodeContext | ValueContext => {
|
|
74
74
|
if (Array.isArray(value)) {
|
|
75
75
|
throw new Error('Nested arrays are not allowed')
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { QueryAstFactory } from './QueryAstFactory'
|
|
2
2
|
import { Mapper } from '../mapper'
|
|
3
|
-
import { Dependencies
|
|
3
|
+
import { Dependencies } from './dependencies'
|
|
4
4
|
import { Input, Model, Value } from '@contember/schema'
|
|
5
5
|
|
|
6
6
|
export class ValidationDataSelector {
|
|
@@ -20,7 +20,7 @@ export class ValidationDataSelector {
|
|
|
20
20
|
return {}
|
|
21
21
|
}
|
|
22
22
|
const queryAst = this.queryAstFactory.create(entity.name, dependencies).withArg('by', where)
|
|
23
|
-
const node = await mapper.selectUnique(entity, queryAst)
|
|
23
|
+
const node = await mapper.selectUnique(entity, queryAst, null)
|
|
24
24
|
if (!node) {
|
|
25
25
|
return null
|
|
26
26
|
}
|