@expo/entity 0.35.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 +0 -27
- package/build/Entity.js +0 -50
- package/build/Entity.js.map +1 -1
- package/build/EntityAssociationLoader.d.ts +1 -1
- package/build/EntityAssociationLoader.js +17 -8
- 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/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.js +5 -1
- package/build/ReadonlyEntity.js.map +1 -1
- package/build/ViewerContext.js +2 -0
- 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 +0 -132
- package/build/__tests__/Entity-test.js.map +1 -1
- package/build/__tests__/EntityAssociationLoader-test.js +6 -2
- package/build/__tests__/EntityAssociationLoader-test.js.map +1 -1
- package/build/__tests__/EntityCommonUseCases-test.js +24 -22
- 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 +61 -20
- 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 +16 -17
- package/build/__tests__/EntityLoader-constructor-test.js.map +1 -1
- package/build/__tests__/EntityLoader-test.js +74 -22
- package/build/__tests__/EntityLoader-test.js.map +1 -1
- package/build/__tests__/EntityMutator-MutationCacheConsistency-test.js +12 -15
- package/build/__tests__/EntityMutator-MutationCacheConsistency-test.js.map +1 -1
- package/build/__tests__/EntityMutator-test.js +54 -9
- 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__/EntitySelfReferentialEdges-test.js +42 -25
- package/build/__tests__/EntitySelfReferentialEdges-test.js.map +1 -1
- package/build/__tests__/ViewerScopedEntityLoaderFactory-test.js.map +1 -1
- package/build/__tests__/cases/TwoEntitySameTableDisjointRows-test.js +20 -18
- package/build/__tests__/cases/TwoEntitySameTableDisjointRows-test.js.map +1 -1
- package/build/__tests__/cases/TwoEntitySameTableOverlappingRows-test.js +12 -15
- 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 +6 -1
- 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__/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.js +12 -15
- package/build/testfixtures/SimpleTestEntity.js.map +1 -1
- package/build/testfixtures/TestEntity.js +12 -15
- package/build/testfixtures/TestEntity.js.map +1 -1
- 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/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 +11 -126
- package/src/EntityAssociationLoader.ts +40 -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 +5 -5
- 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 +5 -5
- package/src/ViewerContext.ts +5 -5
- 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 +0 -202
- package/src/__tests__/EntityAssociationLoader-test.ts +29 -25
- package/src/__tests__/EntityCommonUseCases-test.ts +29 -13
- 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 +108 -36
- package/src/__tests__/EntityFields-test.ts +14 -2
- package/src/__tests__/EntityLoader-constructor-test.ts +20 -7
- package/src/__tests__/EntityLoader-test.ts +214 -86
- package/src/__tests__/EntityMutator-MutationCacheConsistency-test.ts +2 -2
- package/src/__tests__/EntityMutator-test.ts +281 -96
- package/src/__tests__/EntityPrivacyPolicy-test.ts +166 -53
- package/src/__tests__/EntityQueryContext-test.ts +30 -12
- package/src/__tests__/EntitySecondaryCacheLoader-test.ts +7 -7
- package/src/__tests__/EntitySelfReferentialEdges-test.ts +46 -26
- package/src/__tests__/GenericEntityCacheAdapter-test.ts +2 -2
- package/src/__tests__/ViewerContext-test.ts +1 -1
- 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 +19 -19
- 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 +24 -24
- 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 +51 -51
- 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/TestEntity.ts +1 -1
- package/src/testfixtures/TestEntityWithMutationTriggers.ts +156 -0
- 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
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
import Entity from '../Entity';
|
|
2
|
-
import { EntityCompanionDefinition } from '../EntityCompanionProvider';
|
|
3
|
-
import EntityConfiguration from '../EntityConfiguration';
|
|
4
|
-
import { UUIDField } from '../EntityFields';
|
|
5
2
|
import { CreateMutator, UpdateMutator } from '../EntityMutator';
|
|
6
|
-
import EntityPrivacyPolicy from '../EntityPrivacyPolicy';
|
|
7
3
|
import ViewerContext from '../ViewerContext';
|
|
8
|
-
import AlwaysAllowPrivacyPolicyRule from '../rules/AlwaysAllowPrivacyPolicyRule';
|
|
9
|
-
import AlwaysDenyPrivacyPolicyRule from '../rules/AlwaysDenyPrivacyPolicyRule';
|
|
10
4
|
import SimpleTestEntity from '../testfixtures/SimpleTestEntity';
|
|
11
5
|
import { createUnitTestEntityCompanionProvider } from '../utils/testing/createUnitTestEntityCompanionProvider';
|
|
12
6
|
|
|
@@ -35,200 +29,4 @@ describe(Entity, () => {
|
|
|
35
29
|
expect(SimpleTestEntity.updater(testEntity)).toBeInstanceOf(UpdateMutator);
|
|
36
30
|
});
|
|
37
31
|
});
|
|
38
|
-
|
|
39
|
-
describe('canViewerUpdateAsync', () => {
|
|
40
|
-
it('appropriately executes update privacy policy', async () => {
|
|
41
|
-
const companionProvider = createUnitTestEntityCompanionProvider();
|
|
42
|
-
const viewerContext = new ViewerContext(companionProvider);
|
|
43
|
-
const data = {
|
|
44
|
-
id: 'what',
|
|
45
|
-
};
|
|
46
|
-
const testEntity = new SimpleTestDenyDeleteEntity({
|
|
47
|
-
viewerContext,
|
|
48
|
-
id: 'what',
|
|
49
|
-
databaseFields: data,
|
|
50
|
-
selectedFields: data,
|
|
51
|
-
});
|
|
52
|
-
const canViewerUpdate = await SimpleTestDenyDeleteEntity.canViewerUpdateAsync(testEntity);
|
|
53
|
-
expect(canViewerUpdate).toBe(true);
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
it('denies when policy denies', async () => {
|
|
57
|
-
const companionProvider = createUnitTestEntityCompanionProvider();
|
|
58
|
-
const viewerContext = new ViewerContext(companionProvider);
|
|
59
|
-
const data = {
|
|
60
|
-
id: 'what',
|
|
61
|
-
};
|
|
62
|
-
const testEntity = new SimpleTestDenyUpdateEntity({
|
|
63
|
-
viewerContext,
|
|
64
|
-
id: 'what',
|
|
65
|
-
databaseFields: data,
|
|
66
|
-
selectedFields: data,
|
|
67
|
-
});
|
|
68
|
-
const canViewerUpdate = await SimpleTestDenyUpdateEntity.canViewerUpdateAsync(testEntity);
|
|
69
|
-
expect(canViewerUpdate).toBe(false);
|
|
70
|
-
});
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
describe('canViewerDeleteAsync', () => {
|
|
74
|
-
it('appropriately executes update privacy policy', async () => {
|
|
75
|
-
const companionProvider = createUnitTestEntityCompanionProvider();
|
|
76
|
-
const viewerContext = new ViewerContext(companionProvider);
|
|
77
|
-
const data = {
|
|
78
|
-
id: 'what',
|
|
79
|
-
};
|
|
80
|
-
const testEntity = new SimpleTestDenyUpdateEntity({
|
|
81
|
-
viewerContext,
|
|
82
|
-
id: 'what',
|
|
83
|
-
databaseFields: data,
|
|
84
|
-
selectedFields: data,
|
|
85
|
-
});
|
|
86
|
-
const canViewerDelete = await SimpleTestDenyUpdateEntity.canViewerDeleteAsync(testEntity);
|
|
87
|
-
expect(canViewerDelete).toBe(true);
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
it('denies when policy denies', async () => {
|
|
91
|
-
const companionProvider = createUnitTestEntityCompanionProvider();
|
|
92
|
-
const viewerContext = new ViewerContext(companionProvider);
|
|
93
|
-
const data = {
|
|
94
|
-
id: 'what',
|
|
95
|
-
};
|
|
96
|
-
const testEntity = new SimpleTestDenyDeleteEntity({
|
|
97
|
-
viewerContext,
|
|
98
|
-
id: 'what',
|
|
99
|
-
databaseFields: data,
|
|
100
|
-
selectedFields: data,
|
|
101
|
-
});
|
|
102
|
-
const canViewerDelete = await SimpleTestDenyDeleteEntity.canViewerDeleteAsync(testEntity);
|
|
103
|
-
expect(canViewerDelete).toBe(false);
|
|
104
|
-
});
|
|
105
|
-
});
|
|
106
32
|
});
|
|
107
|
-
|
|
108
|
-
type TestEntityFields = {
|
|
109
|
-
id: string;
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
const testEntityConfiguration = new EntityConfiguration<TestEntityFields>({
|
|
113
|
-
idField: 'id',
|
|
114
|
-
tableName: 'blah',
|
|
115
|
-
schema: {
|
|
116
|
-
id: new UUIDField({
|
|
117
|
-
columnName: 'custom_id',
|
|
118
|
-
}),
|
|
119
|
-
},
|
|
120
|
-
databaseAdapterFlavor: 'postgres',
|
|
121
|
-
cacheAdapterFlavor: 'redis',
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
class SimpleTestDenyUpdateEntityPrivacyPolicy extends EntityPrivacyPolicy<
|
|
125
|
-
TestEntityFields,
|
|
126
|
-
string,
|
|
127
|
-
ViewerContext,
|
|
128
|
-
SimpleTestDenyUpdateEntity
|
|
129
|
-
> {
|
|
130
|
-
protected override readonly readRules = [
|
|
131
|
-
new AlwaysAllowPrivacyPolicyRule<
|
|
132
|
-
TestEntityFields,
|
|
133
|
-
string,
|
|
134
|
-
ViewerContext,
|
|
135
|
-
SimpleTestDenyUpdateEntity
|
|
136
|
-
>(),
|
|
137
|
-
];
|
|
138
|
-
protected override readonly createRules = [
|
|
139
|
-
new AlwaysAllowPrivacyPolicyRule<
|
|
140
|
-
TestEntityFields,
|
|
141
|
-
string,
|
|
142
|
-
ViewerContext,
|
|
143
|
-
SimpleTestDenyUpdateEntity
|
|
144
|
-
>(),
|
|
145
|
-
];
|
|
146
|
-
protected override readonly updateRules = [
|
|
147
|
-
new AlwaysDenyPrivacyPolicyRule<
|
|
148
|
-
TestEntityFields,
|
|
149
|
-
string,
|
|
150
|
-
ViewerContext,
|
|
151
|
-
SimpleTestDenyUpdateEntity
|
|
152
|
-
>(),
|
|
153
|
-
];
|
|
154
|
-
protected override readonly deleteRules = [
|
|
155
|
-
new AlwaysAllowPrivacyPolicyRule<
|
|
156
|
-
TestEntityFields,
|
|
157
|
-
string,
|
|
158
|
-
ViewerContext,
|
|
159
|
-
SimpleTestDenyUpdateEntity
|
|
160
|
-
>(),
|
|
161
|
-
];
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
class SimpleTestDenyDeleteEntityPrivacyPolicy extends EntityPrivacyPolicy<
|
|
165
|
-
TestEntityFields,
|
|
166
|
-
string,
|
|
167
|
-
ViewerContext,
|
|
168
|
-
SimpleTestDenyDeleteEntity
|
|
169
|
-
> {
|
|
170
|
-
protected override readonly readRules = [
|
|
171
|
-
new AlwaysAllowPrivacyPolicyRule<
|
|
172
|
-
TestEntityFields,
|
|
173
|
-
string,
|
|
174
|
-
ViewerContext,
|
|
175
|
-
SimpleTestDenyDeleteEntity
|
|
176
|
-
>(),
|
|
177
|
-
];
|
|
178
|
-
protected override readonly createRules = [
|
|
179
|
-
new AlwaysAllowPrivacyPolicyRule<
|
|
180
|
-
TestEntityFields,
|
|
181
|
-
string,
|
|
182
|
-
ViewerContext,
|
|
183
|
-
SimpleTestDenyDeleteEntity
|
|
184
|
-
>(),
|
|
185
|
-
];
|
|
186
|
-
protected override readonly updateRules = [
|
|
187
|
-
new AlwaysAllowPrivacyPolicyRule<
|
|
188
|
-
TestEntityFields,
|
|
189
|
-
string,
|
|
190
|
-
ViewerContext,
|
|
191
|
-
SimpleTestDenyDeleteEntity
|
|
192
|
-
>(),
|
|
193
|
-
];
|
|
194
|
-
protected override readonly deleteRules = [
|
|
195
|
-
new AlwaysDenyPrivacyPolicyRule<
|
|
196
|
-
TestEntityFields,
|
|
197
|
-
string,
|
|
198
|
-
ViewerContext,
|
|
199
|
-
SimpleTestDenyDeleteEntity
|
|
200
|
-
>(),
|
|
201
|
-
];
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
class SimpleTestDenyUpdateEntity extends Entity<TestEntityFields, string, ViewerContext> {
|
|
205
|
-
static defineCompanionDefinition(): EntityCompanionDefinition<
|
|
206
|
-
TestEntityFields,
|
|
207
|
-
string,
|
|
208
|
-
ViewerContext,
|
|
209
|
-
SimpleTestDenyUpdateEntity,
|
|
210
|
-
SimpleTestDenyUpdateEntityPrivacyPolicy
|
|
211
|
-
> {
|
|
212
|
-
return {
|
|
213
|
-
entityClass: SimpleTestDenyUpdateEntity,
|
|
214
|
-
entityConfiguration: testEntityConfiguration,
|
|
215
|
-
privacyPolicyClass: SimpleTestDenyUpdateEntityPrivacyPolicy,
|
|
216
|
-
};
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
class SimpleTestDenyDeleteEntity extends Entity<TestEntityFields, string, ViewerContext> {
|
|
221
|
-
static defineCompanionDefinition(): EntityCompanionDefinition<
|
|
222
|
-
TestEntityFields,
|
|
223
|
-
string,
|
|
224
|
-
ViewerContext,
|
|
225
|
-
SimpleTestDenyDeleteEntity,
|
|
226
|
-
SimpleTestDenyDeleteEntityPrivacyPolicy
|
|
227
|
-
> {
|
|
228
|
-
return {
|
|
229
|
-
entityClass: SimpleTestDenyDeleteEntity,
|
|
230
|
-
entityConfiguration: testEntityConfiguration,
|
|
231
|
-
privacyPolicyClass: SimpleTestDenyDeleteEntityPrivacyPolicy,
|
|
232
|
-
};
|
|
233
|
-
}
|
|
234
|
-
}
|
|
@@ -14,20 +14,20 @@ describe(EntityAssociationLoader, () => {
|
|
|
14
14
|
const companionProvider = createUnitTestEntityCompanionProvider();
|
|
15
15
|
const viewerContext = new TestViewerContext(companionProvider);
|
|
16
16
|
const testOtherEntity = await enforceAsyncResult(
|
|
17
|
-
TestEntity.creator(viewerContext).createAsync()
|
|
17
|
+
TestEntity.creator(viewerContext).createAsync(),
|
|
18
18
|
);
|
|
19
19
|
const testEntity = await enforceAsyncResult(
|
|
20
20
|
TestEntity.creator(viewerContext)
|
|
21
21
|
.setField('stringField', testOtherEntity.getID())
|
|
22
|
-
.createAsync()
|
|
22
|
+
.createAsync(),
|
|
23
23
|
);
|
|
24
24
|
const loadedOther = await enforceAsyncResult(
|
|
25
|
-
testEntity.associationLoader().loadAssociatedEntityAsync('stringField', TestEntity)
|
|
25
|
+
testEntity.associationLoader().loadAssociatedEntityAsync('stringField', TestEntity),
|
|
26
26
|
);
|
|
27
27
|
expect(loadedOther.getID()).toEqual(testOtherEntity.getID());
|
|
28
28
|
|
|
29
29
|
const loadedOther2 = await enforceAsyncResult(
|
|
30
|
-
testEntity.associationLoader().loadAssociatedEntityAsync('nullableField', TestEntity)
|
|
30
|
+
testEntity.associationLoader().loadAssociatedEntityAsync('nullableField', TestEntity),
|
|
31
31
|
);
|
|
32
32
|
expect(loadedOther2).toBeNull();
|
|
33
33
|
});
|
|
@@ -39,13 +39,13 @@ describe(EntityAssociationLoader, () => {
|
|
|
39
39
|
const viewerContext = new TestViewerContext(companionProvider);
|
|
40
40
|
const testEntity = await enforceAsyncResult(TestEntity.creator(viewerContext).createAsync());
|
|
41
41
|
const testOtherEntity1 = await enforceAsyncResult(
|
|
42
|
-
TestEntity.creator(viewerContext).setField('stringField', testEntity.getID()).createAsync()
|
|
42
|
+
TestEntity.creator(viewerContext).setField('stringField', testEntity.getID()).createAsync(),
|
|
43
43
|
);
|
|
44
44
|
const testOtherEntity2 = await enforceAsyncResult(
|
|
45
|
-
TestEntity.creator(viewerContext).setField('stringField', testEntity.getID()).createAsync()
|
|
45
|
+
TestEntity.creator(viewerContext).setField('stringField', testEntity.getID()).createAsync(),
|
|
46
46
|
);
|
|
47
47
|
const loaded = await enforceResultsAsync(
|
|
48
|
-
testEntity.associationLoader().loadManyAssociatedEntitiesAsync(TestEntity, 'stringField')
|
|
48
|
+
testEntity.associationLoader().loadManyAssociatedEntitiesAsync(TestEntity, 'stringField'),
|
|
49
49
|
);
|
|
50
50
|
expect(loaded).toHaveLength(2);
|
|
51
51
|
expect(loaded.find((e) => e.getID() === testOtherEntity1.getID())).not.toBeUndefined();
|
|
@@ -58,12 +58,12 @@ describe(EntityAssociationLoader, () => {
|
|
|
58
58
|
const companionProvider = createUnitTestEntityCompanionProvider();
|
|
59
59
|
const viewerContext = new TestViewerContext(companionProvider);
|
|
60
60
|
const testOtherEntity = await enforceAsyncResult(
|
|
61
|
-
TestEntity.creator(viewerContext).createAsync()
|
|
61
|
+
TestEntity.creator(viewerContext).createAsync(),
|
|
62
62
|
);
|
|
63
63
|
const testEntity = await enforceAsyncResult(
|
|
64
64
|
TestEntity.creator(viewerContext)
|
|
65
65
|
.setField('stringField', testOtherEntity.getID())
|
|
66
|
-
.createAsync()
|
|
66
|
+
.createAsync(),
|
|
67
67
|
);
|
|
68
68
|
const loadedOtherResult = await testEntity
|
|
69
69
|
.associationLoader()
|
|
@@ -75,7 +75,7 @@ describe(EntityAssociationLoader, () => {
|
|
|
75
75
|
const companionProvider = createUnitTestEntityCompanionProvider();
|
|
76
76
|
const viewerContext = new TestViewerContext(companionProvider);
|
|
77
77
|
const testEntity = await enforceAsyncResult(
|
|
78
|
-
TestEntity.creator(viewerContext).setField('stringField', uuidv4()).createAsync()
|
|
78
|
+
TestEntity.creator(viewerContext).setField('stringField', uuidv4()).createAsync(),
|
|
79
79
|
);
|
|
80
80
|
const loadedOtherResult = await testEntity
|
|
81
81
|
.associationLoader()
|
|
@@ -87,7 +87,7 @@ describe(EntityAssociationLoader, () => {
|
|
|
87
87
|
const companionProvider = createUnitTestEntityCompanionProvider();
|
|
88
88
|
const viewerContext = new TestViewerContext(companionProvider);
|
|
89
89
|
const testEntity = await enforceAsyncResult(
|
|
90
|
-
TestEntity.creator(viewerContext).setField('stringField', 'blah').createAsync()
|
|
90
|
+
TestEntity.creator(viewerContext).setField('stringField', 'blah').createAsync(),
|
|
91
91
|
);
|
|
92
92
|
const loadedOtherResult = await testEntity
|
|
93
93
|
.associationLoader()
|
|
@@ -102,10 +102,10 @@ describe(EntityAssociationLoader, () => {
|
|
|
102
102
|
const viewerContext = new TestViewerContext(companionProvider);
|
|
103
103
|
const testEntity = await enforceAsyncResult(TestEntity.creator(viewerContext).createAsync());
|
|
104
104
|
const testOtherEntity1 = await enforceAsyncResult(
|
|
105
|
-
TestEntity.creator(viewerContext).setField('stringField', testEntity.getID()).createAsync()
|
|
105
|
+
TestEntity.creator(viewerContext).setField('stringField', testEntity.getID()).createAsync(),
|
|
106
106
|
);
|
|
107
107
|
const testOtherEntity2 = await enforceAsyncResult(
|
|
108
|
-
TestEntity.creator(viewerContext).setField('stringField', testEntity.getID()).createAsync()
|
|
108
|
+
TestEntity.creator(viewerContext).setField('stringField', testEntity.getID()).createAsync(),
|
|
109
109
|
);
|
|
110
110
|
const loaded = await enforceResultsAsync(
|
|
111
111
|
testEntity
|
|
@@ -113,8 +113,8 @@ describe(EntityAssociationLoader, () => {
|
|
|
113
113
|
.loadManyAssociatedEntitiesByFieldEqualingAsync(
|
|
114
114
|
'customIdField',
|
|
115
115
|
TestEntity,
|
|
116
|
-
'stringField'
|
|
117
|
-
)
|
|
116
|
+
'stringField',
|
|
117
|
+
),
|
|
118
118
|
);
|
|
119
119
|
expect(loaded).toHaveLength(2);
|
|
120
120
|
expect(loaded.find((e) => e.getID() === testOtherEntity1.getID())).not.toBeUndefined();
|
|
@@ -131,8 +131,8 @@ describe(EntityAssociationLoader, () => {
|
|
|
131
131
|
.loadManyAssociatedEntitiesByFieldEqualingAsync(
|
|
132
132
|
'nullableField',
|
|
133
133
|
TestEntity,
|
|
134
|
-
'stringField'
|
|
135
|
-
)
|
|
134
|
+
'stringField',
|
|
135
|
+
),
|
|
136
136
|
);
|
|
137
137
|
expect(loaded).toHaveLength(0);
|
|
138
138
|
});
|
|
@@ -144,15 +144,19 @@ describe(EntityAssociationLoader, () => {
|
|
|
144
144
|
const viewerContext = new TestViewerContext(companionProvider);
|
|
145
145
|
const testEntity4 = await enforceAsyncResult(TestEntity.creator(viewerContext).createAsync());
|
|
146
146
|
const testEntity3 = await enforceAsyncResult(
|
|
147
|
-
TestEntity2.creator(viewerContext)
|
|
147
|
+
TestEntity2.creator(viewerContext)
|
|
148
|
+
.setField('foreignKey', testEntity4.getID())
|
|
149
|
+
.createAsync(),
|
|
148
150
|
);
|
|
149
151
|
const testEntity2 = await enforceAsyncResult(
|
|
150
152
|
TestEntity.creator(viewerContext)
|
|
151
153
|
.setField('testIndexedField', testEntity3.getID())
|
|
152
|
-
.createAsync()
|
|
154
|
+
.createAsync(),
|
|
153
155
|
);
|
|
154
156
|
const testEntity = await enforceAsyncResult(
|
|
155
|
-
TestEntity2.creator(viewerContext)
|
|
157
|
+
TestEntity2.creator(viewerContext)
|
|
158
|
+
.setField('foreignKey', testEntity2.getID())
|
|
159
|
+
.createAsync(),
|
|
156
160
|
);
|
|
157
161
|
|
|
158
162
|
const loaded2Result = await testEntity.associationLoader().loadAssociatedEntityThroughAsync([
|
|
@@ -197,7 +201,7 @@ describe(EntityAssociationLoader, () => {
|
|
|
197
201
|
const viewerContext = new TestViewerContext(companionProvider);
|
|
198
202
|
|
|
199
203
|
const testEntity = await enforceAsyncResult(
|
|
200
|
-
TestEntity2.creator(viewerContext).setField('foreignKey', uuidv4()).createAsync()
|
|
204
|
+
TestEntity2.creator(viewerContext).setField('foreignKey', uuidv4()).createAsync(),
|
|
201
205
|
);
|
|
202
206
|
|
|
203
207
|
const loadResult = await testEntity.associationLoader().loadAssociatedEntityThroughAsync([
|
|
@@ -215,10 +219,10 @@ describe(EntityAssociationLoader, () => {
|
|
|
215
219
|
|
|
216
220
|
const fieldValue = uuidv4();
|
|
217
221
|
const testEntity2 = await enforceAsyncResult(
|
|
218
|
-
TestEntity.creator(viewerContext).setField('stringField', fieldValue).createAsync()
|
|
222
|
+
TestEntity.creator(viewerContext).setField('stringField', fieldValue).createAsync(),
|
|
219
223
|
);
|
|
220
224
|
const testEntity = await enforceAsyncResult(
|
|
221
|
-
TestEntity2.creator(viewerContext).setField('foreignKey', fieldValue).createAsync()
|
|
225
|
+
TestEntity2.creator(viewerContext).setField('foreignKey', fieldValue).createAsync(),
|
|
222
226
|
);
|
|
223
227
|
|
|
224
228
|
const loaded2Result = await testEntity.associationLoader().loadAssociatedEntityThroughAsync([
|
|
@@ -236,7 +240,7 @@ describe(EntityAssociationLoader, () => {
|
|
|
236
240
|
const viewerContext = new TestViewerContext(companionProvider);
|
|
237
241
|
|
|
238
242
|
const testEntity = await enforceAsyncResult(
|
|
239
|
-
TestEntity2.creator(viewerContext).setField('foreignKey', uuidv4()).createAsync()
|
|
243
|
+
TestEntity2.creator(viewerContext).setField('foreignKey', uuidv4()).createAsync(),
|
|
240
244
|
);
|
|
241
245
|
|
|
242
246
|
const loaded2Result = await testEntity.associationLoader().loadAssociatedEntityThroughAsync([
|
|
@@ -254,7 +258,7 @@ describe(EntityAssociationLoader, () => {
|
|
|
254
258
|
const viewerContext = new TestViewerContext(companionProvider);
|
|
255
259
|
|
|
256
260
|
const testEntity = await enforceAsyncResult(
|
|
257
|
-
TestEntity.creator(viewerContext).setField('nullableField', null).createAsync()
|
|
261
|
+
TestEntity.creator(viewerContext).setField('nullableField', null).createAsync(),
|
|
258
262
|
);
|
|
259
263
|
|
|
260
264
|
const loadedResult = await testEntity.associationLoader().loadAssociatedEntityThroughAsync([
|
|
@@ -16,7 +16,10 @@ import PrivacyPolicyRule, { RuleEvaluationResult } from '../rules/PrivacyPolicyR
|
|
|
16
16
|
import { createUnitTestEntityCompanionProvider } from '../utils/testing/createUnitTestEntityCompanionProvider';
|
|
17
17
|
|
|
18
18
|
class TestUserViewerContext extends ViewerContext {
|
|
19
|
-
constructor(
|
|
19
|
+
constructor(
|
|
20
|
+
entityCompanionProvider: EntityCompanionProvider,
|
|
21
|
+
private readonly userID: string,
|
|
22
|
+
) {
|
|
20
23
|
super(entityCompanionProvider);
|
|
21
24
|
}
|
|
22
25
|
|
|
@@ -69,8 +72,13 @@ class DenyIfNotOwnerPrivacyPolicyRule extends PrivacyPolicyRule<
|
|
|
69
72
|
async evaluateAsync(
|
|
70
73
|
viewerContext: TestUserViewerContext,
|
|
71
74
|
_queryContext: EntityQueryContext,
|
|
72
|
-
_evaluationContext: EntityPrivacyPolicyEvaluationContext
|
|
73
|
-
|
|
75
|
+
_evaluationContext: EntityPrivacyPolicyEvaluationContext<
|
|
76
|
+
BlahFields,
|
|
77
|
+
string,
|
|
78
|
+
TestUserViewerContext,
|
|
79
|
+
BlahEntity
|
|
80
|
+
>,
|
|
81
|
+
entity: BlahEntity,
|
|
74
82
|
): Promise<RuleEvaluationResult> {
|
|
75
83
|
if (viewerContext.getUserID() === entity.getField('ownerID')) {
|
|
76
84
|
return RuleEvaluationResult.SKIP;
|
|
@@ -110,15 +118,15 @@ it('runs through a common workflow', async () => {
|
|
|
110
118
|
const vc2 = new TestUserViewerContext(entityCompanionProvider, uuidv4());
|
|
111
119
|
|
|
112
120
|
const blahOwner1 = await enforceAsyncResult(
|
|
113
|
-
BlahEntity.creator(vc1).setField('ownerID', vc1.getUserID()!).createAsync()
|
|
121
|
+
BlahEntity.creator(vc1).setField('ownerID', vc1.getUserID()!).createAsync(),
|
|
114
122
|
);
|
|
115
123
|
|
|
116
124
|
await enforceAsyncResult(
|
|
117
|
-
BlahEntity.creator(vc1).setField('ownerID', vc1.getUserID()!).createAsync()
|
|
125
|
+
BlahEntity.creator(vc1).setField('ownerID', vc1.getUserID()!).createAsync(),
|
|
118
126
|
);
|
|
119
127
|
|
|
120
128
|
const blahOwner2 = await enforceAsyncResult(
|
|
121
|
-
BlahEntity.creator(vc2).setField('ownerID', vc2.getUserID()!).createAsync()
|
|
129
|
+
BlahEntity.creator(vc2).setField('ownerID', vc2.getUserID()!).createAsync(),
|
|
122
130
|
);
|
|
123
131
|
|
|
124
132
|
// sanity check created objects
|
|
@@ -127,33 +135,41 @@ it('runs through a common workflow', async () => {
|
|
|
127
135
|
|
|
128
136
|
// check that two people can't read each others data
|
|
129
137
|
await expect(
|
|
130
|
-
enforceAsyncResult(
|
|
138
|
+
enforceAsyncResult(
|
|
139
|
+
BlahEntity.loader(vc1).withAuthorizationResults().loadByIDAsync(blahOwner2.getID()),
|
|
140
|
+
),
|
|
131
141
|
).rejects.toBeInstanceOf(EntityNotAuthorizedError);
|
|
132
142
|
await expect(
|
|
133
|
-
enforceAsyncResult(
|
|
143
|
+
enforceAsyncResult(
|
|
144
|
+
BlahEntity.loader(vc2).withAuthorizationResults().loadByIDAsync(blahOwner1.getID()),
|
|
145
|
+
),
|
|
134
146
|
).rejects.toBeInstanceOf(EntityNotAuthorizedError);
|
|
135
147
|
|
|
136
148
|
// check that all of owner 1's objects can be loaded
|
|
137
149
|
const results = await enforceResultsAsync(
|
|
138
|
-
BlahEntity.loader(vc1)
|
|
150
|
+
BlahEntity.loader(vc1)
|
|
151
|
+
.withAuthorizationResults()
|
|
152
|
+
.loadManyByFieldEqualingAsync('ownerID', vc1.getUserID()!),
|
|
139
153
|
);
|
|
140
154
|
expect(results).toHaveLength(2);
|
|
141
155
|
|
|
142
156
|
// check that two people can't create objects owned by others
|
|
143
157
|
await expect(
|
|
144
158
|
enforceAsyncResult(
|
|
145
|
-
BlahEntity.creator(vc2).setField('ownerID', blahOwner1.getID()).createAsync()
|
|
146
|
-
)
|
|
159
|
+
BlahEntity.creator(vc2).setField('ownerID', blahOwner1.getID()).createAsync(),
|
|
160
|
+
),
|
|
147
161
|
).rejects.toBeInstanceOf(EntityNotAuthorizedError);
|
|
148
162
|
|
|
149
163
|
// check that empty load many returns nothing
|
|
150
|
-
const results2 = await BlahEntity.loader(vc1)
|
|
164
|
+
const results2 = await BlahEntity.loader(vc1)
|
|
165
|
+
.withAuthorizationResults()
|
|
166
|
+
.loadManyByFieldEqualingManyAsync('ownerID', []);
|
|
151
167
|
for (const value in results2.values) {
|
|
152
168
|
expect(value).toHaveLength(0);
|
|
153
169
|
}
|
|
154
170
|
|
|
155
171
|
// check that the user can't delete their own data (as specified by privacy rules)
|
|
156
172
|
await expect(enforceAsyncResult(BlahEntity.deleteAsync(blahOwner2))).rejects.toBeInstanceOf(
|
|
157
|
-
EntityNotAuthorizedError
|
|
173
|
+
EntityNotAuthorizedError,
|
|
158
174
|
);
|
|
159
175
|
});
|
|
@@ -3,25 +3,77 @@ import { instance, mock, when } from 'ts-mockito';
|
|
|
3
3
|
import EntityCompanion from '../EntityCompanion';
|
|
4
4
|
import EntityCompanionProvider from '../EntityCompanionProvider';
|
|
5
5
|
import EntityLoaderFactory from '../EntityLoaderFactory';
|
|
6
|
+
import EntityMutationTriggerConfiguration from '../EntityMutationTriggerConfiguration';
|
|
6
7
|
import EntityMutatorFactory from '../EntityMutatorFactory';
|
|
8
|
+
import ViewerContext from '../ViewerContext';
|
|
7
9
|
import EntityTableDataCoordinator from '../internal/EntityTableDataCoordinator';
|
|
8
10
|
import IEntityMetricsAdapter from '../metrics/IEntityMetricsAdapter';
|
|
9
|
-
import
|
|
11
|
+
import NoOpEntityMetricsAdapter from '../metrics/NoOpEntityMetricsAdapter';
|
|
12
|
+
import TestEntityWithMutationTriggers, {
|
|
13
|
+
TestMTFields,
|
|
14
|
+
testEntityMTConfiguration,
|
|
15
|
+
TestMutationTrigger,
|
|
16
|
+
} from '../testfixtures/TestEntityWithMutationTriggers';
|
|
10
17
|
|
|
11
18
|
describe(EntityCompanion, () => {
|
|
12
19
|
it('correctly instantiates mutator and loader factories', () => {
|
|
13
20
|
const entityCompanionProvider = instance(mock<EntityCompanionProvider>());
|
|
14
21
|
|
|
15
|
-
const tableDataCoordinatorMock = mock<EntityTableDataCoordinator<
|
|
16
|
-
when(tableDataCoordinatorMock.entityConfiguration).thenReturn(
|
|
22
|
+
const tableDataCoordinatorMock = mock<EntityTableDataCoordinator<TestMTFields>>();
|
|
23
|
+
when(tableDataCoordinatorMock.entityConfiguration).thenReturn(testEntityMTConfiguration);
|
|
17
24
|
|
|
18
25
|
const companion = new EntityCompanion(
|
|
19
26
|
entityCompanionProvider,
|
|
20
|
-
|
|
27
|
+
TestEntityWithMutationTriggers.defineCompanionDefinition(),
|
|
21
28
|
instance(tableDataCoordinatorMock),
|
|
22
|
-
instance(mock<IEntityMetricsAdapter>())
|
|
29
|
+
instance(mock<IEntityMetricsAdapter>()),
|
|
23
30
|
);
|
|
24
31
|
expect(companion.getLoaderFactory()).toBeInstanceOf(EntityLoaderFactory);
|
|
25
32
|
expect(companion.getMutatorFactory()).toBeInstanceOf(EntityMutatorFactory);
|
|
26
33
|
});
|
|
34
|
+
|
|
35
|
+
it('correctly merges local and global mutation triggers', () => {
|
|
36
|
+
const globalMutationTriggers: EntityMutationTriggerConfiguration<
|
|
37
|
+
TestMTFields,
|
|
38
|
+
string,
|
|
39
|
+
ViewerContext,
|
|
40
|
+
TestEntityWithMutationTriggers,
|
|
41
|
+
keyof TestMTFields
|
|
42
|
+
> = {
|
|
43
|
+
afterCreate: [new TestMutationTrigger('globalAfterCreate')],
|
|
44
|
+
afterAll: [new TestMutationTrigger('globalAfterAll')],
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const metricsAdapter = new NoOpEntityMetricsAdapter();
|
|
48
|
+
|
|
49
|
+
const entityCompanionProvider = new EntityCompanionProvider(
|
|
50
|
+
metricsAdapter,
|
|
51
|
+
new Map(),
|
|
52
|
+
new Map(),
|
|
53
|
+
globalMutationTriggers,
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
const tableDataCoordinatorMock = mock<EntityTableDataCoordinator<TestMTFields>>();
|
|
57
|
+
when(tableDataCoordinatorMock.entityConfiguration).thenReturn(testEntityMTConfiguration);
|
|
58
|
+
|
|
59
|
+
const companion = new EntityCompanion(
|
|
60
|
+
entityCompanionProvider,
|
|
61
|
+
TestEntityWithMutationTriggers.defineCompanionDefinition(),
|
|
62
|
+
instance(tableDataCoordinatorMock),
|
|
63
|
+
instance(mock<IEntityMetricsAdapter>()),
|
|
64
|
+
);
|
|
65
|
+
expect(companion.getLoaderFactory()).toBeInstanceOf(EntityLoaderFactory);
|
|
66
|
+
expect(companion.getMutatorFactory()).toBeInstanceOf(EntityMutatorFactory);
|
|
67
|
+
|
|
68
|
+
const mergedTriggers = companion.getMutatorFactory()['mutationTriggers'];
|
|
69
|
+
|
|
70
|
+
const localTriggers = companion.entityCompanionDefinition.mutationTriggers;
|
|
71
|
+
expect(localTriggers).toBeTruthy();
|
|
72
|
+
|
|
73
|
+
expect(mergedTriggers).toStrictEqual({
|
|
74
|
+
afterCreate: [localTriggers!.afterCreate![0], globalMutationTriggers.afterCreate![0]],
|
|
75
|
+
afterAll: [localTriggers!.afterAll![0], globalMutationTriggers!.afterAll![0]],
|
|
76
|
+
afterCommit: [localTriggers!.afterCommit![0]],
|
|
77
|
+
});
|
|
78
|
+
});
|
|
27
79
|
});
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import EntityConfiguration from '../EntityConfiguration';
|
|
2
|
+
import { UUIDField, StringField } from '../EntityFields';
|
|
3
|
+
|
|
4
|
+
describe(EntityConfiguration, () => {
|
|
5
|
+
describe('when valid', () => {
|
|
6
|
+
type BlahT = {
|
|
7
|
+
id: string;
|
|
8
|
+
cacheable: string;
|
|
9
|
+
uniqueButNotCacheable: string;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
type Blah2T = {
|
|
13
|
+
id: string;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const blahEntityConfiguration = new EntityConfiguration<BlahT>({
|
|
17
|
+
idField: 'id',
|
|
18
|
+
tableName: 'blah_table',
|
|
19
|
+
schema: {
|
|
20
|
+
id: new UUIDField({
|
|
21
|
+
columnName: 'id',
|
|
22
|
+
}),
|
|
23
|
+
cacheable: new StringField({
|
|
24
|
+
columnName: 'cacheable',
|
|
25
|
+
cache: true,
|
|
26
|
+
}),
|
|
27
|
+
uniqueButNotCacheable: new StringField({
|
|
28
|
+
columnName: 'unique_but_not_cacheable',
|
|
29
|
+
}),
|
|
30
|
+
},
|
|
31
|
+
databaseAdapterFlavor: 'postgres',
|
|
32
|
+
cacheAdapterFlavor: 'redis',
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('returns correct fields', () => {
|
|
36
|
+
expect(blahEntityConfiguration.idField).toEqual('id');
|
|
37
|
+
expect(blahEntityConfiguration.tableName).toEqual('blah_table');
|
|
38
|
+
expect(blahEntityConfiguration.databaseAdapterFlavor).toEqual('postgres');
|
|
39
|
+
expect(blahEntityConfiguration.cacheAdapterFlavor).toEqual('redis');
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('filters cacheable fields', () => {
|
|
43
|
+
expect(blahEntityConfiguration.cacheableKeys).toEqual(new Set(['cacheable']));
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
describe('cache key version', () => {
|
|
47
|
+
it('defaults to 0', () => {
|
|
48
|
+
const entityConfiguration = new EntityConfiguration<Blah2T>({
|
|
49
|
+
idField: 'id',
|
|
50
|
+
tableName: 'blah',
|
|
51
|
+
schema: {
|
|
52
|
+
id: new UUIDField({
|
|
53
|
+
columnName: 'id',
|
|
54
|
+
}),
|
|
55
|
+
},
|
|
56
|
+
databaseAdapterFlavor: 'postgres',
|
|
57
|
+
cacheAdapterFlavor: 'redis',
|
|
58
|
+
});
|
|
59
|
+
expect(entityConfiguration.cacheKeyVersion).toEqual(0);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('sets to custom version', () => {
|
|
63
|
+
const entityConfiguration = new EntityConfiguration<Blah2T>({
|
|
64
|
+
idField: 'id',
|
|
65
|
+
tableName: 'blah',
|
|
66
|
+
schema: {
|
|
67
|
+
id: new UUIDField({
|
|
68
|
+
columnName: 'id',
|
|
69
|
+
}),
|
|
70
|
+
},
|
|
71
|
+
databaseAdapterFlavor: 'postgres',
|
|
72
|
+
cacheAdapterFlavor: 'redis',
|
|
73
|
+
cacheKeyVersion: 100,
|
|
74
|
+
});
|
|
75
|
+
expect(entityConfiguration.cacheKeyVersion).toEqual(100);
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
describe('validation', () => {
|
|
81
|
+
describe('disallows keys of JS Object prototype for safety', () => {
|
|
82
|
+
test.each([
|
|
83
|
+
'constructor',
|
|
84
|
+
'__defineGetter__',
|
|
85
|
+
'__defineSetter__',
|
|
86
|
+
'hasOwnProperty',
|
|
87
|
+
'__lookupGetter__',
|
|
88
|
+
'__lookupSetter__',
|
|
89
|
+
'isPrototypeOf',
|
|
90
|
+
'propertyIsEnumerable',
|
|
91
|
+
'toString',
|
|
92
|
+
'valueOf',
|
|
93
|
+
'__proto__',
|
|
94
|
+
'toLocaleString',
|
|
95
|
+
])('disallows %p as field key', (keyName) => {
|
|
96
|
+
expect(
|
|
97
|
+
() =>
|
|
98
|
+
new EntityConfiguration<any>({
|
|
99
|
+
idField: 'id',
|
|
100
|
+
tableName: 'blah_table',
|
|
101
|
+
schema: {
|
|
102
|
+
id: new UUIDField({
|
|
103
|
+
columnName: 'id',
|
|
104
|
+
}),
|
|
105
|
+
[keyName]: new StringField({
|
|
106
|
+
columnName: 'any',
|
|
107
|
+
}),
|
|
108
|
+
},
|
|
109
|
+
databaseAdapterFlavor: 'postgres',
|
|
110
|
+
cacheAdapterFlavor: 'redis',
|
|
111
|
+
}),
|
|
112
|
+
).toThrow(
|
|
113
|
+
`Entity field name not allowed to prevent conflicts with standard Object prototype fields: ${keyName}`,
|
|
114
|
+
);
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
});
|