@stoker-platform/utils 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/lib/src/access/collection.d.ts +9 -0
  2. package/lib/src/access/collection.js +59 -0
  3. package/lib/src/access/document.d.ts +3 -0
  4. package/lib/src/access/document.js +191 -0
  5. package/lib/src/access/getCollectionRestrictions.d.ts +7 -0
  6. package/lib/src/access/getCollectionRestrictions.js +71 -0
  7. package/lib/src/access/getRecordSubcollections.d.ts +2 -0
  8. package/lib/src/access/getRecordSubcollections.js +15 -0
  9. package/lib/src/access/getRelatedCollections.d.ts +2 -0
  10. package/lib/src/access/getRelatedCollections.js +24 -0
  11. package/lib/src/access/hasDependencyAccess.d.ts +2 -0
  12. package/lib/src/access/hasDependencyAccess.js +24 -0
  13. package/lib/src/access/isPaginationEnabled.d.ts +2 -0
  14. package/lib/src/access/isPaginationEnabled.js +35 -0
  15. package/lib/src/access/permissions.d.ts +2 -0
  16. package/lib/src/access/permissions.js +543 -0
  17. package/lib/src/access/read/getOne.d.ts +2 -0
  18. package/lib/src/access/read/getOne.js +19 -0
  19. package/lib/src/access/read/getSome.d.ts +2 -0
  20. package/lib/src/access/read/getSome.js +21 -0
  21. package/lib/src/access/roleHasOperationAccess.d.ts +2 -0
  22. package/lib/src/access/roleHasOperationAccess.js +7 -0
  23. package/lib/src/access/write/addRecord.d.ts +2 -0
  24. package/lib/src/access/write/addRecord.js +40 -0
  25. package/lib/src/access/write/deleteRecord.d.ts +2 -0
  26. package/lib/src/access/write/deleteRecord.js +26 -0
  27. package/lib/src/access/write/updateRecord.d.ts +2 -0
  28. package/lib/src/access/write/updateRecord.js +61 -0
  29. package/lib/src/getConfigValue.d.ts +12 -0
  30. package/lib/src/getConfigValue.js +83 -0
  31. package/lib/src/getCustomization.d.ts +4 -0
  32. package/lib/src/getCustomization.js +29 -0
  33. package/lib/src/getFieldCustomization.d.ts +7 -0
  34. package/lib/src/getFieldCustomization.js +3 -0
  35. package/lib/src/main.d.ts +60 -0
  36. package/lib/src/main.js +60 -0
  37. package/lib/src/operations/addInitialValues.d.ts +2 -0
  38. package/lib/src/operations/addInitialValues.js +27 -0
  39. package/lib/src/operations/addLowercaseFields.d.ts +2 -0
  40. package/lib/src/operations/addLowercaseFields.js +12 -0
  41. package/lib/src/operations/addRelationArrays.d.ts +2 -0
  42. package/lib/src/operations/addRelationArrays.js +60 -0
  43. package/lib/src/operations/addSystemFields.d.ts +2 -0
  44. package/lib/src/operations/addSystemFields.js +17 -0
  45. package/lib/src/operations/getDateRange.d.ts +5 -0
  46. package/lib/src/operations/getDateRange.js +56 -0
  47. package/lib/src/operations/getExtendedSchema.d.ts +2 -0
  48. package/lib/src/operations/getExtendedSchema.js +23 -0
  49. package/lib/src/operations/getFinalRecord.d.ts +1 -0
  50. package/lib/src/operations/getFinalRecord.js +11 -0
  51. package/lib/src/operations/getInputSchema.d.ts +15 -0
  52. package/lib/src/operations/getInputSchema.js +352 -0
  53. package/lib/src/operations/getLowercaseFields.d.ts +2 -0
  54. package/lib/src/operations/getLowercaseFields.js +15 -0
  55. package/lib/src/operations/getSingleFieldRelations.d.ts +2 -0
  56. package/lib/src/operations/getSingleFieldRelations.js +27 -0
  57. package/lib/src/operations/getZodSchema.d.ts +15 -0
  58. package/lib/src/operations/getZodSchema.js +303 -0
  59. package/lib/src/operations/isDeleteSentinel.d.ts +1 -0
  60. package/lib/src/operations/isDeleteSentinel.js +4 -0
  61. package/lib/src/operations/isSortingEnabled.d.ts +2 -0
  62. package/lib/src/operations/isSortingEnabled.js +7 -0
  63. package/lib/src/operations/isValidUniqueFieldValue.d.ts +1 -0
  64. package/lib/src/operations/isValidUniqueFieldValue.js +25 -0
  65. package/lib/src/operations/parseDate.d.ts +1 -0
  66. package/lib/src/operations/parseDate.js +4 -0
  67. package/lib/src/operations/prepareDenormalized.d.ts +8 -0
  68. package/lib/src/operations/prepareDenormalized.js +312 -0
  69. package/lib/src/operations/removeDeleteSentinels.d.ts +2 -0
  70. package/lib/src/operations/removeDeleteSentinels.js +15 -0
  71. package/lib/src/operations/removeDeletedFields.d.ts +2 -0
  72. package/lib/src/operations/removeDeletedFields.js +14 -0
  73. package/lib/src/operations/removeEmptyStrings.d.ts +2 -0
  74. package/lib/src/operations/removeEmptyStrings.js +14 -0
  75. package/lib/src/operations/removePrivateFields.d.ts +2 -0
  76. package/lib/src/operations/removePrivateFields.js +14 -0
  77. package/lib/src/operations/removeUndefined.d.ts +2 -0
  78. package/lib/src/operations/removeUndefined.js +14 -0
  79. package/lib/src/operations/retryOperation.d.ts +1 -0
  80. package/lib/src/operations/retryOperation.js +21 -0
  81. package/lib/src/operations/runHooks.d.ts +17 -0
  82. package/lib/src/operations/runHooks.js +18 -0
  83. package/lib/src/operations/sanitizeDownloadFilename.d.ts +1 -0
  84. package/lib/src/operations/sanitizeDownloadFilename.js +18 -0
  85. package/lib/src/operations/sanitizeEmailInput.d.ts +5 -0
  86. package/lib/src/operations/sanitizeEmailInput.js +73 -0
  87. package/lib/src/operations/updateFieldReference.d.ts +2 -0
  88. package/lib/src/operations/updateFieldReference.js +14 -0
  89. package/lib/src/operations/validateRecord.d.ts +2 -0
  90. package/lib/src/operations/validateRecord.js +18 -0
  91. package/lib/src/operations/validateStorageName.d.ts +1 -0
  92. package/lib/src/operations/validateStorageName.js +19 -0
  93. package/lib/src/schema/getAccessFields.d.ts +2 -0
  94. package/lib/src/schema/getAccessFields.js +62 -0
  95. package/lib/src/schema/getCollection.d.ts +2 -0
  96. package/lib/src/schema/getCollection.js +3 -0
  97. package/lib/src/schema/getDependencyFields.d.ts +6 -0
  98. package/lib/src/schema/getDependencyFields.js +22 -0
  99. package/lib/src/schema/getField.d.ts +2 -0
  100. package/lib/src/schema/getField.js +3 -0
  101. package/lib/src/schema/getFieldNames.d.ts +2 -0
  102. package/lib/src/schema/getFieldNames.js +3 -0
  103. package/lib/src/schema/getIndexFields.d.ts +9 -0
  104. package/lib/src/schema/getIndexFields.js +184 -0
  105. package/lib/src/schema/getInverseRelationType.d.ts +1 -0
  106. package/lib/src/schema/getInverseRelationType.js +15 -0
  107. package/lib/src/schema/getPathCollections.d.ts +2 -0
  108. package/lib/src/schema/getPathCollections.js +12 -0
  109. package/lib/src/schema/getRecordSystemFields.d.ts +2 -0
  110. package/lib/src/schema/getRecordSystemFields.js +11 -0
  111. package/lib/src/schema/getRelationLists.d.ts +5 -0
  112. package/lib/src/schema/getRelationLists.js +13 -0
  113. package/lib/src/schema/getSubcollections.d.ts +2 -0
  114. package/lib/src/schema/getSubcollections.js +9 -0
  115. package/lib/src/schema/getSystemFieldsSchema.d.ts +2 -0
  116. package/lib/src/schema/getSystemFieldsSchema.js +52 -0
  117. package/lib/src/schema/isDependencyField.d.ts +2 -0
  118. package/lib/src/schema/isDependencyField.js +18 -0
  119. package/lib/src/schema/isIncludedField.d.ts +2 -0
  120. package/lib/src/schema/isIncludedField.js +18 -0
  121. package/lib/src/schema/isRelationField.d.ts +2 -0
  122. package/lib/src/schema/isRelationField.js +3 -0
  123. package/lib/src/schema/system-fields.d.ts +2 -0
  124. package/lib/src/schema/system-fields.js +13 -0
  125. package/lib/tsconfig.tsbuildinfo +1 -0
  126. package/package.json +35 -0
