@flowerforce/flowerbase 1.8.3 → 1.8.4-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/features/triggers/utils.d.ts.map +1 -1
- package/dist/features/triggers/utils.js +28 -18
- package/dist/monitoring/utils.d.ts +1 -1
- package/dist/services/mongodb-atlas/index.js +11 -11
- package/dist/utils/context/helpers.d.ts +3 -3
- package/dist/utils/roles/helpers.d.ts +1 -0
- package/dist/utils/roles/helpers.d.ts.map +1 -1
- package/dist/utils/roles/helpers.js +77 -8
- package/dist/utils/roles/machines/utils.d.ts +2 -0
- package/dist/utils/roles/machines/utils.d.ts.map +1 -1
- package/dist/utils/roles/machines/utils.js +33 -1
- package/package.json +1 -1
- package/src/features/triggers/__tests__/utils.test.ts +112 -0
- package/src/features/triggers/utils.ts +30 -18
- package/src/services/mongodb-atlas/index.ts +150 -150
- package/src/utils/__tests__/evaluateExpression.test.ts +89 -0
- package/src/utils/__tests__/getWinningRole.test.ts +17 -0
- package/src/utils/roles/helpers.ts +107 -14
- package/src/utils/roles/machines/utils.ts +34 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from 'fs'
|
|
2
2
|
import path from 'node:path'
|
|
3
3
|
import cron from 'node-cron'
|
|
4
|
+
import { EJSON } from 'bson'
|
|
4
5
|
import { AUTH_CONFIG, AUTH_DB_NAME, DB_NAME, CHANGESTREAM } from '../../constants'
|
|
5
6
|
import { createEventId, sanitize } from '../../monitoring/utils'
|
|
6
7
|
import { StateManager } from '../../state'
|
|
@@ -8,6 +9,9 @@ import { readJsonContent } from '../../utils'
|
|
|
8
9
|
import { GenerateContext } from '../../utils/context'
|
|
9
10
|
import { HandlerParams, Trigger, Triggers } from './interface'
|
|
10
11
|
|
|
12
|
+
const normalizeTriggerPayload = <T>(value: T): T =>
|
|
13
|
+
EJSON.deserialize(EJSON.serialize(value, { relaxed: false })) as T
|
|
14
|
+
|
|
11
15
|
const registerOnClose = (
|
|
12
16
|
app: HandlerParams['app'],
|
|
13
17
|
handler: () => Promise<void> | void,
|
|
@@ -150,7 +154,8 @@ const handleCronTrigger = async ({
|
|
|
150
154
|
currentFunction: triggerHandler,
|
|
151
155
|
functionName,
|
|
152
156
|
functionsList,
|
|
153
|
-
services
|
|
157
|
+
services,
|
|
158
|
+
deserializeArgs: false
|
|
154
159
|
})
|
|
155
160
|
} catch (error) {
|
|
156
161
|
emitTriggerEvent({
|
|
@@ -376,7 +381,7 @@ const handleAuthenticationTrigger = async ({
|
|
|
376
381
|
meta: { ...baseMeta, event: 'LOGOUT' }
|
|
377
382
|
})
|
|
378
383
|
await GenerateContext({
|
|
379
|
-
args: [{ user: userData, ...op }],
|
|
384
|
+
args: [normalizeTriggerPayload({ user: userData, ...op })],
|
|
380
385
|
app,
|
|
381
386
|
rules: StateManager.select("rules"),
|
|
382
387
|
user: {}, // TODO from currentUser ??
|
|
@@ -384,7 +389,8 @@ const handleAuthenticationTrigger = async ({
|
|
|
384
389
|
functionName,
|
|
385
390
|
functionsList,
|
|
386
391
|
services,
|
|
387
|
-
runAsSystem: true
|
|
392
|
+
runAsSystem: true,
|
|
393
|
+
deserializeArgs: false
|
|
388
394
|
})
|
|
389
395
|
} catch (error) {
|
|
390
396
|
emitTriggerEvent({
|
|
@@ -395,7 +401,6 @@ const handleAuthenticationTrigger = async ({
|
|
|
395
401
|
meta: { ...baseMeta, event: 'LOGOUT' },
|
|
396
402
|
error
|
|
397
403
|
})
|
|
398
|
-
console.log("🚀 ~ handleAuthenticationTrigger ~ error:", error)
|
|
399
404
|
}
|
|
400
405
|
return
|
|
401
406
|
}
|
|
@@ -433,7 +438,7 @@ const handleAuthenticationTrigger = async ({
|
|
|
433
438
|
meta: { ...baseMeta, event: 'LOGIN' }
|
|
434
439
|
})
|
|
435
440
|
await GenerateContext({
|
|
436
|
-
args: [{ user: userData, ...op }],
|
|
441
|
+
args: [normalizeTriggerPayload({ user: userData, ...op })],
|
|
437
442
|
app,
|
|
438
443
|
rules: StateManager.select("rules"),
|
|
439
444
|
user: {}, // TODO from currentUser ??
|
|
@@ -441,7 +446,8 @@ const handleAuthenticationTrigger = async ({
|
|
|
441
446
|
functionName,
|
|
442
447
|
functionsList,
|
|
443
448
|
services,
|
|
444
|
-
runAsSystem: true
|
|
449
|
+
runAsSystem: true,
|
|
450
|
+
deserializeArgs: false
|
|
445
451
|
})
|
|
446
452
|
} catch (error) {
|
|
447
453
|
emitTriggerEvent({
|
|
@@ -452,7 +458,6 @@ const handleAuthenticationTrigger = async ({
|
|
|
452
458
|
meta: { ...baseMeta, event: 'LOGIN' },
|
|
453
459
|
error
|
|
454
460
|
})
|
|
455
|
-
console.log("🚀 ~ handleAuthenticationTrigger ~ error:", error)
|
|
456
461
|
}
|
|
457
462
|
return
|
|
458
463
|
}
|
|
@@ -485,7 +490,9 @@ const handleAuthenticationTrigger = async ({
|
|
|
485
490
|
meta: { ...baseMeta, event: 'DELETE' }
|
|
486
491
|
})
|
|
487
492
|
await GenerateContext({
|
|
488
|
-
args: isAutoTrigger
|
|
493
|
+
args: isAutoTrigger
|
|
494
|
+
? [normalizeTriggerPayload(userData)]
|
|
495
|
+
: [normalizeTriggerPayload({ user: userData, ...op })],
|
|
489
496
|
app,
|
|
490
497
|
rules: StateManager.select("rules"),
|
|
491
498
|
user: {}, // TODO from currentUser ??
|
|
@@ -493,7 +500,8 @@ const handleAuthenticationTrigger = async ({
|
|
|
493
500
|
functionName,
|
|
494
501
|
functionsList,
|
|
495
502
|
services,
|
|
496
|
-
runAsSystem: true
|
|
503
|
+
runAsSystem: true,
|
|
504
|
+
deserializeArgs: false
|
|
497
505
|
})
|
|
498
506
|
} catch (error) {
|
|
499
507
|
emitTriggerEvent({
|
|
@@ -504,7 +512,6 @@ const handleAuthenticationTrigger = async ({
|
|
|
504
512
|
meta: { ...baseMeta, event: 'DELETE' },
|
|
505
513
|
error
|
|
506
514
|
})
|
|
507
|
-
console.log("🚀 ~ handleAuthenticationTrigger ~ error:", error)
|
|
508
515
|
}
|
|
509
516
|
return
|
|
510
517
|
}
|
|
@@ -539,7 +546,9 @@ const handleAuthenticationTrigger = async ({
|
|
|
539
546
|
meta: { ...baseMeta, event: 'UPDATE' }
|
|
540
547
|
})
|
|
541
548
|
await GenerateContext({
|
|
542
|
-
args: isAutoTrigger
|
|
549
|
+
args: isAutoTrigger
|
|
550
|
+
? [normalizeTriggerPayload(userData)]
|
|
551
|
+
: [normalizeTriggerPayload({ user: userData, ...op })],
|
|
543
552
|
app,
|
|
544
553
|
rules: StateManager.select("rules"),
|
|
545
554
|
user: {}, // TODO from currentUser ??
|
|
@@ -547,7 +556,8 @@ const handleAuthenticationTrigger = async ({
|
|
|
547
556
|
functionName,
|
|
548
557
|
functionsList,
|
|
549
558
|
services,
|
|
550
|
-
runAsSystem: true
|
|
559
|
+
runAsSystem: true,
|
|
560
|
+
deserializeArgs: false
|
|
551
561
|
})
|
|
552
562
|
} catch (error) {
|
|
553
563
|
emitTriggerEvent({
|
|
@@ -558,7 +568,6 @@ const handleAuthenticationTrigger = async ({
|
|
|
558
568
|
meta: { ...baseMeta, event: 'UPDATE' },
|
|
559
569
|
error
|
|
560
570
|
})
|
|
561
|
-
console.log("🚀 ~ handleAuthenticationTrigger ~ error:", error)
|
|
562
571
|
}
|
|
563
572
|
return
|
|
564
573
|
}
|
|
@@ -643,7 +652,9 @@ const handleAuthenticationTrigger = async ({
|
|
|
643
652
|
meta: { ...baseMeta, event: 'CREATE' }
|
|
644
653
|
})
|
|
645
654
|
await GenerateContext({
|
|
646
|
-
args: isAutoTrigger
|
|
655
|
+
args: isAutoTrigger
|
|
656
|
+
? [normalizeTriggerPayload(userData)]
|
|
657
|
+
: [normalizeTriggerPayload({ user: userData, ...op })],
|
|
647
658
|
app,
|
|
648
659
|
rules: StateManager.select("rules"),
|
|
649
660
|
user: {}, // TODO from currentUser ??
|
|
@@ -651,7 +662,8 @@ const handleAuthenticationTrigger = async ({
|
|
|
651
662
|
functionName,
|
|
652
663
|
functionsList,
|
|
653
664
|
services,
|
|
654
|
-
runAsSystem: true
|
|
665
|
+
runAsSystem: true,
|
|
666
|
+
deserializeArgs: false
|
|
655
667
|
})
|
|
656
668
|
} catch (error) {
|
|
657
669
|
emitTriggerEvent({
|
|
@@ -662,7 +674,6 @@ const handleAuthenticationTrigger = async ({
|
|
|
662
674
|
meta: { ...baseMeta, event: 'CREATE' },
|
|
663
675
|
error
|
|
664
676
|
})
|
|
665
|
-
console.log("🚀 ~ handleAuthenticationTrigger ~ error:", error)
|
|
666
677
|
}
|
|
667
678
|
})
|
|
668
679
|
registerOnClose(
|
|
@@ -755,14 +766,15 @@ const handleDataBaseTrigger = async ({
|
|
|
755
766
|
})
|
|
756
767
|
try {
|
|
757
768
|
await GenerateContext({
|
|
758
|
-
args: [change],
|
|
769
|
+
args: [normalizeTriggerPayload(change)],
|
|
759
770
|
app,
|
|
760
771
|
rules: StateManager.select("rules"),
|
|
761
772
|
user: {}, // TODO add from?
|
|
762
773
|
currentFunction: triggerHandler,
|
|
763
774
|
functionName,
|
|
764
775
|
functionsList,
|
|
765
|
-
services
|
|
776
|
+
services,
|
|
777
|
+
deserializeArgs: false
|
|
766
778
|
})
|
|
767
779
|
} catch (error) {
|
|
768
780
|
emitTriggerEvent({
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
import { Rules } from '../../features/rules/interface'
|
|
20
20
|
import { buildRulesMeta } from '../../monitoring/utils'
|
|
21
21
|
import { checkValidation } from '../../utils/roles/machines'
|
|
22
|
-
import {
|
|
22
|
+
import { getWinningRoleAsync } from '../../utils/roles/machines/utils'
|
|
23
23
|
import { emitServiceEvent } from '../monitoring'
|
|
24
24
|
import { CHANGESTREAM } from '../../constants'
|
|
25
25
|
import {
|
|
@@ -561,9 +561,9 @@ const getOperators: GetOperatorsFunction = (
|
|
|
561
561
|
const resolvedOptions =
|
|
562
562
|
projection || normalizedOptions
|
|
563
563
|
? {
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
564
|
+
...(normalizedOptions ?? {}),
|
|
565
|
+
...(projection ? { projection } : {})
|
|
566
|
+
}
|
|
567
567
|
: undefined
|
|
568
568
|
const resolvedQuery = query ?? {}
|
|
569
569
|
if (!run_as_system) {
|
|
@@ -604,7 +604,7 @@ const getOperators: GetOperatorsFunction = (
|
|
|
604
604
|
return null
|
|
605
605
|
}
|
|
606
606
|
|
|
607
|
-
const winningRole =
|
|
607
|
+
const winningRole = await getWinningRoleAsync(result, user, roles)
|
|
608
608
|
|
|
609
609
|
logDebug('findOne winningRole', {
|
|
610
610
|
collection: collName,
|
|
@@ -613,15 +613,15 @@ const getOperators: GetOperatorsFunction = (
|
|
|
613
613
|
})
|
|
614
614
|
const { status, document } = winningRole
|
|
615
615
|
? await checkValidation(
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
616
|
+
winningRole,
|
|
617
|
+
{
|
|
618
|
+
type: 'read',
|
|
619
|
+
roles,
|
|
620
|
+
cursor: result,
|
|
621
|
+
expansions: getValidationExpansions(result)
|
|
622
|
+
},
|
|
623
|
+
user
|
|
624
|
+
)
|
|
625
625
|
: fallbackAccess(result)
|
|
626
626
|
|
|
627
627
|
// Return validated document or empty object if not permitted
|
|
@@ -669,7 +669,7 @@ const getOperators: GetOperatorsFunction = (
|
|
|
669
669
|
|
|
670
670
|
// Retrieve the document to check permissions before deleting
|
|
671
671
|
const result = await collection.findOne(buildAndQuery(formattedQuery))
|
|
672
|
-
const winningRole =
|
|
672
|
+
const winningRole = await getWinningRoleAsync(result, user, roles)
|
|
673
673
|
|
|
674
674
|
logDebug('delete winningRole', {
|
|
675
675
|
collection: collName,
|
|
@@ -678,15 +678,15 @@ const getOperators: GetOperatorsFunction = (
|
|
|
678
678
|
})
|
|
679
679
|
const { status } = winningRole
|
|
680
680
|
? await checkValidation(
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
681
|
+
winningRole,
|
|
682
|
+
{
|
|
683
|
+
type: 'delete',
|
|
684
|
+
roles,
|
|
685
|
+
cursor: result,
|
|
686
|
+
expansions: getValidationExpansions(result)
|
|
687
|
+
},
|
|
688
|
+
user
|
|
689
|
+
)
|
|
690
690
|
: fallbackAccess(result)
|
|
691
691
|
|
|
692
692
|
if (!status) {
|
|
@@ -733,19 +733,19 @@ const getOperators: GetOperatorsFunction = (
|
|
|
733
733
|
collection.collectionName,
|
|
734
734
|
CRUD_OPERATIONS.CREATE
|
|
735
735
|
)
|
|
736
|
-
const winningRole =
|
|
736
|
+
const winningRole = await getWinningRoleAsync(data, user, roles)
|
|
737
737
|
|
|
738
738
|
const { status, document } = winningRole
|
|
739
739
|
? await checkValidation(
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
740
|
+
winningRole,
|
|
741
|
+
{
|
|
742
|
+
type: 'insert',
|
|
743
|
+
roles,
|
|
744
|
+
cursor: data,
|
|
745
|
+
expansions: getValidationExpansions()
|
|
746
|
+
},
|
|
747
|
+
user
|
|
748
|
+
)
|
|
749
749
|
: fallbackAccess(data)
|
|
750
750
|
|
|
751
751
|
if (!status || !isEqual(data, document)) {
|
|
@@ -823,7 +823,7 @@ const getOperators: GetOperatorsFunction = (
|
|
|
823
823
|
throw new Error('Update not permitted')
|
|
824
824
|
}
|
|
825
825
|
|
|
826
|
-
const winningRole =
|
|
826
|
+
const winningRole = await getWinningRoleAsync(result, user, roles)
|
|
827
827
|
|
|
828
828
|
// Check if the update data contains MongoDB update operators (e.g., $set, $inc)
|
|
829
829
|
const updatedPaths = getUpdatedPaths(normalizedData)
|
|
@@ -831,15 +831,15 @@ const getOperators: GetOperatorsFunction = (
|
|
|
831
831
|
// Validate update permissions
|
|
832
832
|
const { status, document } = winningRole
|
|
833
833
|
? await checkValidation(
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
834
|
+
winningRole,
|
|
835
|
+
{
|
|
836
|
+
type: 'write',
|
|
837
|
+
roles,
|
|
838
|
+
cursor: docToCheck,
|
|
839
|
+
expansions: getValidationExpansions(result)
|
|
840
|
+
},
|
|
841
|
+
user
|
|
842
|
+
)
|
|
843
843
|
: fallbackAccess(docToCheck)
|
|
844
844
|
// Ensure no unauthorized changes are made
|
|
845
845
|
const areDocumentsEqual = areUpdatedFieldsAllowed(
|
|
@@ -918,31 +918,31 @@ const getOperators: GetOperatorsFunction = (
|
|
|
918
918
|
} else {
|
|
919
919
|
const [computedDoc] = Array.isArray(normalizedData)
|
|
920
920
|
? await collection
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
921
|
+
.aggregate([
|
|
922
|
+
{ $match: buildAndQuery(safeQuery) },
|
|
923
|
+
{ $limit: 1 },
|
|
924
|
+
...normalizedData
|
|
925
|
+
])
|
|
926
|
+
.toArray()
|
|
927
927
|
: [applyDocumentUpdateOperators(currentDoc, normalizedData as Document)]
|
|
928
928
|
docToCheck = computedDoc
|
|
929
929
|
}
|
|
930
930
|
|
|
931
|
-
const winningRole =
|
|
931
|
+
const winningRole = await getWinningRoleAsync(docToCheck, user, roles)
|
|
932
932
|
|
|
933
933
|
const { status, document } = winningRole
|
|
934
934
|
? await checkValidation(
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
935
|
+
winningRole,
|
|
936
|
+
{
|
|
937
|
+
type: validationType,
|
|
938
|
+
roles,
|
|
939
|
+
cursor: docToCheck,
|
|
940
|
+
expansions: getValidationExpansions(
|
|
941
|
+
validationType === 'insert' ? undefined : currentDoc
|
|
942
|
+
)
|
|
943
|
+
},
|
|
944
|
+
user
|
|
945
|
+
)
|
|
946
946
|
: fallbackAccess(docToCheck)
|
|
947
947
|
|
|
948
948
|
const areDocumentsEqual = areUpdatedFieldsAllowed(
|
|
@@ -956,28 +956,28 @@ const getOperators: GetOperatorsFunction = (
|
|
|
956
956
|
|
|
957
957
|
const updateResult = normalizedOptions
|
|
958
958
|
? await collection.findOneAndUpdate(
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
959
|
+
buildAndQuery(safeQuery),
|
|
960
|
+
normalizedData,
|
|
961
|
+
normalizedOptions
|
|
962
|
+
)
|
|
963
963
|
: await collection.findOneAndUpdate(buildAndQuery(safeQuery), normalizedData)
|
|
964
964
|
if (!updateResult) {
|
|
965
965
|
emitMongoEvent('findOneAndUpdate')
|
|
966
966
|
return updateResult
|
|
967
967
|
}
|
|
968
968
|
|
|
969
|
-
const readRole =
|
|
969
|
+
const readRole = await getWinningRoleAsync(updateResult, user, roles)
|
|
970
970
|
const readResult = readRole
|
|
971
971
|
? await checkValidation(
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
972
|
+
readRole,
|
|
973
|
+
{
|
|
974
|
+
type: 'read',
|
|
975
|
+
roles,
|
|
976
|
+
cursor: updateResult,
|
|
977
|
+
expansions: getValidationExpansions(updateResult)
|
|
978
|
+
},
|
|
979
|
+
user
|
|
980
|
+
)
|
|
981
981
|
: fallbackAccess(updateResult)
|
|
982
982
|
|
|
983
983
|
const sanitizedDoc = readResult.status
|
|
@@ -1026,9 +1026,9 @@ const getOperators: GetOperatorsFunction = (
|
|
|
1026
1026
|
const resolvedOptions =
|
|
1027
1027
|
projection || normalizedOptions
|
|
1028
1028
|
? {
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1029
|
+
...(normalizedOptions ?? {}),
|
|
1030
|
+
...(projection ? { projection } : {})
|
|
1031
|
+
}
|
|
1032
1032
|
: undefined
|
|
1033
1033
|
if (!run_as_system) {
|
|
1034
1034
|
checkDenyOperation(
|
|
@@ -1053,7 +1053,7 @@ const getOperators: GetOperatorsFunction = (
|
|
|
1053
1053
|
|
|
1054
1054
|
const filteredResponse = await Promise.all(
|
|
1055
1055
|
response.map(async (currentDoc) => {
|
|
1056
|
-
const winningRole =
|
|
1056
|
+
const winningRole = await getWinningRoleAsync(currentDoc, user, roles)
|
|
1057
1057
|
|
|
1058
1058
|
logDebug('find winningRole', {
|
|
1059
1059
|
collection: collName,
|
|
@@ -1063,15 +1063,15 @@ const getOperators: GetOperatorsFunction = (
|
|
|
1063
1063
|
})
|
|
1064
1064
|
const { status, document } = winningRole
|
|
1065
1065
|
? await checkValidation(
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1066
|
+
winningRole,
|
|
1067
|
+
{
|
|
1068
|
+
type: 'read',
|
|
1069
|
+
roles,
|
|
1070
|
+
cursor: currentDoc,
|
|
1071
|
+
expansions: getValidationExpansions(currentDoc)
|
|
1072
|
+
},
|
|
1073
|
+
user
|
|
1074
|
+
)
|
|
1075
1075
|
: fallbackAccess(currentDoc)
|
|
1076
1076
|
|
|
1077
1077
|
return status ? document : undefined
|
|
@@ -1190,19 +1190,19 @@ const getOperators: GetOperatorsFunction = (
|
|
|
1190
1190
|
const allowDeleteBypass = watchPipelineRequestsDelete(requestedPipeline)
|
|
1191
1191
|
const firstStep = watchFormattedQuery.length
|
|
1192
1192
|
? {
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
$and: watchFormattedQuery
|
|
1198
|
-
},
|
|
1199
|
-
{ operationType: 'delete' }
|
|
1200
|
-
]
|
|
1201
|
-
}
|
|
1202
|
-
: {
|
|
1193
|
+
$match: allowDeleteBypass
|
|
1194
|
+
? {
|
|
1195
|
+
$or: [
|
|
1196
|
+
{
|
|
1203
1197
|
$and: watchFormattedQuery
|
|
1204
|
-
}
|
|
1205
|
-
|
|
1198
|
+
},
|
|
1199
|
+
{ operationType: 'delete' }
|
|
1200
|
+
]
|
|
1201
|
+
}
|
|
1202
|
+
: {
|
|
1203
|
+
$and: watchFormattedQuery
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
1206
|
: undefined
|
|
1207
1207
|
|
|
1208
1208
|
const formattedPipeline = [firstStep, ...requestedPipeline].filter(
|
|
@@ -1221,33 +1221,33 @@ const getOperators: GetOperatorsFunction = (
|
|
|
1221
1221
|
const isValidChange = async (change: Document) => {
|
|
1222
1222
|
const { fullDocument, updateDescription } = change
|
|
1223
1223
|
const hasFullDocument = !!fullDocument
|
|
1224
|
-
const winningRole =
|
|
1224
|
+
const winningRole = await getWinningRoleAsync(fullDocument, user, roles)
|
|
1225
1225
|
|
|
1226
1226
|
const fullDocumentValidation = winningRole
|
|
1227
1227
|
? await checkValidation(
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1228
|
+
winningRole,
|
|
1229
|
+
{
|
|
1230
|
+
type: 'read',
|
|
1231
|
+
roles,
|
|
1232
|
+
cursor: fullDocument,
|
|
1233
|
+
expansions: getValidationExpansions(fullDocument)
|
|
1234
|
+
},
|
|
1235
|
+
user
|
|
1236
|
+
)
|
|
1237
1237
|
: fallbackAccess(fullDocument)
|
|
1238
1238
|
const { status, document } = fullDocumentValidation
|
|
1239
1239
|
|
|
1240
1240
|
const { status: updatedFieldsStatus, document: updatedFields } = winningRole
|
|
1241
1241
|
? await checkValidation(
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1242
|
+
winningRole,
|
|
1243
|
+
{
|
|
1244
|
+
type: 'read',
|
|
1245
|
+
roles,
|
|
1246
|
+
cursor: updateDescription?.updatedFields,
|
|
1247
|
+
expansions: getValidationExpansions(fullDocument)
|
|
1248
|
+
},
|
|
1249
|
+
user
|
|
1250
|
+
)
|
|
1251
1251
|
: fallbackAccess(updateDescription?.updatedFields)
|
|
1252
1252
|
|
|
1253
1253
|
return {
|
|
@@ -1389,19 +1389,19 @@ const getOperators: GetOperatorsFunction = (
|
|
|
1389
1389
|
// Validate each document against user's roles
|
|
1390
1390
|
const filteredItems = await Promise.all(
|
|
1391
1391
|
documents.map(async (currentDoc) => {
|
|
1392
|
-
const winningRole =
|
|
1392
|
+
const winningRole = await getWinningRoleAsync(currentDoc, user, roles)
|
|
1393
1393
|
|
|
1394
1394
|
const { status, document } = winningRole
|
|
1395
1395
|
? await checkValidation(
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1396
|
+
winningRole,
|
|
1397
|
+
{
|
|
1398
|
+
type: 'insert',
|
|
1399
|
+
roles,
|
|
1400
|
+
cursor: currentDoc,
|
|
1401
|
+
expansions: getValidationExpansions()
|
|
1402
|
+
},
|
|
1403
|
+
user
|
|
1404
|
+
)
|
|
1405
1405
|
: fallbackAccess(currentDoc)
|
|
1406
1406
|
|
|
1407
1407
|
return status ? document : undefined
|
|
@@ -1453,19 +1453,19 @@ const getOperators: GetOperatorsFunction = (
|
|
|
1453
1453
|
|
|
1454
1454
|
const filteredItems = await Promise.all(
|
|
1455
1455
|
docsToCheck.map(async (currentDoc, index) => {
|
|
1456
|
-
const winningRole =
|
|
1456
|
+
const winningRole = await getWinningRoleAsync(currentDoc, user, roles)
|
|
1457
1457
|
|
|
1458
1458
|
const { status, document } = winningRole
|
|
1459
1459
|
? await checkValidation(
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1460
|
+
winningRole,
|
|
1461
|
+
{
|
|
1462
|
+
type: 'write',
|
|
1463
|
+
roles,
|
|
1464
|
+
cursor: currentDoc,
|
|
1465
|
+
expansions: getValidationExpansions(result[index])
|
|
1466
|
+
},
|
|
1467
|
+
user
|
|
1468
|
+
)
|
|
1469
1469
|
: fallbackAccess(currentDoc)
|
|
1470
1470
|
|
|
1471
1471
|
return status ? document : undefined
|
|
@@ -1529,19 +1529,19 @@ const getOperators: GetOperatorsFunction = (
|
|
|
1529
1529
|
// Filter and validate each document based on user's roles
|
|
1530
1530
|
const filteredItems = await Promise.all(
|
|
1531
1531
|
data.map(async (currentDoc) => {
|
|
1532
|
-
const winningRole =
|
|
1532
|
+
const winningRole = await getWinningRoleAsync(currentDoc, user, roles)
|
|
1533
1533
|
|
|
1534
1534
|
const { status, document } = winningRole
|
|
1535
1535
|
? await checkValidation(
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1536
|
+
winningRole,
|
|
1537
|
+
{
|
|
1538
|
+
type: 'delete',
|
|
1539
|
+
roles,
|
|
1540
|
+
cursor: currentDoc,
|
|
1541
|
+
expansions: getValidationExpansions(currentDoc)
|
|
1542
|
+
},
|
|
1543
|
+
user
|
|
1544
|
+
)
|
|
1545
1545
|
: fallbackAccess(currentDoc)
|
|
1546
1546
|
|
|
1547
1547
|
return status ? document : undefined
|