@expo/entity 0.34.0 → 0.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/AuthorizationResultBasedEntityLoader.d.ts +128 -0
- package/build/AuthorizationResultBasedEntityLoader.js +196 -0
- package/build/AuthorizationResultBasedEntityLoader.js.map +1 -0
- package/build/ComposedEntityCacheAdapter.js +1 -0
- package/build/ComposedEntityCacheAdapter.js.map +1 -1
- package/build/ComposedSecondaryEntityCache.js +1 -0
- package/build/ComposedSecondaryEntityCache.js.map +1 -1
- package/build/EnforcingEntityLoader.d.ts +5 -4
- package/build/EnforcingEntityLoader.js +4 -2
- package/build/EnforcingEntityLoader.js.map +1 -1
- package/build/Entity.d.ts +4 -31
- package/build/Entity.js +19 -46
- package/build/Entity.js.map +1 -1
- package/build/EntityAssociationLoader.d.ts +9 -9
- package/build/EntityAssociationLoader.js +37 -12
- package/build/EntityAssociationLoader.js.map +1 -1
- package/build/EntityCompanion.js +9 -1
- package/build/EntityCompanion.js.map +1 -1
- package/build/EntityCompanionProvider.d.ts +3 -1
- package/build/EntityCompanionProvider.js +10 -4
- package/build/EntityCompanionProvider.js.map +1 -1
- package/build/EntityConfiguration.d.ts +2 -1
- package/build/EntityConfiguration.js +19 -1
- package/build/EntityConfiguration.js.map +1 -1
- package/build/EntityDatabaseAdapter.d.ts +2 -2
- package/build/EntityDatabaseAdapter.js +5 -3
- package/build/EntityDatabaseAdapter.js.map +1 -1
- package/build/EntityFieldDefinition.d.ts +21 -10
- package/build/EntityFieldDefinition.js +8 -9
- package/build/EntityFieldDefinition.js.map +1 -1
- package/build/EntityFields.d.ts +10 -0
- package/build/EntityFields.js +15 -1
- package/build/EntityFields.js.map +1 -1
- package/build/EntityLoader.d.ts +12 -125
- package/build/EntityLoader.js +24 -239
- package/build/EntityLoader.js.map +1 -1
- package/build/EntityLoaderFactory.d.ts +1 -1
- package/build/EntityLoaderFactory.js +3 -0
- package/build/EntityLoaderFactory.js.map +1 -1
- package/build/EntityLoaderUtils.d.ts +58 -0
- package/build/EntityLoaderUtils.js +109 -0
- package/build/EntityLoaderUtils.js.map +1 -0
- package/build/EntityMutator.d.ts +1 -0
- package/build/EntityMutator.js +71 -56
- package/build/EntityMutator.js.map +1 -1
- package/build/EntityMutatorFactory.js +9 -0
- package/build/EntityMutatorFactory.js.map +1 -1
- package/build/EntityPrivacyPolicy.d.ts +11 -5
- package/build/EntityPrivacyPolicy.js +5 -7
- package/build/EntityPrivacyPolicy.js.map +1 -1
- package/build/EntityQueryContext.d.ts +2 -1
- package/build/EntityQueryContext.js +11 -6
- package/build/EntityQueryContext.js.map +1 -1
- package/build/EntityQueryContextProvider.d.ts +1 -1
- package/build/EntityQueryContextProvider.js +1 -1
- package/build/EntityQueryContextProvider.js.map +1 -1
- package/build/EntitySecondaryCacheLoader.js +5 -1
- package/build/EntitySecondaryCacheLoader.js.map +1 -1
- package/build/GenericEntityCacheAdapter.js +1 -0
- package/build/GenericEntityCacheAdapter.js.map +1 -1
- package/build/GenericSecondaryEntityCache.js +2 -0
- package/build/GenericSecondaryEntityCache.js.map +1 -1
- package/build/IEntityCacheAdapterProvider.d.ts +1 -1
- package/build/IEntityDatabaseAdapterProvider.d.ts +1 -1
- package/build/ReadonlyEntity.d.ts +1 -1
- package/build/ReadonlyEntity.js +9 -2
- package/build/ReadonlyEntity.js.map +1 -1
- package/build/ViewerContext.d.ts +2 -2
- package/build/ViewerContext.js +5 -3
- package/build/ViewerContext.js.map +1 -1
- package/build/ViewerScopedEntityCompanion.js +2 -0
- package/build/ViewerScopedEntityCompanion.js.map +1 -1
- package/build/ViewerScopedEntityCompanionProvider.d.ts +0 -1
- package/build/ViewerScopedEntityCompanionProvider.js +2 -1
- package/build/ViewerScopedEntityCompanionProvider.js.map +1 -1
- package/build/ViewerScopedEntityLoaderFactory.d.ts +1 -1
- package/build/ViewerScopedEntityLoaderFactory.js +2 -0
- package/build/ViewerScopedEntityLoaderFactory.js.map +1 -1
- package/build/ViewerScopedEntityMutatorFactory.js +2 -0
- package/build/ViewerScopedEntityMutatorFactory.js.map +1 -1
- package/build/__tests__/ComposedCacheAdapter-test.js +2 -0
- package/build/__tests__/ComposedCacheAdapter-test.js.map +1 -1
- package/build/__tests__/ComposedSecondaryEntityCache-test.js +1 -0
- package/build/__tests__/ComposedSecondaryEntityCache-test.js.map +1 -1
- package/build/__tests__/EnforcingEntityLoader-test.js +101 -113
- package/build/__tests__/EnforcingEntityLoader-test.js.map +1 -1
- package/build/__tests__/Entity-test.js +5 -137
- package/build/__tests__/Entity-test.js.map +1 -1
- package/build/__tests__/EntityAssociationLoader-test.js +37 -65
- package/build/__tests__/EntityAssociationLoader-test.js.map +1 -1
- package/build/__tests__/EntityCommonUseCases-test.js +31 -37
- package/build/__tests__/EntityCommonUseCases-test.js.map +1 -1
- package/build/__tests__/EntityCompanion-test.js +26 -3
- package/build/__tests__/EntityCompanion-test.js.map +1 -1
- package/build/__tests__/EntityConfiguration-test.js +103 -0
- package/build/__tests__/EntityConfiguration-test.js.map +1 -0
- package/build/__tests__/EntityDatabaseAdapter-test.js +6 -0
- package/build/__tests__/EntityDatabaseAdapter-test.js.map +1 -1
- package/build/__tests__/EntityEdges-test.js +89 -80
- package/build/__tests__/EntityEdges-test.js.map +1 -1
- package/build/__tests__/EntityFields-test.js +6 -0
- package/build/__tests__/EntityFields-test.js.map +1 -1
- package/build/__tests__/EntityLoader-constructor-test.js +17 -18
- package/build/__tests__/EntityLoader-constructor-test.js.map +1 -1
- package/build/__tests__/EntityLoader-test.js +93 -41
- package/build/__tests__/EntityLoader-test.js.map +1 -1
- package/build/__tests__/EntityMutator-MutationCacheConsistency-test.js +18 -21
- package/build/__tests__/EntityMutator-MutationCacheConsistency-test.js.map +1 -1
- package/build/__tests__/EntityMutator-test.js +74 -29
- package/build/__tests__/EntityMutator-test.js.map +1 -1
- package/build/__tests__/EntityPrivacyPolicy-test.js +77 -59
- package/build/__tests__/EntityPrivacyPolicy-test.js.map +1 -1
- package/build/__tests__/EntityQueryContext-test.js +9 -0
- package/build/__tests__/EntityQueryContext-test.js.map +1 -1
- package/build/__tests__/EntitySecondaryCacheLoader-test.js +10 -10
- package/build/__tests__/EntitySecondaryCacheLoader-test.js.map +1 -1
- package/build/__tests__/EntitySelfReferentialEdges-test.js +59 -74
- package/build/__tests__/EntitySelfReferentialEdges-test.js.map +1 -1
- package/build/__tests__/ReadonlyEntity-test.js +13 -13
- package/build/__tests__/ReadonlyEntity-test.js.map +1 -1
- package/build/__tests__/ViewerContext-test.js +2 -2
- package/build/__tests__/ViewerContext-test.js.map +1 -1
- package/build/__tests__/ViewerScopedEntityLoaderFactory-test.js.map +1 -1
- package/build/__tests__/cases/TwoEntitySameTableDisjointRows-test.js +26 -28
- package/build/__tests__/cases/TwoEntitySameTableDisjointRows-test.js.map +1 -1
- package/build/__tests__/cases/TwoEntitySameTableOverlappingRows-test.js +25 -30
- package/build/__tests__/cases/TwoEntitySameTableOverlappingRows-test.js.map +1 -1
- package/build/entityUtils.d.ts +1 -1
- package/build/entityUtils.js.map +1 -1
- package/build/errors/EntityCacheAdapterError.js +2 -5
- package/build/errors/EntityCacheAdapterError.js.map +1 -1
- package/build/errors/EntityDatabaseAdapterError.js +14 -35
- package/build/errors/EntityDatabaseAdapterError.js.map +1 -1
- package/build/errors/EntityError.js +1 -0
- package/build/errors/EntityError.js.map +1 -1
- package/build/errors/EntityInvalidFieldValueError.js +2 -2
- package/build/errors/EntityInvalidFieldValueError.js.map +1 -1
- package/build/errors/EntityNotAuthorizedError.js +3 -2
- package/build/errors/EntityNotAuthorizedError.js.map +1 -1
- package/build/errors/EntityNotFoundError.js +2 -2
- package/build/errors/EntityNotFoundError.js.map +1 -1
- package/build/index.d.ts +1 -0
- package/build/index.js +1 -0
- package/build/index.js.map +1 -1
- package/build/internal/EntityDataManager.d.ts +1 -1
- package/build/internal/EntityDataManager.js +7 -2
- package/build/internal/EntityDataManager.js.map +1 -1
- package/build/internal/EntityFieldTransformationUtils.d.ts +5 -5
- package/build/internal/EntityFieldTransformationUtils.js +5 -8
- package/build/internal/EntityFieldTransformationUtils.js.map +1 -1
- package/build/internal/EntityTableDataCoordinator.d.ts +1 -1
- package/build/internal/EntityTableDataCoordinator.js +5 -0
- package/build/internal/EntityTableDataCoordinator.js.map +1 -1
- package/build/internal/ReadThroughEntityCache.d.ts +1 -1
- package/build/internal/ReadThroughEntityCache.js +2 -0
- package/build/internal/ReadThroughEntityCache.js.map +1 -1
- package/build/internal/__tests__/EntityDataManager-test.js +11 -11
- package/build/internal/__tests__/EntityDataManager-test.js.map +1 -1
- package/build/internal/__tests__/EntityFieldTransformationUtils-test.js +6 -2
- package/build/internal/__tests__/EntityFieldTransformationUtils-test.js.map +1 -1
- package/build/internal/__tests__/ReadThroughEntityCache-test.js +33 -0
- package/build/internal/__tests__/ReadThroughEntityCache-test.js.map +1 -1
- package/build/metrics/IEntityMetricsAdapter.d.ts +1 -1
- package/build/rules/AlwaysAllowPrivacyPolicyRule.d.ts +1 -1
- package/build/rules/AlwaysAllowPrivacyPolicyRule.js.map +1 -1
- package/build/rules/AlwaysDenyPrivacyPolicyRule.d.ts +1 -1
- package/build/rules/AlwaysDenyPrivacyPolicyRule.js.map +1 -1
- package/build/rules/AlwaysSkipPrivacyPolicyRule.d.ts +1 -1
- package/build/rules/AlwaysSkipPrivacyPolicyRule.js.map +1 -1
- package/build/rules/PrivacyPolicyRule.d.ts +1 -1
- package/build/rules/PrivacyPolicyRule.js.map +1 -1
- package/build/rules/__tests__/AlwaysAllowPrivacyPolicyRule-test.js.map +1 -1
- package/build/rules/__tests__/AlwaysDenyPrivacyPolicyRule-test.js.map +1 -1
- package/build/rules/__tests__/AlwaysSkipPrivacyPolicyRule-test.js.map +1 -1
- package/build/testfixtures/DateIDTestEntity.js +12 -15
- package/build/testfixtures/DateIDTestEntity.js.map +1 -1
- package/build/testfixtures/SimpleTestEntity.d.ts +8 -8
- package/build/testfixtures/SimpleTestEntity.js +12 -15
- package/build/testfixtures/SimpleTestEntity.js.map +1 -1
- package/build/testfixtures/TestEntity.d.ts +12 -12
- package/build/testfixtures/TestEntity.js +12 -15
- package/build/testfixtures/TestEntity.js.map +1 -1
- package/build/testfixtures/TestEntity2.d.ts +8 -8
- package/build/testfixtures/TestEntity2.js +12 -15
- package/build/testfixtures/TestEntity2.js.map +1 -1
- package/build/testfixtures/TestEntityNumberKey.js +12 -15
- package/build/testfixtures/TestEntityNumberKey.js.map +1 -1
- package/build/testfixtures/TestEntityWithMutationTriggers.d.ts +36 -0
- package/build/testfixtures/TestEntityWithMutationTriggers.js +82 -0
- package/build/testfixtures/TestEntityWithMutationTriggers.js.map +1 -0
- package/build/testfixtures/TestViewerContext.d.ts +0 -3
- package/build/testfixtures/TestViewerContext.js +0 -6
- package/build/testfixtures/TestViewerContext.js.map +1 -1
- package/build/utils/EntityPrivacyUtils.d.ts +34 -0
- package/build/utils/EntityPrivacyUtils.js +160 -0
- package/build/utils/EntityPrivacyUtils.js.map +1 -0
- package/build/utils/__tests__/EntityPrivacyUtils-test.d.ts +1 -0
- package/build/utils/__tests__/EntityPrivacyUtils-test.js +395 -0
- package/build/utils/__tests__/EntityPrivacyUtils-test.js.map +1 -0
- package/build/utils/__tests__/mergeEntityMutationTriggerConfigurations-test.d.ts +1 -0
- package/build/utils/__tests__/mergeEntityMutationTriggerConfigurations-test.js +26 -0
- package/build/utils/__tests__/mergeEntityMutationTriggerConfigurations-test.js.map +1 -0
- package/build/utils/collections/maps.js.map +1 -1
- package/build/utils/mergeEntityMutationTriggerConfigurations.d.ts +4 -0
- package/build/utils/mergeEntityMutationTriggerConfigurations.js +28 -0
- package/build/utils/mergeEntityMutationTriggerConfigurations.js.map +1 -0
- package/build/utils/testing/PrivacyPolicyRuleTestUtils.d.ts +1 -1
- package/build/utils/testing/PrivacyPolicyRuleTestUtils.js.map +1 -1
- package/build/utils/testing/StubCacheAdapter.d.ts +3 -3
- package/build/utils/testing/StubCacheAdapter.js +3 -3
- package/build/utils/testing/StubCacheAdapter.js.map +1 -1
- package/build/utils/testing/StubDatabaseAdapter.d.ts +2 -2
- package/build/utils/testing/StubDatabaseAdapter.js +4 -2
- package/build/utils/testing/StubDatabaseAdapter.js.map +1 -1
- package/build/utils/testing/StubDatabaseAdapterProvider.d.ts +1 -1
- package/build/utils/testing/StubDatabaseAdapterProvider.js +1 -3
- package/build/utils/testing/StubDatabaseAdapterProvider.js.map +1 -1
- package/build/utils/testing/__tests__/PrivacyPolicyRuleTestUtils-test.d.ts +1 -0
- package/build/utils/testing/__tests__/PrivacyPolicyRuleTestUtils-test.js +42 -0
- package/build/utils/testing/__tests__/PrivacyPolicyRuleTestUtils-test.js.map +1 -0
- package/build/utils/testing/__tests__/StubDatabaseAdapter-test.js +53 -0
- package/build/utils/testing/__tests__/StubDatabaseAdapter-test.js.map +1 -1
- package/build/utils/testing/describeFieldTestCase.js.map +1 -1
- package/package.json +4 -3
- package/src/AuthorizationResultBasedEntityLoader.ts +297 -0
- package/src/ComposedEntityCacheAdapter.ts +6 -6
- package/src/ComposedSecondaryEntityCache.ts +8 -8
- package/src/EnforcingEntityLoader.ts +20 -19
- package/src/Entity.ts +26 -118
- package/src/EntityAssociationLoader.ts +56 -41
- package/src/EntityCompanion.ts +8 -4
- package/src/EntityCompanionProvider.ts +24 -16
- package/src/EntityConfiguration.ts +18 -7
- package/src/EntityDatabaseAdapter.ts +41 -41
- package/src/EntityFieldDefinition.ts +28 -18
- package/src/EntityFields.ts +15 -0
- package/src/EntityLoader.ts +63 -357
- package/src/EntityLoaderFactory.ts +10 -4
- package/src/EntityLoaderUtils.ts +149 -0
- package/src/EntityMutationInfo.ts +2 -2
- package/src/EntityMutationTriggerConfiguration.ts +5 -5
- package/src/EntityMutationValidator.ts +2 -2
- package/src/EntityMutator.ts +146 -144
- package/src/EntityMutatorFactory.ts +8 -8
- package/src/EntityPrivacyPolicy.ts +78 -28
- package/src/EntityQueryContext.ts +14 -13
- package/src/EntityQueryContextProvider.ts +6 -6
- package/src/EntitySecondaryCacheLoader.ts +13 -11
- package/src/GenericEntityCacheAdapter.ts +10 -10
- package/src/GenericSecondaryEntityCache.ts +6 -6
- package/src/IEntityCacheAdapter.ts +4 -4
- package/src/IEntityCacheAdapterProvider.ts +2 -2
- package/src/IEntityDatabaseAdapterProvider.ts +2 -2
- package/src/ReadonlyEntity.ts +8 -5
- package/src/ViewerContext.ts +10 -10
- package/src/ViewerScopedEntityCompanion.ts +4 -4
- package/src/ViewerScopedEntityCompanionProvider.ts +4 -5
- package/src/ViewerScopedEntityLoaderFactory.ts +10 -4
- package/src/ViewerScopedEntityMutatorFactory.ts +5 -5
- package/src/__tests__/ComposedCacheAdapter-test.ts +12 -10
- package/src/__tests__/ComposedSecondaryEntityCache-test.ts +8 -8
- package/src/__tests__/EnforcingEntityLoader-test.ts +236 -159
- package/src/__tests__/Entity-test.ts +5 -223
- package/src/__tests__/EntityAssociationLoader-test.ts +91 -169
- package/src/__tests__/EntityCommonUseCases-test.ts +36 -38
- package/src/__tests__/EntityCompanion-test.ts +57 -5
- package/src/__tests__/EntityConfiguration-test.ts +118 -0
- package/src/__tests__/EntityDatabaseAdapter-test.ts +11 -11
- package/src/__tests__/EntityEdges-test.ts +128 -118
- package/src/__tests__/EntityFields-test.ts +14 -2
- package/src/__tests__/EntityLoader-constructor-test.ts +21 -8
- package/src/__tests__/EntityLoader-test.ts +233 -105
- package/src/__tests__/EntityMutator-MutationCacheConsistency-test.ts +17 -20
- package/src/__tests__/EntityMutator-test.ts +342 -163
- package/src/__tests__/EntityPrivacyPolicy-test.ts +166 -53
- package/src/__tests__/EntityQueryContext-test.ts +30 -12
- package/src/__tests__/EntitySecondaryCacheLoader-test.ts +17 -26
- package/src/__tests__/EntitySelfReferentialEdges-test.ts +67 -115
- package/src/__tests__/GenericEntityCacheAdapter-test.ts +2 -2
- package/src/__tests__/ReadonlyEntity-test.ts +13 -15
- package/src/__tests__/ViewerContext-test.ts +3 -4
- package/src/__tests__/ViewerScopedEntityCompanion-test.ts +2 -2
- package/src/__tests__/ViewerScopedEntityCompanionProvider-test.ts +2 -2
- package/src/__tests__/ViewerScopedEntityLoaderFactory-test.ts +2 -1
- package/src/__tests__/cases/TwoEntitySameTableDisjointRows-test.ts +34 -45
- package/src/__tests__/cases/TwoEntitySameTableOverlappingRows-test.ts +22 -30
- package/src/__tests__/entityUtils-test.ts +2 -2
- package/src/entityUtils.ts +4 -4
- package/src/errors/EntityError.ts +4 -1
- package/src/errors/EntityInvalidFieldValueError.ts +2 -2
- package/src/errors/EntityNotAuthorizedError.ts +3 -3
- package/src/errors/EntityNotFoundError.ts +2 -2
- package/src/index.ts +1 -0
- package/src/internal/EntityDataManager.ts +25 -25
- package/src/internal/EntityFieldTransformationUtils.ts +39 -32
- package/src/internal/EntityTableDataCoordinator.ts +3 -3
- package/src/internal/ReadThroughEntityCache.ts +9 -9
- package/src/internal/__tests__/EntityDataManager-test.ts +62 -62
- package/src/internal/__tests__/EntityFieldTransformationUtils-test.ts +14 -10
- package/src/internal/__tests__/ReadThroughEntityCache-test.ts +74 -18
- package/src/metrics/EntityMetricsUtils.ts +4 -4
- package/src/metrics/IEntityMetricsAdapter.ts +1 -1
- package/src/rules/AlwaysAllowPrivacyPolicyRule.ts +9 -3
- package/src/rules/AlwaysDenyPrivacyPolicyRule.ts +9 -3
- package/src/rules/AlwaysSkipPrivacyPolicyRule.ts +9 -3
- package/src/rules/PrivacyPolicyRule.ts +9 -3
- package/src/rules/__tests__/AlwaysAllowPrivacyPolicyRule-test.ts +2 -1
- package/src/rules/__tests__/AlwaysDenyPrivacyPolicyRule-test.ts +2 -1
- package/src/rules/__tests__/AlwaysSkipPrivacyPolicyRule-test.ts +2 -1
- package/src/testfixtures/SimpleTestEntity.ts +8 -8
- package/src/testfixtures/TestEntity.ts +13 -16
- package/src/testfixtures/TestEntity2.ts +8 -8
- package/src/testfixtures/TestEntityWithMutationTriggers.ts +156 -0
- package/src/testfixtures/TestViewerContext.ts +1 -12
- package/src/utils/EntityPrivacyUtils.ts +325 -0
- package/src/utils/__tests__/EntityPrivacyUtils-test.ts +570 -0
- package/src/utils/__tests__/mergeEntityMutationTriggerConfigurations-test.ts +29 -0
- package/src/utils/collections/__tests__/maps-test.ts +2 -2
- package/src/utils/collections/maps.ts +11 -11
- package/src/utils/mergeEntityMutationTriggerConfigurations.ts +44 -0
- package/src/utils/testing/PrivacyPolicyRuleTestUtils.ts +25 -22
- package/src/utils/testing/StubCacheAdapter.ts +17 -15
- package/src/utils/testing/StubDatabaseAdapter.ts +35 -30
- package/src/utils/testing/StubDatabaseAdapterProvider.ts +2 -2
- package/src/utils/testing/StubQueryContextProvider.ts +2 -2
- package/src/utils/testing/__tests__/PrivacyPolicyRuleTestUtils-test.ts +42 -0
- package/src/utils/testing/__tests__/StubDatabaseAdapter-test.ts +111 -29
- package/src/utils/testing/createUnitTestEntityCompanionProvider.ts +2 -2
- package/src/utils/testing/describeFieldTestCase.ts +1 -1
- package/build/__tests__/EntityDataConfiguration-test.js +0 -68
- package/build/__tests__/EntityDataConfiguration-test.js.map +0 -1
- package/src/__tests__/EntityDataConfiguration-test.ts +0 -77
- /package/build/__tests__/{EntityDataConfiguration-test.d.ts → EntityConfiguration-test.d.ts} +0 -0
|
@@ -0,0 +1,570 @@
|
|
|
1
|
+
import Entity from '../../Entity';
|
|
2
|
+
import { EntityCompanionDefinition } from '../../EntityCompanionProvider';
|
|
3
|
+
import EntityConfiguration from '../../EntityConfiguration';
|
|
4
|
+
import { EntityEdgeDeletionBehavior } from '../../EntityFieldDefinition';
|
|
5
|
+
import { UUIDField } from '../../EntityFields';
|
|
6
|
+
import EntityPrivacyPolicy, {
|
|
7
|
+
EntityPrivacyPolicyEvaluationContext,
|
|
8
|
+
} from '../../EntityPrivacyPolicy';
|
|
9
|
+
import { EntityQueryContext } from '../../EntityQueryContext';
|
|
10
|
+
import ReadonlyEntity from '../../ReadonlyEntity';
|
|
11
|
+
import ViewerContext from '../../ViewerContext';
|
|
12
|
+
import AlwaysAllowPrivacyPolicyRule from '../../rules/AlwaysAllowPrivacyPolicyRule';
|
|
13
|
+
import AlwaysDenyPrivacyPolicyRule from '../../rules/AlwaysDenyPrivacyPolicyRule';
|
|
14
|
+
import { RuleEvaluationResult } from '../../rules/PrivacyPolicyRule';
|
|
15
|
+
import { canViewerDeleteAsync, canViewerUpdateAsync } from '../EntityPrivacyUtils';
|
|
16
|
+
import { createUnitTestEntityCompanionProvider } from '../testing/createUnitTestEntityCompanionProvider';
|
|
17
|
+
|
|
18
|
+
describe(canViewerUpdateAsync, () => {
|
|
19
|
+
it('appropriately executes update privacy policy', async () => {
|
|
20
|
+
const companionProvider = createUnitTestEntityCompanionProvider();
|
|
21
|
+
const viewerContext = new ViewerContext(companionProvider);
|
|
22
|
+
const testEntity = await SimpleTestDenyDeleteEntity.creator(viewerContext).enforceCreateAsync();
|
|
23
|
+
const canViewerUpdate = await canViewerUpdateAsync(SimpleTestDenyDeleteEntity, testEntity);
|
|
24
|
+
expect(canViewerUpdate).toBe(true);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('denies when policy denies', async () => {
|
|
28
|
+
const companionProvider = createUnitTestEntityCompanionProvider();
|
|
29
|
+
const viewerContext = new ViewerContext(companionProvider);
|
|
30
|
+
const testEntity = await SimpleTestDenyUpdateEntity.creator(viewerContext).enforceCreateAsync();
|
|
31
|
+
const canViewerUpdate = await canViewerUpdateAsync(SimpleTestDenyUpdateEntity, testEntity);
|
|
32
|
+
expect(canViewerUpdate).toBe(false);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('rethrows non-authorization errors', async () => {
|
|
36
|
+
const companionProvider = createUnitTestEntityCompanionProvider();
|
|
37
|
+
const viewerContext = new ViewerContext(companionProvider);
|
|
38
|
+
const testEntity =
|
|
39
|
+
await SimpleTestThrowOtherErrorEntity.creator(viewerContext).enforceCreateAsync();
|
|
40
|
+
await expect(canViewerUpdateAsync(SimpleTestThrowOtherErrorEntity, testEntity)).rejects.toThrow(
|
|
41
|
+
'update error',
|
|
42
|
+
);
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
describe(canViewerDeleteAsync, () => {
|
|
47
|
+
it('appropriately executes update privacy policy', async () => {
|
|
48
|
+
const companionProvider = createUnitTestEntityCompanionProvider();
|
|
49
|
+
const viewerContext = new ViewerContext(companionProvider);
|
|
50
|
+
const testEntity = await SimpleTestDenyUpdateEntity.creator(viewerContext).enforceCreateAsync();
|
|
51
|
+
const canViewerDelete = await canViewerDeleteAsync(SimpleTestDenyUpdateEntity, testEntity);
|
|
52
|
+
expect(canViewerDelete).toBe(true);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('denies when policy denies', async () => {
|
|
56
|
+
const companionProvider = createUnitTestEntityCompanionProvider();
|
|
57
|
+
const viewerContext = new ViewerContext(companionProvider);
|
|
58
|
+
const testEntity = await SimpleTestDenyDeleteEntity.creator(viewerContext).enforceCreateAsync();
|
|
59
|
+
const canViewerDelete = await canViewerDeleteAsync(SimpleTestDenyDeleteEntity, testEntity);
|
|
60
|
+
expect(canViewerDelete).toBe(false);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('denies when recursive policy denies for CASCADE_DELETE', async () => {
|
|
64
|
+
const companionProvider = createUnitTestEntityCompanionProvider();
|
|
65
|
+
const viewerContext = new ViewerContext(companionProvider);
|
|
66
|
+
const testEntity = await SimpleTestDenyUpdateEntity.creator(viewerContext).enforceCreateAsync();
|
|
67
|
+
// add another entity referencing testEntity that would cascade deletion to itself when testEntity is deleted
|
|
68
|
+
await LeafDenyDeleteEntity.creator(viewerContext)
|
|
69
|
+
.setField('simple_test_deny_update_cascade_delete_id', testEntity.getID())
|
|
70
|
+
.enforceCreateAsync();
|
|
71
|
+
const canViewerDelete = await canViewerDeleteAsync(SimpleTestDenyUpdateEntity, testEntity);
|
|
72
|
+
expect(canViewerDelete).toBe(false);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('denies when recursive policy denies for SET_NULL', async () => {
|
|
76
|
+
const companionProvider = createUnitTestEntityCompanionProvider();
|
|
77
|
+
const viewerContext = new ViewerContext(companionProvider);
|
|
78
|
+
const testEntity = await SimpleTestDenyUpdateEntity.creator(viewerContext).enforceCreateAsync();
|
|
79
|
+
// add another entity referencing testEntity that would set null to its column when testEntity is deleted
|
|
80
|
+
await LeafDenyUpdateEntity.creator(viewerContext)
|
|
81
|
+
.setField('simple_test_deny_update_set_null_id', testEntity.getID())
|
|
82
|
+
.enforceCreateAsync();
|
|
83
|
+
const canViewerDelete = await canViewerDeleteAsync(SimpleTestDenyUpdateEntity, testEntity);
|
|
84
|
+
expect(canViewerDelete).toBe(false);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('allows when recursive policy allows for CASCADE_DELETE and SET_NULL', async () => {
|
|
88
|
+
const companionProvider = createUnitTestEntityCompanionProvider();
|
|
89
|
+
const viewerContext = new ViewerContext(companionProvider);
|
|
90
|
+
const testEntity = await SimpleTestDenyUpdateEntity.creator(viewerContext).enforceCreateAsync();
|
|
91
|
+
// add another entity referencing testEntity that would cascade deletion to itself when testEntity is deleted
|
|
92
|
+
await LeafDenyUpdateEntity.creator(viewerContext)
|
|
93
|
+
.setField('simple_test_deny_update_cascade_delete_id', testEntity.getID())
|
|
94
|
+
.enforceCreateAsync();
|
|
95
|
+
// add another entity referencing testEntity that would set null to its column when testEntity is deleted
|
|
96
|
+
await LeafDenyDeleteEntity.creator(viewerContext)
|
|
97
|
+
.setField('simple_test_deny_update_set_null_id', testEntity.getID())
|
|
98
|
+
.enforceCreateAsync();
|
|
99
|
+
|
|
100
|
+
const canViewerDelete = await canViewerDeleteAsync(SimpleTestDenyUpdateEntity, testEntity);
|
|
101
|
+
expect(canViewerDelete).toBe(true);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it('rethrows non-authorization errors', async () => {
|
|
105
|
+
const companionProvider = createUnitTestEntityCompanionProvider();
|
|
106
|
+
const viewerContext = new ViewerContext(companionProvider);
|
|
107
|
+
const testEntity =
|
|
108
|
+
await SimpleTestThrowOtherErrorEntity.creator(viewerContext).enforceCreateAsync();
|
|
109
|
+
await expect(
|
|
110
|
+
canViewerDeleteAsync(SimpleTestThrowOtherErrorEntity, testEntity),
|
|
111
|
+
).rejects.toThrowError('delete error');
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('returns false when edge cannot be read', async () => {
|
|
115
|
+
const companionProvider = createUnitTestEntityCompanionProvider();
|
|
116
|
+
const viewerContext = new ViewerContext(companionProvider);
|
|
117
|
+
const testEntity = await SimpleTestDenyUpdateEntity.creator(viewerContext).enforceCreateAsync();
|
|
118
|
+
await LeafDenyReadEntity.creator(viewerContext)
|
|
119
|
+
.setField('simple_test_id', testEntity.getID())
|
|
120
|
+
.enforceCreateAsync();
|
|
121
|
+
const canViewerDelete = await canViewerDeleteAsync(SimpleTestDenyUpdateEntity, testEntity);
|
|
122
|
+
expect(canViewerDelete).toBe(false);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('rethrows non-authorization edge read errors', async () => {
|
|
126
|
+
const companionProvider = createUnitTestEntityCompanionProvider();
|
|
127
|
+
const viewerContext = new ViewerContext(companionProvider);
|
|
128
|
+
const testEntity = await SimpleTestDenyUpdateEntity.creator(viewerContext).enforceCreateAsync();
|
|
129
|
+
await SimpleTestThrowOtherErrorEntity.creator(viewerContext)
|
|
130
|
+
.setField('simple_test_id', testEntity.getID())
|
|
131
|
+
.enforceCreateAsync();
|
|
132
|
+
await expect(canViewerDeleteAsync(SimpleTestDenyUpdateEntity, testEntity)).rejects.toThrowError(
|
|
133
|
+
'read in cascading delete error',
|
|
134
|
+
);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it('supports running within a transaction', async () => {
|
|
138
|
+
const companionProvider = createUnitTestEntityCompanionProvider();
|
|
139
|
+
const viewerContext = new ViewerContext(companionProvider);
|
|
140
|
+
const canViewerDelete = await viewerContext.runInTransactionForDatabaseAdaptorFlavorAsync(
|
|
141
|
+
'postgres',
|
|
142
|
+
async (queryContext) => {
|
|
143
|
+
const testEntity = await SimpleTestDenyUpdateEntity.creator(
|
|
144
|
+
viewerContext,
|
|
145
|
+
queryContext,
|
|
146
|
+
).enforceCreateAsync();
|
|
147
|
+
await LeafDenyReadEntity.creator(viewerContext, queryContext)
|
|
148
|
+
.setField('simple_test_id', testEntity.getID())
|
|
149
|
+
.enforceCreateAsync();
|
|
150
|
+
// this would fail if transactions weren't supported or correctly passed through
|
|
151
|
+
return await canViewerDeleteAsync(SimpleTestDenyUpdateEntity, testEntity, queryContext);
|
|
152
|
+
},
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
expect(canViewerDelete).toBe(true);
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
type TestEntityFields = {
|
|
160
|
+
id: string;
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
type TestLeafDenyDeleteFields = {
|
|
164
|
+
id: string;
|
|
165
|
+
simple_test_deny_update_cascade_delete_id: string | null;
|
|
166
|
+
simple_test_deny_update_set_null_id: string | null;
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
type TestLeafDenyUpdateFields = {
|
|
170
|
+
id: string;
|
|
171
|
+
unused_other_association: string | null;
|
|
172
|
+
simple_test_deny_update_set_null_id: string | null;
|
|
173
|
+
simple_test_deny_update_cascade_delete_id: string | null;
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
type TestLeafDenyReadFields = {
|
|
177
|
+
id: string;
|
|
178
|
+
simple_test_id: string | null;
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
type TestEntityThrowOtherErrorFields = {
|
|
182
|
+
id: string;
|
|
183
|
+
simple_test_id: string | null;
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
class DenyUpdateEntityPrivacyPolicy<
|
|
187
|
+
TFields extends object,
|
|
188
|
+
TID extends NonNullable<TFields[TSelectedFields]>,
|
|
189
|
+
TViewerContext extends ViewerContext,
|
|
190
|
+
TEntity extends ReadonlyEntity<TFields, TID, TViewerContext, TSelectedFields>,
|
|
191
|
+
TSelectedFields extends keyof TFields = keyof TFields,
|
|
192
|
+
> extends EntityPrivacyPolicy<TFields, TID, TViewerContext, TEntity, TSelectedFields> {
|
|
193
|
+
protected override readonly readRules = [
|
|
194
|
+
new AlwaysAllowPrivacyPolicyRule<TFields, TID, TViewerContext, TEntity, TSelectedFields>(),
|
|
195
|
+
];
|
|
196
|
+
protected override readonly createRules = [
|
|
197
|
+
new AlwaysAllowPrivacyPolicyRule<TFields, TID, TViewerContext, TEntity, TSelectedFields>(),
|
|
198
|
+
];
|
|
199
|
+
protected override readonly updateRules = [
|
|
200
|
+
new AlwaysDenyPrivacyPolicyRule<TFields, TID, TViewerContext, TEntity, TSelectedFields>(),
|
|
201
|
+
];
|
|
202
|
+
protected override readonly deleteRules = [
|
|
203
|
+
new AlwaysAllowPrivacyPolicyRule<TFields, TID, TViewerContext, TEntity, TSelectedFields>(),
|
|
204
|
+
];
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
class DenyDeleteEntityPrivacyPolicy<
|
|
208
|
+
TFields extends object,
|
|
209
|
+
TID extends NonNullable<TFields[TSelectedFields]>,
|
|
210
|
+
TViewerContext extends ViewerContext,
|
|
211
|
+
TEntity extends ReadonlyEntity<TFields, TID, TViewerContext, TSelectedFields>,
|
|
212
|
+
TSelectedFields extends keyof TFields = keyof TFields,
|
|
213
|
+
> extends EntityPrivacyPolicy<TFields, TID, TViewerContext, TEntity, TSelectedFields> {
|
|
214
|
+
protected override readonly readRules = [
|
|
215
|
+
new AlwaysAllowPrivacyPolicyRule<TFields, TID, TViewerContext, TEntity, TSelectedFields>(),
|
|
216
|
+
];
|
|
217
|
+
protected override readonly createRules = [
|
|
218
|
+
new AlwaysAllowPrivacyPolicyRule<TFields, TID, TViewerContext, TEntity, TSelectedFields>(),
|
|
219
|
+
];
|
|
220
|
+
protected override readonly updateRules = [
|
|
221
|
+
new AlwaysAllowPrivacyPolicyRule<TFields, TID, TViewerContext, TEntity, TSelectedFields>(),
|
|
222
|
+
];
|
|
223
|
+
protected override readonly deleteRules = [
|
|
224
|
+
new AlwaysDenyPrivacyPolicyRule<TFields, TID, TViewerContext, TEntity, TSelectedFields>(),
|
|
225
|
+
];
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
class ThrowOtherErrorEntityPrivacyPolicy<
|
|
229
|
+
TFields extends object,
|
|
230
|
+
TID extends NonNullable<TFields[TSelectedFields]>,
|
|
231
|
+
TViewerContext extends ViewerContext,
|
|
232
|
+
TEntity extends ReadonlyEntity<TFields, TID, TViewerContext, TSelectedFields>,
|
|
233
|
+
TSelectedFields extends keyof TFields = keyof TFields,
|
|
234
|
+
> extends EntityPrivacyPolicy<TFields, TID, TViewerContext, TEntity, TSelectedFields> {
|
|
235
|
+
protected override readonly readRules = [
|
|
236
|
+
{
|
|
237
|
+
async evaluateAsync(
|
|
238
|
+
_viewerContext: TViewerContext,
|
|
239
|
+
_queryContext: EntityQueryContext,
|
|
240
|
+
evaluationContext: EntityPrivacyPolicyEvaluationContext<
|
|
241
|
+
TFields,
|
|
242
|
+
TID,
|
|
243
|
+
TViewerContext,
|
|
244
|
+
TEntity,
|
|
245
|
+
TSelectedFields
|
|
246
|
+
>,
|
|
247
|
+
_entity: TEntity,
|
|
248
|
+
): Promise<RuleEvaluationResult> {
|
|
249
|
+
if (evaluationContext.cascadingDeleteCause) {
|
|
250
|
+
throw new Error('read in cascading delete error');
|
|
251
|
+
}
|
|
252
|
+
return RuleEvaluationResult.SKIP;
|
|
253
|
+
},
|
|
254
|
+
},
|
|
255
|
+
new AlwaysAllowPrivacyPolicyRule<TFields, TID, TViewerContext, TEntity, TSelectedFields>(),
|
|
256
|
+
];
|
|
257
|
+
protected override readonly createRules = [
|
|
258
|
+
new AlwaysAllowPrivacyPolicyRule<TFields, TID, TViewerContext, TEntity, TSelectedFields>(),
|
|
259
|
+
];
|
|
260
|
+
protected override readonly updateRules = [
|
|
261
|
+
{
|
|
262
|
+
async evaluateAsync(): Promise<RuleEvaluationResult> {
|
|
263
|
+
throw new Error('update error');
|
|
264
|
+
},
|
|
265
|
+
},
|
|
266
|
+
];
|
|
267
|
+
protected override readonly deleteRules = [
|
|
268
|
+
{
|
|
269
|
+
async evaluateAsync(): Promise<RuleEvaluationResult> {
|
|
270
|
+
throw new Error('delete error');
|
|
271
|
+
},
|
|
272
|
+
},
|
|
273
|
+
];
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
class DenyReadEntityPrivacyPolicy<
|
|
277
|
+
TFields extends object,
|
|
278
|
+
TID extends NonNullable<TFields[TSelectedFields]>,
|
|
279
|
+
TViewerContext extends ViewerContext,
|
|
280
|
+
TEntity extends ReadonlyEntity<TFields, TID, TViewerContext, TSelectedFields>,
|
|
281
|
+
TSelectedFields extends keyof TFields = keyof TFields,
|
|
282
|
+
> extends EntityPrivacyPolicy<TFields, TID, TViewerContext, TEntity, TSelectedFields> {
|
|
283
|
+
protected override readonly readRules = [
|
|
284
|
+
{
|
|
285
|
+
async evaluateAsync(
|
|
286
|
+
_viewerContext: TViewerContext,
|
|
287
|
+
queryContext: EntityQueryContext,
|
|
288
|
+
evaluationContext: EntityPrivacyPolicyEvaluationContext<
|
|
289
|
+
TFields,
|
|
290
|
+
TID,
|
|
291
|
+
TViewerContext,
|
|
292
|
+
TEntity,
|
|
293
|
+
TSelectedFields
|
|
294
|
+
>,
|
|
295
|
+
_entity: TEntity,
|
|
296
|
+
): Promise<RuleEvaluationResult> {
|
|
297
|
+
if (queryContext.isInTransaction()) {
|
|
298
|
+
return RuleEvaluationResult.ALLOW;
|
|
299
|
+
}
|
|
300
|
+
return evaluationContext.cascadingDeleteCause
|
|
301
|
+
? RuleEvaluationResult.SKIP
|
|
302
|
+
: RuleEvaluationResult.ALLOW;
|
|
303
|
+
},
|
|
304
|
+
},
|
|
305
|
+
];
|
|
306
|
+
protected override readonly createRules = [
|
|
307
|
+
new AlwaysAllowPrivacyPolicyRule<TFields, TID, TViewerContext, TEntity, TSelectedFields>(),
|
|
308
|
+
];
|
|
309
|
+
protected override readonly updateRules = [
|
|
310
|
+
new AlwaysAllowPrivacyPolicyRule<TFields, TID, TViewerContext, TEntity, TSelectedFields>(),
|
|
311
|
+
];
|
|
312
|
+
protected override readonly deleteRules = [
|
|
313
|
+
new AlwaysAllowPrivacyPolicyRule<TFields, TID, TViewerContext, TEntity, TSelectedFields>(),
|
|
314
|
+
];
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
class LeafDenyUpdateEntity extends Entity<TestLeafDenyUpdateFields, string, ViewerContext> {
|
|
318
|
+
static defineCompanionDefinition(): EntityCompanionDefinition<
|
|
319
|
+
TestLeafDenyUpdateFields,
|
|
320
|
+
string,
|
|
321
|
+
ViewerContext,
|
|
322
|
+
LeafDenyUpdateEntity,
|
|
323
|
+
DenyUpdateEntityPrivacyPolicy<
|
|
324
|
+
TestLeafDenyUpdateFields,
|
|
325
|
+
string,
|
|
326
|
+
ViewerContext,
|
|
327
|
+
LeafDenyUpdateEntity
|
|
328
|
+
>
|
|
329
|
+
> {
|
|
330
|
+
return {
|
|
331
|
+
entityClass: LeafDenyUpdateEntity,
|
|
332
|
+
entityConfiguration: new EntityConfiguration<TestLeafDenyUpdateFields>({
|
|
333
|
+
idField: 'id',
|
|
334
|
+
tableName: 'leaf_1',
|
|
335
|
+
schema: {
|
|
336
|
+
id: new UUIDField({
|
|
337
|
+
columnName: 'custom_id',
|
|
338
|
+
}),
|
|
339
|
+
// to ensure edge traversal doesn't process other edges
|
|
340
|
+
unused_other_association: new UUIDField({
|
|
341
|
+
columnName: 'unused_other_association',
|
|
342
|
+
association: {
|
|
343
|
+
associatedEntityClass: LeafDenyDeleteEntity,
|
|
344
|
+
edgeDeletionBehavior: EntityEdgeDeletionBehavior.SET_NULL,
|
|
345
|
+
},
|
|
346
|
+
}),
|
|
347
|
+
// deletion behavior should fail since this entity can't be updated and a SET NULL does an update
|
|
348
|
+
simple_test_deny_update_set_null_id: new UUIDField({
|
|
349
|
+
columnName: 'simple_test_deny_update_set_null_id',
|
|
350
|
+
association: {
|
|
351
|
+
associatedEntityClass: SimpleTestDenyUpdateEntity,
|
|
352
|
+
edgeDeletionBehavior: EntityEdgeDeletionBehavior.SET_NULL,
|
|
353
|
+
},
|
|
354
|
+
}),
|
|
355
|
+
// deletion behavior should succeed since this entity can be deleted
|
|
356
|
+
simple_test_deny_update_cascade_delete_id: new UUIDField({
|
|
357
|
+
columnName: 'simple_test_deny_update_cascade_delete_id',
|
|
358
|
+
association: {
|
|
359
|
+
associatedEntityClass: SimpleTestDenyUpdateEntity,
|
|
360
|
+
edgeDeletionBehavior: EntityEdgeDeletionBehavior.CASCADE_DELETE,
|
|
361
|
+
},
|
|
362
|
+
}),
|
|
363
|
+
},
|
|
364
|
+
databaseAdapterFlavor: 'postgres',
|
|
365
|
+
cacheAdapterFlavor: 'redis',
|
|
366
|
+
}),
|
|
367
|
+
privacyPolicyClass: DenyUpdateEntityPrivacyPolicy,
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
class LeafDenyDeleteEntity extends Entity<TestLeafDenyDeleteFields, string, ViewerContext> {
|
|
373
|
+
static defineCompanionDefinition(): EntityCompanionDefinition<
|
|
374
|
+
TestLeafDenyDeleteFields,
|
|
375
|
+
string,
|
|
376
|
+
ViewerContext,
|
|
377
|
+
LeafDenyDeleteEntity,
|
|
378
|
+
DenyDeleteEntityPrivacyPolicy<
|
|
379
|
+
TestLeafDenyDeleteFields,
|
|
380
|
+
string,
|
|
381
|
+
ViewerContext,
|
|
382
|
+
LeafDenyDeleteEntity
|
|
383
|
+
>
|
|
384
|
+
> {
|
|
385
|
+
return {
|
|
386
|
+
entityClass: LeafDenyDeleteEntity,
|
|
387
|
+
entityConfiguration: new EntityConfiguration<TestLeafDenyDeleteFields>({
|
|
388
|
+
idField: 'id',
|
|
389
|
+
tableName: 'leaf_2',
|
|
390
|
+
schema: {
|
|
391
|
+
id: new UUIDField({
|
|
392
|
+
columnName: 'custom_id',
|
|
393
|
+
}),
|
|
394
|
+
// deletion behavior should fail since this entity can't be deleted
|
|
395
|
+
simple_test_deny_update_cascade_delete_id: new UUIDField({
|
|
396
|
+
columnName: 'simple_test_deny_update_cascade_delete_id',
|
|
397
|
+
association: {
|
|
398
|
+
associatedEntityClass: SimpleTestDenyUpdateEntity,
|
|
399
|
+
edgeDeletionBehavior: EntityEdgeDeletionBehavior.CASCADE_DELETE,
|
|
400
|
+
},
|
|
401
|
+
}),
|
|
402
|
+
// deletion behavior should succeed since this entity can be updated and a SET NULL does an update
|
|
403
|
+
simple_test_deny_update_set_null_id: new UUIDField({
|
|
404
|
+
columnName: 'simple_test_deny_update_set_null_id',
|
|
405
|
+
association: {
|
|
406
|
+
associatedEntityClass: SimpleTestDenyUpdateEntity,
|
|
407
|
+
edgeDeletionBehavior: EntityEdgeDeletionBehavior.SET_NULL,
|
|
408
|
+
},
|
|
409
|
+
}),
|
|
410
|
+
},
|
|
411
|
+
databaseAdapterFlavor: 'postgres',
|
|
412
|
+
cacheAdapterFlavor: 'redis',
|
|
413
|
+
}),
|
|
414
|
+
privacyPolicyClass: DenyDeleteEntityPrivacyPolicy,
|
|
415
|
+
};
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
class LeafDenyReadEntity extends Entity<TestLeafDenyReadFields, string, ViewerContext> {
|
|
420
|
+
static defineCompanionDefinition(): EntityCompanionDefinition<
|
|
421
|
+
TestLeafDenyReadFields,
|
|
422
|
+
string,
|
|
423
|
+
ViewerContext,
|
|
424
|
+
LeafDenyReadEntity,
|
|
425
|
+
DenyReadEntityPrivacyPolicy<TestLeafDenyReadFields, string, ViewerContext, LeafDenyReadEntity>
|
|
426
|
+
> {
|
|
427
|
+
return {
|
|
428
|
+
entityClass: LeafDenyReadEntity,
|
|
429
|
+
entityConfiguration: new EntityConfiguration<TestLeafDenyReadFields>({
|
|
430
|
+
idField: 'id',
|
|
431
|
+
tableName: 'leaf_4',
|
|
432
|
+
inboundEdges: [],
|
|
433
|
+
schema: {
|
|
434
|
+
id: new UUIDField({
|
|
435
|
+
columnName: 'custom_id',
|
|
436
|
+
}),
|
|
437
|
+
simple_test_id: new UUIDField({
|
|
438
|
+
columnName: 'simple_test_id',
|
|
439
|
+
association: {
|
|
440
|
+
associatedEntityClass: SimpleTestDenyUpdateEntity,
|
|
441
|
+
associatedEntityLookupByField: 'id',
|
|
442
|
+
edgeDeletionBehavior: EntityEdgeDeletionBehavior.SET_NULL,
|
|
443
|
+
},
|
|
444
|
+
}),
|
|
445
|
+
},
|
|
446
|
+
databaseAdapterFlavor: 'postgres',
|
|
447
|
+
cacheAdapterFlavor: 'redis',
|
|
448
|
+
}),
|
|
449
|
+
privacyPolicyClass: DenyReadEntityPrivacyPolicy,
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
class SimpleTestDenyUpdateEntity extends Entity<TestEntityFields, string, ViewerContext> {
|
|
455
|
+
static defineCompanionDefinition(): EntityCompanionDefinition<
|
|
456
|
+
TestEntityFields,
|
|
457
|
+
string,
|
|
458
|
+
ViewerContext,
|
|
459
|
+
SimpleTestDenyUpdateEntity,
|
|
460
|
+
DenyUpdateEntityPrivacyPolicy<
|
|
461
|
+
TestEntityFields,
|
|
462
|
+
string,
|
|
463
|
+
ViewerContext,
|
|
464
|
+
SimpleTestDenyUpdateEntity
|
|
465
|
+
>
|
|
466
|
+
> {
|
|
467
|
+
return {
|
|
468
|
+
entityClass: SimpleTestDenyUpdateEntity,
|
|
469
|
+
entityConfiguration: new EntityConfiguration<TestEntityFields>({
|
|
470
|
+
idField: 'id',
|
|
471
|
+
tableName: 'blah',
|
|
472
|
+
inboundEdges: [
|
|
473
|
+
LeafDenyUpdateEntity,
|
|
474
|
+
LeafDenyDeleteEntity,
|
|
475
|
+
LeafDenyReadEntity,
|
|
476
|
+
SimpleTestThrowOtherErrorEntity,
|
|
477
|
+
],
|
|
478
|
+
schema: {
|
|
479
|
+
id: new UUIDField({
|
|
480
|
+
columnName: 'custom_id',
|
|
481
|
+
}),
|
|
482
|
+
},
|
|
483
|
+
databaseAdapterFlavor: 'postgres',
|
|
484
|
+
cacheAdapterFlavor: 'redis',
|
|
485
|
+
}),
|
|
486
|
+
privacyPolicyClass: DenyUpdateEntityPrivacyPolicy,
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
class SimpleTestDenyDeleteEntity extends Entity<TestEntityFields, string, ViewerContext> {
|
|
492
|
+
static defineCompanionDefinition(): EntityCompanionDefinition<
|
|
493
|
+
TestEntityFields,
|
|
494
|
+
string,
|
|
495
|
+
ViewerContext,
|
|
496
|
+
SimpleTestDenyDeleteEntity,
|
|
497
|
+
DenyDeleteEntityPrivacyPolicy<
|
|
498
|
+
TestEntityFields,
|
|
499
|
+
string,
|
|
500
|
+
ViewerContext,
|
|
501
|
+
SimpleTestDenyDeleteEntity
|
|
502
|
+
>
|
|
503
|
+
> {
|
|
504
|
+
return {
|
|
505
|
+
entityClass: SimpleTestDenyDeleteEntity,
|
|
506
|
+
entityConfiguration: new EntityConfiguration<TestEntityFields>({
|
|
507
|
+
idField: 'id',
|
|
508
|
+
tableName: 'blah_2',
|
|
509
|
+
inboundEdges: [
|
|
510
|
+
LeafDenyUpdateEntity,
|
|
511
|
+
LeafDenyDeleteEntity,
|
|
512
|
+
LeafDenyReadEntity,
|
|
513
|
+
SimpleTestThrowOtherErrorEntity,
|
|
514
|
+
],
|
|
515
|
+
schema: {
|
|
516
|
+
id: new UUIDField({
|
|
517
|
+
columnName: 'custom_id',
|
|
518
|
+
}),
|
|
519
|
+
},
|
|
520
|
+
databaseAdapterFlavor: 'postgres',
|
|
521
|
+
cacheAdapterFlavor: 'redis',
|
|
522
|
+
}),
|
|
523
|
+
privacyPolicyClass: DenyDeleteEntityPrivacyPolicy,
|
|
524
|
+
};
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
class SimpleTestThrowOtherErrorEntity extends Entity<
|
|
529
|
+
TestEntityThrowOtherErrorFields,
|
|
530
|
+
string,
|
|
531
|
+
ViewerContext
|
|
532
|
+
> {
|
|
533
|
+
static defineCompanionDefinition(): EntityCompanionDefinition<
|
|
534
|
+
TestEntityThrowOtherErrorFields,
|
|
535
|
+
string,
|
|
536
|
+
ViewerContext,
|
|
537
|
+
SimpleTestThrowOtherErrorEntity,
|
|
538
|
+
ThrowOtherErrorEntityPrivacyPolicy<
|
|
539
|
+
TestEntityThrowOtherErrorFields,
|
|
540
|
+
string,
|
|
541
|
+
ViewerContext,
|
|
542
|
+
SimpleTestThrowOtherErrorEntity
|
|
543
|
+
>
|
|
544
|
+
> {
|
|
545
|
+
return {
|
|
546
|
+
entityClass: SimpleTestThrowOtherErrorEntity,
|
|
547
|
+
entityConfiguration: new EntityConfiguration<TestEntityThrowOtherErrorFields>({
|
|
548
|
+
idField: 'id',
|
|
549
|
+
tableName: 'blah_3',
|
|
550
|
+
inboundEdges: [],
|
|
551
|
+
schema: {
|
|
552
|
+
id: new UUIDField({
|
|
553
|
+
columnName: 'custom_id',
|
|
554
|
+
}),
|
|
555
|
+
simple_test_id: new UUIDField({
|
|
556
|
+
columnName: 'simple_test_id',
|
|
557
|
+
association: {
|
|
558
|
+
associatedEntityClass: SimpleTestDenyUpdateEntity,
|
|
559
|
+
associatedEntityLookupByField: 'id',
|
|
560
|
+
edgeDeletionBehavior: EntityEdgeDeletionBehavior.SET_NULL,
|
|
561
|
+
},
|
|
562
|
+
}),
|
|
563
|
+
},
|
|
564
|
+
databaseAdapterFlavor: 'postgres',
|
|
565
|
+
cacheAdapterFlavor: 'redis',
|
|
566
|
+
}),
|
|
567
|
+
privacyPolicyClass: ThrowOtherErrorEntityPrivacyPolicy,
|
|
568
|
+
};
|
|
569
|
+
}
|
|
570
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { TestMutationTrigger } from '../../testfixtures/TestEntityWithMutationTriggers';
|
|
2
|
+
import { mergeEntityMutationTriggerConfigurations } from '../mergeEntityMutationTriggerConfigurations';
|
|
3
|
+
|
|
4
|
+
describe(mergeEntityMutationTriggerConfigurations, () => {
|
|
5
|
+
it('successfully merges triggers', async () => {
|
|
6
|
+
const firstAfter = new TestMutationTrigger('2');
|
|
7
|
+
const secondAfter = new TestMutationTrigger('3');
|
|
8
|
+
|
|
9
|
+
const merged = mergeEntityMutationTriggerConfigurations(
|
|
10
|
+
{
|
|
11
|
+
beforeAll: [new TestMutationTrigger('1')],
|
|
12
|
+
afterAll: [firstAfter],
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
afterAll: [secondAfter],
|
|
16
|
+
},
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
expect(merged.beforeAll?.length).toBe(1);
|
|
20
|
+
expect(merged.afterAll).toEqual([firstAfter, secondAfter]);
|
|
21
|
+
expect(merged.beforeCreate?.length).toBeFalsy();
|
|
22
|
+
expect(merged.afterCreate?.length).toBeFalsy();
|
|
23
|
+
expect(merged.beforeUpdate?.length).toBeFalsy();
|
|
24
|
+
expect(merged.afterUpdate?.length).toBeFalsy();
|
|
25
|
+
expect(merged.beforeDelete?.length).toBeFalsy();
|
|
26
|
+
expect(merged.afterDelete?.length).toBeFalsy();
|
|
27
|
+
expect(merged.afterCommit?.length).toBeFalsy();
|
|
28
|
+
});
|
|
29
|
+
});
|
|
@@ -70,7 +70,7 @@ describe(zipToMap, () => {
|
|
|
70
70
|
const keys = [1, 2];
|
|
71
71
|
const values = [1];
|
|
72
72
|
expect(() => zipToMap(keys, values)).toThrowError(
|
|
73
|
-
'zipToMap input length mismatch: keys[2], values[1]'
|
|
73
|
+
'zipToMap input length mismatch: keys[2], values[1]',
|
|
74
74
|
);
|
|
75
75
|
});
|
|
76
76
|
});
|
|
@@ -115,7 +115,7 @@ describe(reduceMapAsync, () => {
|
|
|
115
115
|
const reduction = await reduceMapAsync(
|
|
116
116
|
map,
|
|
117
117
|
async (acc, v, k) => acc.concat(v).concat(k),
|
|
118
|
-
'initial-'
|
|
118
|
+
'initial-',
|
|
119
119
|
);
|
|
120
120
|
expect(reduction).toEqual('initial-aabb');
|
|
121
121
|
});
|