@@ -0,0 +1,9 @@
1
+ import { CollectionField, CollectionPermissions, CollectionSchema, StokerPermissions } from "@stoker-platform/types";
2
+ export declare const collectionAuthAccess: (permissions: CollectionPermissions) => boolean;
3
+ export declare const collectionAccess: (operation: "Read" | "Create" | "Update" | "Delete", permissions: CollectionPermissions) => boolean | undefined;
4
+ export declare const collectionSomeWriteAccess: (permissions: CollectionPermissions) => boolean | undefined;
5
+ export declare const collectionAllWriteAccess: (permissions: CollectionPermissions) => boolean | undefined;
6
+ export declare const privateFieldAccess: (field: CollectionField, permissions?: StokerPermissions) => boolean | undefined;
7
+ export declare const restrictCreateAccess: (field: CollectionField, permissions?: StokerPermissions) => boolean;
8
+ export declare const restrictUpdateAccess: (field: CollectionField, permissions?: StokerPermissions) => boolean;
9
+ export declare const canUpdateField: (collection: CollectionSchema, field: CollectionField, permissions: StokerPermissions) => boolean | undefined;
@@ -0,0 +1,59 @@
1
+ export const collectionAuthAccess = (permissions) => {
2
+ return !!permissions.auth;
3
+ };
4
+ export const collectionAccess = (operation, permissions) => {
5
+ if (permissions?.operations) {
6
+ return permissions.operations.includes(operation);
7
+ }
8
+ return;
9
+ };
10
+ export const collectionSomeWriteAccess = (permissions) => {
11
+ if (permissions?.operations) {
12
+ return permissions.operations.some((operation) => operation === "Create" || operation === "Update" || operation === "Delete");
13
+ }
14
+ return;
15
+ };
16
+ export const collectionAllWriteAccess = (permissions) => {
17
+ if (permissions?.operations) {
18
+ return permissions.operations.every((operation) => operation === "Create" || operation === "Update" || operation === "Delete");
19
+ }
20
+ return;
21
+ };
22
+ export const privateFieldAccess = (field, permissions) => {
23
+ if (!permissions)
24
+ return true;
25
+ if (!permissions.Role)
26
+ return false;
27
+ return field.access?.includes(permissions.Role);
28
+ };
29
+ export const restrictCreateAccess = (field, permissions) => {
30
+ if (field.restrictCreate === true)
31
+ return false;
32
+ else if (permissions && typeof field.restrictCreate === "object") {
33
+ if (!permissions.Role)
34
+ return false;
35
+ return field.restrictCreate?.includes(permissions.Role);
36
+ }
37
+ return true;
38
+ };
39
+ export const restrictUpdateAccess = (field, permissions) => {
40
+ if (field.restrictUpdate === true)
41
+ return false;
42
+ else if (permissions && typeof field.restrictUpdate === "object") {
43
+ if (!permissions.Role)
44
+ return false;
45
+ return field.restrictUpdate?.includes(permissions.Role);
46
+ }
47
+ return true;
48
+ };
49
+ export const canUpdateField = (collection, field, permissions) => {
50
+ const { labels } = collection;
51
+ return (permissions.collections &&
52
+ // eslint-disable-next-line security/detect-object-injection
53
+ collectionAccess("Update", permissions.collections[labels.collection]) &&
54
+ (!field.access || privateFieldAccess(field, permissions)) &&
55
+ restrictUpdateAccess(field, permissions) &&
56
+ !(collection.auth &&
57
+ !permissions.collections?.[labels.collection].auth &&
58
+ ["Enabled", "Role", "Name", "Email", "Photo_URL"].includes(field.name)));
59
+ };
@@ -0,0 +1,3 @@
1
+ import { CollectionSchema, CollectionsSchema, StokerPermissions, StokerRecord } from "@stoker-platform/types";
2
+ export declare const documentAccess: (operation: "Read" | "Create" | "Update" | "Delete", collectionSchema: CollectionSchema, schema: CollectionsSchema, userId: string, permissions: StokerPermissions, record: StokerRecord) => boolean;
3
+ export declare const dependencyAccess: (collectionSchema: CollectionSchema, schema: CollectionsSchema, userId: string, permissions: StokerPermissions, record: StokerRecord) => boolean;
@@ -0,0 +1,191 @@
1
+ import { getField } from "../schema/getField.js";
2
+ import { collectionAccess } from "./collection.js";
3
+ import { getAttributeRestrictions, getEntityRestrictions, getEntityParentFilters, } from "../access/getCollectionRestrictions.js";
4
+ import { hasDependencyAccess } from "./hasDependencyAccess.js";
5
+ const filterAccess = (operation, collectionSchema, schema, userId, permissions, record) => {
6
+ const { fields } = collectionSchema;
7
+ const collectionPermissions = permissions.collections?.[collectionSchema.labels.collection];
8
+ let granted = true;
9
+ if (!collectionPermissions) {
10
+ granted = false;
11
+ return;
12
+ }
13
+ const hasAttributeRestrictions = getAttributeRestrictions(collectionSchema, permissions);
14
+ const hasEntityRestrictions = getEntityRestrictions(collectionSchema, permissions);
15
+ const hasEntityParentFilters = getEntityParentFilters(collectionSchema, schema, permissions);
16
+ hasAttributeRestrictions
17
+ ?.filter((attributeRestriction) => attributeRestriction.type === "Record_Owner")
18
+ .forEach((attributeRestriction) => {
19
+ if ("operations" in attributeRestriction &&
20
+ attributeRestriction.operations &&
21
+ !attributeRestriction.operations.includes(operation))
22
+ return;
23
+ if (record.Created_By !== userId)
24
+ granted = false;
25
+ });
26
+ hasAttributeRestrictions
27
+ ?.filter((attributeRestriction) => attributeRestriction.type === "Record_User")
28
+ .forEach((attributeRestriction) => {
29
+ if ("operations" in attributeRestriction &&
30
+ attributeRestriction.operations &&
31
+ !attributeRestriction.operations.includes(operation))
32
+ return;
33
+ const field = getField(fields, attributeRestriction.collectionField);
34
+ if (!record[`${field.name}_Array`]?.includes(permissions.Doc_ID))
35
+ granted = false;
36
+ });
37
+ hasAttributeRestrictions
38
+ ?.filter((attributeRestriction) => attributeRestriction.type === "Record_Property")
39
+ .forEach((attributeRestriction) => {
40
+ if ("operations" in attributeRestriction &&
41
+ attributeRestriction.operations &&
42
+ !attributeRestriction.operations.includes(operation))
43
+ return;
44
+ const field = getField(fields, attributeRestriction.propertyField);
45
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
46
+ const recordPropertyRole = attributeRestriction.roles.find((role) => role.role === permissions.Role);
47
+ if (field.type === "Array") {
48
+ if (!recordPropertyRole.values?.some((value) => record[field.name].includes(value)))
49
+ granted = false;
50
+ }
51
+ else if (!recordPropertyRole.values?.includes(record[field.name]))
52
+ granted = false;
53
+ });
54
+ let individualEntityRestrictionPassed = true;
55
+ let hasIndividualEntityRestriction = false;
56
+ hasEntityRestrictions
57
+ ?.filter((entityRestriction) => entityRestriction.type === "Individual")
58
+ .forEach(() => {
59
+ hasIndividualEntityRestriction = true;
60
+ if (!collectionPermissions.individualEntities?.includes(record.id))
61
+ individualEntityRestrictionPassed = false;
62
+ });
63
+ let parentEntityRestrictionPassed = true;
64
+ let hasParentEntityRestriction = false;
65
+ hasEntityRestrictions
66
+ ?.filter((entityRestriction) => entityRestriction.type === "Parent")
67
+ .forEach((entityRestriction) => {
68
+ hasParentEntityRestriction = true;
69
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
70
+ const field = getField(fields, entityRestriction.collectionField);
71
+ if (!collectionPermissions.parentEntities?.some((entity) => record[`${field.name}_Array`].includes(entity)))
72
+ parentEntityRestrictionPassed = false;
73
+ });
74
+ hasEntityRestrictions
75
+ ?.filter((entityRestriction) => entityRestriction.type === "Parent_Property")
76
+ .forEach((entityRestriction) => {
77
+ hasParentEntityRestriction = true;
78
+ const collectionField = getField(fields, entityRestriction.collectionField);
79
+ const propertyField = getField(fields, entityRestriction.propertyField);
80
+ if (!Object.entries(collectionPermissions.parentPropertyEntities || {}).some((property) => {
81
+ const [propertyKey, entities] = property;
82
+ return (propertyKey === record[propertyField.name] &&
83
+ record[`${collectionField.name}_Array`].some((entity) => entities.includes(entity)));
84
+ }))
85
+ parentEntityRestrictionPassed = false;
86
+ });
87
+ if (hasIndividualEntityRestriction && hasParentEntityRestriction) {
88
+ if (!(individualEntityRestrictionPassed || parentEntityRestrictionPassed)) {
89
+ granted = false;
90
+ return;
91
+ }
92
+ }
93
+ else if (!individualEntityRestrictionPassed || !parentEntityRestrictionPassed) {
94
+ granted = false;
95
+ return;
96
+ }
97
+ let individualParentFilterPassed = true;
98
+ let hasIndividualParentFilter = false;
99
+ hasEntityParentFilters
100
+ ?.filter((entityParentFilter) => entityParentFilter.parentFilter.type === "Individual")
101
+ .forEach((entityParentFilter) => {
102
+ hasIndividualParentFilter = true;
103
+ const { parentFilter } = entityParentFilter;
104
+ const collectionField = getField(fields, parentFilter.collectionField);
105
+ const parentCollectionPermissions = permissions.collections?.[collectionField.collection];
106
+ if (!parentCollectionPermissions) {
107
+ granted = false;
108
+ return;
109
+ }
110
+ if (!parentCollectionPermissions.individualEntities?.some((entity) => record[`${collectionField.name}_Array`].includes(entity)))
111
+ individualParentFilterPassed = false;
112
+ });
113
+ let parentParentFilterPassed = true;
114
+ let hasParentParentFilter = false;
115
+ hasEntityParentFilters
116
+ ?.filter((entityParentFilter) => entityParentFilter.parentFilter.type === "Parent")
117
+ .forEach((entityParentFilter) => {
118
+ hasParentParentFilter = true;
119
+ const { parentFilter } = entityParentFilter;
120
+ const collectionField = getField(fields, parentFilter.collectionField);
121
+ const parentCollectionField = getField(fields, parentFilter.parentCollectionField);
122
+ const parentCollectionPermissions = permissions.collections?.[collectionField.collection];
123
+ if (!parentCollectionPermissions) {
124
+ granted = false;
125
+ return;
126
+ }
127
+ if (!parentCollectionPermissions.parentEntities?.some((entity) => record[`${parentCollectionField.name}_Array`].includes(entity)))
128
+ parentParentFilterPassed = false;
129
+ });
130
+ hasEntityParentFilters
131
+ ?.filter((entityParentFilter) => entityParentFilter.parentFilter.type === "Parent_Property")
132
+ .forEach((entityParentFilter) => {
133
+ hasParentParentFilter = true;
134
+ const { parentFilter } = entityParentFilter;
135
+ const collectionField = getField(fields, parentFilter.collectionField);
136
+ const parentPropertyField = getField(fields, parentFilter.parentPropertyField);
137
+ const parentCollectionField = getField(fields, parentFilter.parentCollectionField);
138
+ const parentCollectionPermissions = permissions.collections?.[collectionField.collection];
139
+ if (!parentCollectionPermissions) {
140
+ granted = false;
141
+ return;
142
+ }
143
+ if (!Object.entries(parentCollectionPermissions.parentPropertyEntities || {}).some((property) => {
144
+ const [propertyKey, entities] = property;
145
+ return (propertyKey === record[parentPropertyField.name] &&
146
+ record[`${parentCollectionField.name}_Array`].some((entity) => entities.includes(entity)));
147
+ }))
148
+ parentParentFilterPassed = false;
149
+ });
150
+ if (hasIndividualParentFilter && hasParentParentFilter) {
151
+ if (!(individualParentFilterPassed || parentParentFilterPassed)) {
152
+ granted = false;
153
+ return;
154
+ }
155
+ }
156
+ else if (!individualParentFilterPassed || !parentParentFilterPassed) {
157
+ granted = false;
158
+ return;
159
+ }
160
+ return granted;
161
+ };
162
+ export const documentAccess = (operation, collectionSchema, schema, userId, permissions, record) => {
163
+ const { labels } = collectionSchema;
164
+ const collectionPermissions = permissions.collections?.[labels.collection];
165
+ let granted = true;
166
+ if (!collectionPermissions || !permissions.Role) {
167
+ granted = false;
168
+ return granted;
169
+ }
170
+ if (!collectionAccess(operation, collectionPermissions))
171
+ granted = false;
172
+ const hasEntityRestrictions = getEntityRestrictions(collectionSchema, permissions);
173
+ const hasIndividualEntityRestriction = hasEntityRestrictions?.filter((entityRestriction) => entityRestriction.type === "Individual").length > 0;
174
+ if (operation === "Create" && hasIndividualEntityRestriction)
175
+ granted = false;
176
+ if (!filterAccess(operation, collectionSchema, schema, userId, permissions, record))
177
+ granted = false;
178
+ return granted;
179
+ };
180
+ export const dependencyAccess = (collectionSchema, schema, userId, permissions, record) => {
181
+ let granted = true;
182
+ if (!permissions.Role) {
183
+ granted = false;
184
+ return granted;
185
+ }
186
+ if (hasDependencyAccess(collectionSchema, schema, permissions).length === 0)
187
+ granted = false;
188
+ if (!filterAccess("Read", collectionSchema, schema, userId, permissions, record))
189
+ granted = false;
190
+ return granted;
191
+ };
@@ -0,0 +1,7 @@
1
+ import { AttributeRestriction, CollectionSchema, CollectionsSchema, EntityParentFilter, EntityRestriction, StokerPermissions } from "@stoker-platform/types";
2
+ export declare const getAttributeRestrictions: (collection: CollectionSchema, permissions: StokerPermissions) => AttributeRestriction[];
3
+ export declare const getEntityRestrictions: (collection: CollectionSchema, permissions: StokerPermissions) => EntityRestriction[];
4
+ export declare const getEntityParentFilters: (collection: CollectionSchema, schema: CollectionsSchema, permissions: StokerPermissions) => {
5
+ parentFilter: EntityParentFilter;
6
+ parentRestriction: EntityRestriction;
7
+ }[];
@@ -0,0 +1,71 @@
1
+ import { getField } from "../schema/getField.js";
2
+ import { isRelationField } from "../schema/isRelationField.js";
3
+ export const getAttributeRestrictions = (collection, permissions) => {
4
+ const restrictionKeys = {
5
+ Record_Owner: "recordOwner",
6
+ Record_User: "recordUser",
7
+ Record_Property: "recordProperty",
8
+ };
9
+ const restrictions = [];
10
+ const { labels, access } = collection;
11
+ const { attributeRestrictions } = access;
12
+ const collectionPermissions = permissions.collections?.[labels.collection];
13
+ attributeRestrictions?.forEach((attributeRestriction) => {
14
+ if ("roles" in attributeRestriction) {
15
+ attributeRestriction.roles.forEach((role) => {
16
+ const permissionRestriction = collectionPermissions?.[restrictionKeys[attributeRestriction.type]];
17
+ if (role.role === permissions.Role && (!role.assignable || permissionRestriction?.active))
18
+ restrictions.push(attributeRestriction);
19
+ });
20
+ }
21
+ });
22
+ return restrictions;
23
+ };
24
+ export const getEntityRestrictions = (collection, permissions) => {
25
+ const restrictions = [];
26
+ const { labels, access } = collection;
27
+ const { entityRestrictions } = access;
28
+ const collectionPermissions = permissions.collections?.[labels.collection];
29
+ entityRestrictions?.restrictions?.forEach((entityRestriction) => {
30
+ if ("roles" in entityRestriction) {
31
+ entityRestriction.roles.forEach((role) => {
32
+ if (role.role === permissions.Role &&
33
+ (!entityRestrictions.assignable?.includes(permissions.Role) ||
34
+ collectionPermissions?.restrictEntities))
35
+ restrictions.push(entityRestriction);
36
+ });
37
+ }
38
+ });
39
+ return restrictions;
40
+ };
41
+ export const getEntityParentFilters = (collection, schema, permissions) => {
42
+ const parentFilters = [];
43
+ const { access } = collection;
44
+ const { entityRestrictions } = access;
45
+ entityRestrictions?.parentFilters?.forEach((entityParentFilter) => {
46
+ if (!entityParentFilter.roles.some((role) => role.role === permissions.Role))
47
+ return;
48
+ const collectionField = entityParentFilter.collectionField;
49
+ const collectionFieldSchema = getField(collection.fields, collectionField);
50
+ if (!isRelationField(collectionFieldSchema))
51
+ throw new Error("PERMISSION_DENIED");
52
+ // eslint-disable-next-line security/detect-object-injection
53
+ const parentPermissions = permissions.collections?.[collectionFieldSchema.collection];
54
+ const parentCollection = schema.collections[collectionFieldSchema.collection];
55
+ const parentEntityRestrictions = parentCollection.access.entityRestrictions;
56
+ if (!parentEntityRestrictions)
57
+ throw new Error("PERMISSION_DENIED");
58
+ const parentRestriction = parentEntityRestrictions.restrictions?.find((restriction) => restriction.type === entityParentFilter.type &&
59
+ restriction.roles.some((role) => role.role === permissions.Role));
60
+ if (!parentRestriction)
61
+ throw new Error("PERMISSION_DENIED");
62
+ parentRestriction.roles.forEach((role) => {
63
+ if (role.role === permissions.Role &&
64
+ (!parentEntityRestrictions.assignable?.includes(permissions.Role) ||
65
+ parentPermissions?.restrictEntities)) {
66
+ parentFilters.push({ parentFilter: entityParentFilter, parentRestriction });
67
+ }
68
+ });
69
+ });
70
+ return parentFilters;
71
+ };
@@ -0,0 +1,2 @@
1
+ import { CollectionSchema, CollectionsSchema, StokerPermissions } from "@stoker-platform/types";
2
+ export declare const getRecordSubcollections: (collectionSchema: CollectionSchema, schema: CollectionsSchema, permissions?: StokerPermissions) => CollectionSchema[];
@@ -0,0 +1,15 @@
1
+ import { collectionAccess } from "./collection.js";
2
+ export const getRecordSubcollections = (collectionSchema, schema, permissions) => {
3
+ const { labels } = collectionSchema;
4
+ const subcollections = [];
5
+ for (const collection of Object.values(schema.collections)) {
6
+ const collectionPermissions = permissions?.collections?.[collection.labels.collection];
7
+ if (!collectionPermissions)
8
+ continue;
9
+ if (collection.parentCollection === labels.collection &&
10
+ (!permissions || collectionAccess("Read", collectionPermissions))) {
11
+ subcollections.push(collection);
12
+ }
13
+ }
14
+ return subcollections;
15
+ };
@@ -0,0 +1,2 @@
1
+ import { CollectionSchema, CollectionsSchema, StokerPermissions } from "@stoker-platform/types";
2
+ export declare const getRelatedCollections: (collectionSchema: CollectionSchema, schema: CollectionsSchema, permissions?: StokerPermissions) => string[];
@@ -0,0 +1,24 @@
1
+ import { isRelationField } from "../schema/isRelationField.js";
2
+ import { collectionAccess, privateFieldAccess } from "../access/collection.js";
3
+ import { hasDependencyAccess } from "./hasDependencyAccess.js";
4
+ export const getRelatedCollections = (collectionSchema, schema, permissions) => {
5
+ const relatedCollections = [];
6
+ for (const field of collectionSchema.fields) {
7
+ if (isRelationField(field)) {
8
+ if (field.access && (!permissions || !privateFieldAccess(field, permissions)))
9
+ continue;
10
+ const relatedCollection = schema.collections[field.collection];
11
+ if (!relatedCollection)
12
+ continue;
13
+ const relatedCollectionPermissions = permissions?.collections?.[field.collection];
14
+ if (!relatedCollectionPermissions)
15
+ continue;
16
+ if (!permissions ||
17
+ collectionAccess("Read", relatedCollectionPermissions) ||
18
+ hasDependencyAccess(collectionSchema, schema, permissions)) {
19
+ relatedCollections.push(field.collection);
20
+ }
21
+ }
22
+ }
23
+ return Array.from(new Set(relatedCollections));
24
+ };
@@ -0,0 +1,2 @@
1
+ import { CollectionSchema, CollectionsSchema, DependencyField, StokerPermissions } from "@stoker-platform/types";
2
+ export declare const hasDependencyAccess: (collection: CollectionSchema, schema: CollectionsSchema, permissions: StokerPermissions) => DependencyField[];
@@ -0,0 +1,24 @@
1
+ import { privateFieldAccess } from "./collection.js";
2
+ import { isRelationField } from "../schema/isRelationField.js";
3
+ export const hasDependencyAccess = (collection, schema, permissions) => {
4
+ const collections = Object.values(schema.collections);
5
+ const { labels } = collection;
6
+ const hasDependencyAccess = [];
7
+ for (const collectionSchema of collections) {
8
+ const { fields: dependencyFields } = collectionSchema;
9
+ for (const field of dependencyFields) {
10
+ if (field.access && !privateFieldAccess(field, permissions))
11
+ continue;
12
+ if (!permissions.Role)
13
+ continue;
14
+ if (isRelationField(field) && field.collection === labels.collection && field.dependencyFields) {
15
+ for (const dependencyField of field.dependencyFields) {
16
+ const existingField = hasDependencyAccess.find((field) => field.field === dependencyField.field);
17
+ if (!existingField && dependencyField.roles.includes(permissions.Role))
18
+ hasDependencyAccess.push(dependencyField);
19
+ }
20
+ }
21
+ }
22
+ }
23
+ return hasDependencyAccess;
24
+ };
@@ -0,0 +1,2 @@
1
+ import { CollectionSchema, CollectionsSchema, StokerRole } from "@stoker-platform/types";
2
+ export declare const isPaginationEnabled: (role: StokerRole, collectionSchema: CollectionSchema, schema: CollectionsSchema) => string | true;
@@ -0,0 +1,35 @@
1
+ import { getField } from "../schema/getField.js";
2
+ import { isRelationField } from "../schema/isRelationField.js";
3
+ export const isPaginationEnabled = (role, collectionSchema, schema) => {
4
+ const { access } = collectionSchema;
5
+ const { entityRestrictions } = access;
6
+ if (entityRestrictions?.restrictions) {
7
+ for (const restriction of entityRestrictions.restrictions) {
8
+ if (restriction.roles?.some((accessRole) => accessRole.role === role)) {
9
+ if (!("singleQuery" in restriction && restriction.singleQuery)) {
10
+ return `${restriction.type} entity restriction`;
11
+ }
12
+ }
13
+ }
14
+ }
15
+ if (entityRestrictions?.parentFilters) {
16
+ for (const parentFilter of entityRestrictions.parentFilters) {
17
+ if (!parentFilter.roles.some((accessRole) => accessRole.role === role))
18
+ continue;
19
+ const collectionFieldSchema = getField(collectionSchema.fields, parentFilter.collectionField);
20
+ if (!isRelationField(collectionFieldSchema))
21
+ throw new Error("PERMISSION_DENIED");
22
+ const parentCollection = schema.collections[collectionFieldSchema.collection];
23
+ const parentRestriction = parentCollection.access.entityRestrictions?.restrictions?.find((restriction) => restriction.type === parentFilter.type &&
24
+ restriction.roles.some((accessRole) => accessRole.role === role));
25
+ if (!parentRestriction)
26
+ throw new Error("PERMISSION_DENIED");
27
+ if (parentRestriction.type !== parentFilter.type)
28
+ throw new Error("PERMISSION_DENIED");
29
+ if (!("singleQuery" in parentRestriction && parentRestriction.singleQuery)) {
30
+ return `${parentFilter.type} parent filter`;
31
+ }
32
+ }
33
+ }
34
+ return true;
35
+ };
@@ -0,0 +1,2 @@
1
+ import { CollectionSchema, CollectionsSchema, StokerPermissions, StokerRecord } from "@stoker-platform/types";
2
+ export declare const permissionsWriteAccess: (operation: "create" | "update" | "delete", record: StokerRecord, docId: string, collectionSchema: CollectionSchema, schema: CollectionsSchema, currentUserId?: string, currentUserPermissions?: StokerPermissions, permissions?: StokerPermissions, originalPermissions?: StokerPermissions, originalRecord?: StokerRecord, userOperation?: string) => boolean;