@webiny/api-aco 0.0.0-unstable.7be00a75a9 → 0.0.0-unstable.7c2def32a7

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 (241) hide show
  1. package/AcoFeature.d.ts +5 -0
  2. package/AcoFeature.js +134 -0
  3. package/AcoFeature.js.map +1 -0
  4. package/AcoFolderSchemaFactory.d.ts +32 -0
  5. package/AcoFolderSchemaFactory.js +82 -0
  6. package/AcoFolderSchemaFactory.js.map +1 -0
  7. package/createAcoGraphQL.d.ts +8 -4
  8. package/createAcoGraphQL.js +56 -96
  9. package/createAcoGraphQL.js.map +1 -1
  10. package/domain/folder/abstractions.d.ts +12 -5
  11. package/domain/folder/abstractions.js +2 -2
  12. package/domain/folder/abstractions.js.map +1 -1
  13. package/domain/folder/folder.model.js +2 -1
  14. package/domain/folder/folder.model.js.map +1 -1
  15. package/exports/api/aco/flp.d.ts +1 -0
  16. package/exports/api/aco/flp.js +1 -0
  17. package/exports/api/aco/folder.d.ts +2 -1
  18. package/exports/api/aco/folder.js +1 -1
  19. package/features/ai/CreateFolderTool.d.ts +49 -0
  20. package/features/ai/CreateFolderTool.js +58 -0
  21. package/features/ai/CreateFolderTool.js.map +1 -0
  22. package/features/ai/CreateTeamTool.d.ts +48 -0
  23. package/features/ai/CreateTeamTool.js +56 -0
  24. package/features/ai/CreateTeamTool.js.map +1 -0
  25. package/features/ai/DeleteFolderTool.d.ts +48 -0
  26. package/features/ai/DeleteFolderTool.js +55 -0
  27. package/features/ai/DeleteFolderTool.js.map +1 -0
  28. package/features/ai/GrantFolderAccessTool.d.ts +77 -0
  29. package/features/ai/GrantFolderAccessTool.js +80 -0
  30. package/features/ai/GrantFolderAccessTool.js.map +1 -0
  31. package/features/ai/ListFoldersTool.d.ts +47 -0
  32. package/features/ai/ListFoldersTool.js +57 -0
  33. package/features/ai/ListFoldersTool.js.map +1 -0
  34. package/features/ai/ListRolesTool.d.ts +39 -0
  35. package/features/ai/ListRolesTool.js +48 -0
  36. package/features/ai/ListRolesTool.js.map +1 -0
  37. package/features/ai/ListTeamsTool.d.ts +39 -0
  38. package/features/ai/ListTeamsTool.js +48 -0
  39. package/features/ai/ListTeamsTool.js.map +1 -0
  40. package/features/ai/RevokeFolderAccessTool.d.ts +63 -0
  41. package/features/ai/RevokeFolderAccessTool.js +69 -0
  42. package/features/ai/RevokeFolderAccessTool.js.map +1 -0
  43. package/features/ai/assertTargetIsUsable.d.ts +10 -0
  44. package/features/ai/assertTargetIsUsable.js +14 -0
  45. package/features/ai/assertTargetIsUsable.js.map +1 -0
  46. package/features/ai/feature.d.ts +12 -0
  47. package/features/ai/feature.js +25 -0
  48. package/features/ai/feature.js.map +1 -0
  49. package/features/ai/index.d.ts +9 -0
  50. package/features/ai/index.js +9 -0
  51. package/features/ai/loadFolderPermissions.d.ts +16 -0
  52. package/features/ai/loadFolderPermissions.js +14 -0
  53. package/features/ai/loadFolderPermissions.js.map +1 -0
  54. package/features/cms/decorators/ListDeletedEntriesWithFlpDecorator.js +1 -0
  55. package/features/cms/decorators/ListDeletedEntriesWithFlpDecorator.js.map +1 -1
  56. package/features/cms/decorators/ListEntriesWithFlpDecorator.js +1 -0
  57. package/features/cms/decorators/ListEntriesWithFlpDecorator.js.map +1 -1
  58. package/features/cms/decorators/ListLatestEntriesWithFlpDecorator.js +1 -0
  59. package/features/cms/decorators/ListLatestEntriesWithFlpDecorator.js.map +1 -1
  60. package/features/cms/decorators/ListPublishedEntriesWithFlpDecorator.js +1 -0
  61. package/features/cms/decorators/ListPublishedEntriesWithFlpDecorator.js.map +1 -1
  62. package/features/cms/decorators/MoveEntryWithFlpDecorator.d.ts +1 -1
  63. package/features/flp/CreateFlp/CreateFlpUseCase.d.ts +3 -3
  64. package/features/flp/CreateFlp/CreateFlpUseCase.js +4 -4
  65. package/features/flp/CreateFlp/CreateFlpUseCase.js.map +1 -1
  66. package/features/flp/CreateFlp/feature.d.ts +1 -6
  67. package/features/flp/CreateFlp/feature.js +3 -2
  68. package/features/flp/CreateFlp/feature.js.map +1 -1
  69. package/features/flp/CreateFlpOnFolderCreated/CreateFlpOnFolderCreatedHandler.d.ts +8 -5
  70. package/features/flp/CreateFlpOnFolderCreated/CreateFlpOnFolderCreatedHandler.js +21 -14
  71. package/features/flp/CreateFlpOnFolderCreated/CreateFlpOnFolderCreatedHandler.js.map +1 -1
  72. package/features/flp/DeleteFlp/DeleteFlpUseCase.d.ts +3 -3
  73. package/features/flp/DeleteFlp/DeleteFlpUseCase.js +3 -3
  74. package/features/flp/DeleteFlp/DeleteFlpUseCase.js.map +1 -1
  75. package/features/flp/DeleteFlp/feature.d.ts +1 -6
  76. package/features/flp/DeleteFlp/feature.js +3 -2
  77. package/features/flp/DeleteFlp/feature.js.map +1 -1
  78. package/features/flp/DeleteFlpOnFolderDeleted/DeleteFlpOnFolderDeletedHandler.d.ts +6 -5
  79. package/features/flp/DeleteFlpOnFolderDeleted/DeleteFlpOnFolderDeletedHandler.js +16 -13
  80. package/features/flp/DeleteFlpOnFolderDeleted/DeleteFlpOnFolderDeletedHandler.js.map +1 -1
  81. package/features/flp/FolderLevelPermissions/FolderLevelPermissions.d.ts +3 -3
  82. package/features/flp/FolderLevelPermissions/FolderLevelPermissions.js +6 -6
  83. package/features/flp/FolderLevelPermissions/FolderLevelPermissions.js.map +1 -1
  84. package/features/flp/FolderLevelPermissions/NoopFolderLevelPermissions.d.ts +25 -0
  85. package/features/flp/FolderLevelPermissions/NoopFolderLevelPermissions.js +48 -0
  86. package/features/flp/FolderLevelPermissions/NoopFolderLevelPermissions.js.map +1 -0
  87. package/features/flp/FolderLevelPermissions/index.d.ts +1 -0
  88. package/features/flp/FolderLevelPermissions/index.js +1 -0
  89. package/features/flp/GetFlp/decorators/GetFlpWithCodeFlps.d.ts +13 -0
  90. package/features/flp/GetFlp/decorators/GetFlpWithCodeFlps.js +26 -0
  91. package/features/flp/GetFlp/decorators/GetFlpWithCodeFlps.js.map +1 -0
  92. package/features/flp/GetFlp/feature.d.ts +1 -1
  93. package/features/flp/GetFlp/feature.js +3 -2
  94. package/features/flp/GetFlp/feature.js.map +1 -1
  95. package/features/flp/ListFlps/decorators/ListFlpsWithCodeFlps.d.ts +13 -0
  96. package/features/flp/ListFlps/decorators/ListFlpsWithCodeFlps.js +27 -0
  97. package/features/flp/ListFlps/decorators/ListFlpsWithCodeFlps.js.map +1 -0
  98. package/features/flp/ListFlps/feature.d.ts +1 -1
  99. package/features/flp/ListFlps/feature.js +3 -2
  100. package/features/flp/ListFlps/feature.js.map +1 -1
  101. package/features/flp/UpdateFlp/UpdateFlpUseCase.d.ts +15 -8
  102. package/features/flp/UpdateFlp/UpdateFlpUseCase.js +37 -42
  103. package/features/flp/UpdateFlp/UpdateFlpUseCase.js.map +1 -1
  104. package/features/flp/UpdateFlp/abstractions.d.ts +6 -2
  105. package/features/flp/UpdateFlp/abstractions.js.map +1 -1
  106. package/features/flp/UpdateFlp/feature.d.ts +1 -6
  107. package/features/flp/UpdateFlp/feature.js +7 -2
  108. package/features/flp/UpdateFlp/feature.js.map +1 -1
  109. package/features/flp/UpdateFlpOnFolderUpdated/UpdateFlpOnFolderUpdatedHandler.d.ts +8 -5
  110. package/features/flp/UpdateFlpOnFolderUpdated/UpdateFlpOnFolderUpdatedHandler.js +21 -16
  111. package/features/flp/UpdateFlpOnFolderUpdated/UpdateFlpOnFolderUpdatedHandler.js.map +1 -1
  112. package/features/flp/shared/CodeFlpMerger.d.ts +26 -0
  113. package/features/flp/shared/CodeFlpMerger.js +20 -0
  114. package/features/flp/shared/CodeFlpMerger.js.map +1 -0
  115. package/features/flp/shared/CodeFlpPath.d.ts +15 -0
  116. package/features/flp/shared/CodeFlpPath.js +29 -0
  117. package/features/flp/shared/CodeFlpPath.js.map +1 -0
  118. package/features/flp/shared/CodeFlpTarget.d.ts +10 -0
  119. package/features/flp/shared/CodeFlpTarget.js +26 -0
  120. package/features/flp/shared/CodeFlpTarget.js.map +1 -0
  121. package/features/flp/shared/CodeFlpsProvider.d.ts +14 -0
  122. package/features/flp/shared/CodeFlpsProvider.js +33 -0
  123. package/features/flp/shared/CodeFlpsProvider.js.map +1 -0
  124. package/features/flp/shared/abstractions.d.ts +77 -0
  125. package/features/flp/shared/abstractions.js +19 -0
  126. package/features/flp/shared/abstractions.js.map +1 -0
  127. package/features/flp/shared/feature.d.ts +5 -0
  128. package/features/flp/shared/feature.js +17 -0
  129. package/features/flp/shared/feature.js.map +1 -0
  130. package/features/flp/shared/index.d.ts +4 -0
  131. package/features/flp/shared/index.js +4 -0
  132. package/features/folder/CreateFolder/CreateFolderRepository.d.ts +3 -3
  133. package/features/folder/CreateFolder/CreateFolderRepository.js +10 -7
  134. package/features/folder/CreateFolder/CreateFolderRepository.js.map +1 -1
  135. package/features/folder/CreateFolder/decorators/CreateFolderWithFolderLevelPermissions.d.ts +9 -1
  136. package/features/folder/CreateFolder/decorators/CreateFolderWithFolderLevelPermissions.js +20 -3
  137. package/features/folder/CreateFolder/decorators/CreateFolderWithFolderLevelPermissions.js.map +1 -1
  138. package/features/folder/DeleteFolder/DeleteFolderRepository.d.ts +3 -3
  139. package/features/folder/DeleteFolder/DeleteFolderRepository.js +6 -5
  140. package/features/folder/DeleteFolder/DeleteFolderRepository.js.map +1 -1
  141. package/features/folder/DeleteFolder/decorators/DeleteFolderWithFolderLevelPermissions.d.ts +1 -1
  142. package/features/folder/EnsureFolderIsEmpty/EnsureFolderIsEmpty.js +4 -0
  143. package/features/folder/EnsureFolderIsEmpty/EnsureFolderIsEmpty.js.map +1 -1
  144. package/features/folder/EnsureHcmsFolderIsEmptyOnDelete/ModelFolderBeforeDeleteHandler.js +4 -0
  145. package/features/folder/EnsureHcmsFolderIsEmptyOnDelete/ModelFolderBeforeDeleteHandler.js.map +1 -1
  146. package/features/folder/FolderModelProvider.d.ts +26 -0
  147. package/features/folder/FolderModelProvider.js +22 -0
  148. package/features/folder/FolderModelProvider.js.map +1 -0
  149. package/features/folder/GetAncestors/GetAncestorsRepository.d.ts +3 -3
  150. package/features/folder/GetAncestors/GetAncestorsRepository.js +6 -5
  151. package/features/folder/GetAncestors/GetAncestorsRepository.js.map +1 -1
  152. package/features/folder/GetFolder/GetFolderRepository.d.ts +3 -3
  153. package/features/folder/GetFolder/GetFolderRepository.js +6 -5
  154. package/features/folder/GetFolder/GetFolderRepository.js.map +1 -1
  155. package/features/folder/GetFolder/decorators/GetFolderWithFolderLevelPermissions.d.ts +8 -8
  156. package/features/folder/GetFolderHierarchy/GetFolderHierarchyRepository.d.ts +3 -3
  157. package/features/folder/GetFolderHierarchy/GetFolderHierarchyRepository.js +10 -8
  158. package/features/folder/GetFolderHierarchy/GetFolderHierarchyRepository.js.map +1 -1
  159. package/features/folder/ListFolders/ListFoldersRepository.d.ts +3 -3
  160. package/features/folder/ListFolders/ListFoldersRepository.js +8 -7
  161. package/features/folder/ListFolders/ListFoldersRepository.js.map +1 -1
  162. package/features/folder/NotifyFolderChange/NotifyFolderChangeUseCase.d.ts +11 -0
  163. package/features/folder/NotifyFolderChange/NotifyFolderChangeUseCase.js +38 -0
  164. package/features/folder/NotifyFolderChange/NotifyFolderChangeUseCase.js.map +1 -0
  165. package/features/folder/NotifyFolderChange/NotifyOnFolderDeletedHandler.d.ts +12 -0
  166. package/features/folder/NotifyFolderChange/NotifyOnFolderDeletedHandler.js +24 -0
  167. package/features/folder/NotifyFolderChange/NotifyOnFolderDeletedHandler.js.map +1 -0
  168. package/features/folder/NotifyFolderChange/abstractions.d.ts +28 -0
  169. package/features/folder/NotifyFolderChange/abstractions.js +8 -0
  170. package/features/folder/NotifyFolderChange/abstractions.js.map +1 -0
  171. package/features/folder/NotifyFolderChange/feature.d.ts +9 -0
  172. package/features/folder/NotifyFolderChange/feature.js +13 -0
  173. package/features/folder/NotifyFolderChange/feature.js.map +1 -0
  174. package/features/folder/NotifyFolderChange/index.d.ts +2 -0
  175. package/features/folder/NotifyFolderChange/index.js +2 -0
  176. package/features/folder/UpdateFolder/UpdateFolderRepository.d.ts +3 -3
  177. package/features/folder/UpdateFolder/UpdateFolderRepository.js +11 -8
  178. package/features/folder/UpdateFolder/UpdateFolderRepository.js.map +1 -1
  179. package/features/folder/UpdateFolder/decorators/UpdateFolderWithFolderLevelPermissions.d.ts +14 -1
  180. package/features/folder/UpdateFolder/decorators/UpdateFolderWithFolderLevelPermissions.js +52 -4
  181. package/features/folder/UpdateFolder/decorators/UpdateFolderWithFolderLevelPermissions.js.map +1 -1
  182. package/features/folder/shared/abstractions.d.ts +14 -0
  183. package/features/folder/shared/abstractions.js +4 -1
  184. package/features/folder/shared/abstractions.js.map +1 -1
  185. package/filter/filter.gql.d.ts +2 -3
  186. package/filter/filter.gql.js +61 -27
  187. package/filter/filter.gql.js.map +1 -1
  188. package/filter/filter.model.js +2 -1
  189. package/filter/filter.model.js.map +1 -1
  190. package/filter/filter.so.d.ts +8 -2
  191. package/filter/filter.so.js +21 -9
  192. package/filter/filter.so.js.map +1 -1
  193. package/flp/flp.types.d.ts +6 -1
  194. package/flp/index.d.ts +0 -1
  195. package/flp/index.js +0 -1
  196. package/flp/tasks/createFlp.task.d.ts +12 -5
  197. package/flp/tasks/createFlp.task.js +32 -15
  198. package/flp/tasks/createFlp.task.js.map +1 -1
  199. package/flp/tasks/deleteFlp.task.d.ts +10 -5
  200. package/flp/tasks/deleteFlp.task.js +22 -13
  201. package/flp/tasks/deleteFlp.task.js.map +1 -1
  202. package/flp/tasks/index.d.ts +0 -1
  203. package/flp/tasks/index.js +1 -14
  204. package/flp/tasks/index.js.map +1 -1
  205. package/flp/tasks/syncFlp.task.d.ts +10 -5
  206. package/flp/tasks/syncFlp.task.js +34 -13
  207. package/flp/tasks/syncFlp.task.js.map +1 -1
  208. package/flp/tasks/updateFlp.task.d.ts +12 -5
  209. package/flp/tasks/updateFlp.task.js +40 -19
  210. package/flp/tasks/updateFlp.task.js.map +1 -1
  211. package/folder/createFolderTypeDefs.js +4 -1
  212. package/folder/createFolderTypeDefs.js.map +1 -1
  213. package/folder/folder.gql.d.ts +1 -1
  214. package/folder/folder.gql.js +10 -4
  215. package/folder/folder.gql.js.map +1 -1
  216. package/index.d.ts +1 -6
  217. package/index.js +1 -11
  218. package/package.json +25 -26
  219. package/types.d.ts +1 -2
  220. package/types.js.map +1 -1
  221. package/utils/createOperationsWrapper.d.ts +5 -2
  222. package/utils/createOperationsWrapper.js +5 -5
  223. package/utils/createOperationsWrapper.js.map +1 -1
  224. package/utils/decorators/CmsEntriesCrudDecorators.js +9 -5
  225. package/utils/decorators/CmsEntriesCrudDecorators.js.map +1 -1
  226. package/utils/resolve.d.ts +2 -2
  227. package/utils/resolve.js +1 -1
  228. package/utils/resolve.js.map +1 -1
  229. package/createAcoContext.d.ts +0 -9
  230. package/createAcoContext.js +0 -109
  231. package/createAcoContext.js.map +0 -1
  232. package/createAcoStorageOperations.d.ts +0 -12
  233. package/createAcoStorageOperations.js +0 -9
  234. package/createAcoStorageOperations.js.map +0 -1
  235. package/createAcoTasks.d.ts +0 -1
  236. package/createAcoTasks.js +0 -14
  237. package/createAcoTasks.js.map +0 -1
  238. package/flp/flp.so.d.ts +0 -20
  239. package/flp/flp.so.js +0 -183
  240. package/flp/flp.so.js.map +0 -1
  241. package/index.js.map +0 -1
@@ -0,0 +1,20 @@
1
+ class CodeFlpMerger {
2
+ static merge(flp, codePermissions) {
3
+ if (!codePermissions.length) return flp;
4
+ return {
5
+ ...flp,
6
+ permissions: CodeFlpMerger.mergePermissions(flp.permissions, codePermissions)
7
+ };
8
+ }
9
+ static mergePermissions(permissions, codePermissions) {
10
+ if (!codePermissions.length) return permissions;
11
+ const codeTargets = new Set(codePermissions.map((permission)=>permission.target));
12
+ return [
13
+ ...codePermissions,
14
+ ...permissions.filter((permission)=>!codeTargets.has(permission.target))
15
+ ];
16
+ }
17
+ }
18
+ export { CodeFlpMerger };
19
+
20
+ //# sourceMappingURL=CodeFlpMerger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"features/flp/shared/CodeFlpMerger.js","sources":["../../../../src/features/flp/shared/CodeFlpMerger.ts"],"sourcesContent":["import type { FolderLevelPermission, FolderPermission } from \"~/flp/flp.types.js\";\n\nexport class CodeFlpMerger {\n /**\n * Merge code-defined permissions into a stored FLP record.\n *\n * A code-defined permission always wins over a stored one for the same target, and that takes\n * both steps below — ordering alone is not enough, because the two downstream consumers pick a\n * target's permission in different ways:\n *\n * - `CanAccessFolder` takes the first match (`permissions.find(p => p.target === ...)`), so code\n * permissions go first.\n * - `DefaultPermissionsMerger` instead collects *every* permission for the identity and reduces\n * them by access level, preferring `no-access` and then `owner`. A leftover duplicate would\n * join that reduce and could outrank the code-defined entry — a stored `owner` would beat a\n * code-defined `viewer`. Dropping the stored permission for a code-defined target is what\n * prevents it.\n *\n * So: exactly one permission per target, and for code-defined targets it is the code one.\n */\n static merge(\n flp: FolderLevelPermission,\n codePermissions: FolderPermission[]\n ): FolderLevelPermission {\n if (!codePermissions.length) {\n return flp;\n }\n\n return {\n ...flp,\n permissions: CodeFlpMerger.mergePermissions(flp.permissions, codePermissions)\n };\n }\n\n /**\n * The same merge, for callers that hold a plain permission list rather than a stored FLP record\n * — the write paths, which resolve code permissions from the folder's own type and path.\n */\n static mergePermissions(\n permissions: FolderPermission[],\n codePermissions: FolderPermission[]\n ): FolderPermission[] {\n if (!codePermissions.length) {\n return permissions;\n }\n\n const codeTargets = new Set(codePermissions.map(permission => permission.target));\n\n return [\n ...codePermissions,\n ...permissions.filter(permission => !codeTargets.has(permission.target))\n ];\n }\n}\n"],"names":["CodeFlpMerger","flp","codePermissions","permissions","codeTargets","Set","permission"],"mappings":"AAEO,MAAMA;IAkBT,OAAO,MACHC,GAA0B,EAC1BC,eAAmC,EACd;QACrB,IAAI,CAACA,gBAAgB,MAAM,EACvB,OAAOD;QAGX,OAAO;YACH,GAAGA,GAAG;YACN,aAAaD,cAAc,gBAAgB,CAACC,IAAI,WAAW,EAAEC;QACjE;IACJ;IAMA,OAAO,iBACHC,WAA+B,EAC/BD,eAAmC,EACjB;QAClB,IAAI,CAACA,gBAAgB,MAAM,EACvB,OAAOC;QAGX,MAAMC,cAAc,IAAIC,IAAIH,gBAAgB,GAAG,CAACI,CAAAA,aAAcA,WAAW,MAAM;QAE/E,OAAO;eACAJ;eACAC,YAAY,MAAM,CAACG,CAAAA,aAAc,CAACF,YAAY,GAAG,CAACE,WAAW,MAAM;SACzE;IACL;AACJ"}
@@ -0,0 +1,15 @@
1
+ interface ParsedPath {
2
+ /** Normalized path, without the wildcard suffix, e.g. `root/marketing`. */
3
+ base: string;
4
+ /** Whether the rule was written with a trailing `/*`, meaning "this folder and its subtree". */
5
+ subtree: boolean;
6
+ }
7
+ /**
8
+ * Folder paths are stored as `root/<slug>[/<slug>...]` (see `~/utils/Path.ts`). Code-defined FLPs
9
+ * are authored by hand, so we accept the friendlier `/marketing` form as well and normalize it.
10
+ */
11
+ export declare class CodeFlpPath {
12
+ static parse(path: string): ParsedPath;
13
+ static matches(rulePath: string, folderPath: string): boolean;
14
+ }
15
+ export {};
@@ -0,0 +1,29 @@
1
+ import { ROOT_FOLDER } from "@webiny/shared-aco";
2
+ class CodeFlpPath {
3
+ static parse(path) {
4
+ let value = path.trim();
5
+ let subtree = false;
6
+ if (value.endsWith("*")) {
7
+ subtree = true;
8
+ value = value.slice(0, -1);
9
+ }
10
+ value = value.replace(/^\/+/, "").replace(/\/+$/, "");
11
+ if (value === ROOT_FOLDER || "" === value) return {
12
+ base: ROOT_FOLDER,
13
+ subtree: "" === value ? true : subtree
14
+ };
15
+ const base = value.startsWith(`${ROOT_FOLDER}/`) ? value : `${ROOT_FOLDER}/${value}`;
16
+ return {
17
+ base,
18
+ subtree
19
+ };
20
+ }
21
+ static matches(rulePath, folderPath) {
22
+ const { base, subtree } = CodeFlpPath.parse(rulePath);
23
+ if (folderPath === base) return true;
24
+ return subtree ? folderPath.startsWith(`${base}/`) : false;
25
+ }
26
+ }
27
+ export { CodeFlpPath };
28
+
29
+ //# sourceMappingURL=CodeFlpPath.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"features/flp/shared/CodeFlpPath.js","sources":["../../../../src/features/flp/shared/CodeFlpPath.ts"],"sourcesContent":["import { ROOT_FOLDER } from \"@webiny/shared-aco\";\n\ninterface ParsedPath {\n /** Normalized path, without the wildcard suffix, e.g. `root/marketing`. */\n base: string;\n /** Whether the rule was written with a trailing `/*`, meaning \"this folder and its subtree\". */\n subtree: boolean;\n}\n\n/**\n * Folder paths are stored as `root/<slug>[/<slug>...]` (see `~/utils/Path.ts`). Code-defined FLPs\n * are authored by hand, so we accept the friendlier `/marketing` form as well and normalize it.\n */\nexport class CodeFlpPath {\n static parse(path: string): ParsedPath {\n let value = path.trim();\n let subtree = false;\n\n // A trailing \"*\" (with or without the separator) means \"this folder and everything below\".\n if (value.endsWith(\"*\")) {\n subtree = true;\n value = value.slice(0, -1);\n }\n\n // Strip surrounding separators, so \"/marketing/\" and \"marketing\" normalize the same way.\n value = value.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\");\n\n if (value === ROOT_FOLDER || value === \"\") {\n return { base: ROOT_FOLDER, subtree: value === \"\" ? true : subtree };\n }\n\n // The \"root\" prefix is an implementation detail of stored paths — make it optional.\n const base = value.startsWith(`${ROOT_FOLDER}/`) ? value : `${ROOT_FOLDER}/${value}`;\n\n return { base, subtree };\n }\n\n static matches(rulePath: string, folderPath: string): boolean {\n const { base, subtree } = CodeFlpPath.parse(rulePath);\n\n if (folderPath === base) {\n return true;\n }\n\n return subtree ? folderPath.startsWith(`${base}/`) : false;\n }\n}\n"],"names":["CodeFlpPath","path","value","subtree","ROOT_FOLDER","base","rulePath","folderPath"],"mappings":";AAaO,MAAMA;IACT,OAAO,MAAMC,IAAY,EAAc;QACnC,IAAIC,QAAQD,KAAK,IAAI;QACrB,IAAIE,UAAU;QAGd,IAAID,MAAM,QAAQ,CAAC,MAAM;YACrBC,UAAU;YACVD,QAAQA,MAAM,KAAK,CAAC,GAAG;QAC3B;QAGAA,QAAQA,MAAM,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,QAAQ;QAElD,IAAIA,UAAUE,eAAeF,AAAU,OAAVA,OACzB,OAAO;YAAE,MAAME;YAAa,SAASF,AAAU,OAAVA,QAAe,OAAOC;QAAQ;QAIvE,MAAME,OAAOH,MAAM,UAAU,CAAC,GAAGE,YAAY,CAAC,CAAC,IAAIF,QAAQ,GAAGE,YAAY,CAAC,EAAEF,OAAO;QAEpF,OAAO;YAAEG;YAAMF;QAAQ;IAC3B;IAEA,OAAO,QAAQG,QAAgB,EAAEC,UAAkB,EAAW;QAC1D,MAAM,EAAEF,IAAI,EAAEF,OAAO,EAAE,GAAGH,YAAY,KAAK,CAACM;QAE5C,IAAIC,eAAeF,MACf,OAAO;QAGX,OAAOF,UAAUI,WAAW,UAAU,CAAC,GAAGF,KAAK,CAAC,CAAC,IAAI;IACzD;AACJ"}
@@ -0,0 +1,10 @@
1
+ import type { CodeFolderPermission } from "./abstractions.js";
2
+ import type { FolderPermission } from "../../../flp/flp.types.js";
3
+ /**
4
+ * Code-defined permissions are authored as `{ team: "editors" }` or `{ user: "<id>" }`. Internally,
5
+ * a permission's target is a single string — `team:editors` or `admin:<id>` — so this is where the
6
+ * authored form is turned into the stored one.
7
+ */
8
+ export declare class CodeFlpTarget {
9
+ static resolve(permission: CodeFolderPermission): FolderPermission;
10
+ }
@@ -0,0 +1,26 @@
1
+ import { WebinyError } from "@webiny/error";
2
+ class CodeFlpTarget {
3
+ static resolve(permission) {
4
+ const { team, user, level } = permission;
5
+ if (void 0 !== team && void 0 !== user) throw new WebinyError("A code-defined folder permission must target either a team or a user, not both.", "CODE_FLP_AMBIGUOUS_TARGET", {
6
+ team,
7
+ user
8
+ });
9
+ if (void 0 !== team) return {
10
+ target: `team:${team}`,
11
+ level,
12
+ plugin: true
13
+ };
14
+ if (void 0 !== user) return {
15
+ target: `admin:${user}`,
16
+ level,
17
+ plugin: true
18
+ };
19
+ throw new WebinyError('A code-defined folder permission must specify either "team" or "user".', "CODE_FLP_MISSING_TARGET", {
20
+ permission
21
+ });
22
+ }
23
+ }
24
+ export { CodeFlpTarget };
25
+
26
+ //# sourceMappingURL=CodeFlpTarget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"features/flp/shared/CodeFlpTarget.js","sources":["../../../../src/features/flp/shared/CodeFlpTarget.ts"],"sourcesContent":["import { WebinyError } from \"@webiny/error\";\nimport type { CodeFolderPermission } from \"./abstractions.js\";\nimport type { FolderPermission } from \"~/flp/flp.types.js\";\n\n/**\n * Code-defined permissions are authored as `{ team: \"editors\" }` or `{ user: \"<id>\" }`. Internally,\n * a permission's target is a single string — `team:editors` or `admin:<id>` — so this is where the\n * authored form is turned into the stored one.\n */\nexport class CodeFlpTarget {\n static resolve(permission: CodeFolderPermission): FolderPermission {\n const { team, user, level } = permission;\n\n if (team !== undefined && user !== undefined) {\n throw new WebinyError(\n `A code-defined folder permission must target either a team or a user, not both.`,\n \"CODE_FLP_AMBIGUOUS_TARGET\",\n { team, user }\n );\n }\n\n if (team !== undefined) {\n return { target: `team:${team}`, level, plugin: true };\n }\n\n if (user !== undefined) {\n return { target: `admin:${user}`, level, plugin: true };\n }\n\n // Without a target we'd silently produce a permission that matches nobody. For a rule that\n // denies access, dropping it quietly would mean accidental exposure — so fail loudly.\n throw new WebinyError(\n `A code-defined folder permission must specify either \"team\" or \"user\".`,\n \"CODE_FLP_MISSING_TARGET\",\n { permission }\n );\n }\n}\n"],"names":["CodeFlpTarget","permission","team","user","level","undefined","WebinyError"],"mappings":";AASO,MAAMA;IACT,OAAO,QAAQC,UAAgC,EAAoB;QAC/D,MAAM,EAAEC,IAAI,EAAEC,IAAI,EAAEC,KAAK,EAAE,GAAGH;QAE9B,IAAIC,AAASG,WAATH,QAAsBC,AAASE,WAATF,MACtB,MAAM,IAAIG,YACN,mFACA,6BACA;YAAEJ;YAAMC;QAAK;QAIrB,IAAID,AAASG,WAATH,MACA,OAAO;YAAE,QAAQ,CAAC,KAAK,EAAEA,MAAM;YAAEE;YAAO,QAAQ;QAAK;QAGzD,IAAID,AAASE,WAATF,MACA,OAAO;YAAE,QAAQ,CAAC,MAAM,EAAEA,MAAM;YAAEC;YAAO,QAAQ;QAAK;QAK1D,MAAM,IAAIE,YACN,0EACA,2BACA;YAAEL;QAAW;IAErB;AACJ"}
@@ -0,0 +1,14 @@
1
+ import { CodeFlpsProvider as CodeFlpsProviderAbstraction, FlpFactory, type GetCodePermissionsParams } from "./abstractions.js";
2
+ import type { FolderPermission } from "../../../flp/flp.types.js";
3
+ declare class CodeFlpsProviderImpl implements CodeFlpsProviderAbstraction.Interface {
4
+ private flpFactories;
5
+ private cache;
6
+ constructor(flpFactories: FlpFactory.Interface[]);
7
+ getPermissions({ type, path }: GetCodePermissionsParams): Promise<FolderPermission[]>;
8
+ /** All code-defined FLPs, collected from every registered `FlpFactory`. */
9
+ private getCodeFlps;
10
+ }
11
+ export declare const CodeFlpsProvider: typeof CodeFlpsProviderImpl & {
12
+ __abstraction: import("@webiny/di").Abstraction<import("./abstractions.js").ICodeFlpsProvider>;
13
+ };
14
+ export {};
@@ -0,0 +1,33 @@
1
+ import { CodeFlpsProvider, FlpFactory } from "./abstractions.js";
2
+ import { CodeFlpPath } from "./CodeFlpPath.js";
3
+ import { CodeFlpTarget } from "./CodeFlpTarget.js";
4
+ class CodeFlpsProviderImpl {
5
+ constructor(flpFactories){
6
+ this.flpFactories = flpFactories;
7
+ }
8
+ async getPermissions({ type, path }) {
9
+ const codeFlps = await this.getCodeFlps();
10
+ return codeFlps.filter((flp)=>flp.type === type && CodeFlpPath.matches(flp.path, path)).flatMap((flp)=>flp.permissions.map((permission)=>CodeFlpTarget.resolve(permission)));
11
+ }
12
+ async getCodeFlps() {
13
+ if (void 0 === this.cache) {
14
+ const results = await Promise.all(this.flpFactories.map((factory)=>factory.execute()));
15
+ this.cache = results.flat();
16
+ }
17
+ return this.cache;
18
+ }
19
+ }
20
+ const CodeFlpsProvider_CodeFlpsProvider = CodeFlpsProvider.createImplementation({
21
+ implementation: CodeFlpsProviderImpl,
22
+ dependencies: [
23
+ [
24
+ FlpFactory,
25
+ {
26
+ multiple: true
27
+ }
28
+ ]
29
+ ]
30
+ });
31
+ export { CodeFlpsProvider_CodeFlpsProvider as CodeFlpsProvider };
32
+
33
+ //# sourceMappingURL=CodeFlpsProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"features/flp/shared/CodeFlpsProvider.js","sources":["../../../../src/features/flp/shared/CodeFlpsProvider.ts"],"sourcesContent":["import {\n type CodeFlp,\n CodeFlpsProvider as CodeFlpsProviderAbstraction,\n FlpFactory,\n type GetCodePermissionsParams\n} from \"./abstractions.js\";\nimport { CodeFlpPath } from \"./CodeFlpPath.js\";\nimport { CodeFlpTarget } from \"./CodeFlpTarget.js\";\nimport type { FolderPermission } from \"~/flp/flp.types.js\";\n\nclass CodeFlpsProviderImpl implements CodeFlpsProviderAbstraction.Interface {\n private cache: CodeFlp[] | undefined;\n\n constructor(private flpFactories: FlpFactory.Interface[]) {}\n\n async getPermissions({ type, path }: GetCodePermissionsParams): Promise<FolderPermission[]> {\n const codeFlps = await this.getCodeFlps();\n\n return codeFlps\n .filter(flp => flp.type === type && CodeFlpPath.matches(flp.path, path))\n .flatMap<FolderPermission>(flp => {\n return flp.permissions.map(permission => CodeFlpTarget.resolve(permission));\n });\n }\n\n /** All code-defined FLPs, collected from every registered `FlpFactory`. */\n private async getCodeFlps(): Promise<CodeFlp[]> {\n if (this.cache === undefined) {\n const results = await Promise.all(this.flpFactories.map(factory => factory.execute()));\n this.cache = results.flat();\n }\n\n return this.cache;\n }\n}\n\nexport const CodeFlpsProvider = CodeFlpsProviderAbstraction.createImplementation({\n implementation: CodeFlpsProviderImpl,\n dependencies: [[FlpFactory, { multiple: true }]]\n});\n"],"names":["CodeFlpsProviderImpl","flpFactories","type","path","codeFlps","flp","CodeFlpPath","permission","CodeFlpTarget","undefined","results","Promise","factory","CodeFlpsProvider","CodeFlpsProviderAbstraction","FlpFactory"],"mappings":";;;AAUA,MAAMA;IAGF,YAAoBC,YAAoC,CAAE;aAAtCA,YAAY,GAAZA;IAAuC;IAE3D,MAAM,eAAe,EAAEC,IAAI,EAAEC,IAAI,EAA4B,EAA+B;QACxF,MAAMC,WAAW,MAAM,IAAI,CAAC,WAAW;QAEvC,OAAOA,SACF,MAAM,CAACC,CAAAA,MAAOA,IAAI,IAAI,KAAKH,QAAQI,YAAY,OAAO,CAACD,IAAI,IAAI,EAAEF,OACjE,OAAO,CAAmBE,CAAAA,MAChBA,IAAI,WAAW,CAAC,GAAG,CAACE,CAAAA,aAAcC,cAAc,OAAO,CAACD;IAE3E;IAGA,MAAc,cAAkC;QAC5C,IAAI,AAAeE,WAAf,IAAI,CAAC,KAAK,EAAgB;YAC1B,MAAMC,UAAU,MAAMC,QAAQ,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAACC,CAAAA,UAAWA,QAAQ,OAAO;YAClF,IAAI,CAAC,KAAK,GAAGF,QAAQ,IAAI;QAC7B;QAEA,OAAO,IAAI,CAAC,KAAK;IACrB;AACJ;AAEO,MAAMG,oCAAmBC,iBAAAA,oBAAgD,CAAC;IAC7E,gBAAgBd;IAChB,cAAc;QAAC;YAACe;YAAY;gBAAE,UAAU;YAAK;SAAE;KAAC;AACpD"}
@@ -0,0 +1,77 @@
1
+ import type { FolderAccessLevel, FolderPermission } from "../../../flp/flp.types.js";
2
+ interface CodeTeamPermission {
3
+ /** Slug of the team the permission is granted to. */
4
+ team: string;
5
+ user?: never;
6
+ level: FolderAccessLevel;
7
+ }
8
+ interface CodeUserPermission {
9
+ /** ID of the admin user the permission is granted to. */
10
+ user: string;
11
+ team?: never;
12
+ level: FolderAccessLevel;
13
+ }
14
+ /**
15
+ * A permission grants a level to exactly one target: either a team or a single admin user. The
16
+ * `team:` / `admin:` target strings used internally are generated from these.
17
+ *
18
+ * Prefer `team` — team slugs are authored by hand and stable, while user IDs are generated at
19
+ * runtime and differ per environment.
20
+ */
21
+ export type CodeFolderPermission = CodeTeamPermission | CodeUserPermission;
22
+ export type CodeFlp = {
23
+ /**
24
+ * Folder type the rule applies to. Use `FlpFactory.FolderType` to build the built-in ones
25
+ * instead of writing the string by hand.
26
+ */
27
+ type: string;
28
+ /**
29
+ * Folder path the rule binds to. The leading `root` segment is optional, so both `/marketing`
30
+ * and `root/marketing` are accepted. A trailing `/*` matches the folder and its whole subtree.
31
+ */
32
+ path: string;
33
+ permissions: CodeFolderPermission[];
34
+ };
35
+ export interface IFlpFactory {
36
+ execute(): Promise<CodeFlp[]>;
37
+ }
38
+ /** Provide code-defined folder-level permissions. */
39
+ export declare const FlpFactory: import("@webiny/di").Abstraction<IFlpFactory> & {
40
+ FolderType: {
41
+ /** File Manager folders. */
42
+ FileManager: {
43
+ /** Folders holding files. */
44
+ Files: string;
45
+ };
46
+ /** Headless CMS folders. */
47
+ Cms: {
48
+ /** Folders holding entries of a content model, addressed by its `modelId`. */
49
+ Entries(modelId: string): string;
50
+ };
51
+ };
52
+ };
53
+ export declare namespace FlpFactory {
54
+ type Interface = IFlpFactory;
55
+ type Return = Promise<CodeFlp[]>;
56
+ type Flp = CodeFlp;
57
+ type Permission = CodeFolderPermission;
58
+ }
59
+ export interface GetCodePermissionsParams {
60
+ type: string;
61
+ path: string;
62
+ }
63
+ export interface ICodeFlpsProvider {
64
+ /**
65
+ * Return all code-defined permissions that apply to the given folder type and path.
66
+ */
67
+ getPermissions(params: GetCodePermissionsParams): Promise<FolderPermission[]>;
68
+ }
69
+ /**
70
+ * Resolve code-defined folder-level permissions for a given folder. Only permissions contributed by
71
+ * an `FlpFactory` are considered — the ones stored in the database are loaded separately.
72
+ */
73
+ export declare const CodeFlpsProvider: import("@webiny/di").Abstraction<ICodeFlpsProvider>;
74
+ export declare namespace CodeFlpsProvider {
75
+ type Interface = ICodeFlpsProvider;
76
+ }
77
+ export {};
@@ -0,0 +1,19 @@
1
+ import { createAbstraction } from "@webiny/feature/api";
2
+ import { FM_FILE_TYPE } from "../../../constants.js";
3
+ const FolderType = {
4
+ FileManager: {
5
+ Files: FM_FILE_TYPE
6
+ },
7
+ Cms: {
8
+ Entries (modelId) {
9
+ return `cms:${modelId}`;
10
+ }
11
+ }
12
+ };
13
+ const FlpFactory = Object.assign(createAbstraction("FlpFactory"), {
14
+ FolderType: FolderType
15
+ });
16
+ const CodeFlpsProvider = createAbstraction("CodeFlpsProvider");
17
+ export { CodeFlpsProvider, FlpFactory };
18
+
19
+ //# sourceMappingURL=abstractions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"features/flp/shared/abstractions.js","sources":["../../../../src/features/flp/shared/abstractions.ts"],"sourcesContent":["import { createAbstraction } from \"@webiny/feature/api\";\nimport { FM_FILE_TYPE } from \"~/constants.js\";\nimport type { FolderAccessLevel, FolderPermission } from \"~/flp/flp.types.js\";\n\ninterface CodeTeamPermission {\n /** Slug of the team the permission is granted to. */\n team: string;\n user?: never;\n level: FolderAccessLevel;\n}\n\ninterface CodeUserPermission {\n /** ID of the admin user the permission is granted to. */\n user: string;\n team?: never;\n level: FolderAccessLevel;\n}\n\n/**\n * A permission grants a level to exactly one target: either a team or a single admin user. The\n * `team:` / `admin:` target strings used internally are generated from these.\n *\n * Prefer `team` — team slugs are authored by hand and stable, while user IDs are generated at\n * runtime and differ per environment.\n */\nexport type CodeFolderPermission = CodeTeamPermission | CodeUserPermission;\n\nexport type CodeFlp = {\n /**\n * Folder type the rule applies to. Use `FlpFactory.FolderType` to build the built-in ones\n * instead of writing the string by hand.\n */\n type: string;\n /**\n * Folder path the rule binds to. The leading `root` segment is optional, so both `/marketing`\n * and `root/marketing` are accepted. A trailing `/*` matches the folder and its whole subtree.\n */\n path: string;\n permissions: CodeFolderPermission[];\n};\n\nexport interface IFlpFactory {\n execute(): Promise<CodeFlp[]>;\n}\n\n/**\n * The folder types shipped with Webiny, grouped by the app that owns them, so `CodeFlp.type` does\n * not have to be written by hand.\n *\n * Folder types stay open-ended — every app registering folders picks its own type — so `type`\n * remains a plain `string` and a custom app can still pass its own value directly.\n */\nconst FolderType = {\n /** File Manager folders. */\n FileManager: {\n /** Folders holding files. */\n Files: FM_FILE_TYPE as string\n },\n /** Headless CMS folders. */\n Cms: {\n /** Folders holding entries of a content model, addressed by its `modelId`. */\n Entries(modelId: string): string {\n return `cms:${modelId}`;\n }\n }\n};\n\n/** Provide code-defined folder-level permissions. */\nexport const FlpFactory = Object.assign(createAbstraction<IFlpFactory>(\"FlpFactory\"), {\n FolderType\n});\n\nexport namespace FlpFactory {\n export type Interface = IFlpFactory;\n export type Return = Promise<CodeFlp[]>;\n export type Flp = CodeFlp;\n export type Permission = CodeFolderPermission;\n}\n\nexport interface GetCodePermissionsParams {\n type: string;\n path: string;\n}\n\nexport interface ICodeFlpsProvider {\n /**\n * Return all code-defined permissions that apply to the given folder type and path.\n */\n getPermissions(params: GetCodePermissionsParams): Promise<FolderPermission[]>;\n}\n\n/**\n * Resolve code-defined folder-level permissions for a given folder. Only permissions contributed by\n * an `FlpFactory` are considered — the ones stored in the database are loaded separately.\n */\nexport const CodeFlpsProvider = createAbstraction<ICodeFlpsProvider>(\"CodeFlpsProvider\");\n\nexport namespace CodeFlpsProvider {\n export type Interface = ICodeFlpsProvider;\n}\n"],"names":["FolderType","FM_FILE_TYPE","modelId","FlpFactory","Object","createAbstraction","CodeFlpsProvider"],"mappings":";;AAoDA,MAAMA,aAAa;IAEf,aAAa;QAET,OAAOC;IACX;IAEA,KAAK;QAED,SAAQC,OAAe;YACnB,OAAO,CAAC,IAAI,EAAEA,SAAS;QAC3B;IACJ;AACJ;AAGO,MAAMC,aAAaC,OAAO,MAAM,CAACC,kBAA+B,eAAe;IAClFL,YAAAA;AACJ;AAyBO,MAAMM,mBAAmBD,kBAAqC"}
@@ -0,0 +1,5 @@
1
+ import { type Container } from "@webiny/feature/api";
2
+ export declare const CodeFlpsFeature: {
3
+ name: string;
4
+ register(container: Container): void;
5
+ };
@@ -0,0 +1,17 @@
1
+ import { createFeature } from "@webiny/feature/api";
2
+ import { FeatureFlags } from "@webiny/api-core/features/featureFlags/abstractions.js";
3
+ import { CodeFlpsProvider } from "./CodeFlpsProvider.js";
4
+ import { GetFlpWithCodeFlps } from "../GetFlp/decorators/GetFlpWithCodeFlps.js";
5
+ import { ListFlpsWithCodeFlps } from "../ListFlps/decorators/ListFlpsWithCodeFlps.js";
6
+ const CodeFlpsFeature = createFeature({
7
+ name: "CodeFlps",
8
+ register (container) {
9
+ if (!container.resolve(FeatureFlags).get().isEnabled("advancedAccessControlLayer.folderLevelPermissions")) return;
10
+ container.register(CodeFlpsProvider).inSingletonScope();
11
+ container.registerDecorator(GetFlpWithCodeFlps);
12
+ container.registerDecorator(ListFlpsWithCodeFlps);
13
+ }
14
+ });
15
+ export { CodeFlpsFeature };
16
+
17
+ //# sourceMappingURL=feature.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"features/flp/shared/feature.js","sources":["../../../../src/features/flp/shared/feature.ts"],"sourcesContent":["import { type Container, createFeature } from \"@webiny/feature/api\";\nimport { FeatureFlags } from \"@webiny/api-core/features/featureFlags/abstractions.js\";\nimport { CodeFlpsProvider } from \"./CodeFlpsProvider.js\";\nimport { GetFlpWithCodeFlps } from \"~/features/flp/GetFlp/decorators/GetFlpWithCodeFlps.js\";\nimport { ListFlpsWithCodeFlps } from \"~/features/flp/ListFlps/decorators/ListFlpsWithCodeFlps.js\";\n\nexport const CodeFlpsFeature = createFeature({\n name: \"CodeFlps\",\n register(container: Container) {\n // Code-defined FLPs are part of folder-level permissions, which is license-gated. Check at\n // register time so nothing wires up — and no code permission is ever enforced — without the\n // entitlement.\n if (\n !container\n .resolve(FeatureFlags)\n .get()\n .isEnabled(\"advancedAccessControlLayer.folderLevelPermissions\")\n ) {\n return;\n }\n\n container.register(CodeFlpsProvider).inSingletonScope();\n container.registerDecorator(GetFlpWithCodeFlps);\n container.registerDecorator(ListFlpsWithCodeFlps);\n }\n});\n"],"names":["CodeFlpsFeature","createFeature","container","FeatureFlags","CodeFlpsProvider","GetFlpWithCodeFlps","ListFlpsWithCodeFlps"],"mappings":";;;;;AAMO,MAAMA,kBAAkBC,cAAc;IACzC,MAAM;IACN,UAASC,SAAoB;QAIzB,IACI,CAACA,UACI,OAAO,CAACC,cACR,GAAG,GACH,SAAS,CAAC,sDAEf;QAGJD,UAAU,QAAQ,CAACE,kBAAkB,gBAAgB;QACrDF,UAAU,iBAAiB,CAACG;QAC5BH,UAAU,iBAAiB,CAACI;IAChC;AACJ"}
@@ -0,0 +1,4 @@
1
+ export * from "./abstractions.js";
2
+ export * from "./CodeFlpMerger.js";
3
+ export * from "./CodeFlpPath.js";
4
+ export * from "./CodeFlpTarget.js";
@@ -0,0 +1,4 @@
1
+ export * from "./abstractions.js";
2
+ export * from "./CodeFlpMerger.js";
3
+ export * from "./CodeFlpPath.js";
4
+ export * from "./CodeFlpTarget.js";
@@ -3,14 +3,14 @@ import { CreateFolderRepository as RepositoryAbstraction, type ICreateFolderRepo
3
3
  import { CreateEntryUseCase } from "@webiny/api-headless-cms/features/contentEntry/CreateEntry";
4
4
  import { ListLatestEntriesUseCase } from "@webiny/api-headless-cms/features/contentEntry/ListEntries";
5
5
  import { GetEntryByIdUseCase } from "@webiny/api-headless-cms/features/contentEntry/GetEntryById";
6
- import { FolderModel } from "../../../domain/folder/abstractions.js";
6
+ import { FolderModelProvider } from "../../../domain/folder/abstractions.js";
7
7
  import type { CreateFolderParams, Folder } from "../../../folder/folder.types.js";
8
8
  declare class CreateFolderRepositoryImpl implements ICreateFolderRepository {
9
9
  private createEntry;
10
10
  private listLatestEntries;
11
11
  private getEntryById;
12
- private folderModel;
13
- constructor(createEntry: CreateEntryUseCase.Interface, listLatestEntries: ListLatestEntriesUseCase.Interface, getEntryById: GetEntryByIdUseCase.Interface, folderModel: FolderModel.Interface);
12
+ private folderModelProvider;
13
+ constructor(createEntry: CreateEntryUseCase.Interface, listLatestEntries: ListLatestEntriesUseCase.Interface, getEntryById: GetEntryByIdUseCase.Interface, folderModelProvider: FolderModelProvider.Interface);
14
14
  execute(data: CreateFolderParams): Promise<Result<Folder, RepositoryAbstraction.Error>>;
15
15
  private checkExistingFolder;
16
16
  private createFolderPath;
@@ -3,19 +3,20 @@ import { CreateFolderRepository } from "./abstractions.js";
3
3
  import { CreateEntryUseCase } from "@webiny/api-headless-cms/features/contentEntry/CreateEntry";
4
4
  import { ListLatestEntriesUseCase } from "@webiny/api-headless-cms/features/contentEntry/ListEntries";
5
5
  import { GetEntryByIdUseCase } from "@webiny/api-headless-cms/features/contentEntry/GetEntryById";
6
- import { FolderModel } from "../../../domain/folder/abstractions.js";
6
+ import { FolderModelProvider } from "../../../domain/folder/abstractions.js";
7
7
  import { EntryToFolderMapper } from "../shared/EntryToFolderMapper.js";
8
8
  import { FolderPersistenceError, FolderValidationError } from "../../../domain/folder/errors.js";
9
9
  import { Path } from "../../../utils/Path.js";
10
10
  import { EntryId } from "@webiny/api-headless-cms/exports/api/cms/entry.js";
11
11
  class CreateFolderRepositoryImpl {
12
- constructor(createEntry, listLatestEntries, getEntryById, folderModel){
12
+ constructor(createEntry, listLatestEntries, getEntryById, folderModelProvider){
13
13
  this.createEntry = createEntry;
14
14
  this.listLatestEntries = listLatestEntries;
15
15
  this.getEntryById = getEntryById;
16
- this.folderModel = folderModel;
16
+ this.folderModelProvider = folderModelProvider;
17
17
  }
18
18
  async execute(data) {
19
+ const folderModel = await this.folderModelProvider.get();
19
20
  const checkResult = await this.checkExistingFolder({
20
21
  type: data.type,
21
22
  slug: data.slug,
@@ -27,7 +28,7 @@ class CreateFolderRepositoryImpl {
27
28
  parentId: data.parentId
28
29
  });
29
30
  if (pathResult.isFail()) return Result.fail(pathResult.error);
30
- const result = await this.createEntry.execute(this.folderModel, {
31
+ const result = await this.createEntry.execute(folderModel, {
31
32
  values: {
32
33
  ...data,
33
34
  parentId: data.parentId || null,
@@ -42,8 +43,9 @@ class CreateFolderRepositoryImpl {
42
43
  return Result.ok(folder);
43
44
  }
44
45
  async checkExistingFolder(params) {
46
+ const folderModel = await this.folderModelProvider.get();
45
47
  const { type, slug, parentId, excludeId } = params;
46
- const result = await this.listLatestEntries.execute(this.folderModel, {
48
+ const result = await this.listLatestEntries.execute(folderModel, {
47
49
  where: {
48
50
  latest: true,
49
51
  values: {
@@ -63,9 +65,10 @@ class CreateFolderRepositoryImpl {
63
65
  return Result.ok();
64
66
  }
65
67
  async createFolderPath(params) {
68
+ const folderModel = await this.folderModelProvider.get();
66
69
  const { slug, parentId } = params;
67
70
  if (!parentId) return Result.ok(Path.create(slug));
68
- const parentResult = await this.getEntryById.execute(this.folderModel, EntryId.from(parentId).toString());
71
+ const parentResult = await this.getEntryById.execute(folderModel, EntryId.from(parentId).toString());
69
72
  if (parentResult.isFail()) return Result.fail(new FolderPersistenceError(new Error("Parent folder not found. Unable to create the folder path")));
70
73
  const parentFolder = EntryToFolderMapper.toFolder(parentResult.value);
71
74
  return Result.ok(Path.create(slug, parentFolder.path));
@@ -77,7 +80,7 @@ const CreateFolderRepository_CreateFolderRepository = CreateFolderRepository.cre
77
80
  CreateEntryUseCase,
78
81
  ListLatestEntriesUseCase,
79
82
  GetEntryByIdUseCase,
80
- FolderModel
83
+ FolderModelProvider
81
84
  ]
82
85
  });
83
86
  export { CreateFolderRepository_CreateFolderRepository as CreateFolderRepository };
@@ -1 +1 @@
1
- {"version":3,"file":"features/folder/CreateFolder/CreateFolderRepository.js","sources":["../../../../src/features/folder/CreateFolder/CreateFolderRepository.ts"],"sourcesContent":["import { Result } from \"@webiny/feature/api\";\nimport {\n CreateFolderRepository as RepositoryAbstraction,\n type ICreateFolderRepository\n} from \"./abstractions.js\";\nimport { CreateEntryUseCase } from \"@webiny/api-headless-cms/features/contentEntry/CreateEntry\";\nimport { ListLatestEntriesUseCase } from \"@webiny/api-headless-cms/features/contentEntry/ListEntries\";\nimport { GetEntryByIdUseCase } from \"@webiny/api-headless-cms/features/contentEntry/GetEntryById\";\nimport { FolderModel } from \"~/domain/folder/abstractions.js\";\nimport type { CmsEntryFolder, CreateFolderParams, Folder } from \"~/folder/folder.types.js\";\nimport { EntryToFolderMapper } from \"../shared/EntryToFolderMapper.js\";\nimport { FolderPersistenceError, FolderValidationError } from \"~/domain/folder/errors.js\";\nimport { Path } from \"~/utils/Path.js\";\nimport { EntryId } from \"@webiny/api-headless-cms/exports/api/cms/entry.js\";\n\nclass CreateFolderRepositoryImpl implements ICreateFolderRepository {\n constructor(\n private createEntry: CreateEntryUseCase.Interface,\n private listLatestEntries: ListLatestEntriesUseCase.Interface,\n private getEntryById: GetEntryByIdUseCase.Interface,\n private folderModel: FolderModel.Interface\n ) {}\n\n async execute(data: CreateFolderParams): Promise<Result<Folder, RepositoryAbstraction.Error>> {\n // Check if folder already exists\n const checkResult = await this.checkExistingFolder({\n type: data.type,\n slug: data.slug,\n parentId: data.parentId\n });\n\n if (checkResult.isFail()) {\n return Result.fail(checkResult.error);\n }\n\n // Create folder path\n const pathResult = await this.createFolderPath({\n slug: data.slug,\n parentId: data.parentId\n });\n\n if (pathResult.isFail()) {\n return Result.fail(pathResult.error);\n }\n\n // Create the entry\n const result = await this.createEntry.execute<CmsEntryFolder>(this.folderModel, {\n values: {\n ...data,\n parentId: data.parentId || null,\n path: pathResult.value\n }\n });\n\n if (result.isFail()) {\n if (result.error.code === \"Cms/Entry/ValidationError\") {\n return Result.fail(new FolderValidationError(result.error.message));\n }\n return Result.fail(new FolderPersistenceError(result.error));\n }\n\n const folder = EntryToFolderMapper.toFolder(result.value);\n return Result.ok(folder);\n }\n\n private async checkExistingFolder(params: {\n type: string;\n slug: string;\n parentId?: string | null;\n excludeId?: string;\n }): Promise<Result<void, RepositoryAbstraction.Error>> {\n const { type, slug, parentId, excludeId } = params;\n\n const result = await this.listLatestEntries.execute<CmsEntryFolder>(this.folderModel, {\n where: {\n latest: true,\n values: {\n type,\n slug,\n parentId\n },\n ...(excludeId ? { entryId_not: excludeId } : {})\n },\n limit: 1\n });\n\n if (result.isFail()) {\n return Result.fail(new FolderPersistenceError(result.error));\n }\n\n const { entries } = result.value;\n\n if (entries.length > 0) {\n return Result.fail(\n new FolderValidationError(\n `Folder with slug \"${slug}\" already exists at this level.`\n )\n );\n }\n\n return Result.ok();\n }\n\n private async createFolderPath(params: {\n slug: string;\n parentId?: string | null;\n }): Promise<Result<string, RepositoryAbstraction.Error>> {\n const { slug, parentId } = params;\n\n if (!parentId) {\n return Result.ok(Path.create(slug));\n }\n\n const parentResult = await this.getEntryById.execute<CmsEntryFolder>(\n this.folderModel,\n EntryId.from(parentId).toString()\n );\n\n if (parentResult.isFail()) {\n return Result.fail(\n new FolderPersistenceError(\n new Error(\"Parent folder not found. Unable to create the folder path\")\n )\n );\n }\n\n const parentFolder = EntryToFolderMapper.toFolder(parentResult.value);\n return Result.ok(Path.create(slug, parentFolder.path));\n }\n}\n\nexport const CreateFolderRepository = RepositoryAbstraction.createImplementation({\n implementation: CreateFolderRepositoryImpl,\n dependencies: [CreateEntryUseCase, ListLatestEntriesUseCase, GetEntryByIdUseCase, FolderModel]\n});\n"],"names":["CreateFolderRepositoryImpl","createEntry","listLatestEntries","getEntryById","folderModel","data","checkResult","Result","pathResult","result","FolderValidationError","FolderPersistenceError","folder","EntryToFolderMapper","params","type","slug","parentId","excludeId","entries","Path","parentResult","EntryId","Error","parentFolder","CreateFolderRepository","RepositoryAbstraction","CreateEntryUseCase","ListLatestEntriesUseCase","GetEntryByIdUseCase","FolderModel"],"mappings":";;;;;;;;;;AAeA,MAAMA;IACF,YACYC,WAAyC,EACzCC,iBAAqD,EACrDC,YAA2C,EAC3CC,WAAkC,CAC5C;aAJUH,WAAW,GAAXA;aACAC,iBAAiB,GAAjBA;aACAC,YAAY,GAAZA;aACAC,WAAW,GAAXA;IACT;IAEH,MAAM,QAAQC,IAAwB,EAAwD;QAE1F,MAAMC,cAAc,MAAM,IAAI,CAAC,mBAAmB,CAAC;YAC/C,MAAMD,KAAK,IAAI;YACf,MAAMA,KAAK,IAAI;YACf,UAAUA,KAAK,QAAQ;QAC3B;QAEA,IAAIC,YAAY,MAAM,IAClB,OAAOC,OAAO,IAAI,CAACD,YAAY,KAAK;QAIxC,MAAME,aAAa,MAAM,IAAI,CAAC,gBAAgB,CAAC;YAC3C,MAAMH,KAAK,IAAI;YACf,UAAUA,KAAK,QAAQ;QAC3B;QAEA,IAAIG,WAAW,MAAM,IACjB,OAAOD,OAAO,IAAI,CAACC,WAAW,KAAK;QAIvC,MAAMC,SAAS,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,CAAiB,IAAI,CAAC,WAAW,EAAE;YAC5E,QAAQ;gBACJ,GAAGJ,IAAI;gBACP,UAAUA,KAAK,QAAQ,IAAI;gBAC3B,MAAMG,WAAW,KAAK;YAC1B;QACJ;QAEA,IAAIC,OAAO,MAAM,IAAI;YACjB,IAAIA,AAAsB,gCAAtBA,OAAO,KAAK,CAAC,IAAI,EACjB,OAAOF,OAAO,IAAI,CAAC,IAAIG,sBAAsBD,OAAO,KAAK,CAAC,OAAO;YAErE,OAAOF,OAAO,IAAI,CAAC,IAAII,uBAAuBF,OAAO,KAAK;QAC9D;QAEA,MAAMG,SAASC,oBAAoB,QAAQ,CAACJ,OAAO,KAAK;QACxD,OAAOF,OAAO,EAAE,CAACK;IACrB;IAEA,MAAc,oBAAoBE,MAKjC,EAAsD;QACnD,MAAM,EAAEC,IAAI,EAAEC,IAAI,EAAEC,QAAQ,EAAEC,SAAS,EAAE,GAAGJ;QAE5C,MAAML,SAAS,MAAM,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAiB,IAAI,CAAC,WAAW,EAAE;YAClF,OAAO;gBACH,QAAQ;gBACR,QAAQ;oBACJM;oBACAC;oBACAC;gBACJ;gBACA,GAAIC,YAAY;oBAAE,aAAaA;gBAAU,IAAI,CAAC,CAAC;YACnD;YACA,OAAO;QACX;QAEA,IAAIT,OAAO,MAAM,IACb,OAAOF,OAAO,IAAI,CAAC,IAAII,uBAAuBF,OAAO,KAAK;QAG9D,MAAM,EAAEU,OAAO,EAAE,GAAGV,OAAO,KAAK;QAEhC,IAAIU,QAAQ,MAAM,GAAG,GACjB,OAAOZ,OAAO,IAAI,CACd,IAAIG,sBACA,CAAC,kBAAkB,EAAEM,KAAK,+BAA+B,CAAC;QAKtE,OAAOT,OAAO,EAAE;IACpB;IAEA,MAAc,iBAAiBO,MAG9B,EAAwD;QACrD,MAAM,EAAEE,IAAI,EAAEC,QAAQ,EAAE,GAAGH;QAE3B,IAAI,CAACG,UACD,OAAOV,OAAO,EAAE,CAACa,KAAK,MAAM,CAACJ;QAGjC,MAAMK,eAAe,MAAM,IAAI,CAAC,YAAY,CAAC,OAAO,CAChD,IAAI,CAAC,WAAW,EAChBC,QAAQ,IAAI,CAACL,UAAU,QAAQ;QAGnC,IAAII,aAAa,MAAM,IACnB,OAAOd,OAAO,IAAI,CACd,IAAII,uBACA,IAAIY,MAAM;QAKtB,MAAMC,eAAeX,oBAAoB,QAAQ,CAACQ,aAAa,KAAK;QACpE,OAAOd,OAAO,EAAE,CAACa,KAAK,MAAM,CAACJ,MAAMQ,aAAa,IAAI;IACxD;AACJ;AAEO,MAAMC,gDAAyBC,uBAAAA,oBAA0C,CAAC;IAC7E,gBAAgB1B;IAChB,cAAc;QAAC2B;QAAoBC;QAA0BC;QAAqBC;KAAY;AAClG"}
1
+ {"version":3,"file":"features/folder/CreateFolder/CreateFolderRepository.js","sources":["../../../../src/features/folder/CreateFolder/CreateFolderRepository.ts"],"sourcesContent":["import { Result } from \"@webiny/feature/api\";\nimport {\n CreateFolderRepository as RepositoryAbstraction,\n type ICreateFolderRepository\n} from \"./abstractions.js\";\nimport { CreateEntryUseCase } from \"@webiny/api-headless-cms/features/contentEntry/CreateEntry\";\nimport { ListLatestEntriesUseCase } from \"@webiny/api-headless-cms/features/contentEntry/ListEntries\";\nimport { GetEntryByIdUseCase } from \"@webiny/api-headless-cms/features/contentEntry/GetEntryById\";\nimport { FolderModelProvider } from \"~/domain/folder/abstractions.js\";\nimport type { CmsEntryFolder, CreateFolderParams, Folder } from \"~/folder/folder.types.js\";\nimport { EntryToFolderMapper } from \"../shared/EntryToFolderMapper.js\";\nimport { FolderPersistenceError, FolderValidationError } from \"~/domain/folder/errors.js\";\nimport { Path } from \"~/utils/Path.js\";\nimport { EntryId } from \"@webiny/api-headless-cms/exports/api/cms/entry.js\";\n\nclass CreateFolderRepositoryImpl implements ICreateFolderRepository {\n constructor(\n private createEntry: CreateEntryUseCase.Interface,\n private listLatestEntries: ListLatestEntriesUseCase.Interface,\n private getEntryById: GetEntryByIdUseCase.Interface,\n private folderModelProvider: FolderModelProvider.Interface\n ) {}\n\n async execute(data: CreateFolderParams): Promise<Result<Folder, RepositoryAbstraction.Error>> {\n const folderModel = await this.folderModelProvider.get();\n // Check if folder already exists\n const checkResult = await this.checkExistingFolder({\n type: data.type,\n slug: data.slug,\n parentId: data.parentId\n });\n\n if (checkResult.isFail()) {\n return Result.fail(checkResult.error);\n }\n\n // Create folder path\n const pathResult = await this.createFolderPath({\n slug: data.slug,\n parentId: data.parentId\n });\n\n if (pathResult.isFail()) {\n return Result.fail(pathResult.error);\n }\n\n // Create the entry\n const result = await this.createEntry.execute<CmsEntryFolder>(folderModel, {\n values: {\n ...data,\n parentId: data.parentId || null,\n path: pathResult.value\n }\n });\n\n if (result.isFail()) {\n if (result.error.code === \"Cms/Entry/ValidationError\") {\n return Result.fail(new FolderValidationError(result.error.message));\n }\n return Result.fail(new FolderPersistenceError(result.error));\n }\n\n const folder = EntryToFolderMapper.toFolder(result.value);\n return Result.ok(folder);\n }\n\n private async checkExistingFolder(params: {\n type: string;\n slug: string;\n parentId?: string | null;\n excludeId?: string;\n }): Promise<Result<void, RepositoryAbstraction.Error>> {\n const folderModel = await this.folderModelProvider.get();\n const { type, slug, parentId, excludeId } = params;\n\n const result = await this.listLatestEntries.execute<CmsEntryFolder>(folderModel, {\n where: {\n latest: true,\n values: {\n type,\n slug,\n parentId\n },\n ...(excludeId ? { entryId_not: excludeId } : {})\n },\n limit: 1\n });\n\n if (result.isFail()) {\n return Result.fail(new FolderPersistenceError(result.error));\n }\n\n const { entries } = result.value;\n\n if (entries.length > 0) {\n return Result.fail(\n new FolderValidationError(\n `Folder with slug \"${slug}\" already exists at this level.`\n )\n );\n }\n\n return Result.ok();\n }\n\n private async createFolderPath(params: {\n slug: string;\n parentId?: string | null;\n }): Promise<Result<string, RepositoryAbstraction.Error>> {\n const folderModel = await this.folderModelProvider.get();\n const { slug, parentId } = params;\n\n if (!parentId) {\n return Result.ok(Path.create(slug));\n }\n\n const parentResult = await this.getEntryById.execute<CmsEntryFolder>(\n folderModel,\n EntryId.from(parentId).toString()\n );\n\n if (parentResult.isFail()) {\n return Result.fail(\n new FolderPersistenceError(\n new Error(\"Parent folder not found. Unable to create the folder path\")\n )\n );\n }\n\n const parentFolder = EntryToFolderMapper.toFolder(parentResult.value);\n return Result.ok(Path.create(slug, parentFolder.path));\n }\n}\n\nexport const CreateFolderRepository = RepositoryAbstraction.createImplementation({\n implementation: CreateFolderRepositoryImpl,\n dependencies: [\n CreateEntryUseCase,\n ListLatestEntriesUseCase,\n GetEntryByIdUseCase,\n FolderModelProvider\n ]\n});\n"],"names":["CreateFolderRepositoryImpl","createEntry","listLatestEntries","getEntryById","folderModelProvider","data","folderModel","checkResult","Result","pathResult","result","FolderValidationError","FolderPersistenceError","folder","EntryToFolderMapper","params","type","slug","parentId","excludeId","entries","Path","parentResult","EntryId","Error","parentFolder","CreateFolderRepository","RepositoryAbstraction","CreateEntryUseCase","ListLatestEntriesUseCase","GetEntryByIdUseCase","FolderModelProvider"],"mappings":"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"}
@@ -1,11 +1,19 @@
1
1
  import { FolderLevelPermissions } from "../../../../features/flp/FolderLevelPermissions/index.js";
2
2
  import { CreateFolderUseCase } from "../abstractions.js";
3
3
  import type { CreateFolderParams } from "../../../../folder/folder.types.js";
4
+ import { CodeFlpsProvider } from "../../../../features/flp/shared/index.js";
4
5
  declare class CreateFolderWithFolderLevelPermissionsImpl implements CreateFolderUseCase.Interface {
5
6
  private folderLevelPermissions;
6
7
  private readonly decoretee;
7
- constructor(folderLevelPermissions: FolderLevelPermissions.Interface, decoretee: CreateFolderUseCase.Interface);
8
+ private readonly codeFlpsProvider?;
9
+ constructor(folderLevelPermissions: FolderLevelPermissions.Interface, codeFlpsProvider: CodeFlpsProvider.Interface | undefined, decoretee: CreateFolderUseCase.Interface);
8
10
  execute(params: CreateFolderParams): CreateFolderUseCase.Return;
11
+ /**
12
+ * Code-defined permissions are resolved from the folder's own type and path rather than the FLP
13
+ * catalog: the record for a folder this new is written by an event handler and may not exist
14
+ * yet. Without this the response would omit them until something refetched the folder.
15
+ */
16
+ private withCodePermissions;
9
17
  }
10
18
  export declare const CreateFolderWithFolderLevelPermissions: typeof CreateFolderWithFolderLevelPermissionsImpl;
11
19
  export {};
@@ -2,9 +2,11 @@ import { FolderLevelPermissions } from "../../../flp/FolderLevelPermissions/inde
2
2
  import { CreateFolderUseCase } from "../abstractions.js";
3
3
  import { Result, createDecorator } from "@webiny/feature/api";
4
4
  import { FolderNotAuthorizedError } from "../../../../domain/folder/errors.js";
5
+ import { CodeFlpMerger, CodeFlpsProvider } from "../../../flp/shared/index.js";
5
6
  class CreateFolderWithFolderLevelPermissionsImpl {
6
- constructor(folderLevelPermissions, decoretee){
7
+ constructor(folderLevelPermissions, codeFlpsProvider, decoretee){
7
8
  this.folderLevelPermissions = folderLevelPermissions;
9
+ this.codeFlpsProvider = codeFlpsProvider;
8
10
  this.decoretee = decoretee;
9
11
  }
10
12
  async execute(params) {
@@ -20,18 +22,33 @@ class CreateFolderWithFolderLevelPermissionsImpl {
20
22
  const result = await this.decoretee.execute(params);
21
23
  if (result.isFail()) return Result.fail(result.error);
22
24
  const folder = result.value;
23
- const permissionsWithDefaults = await this.folderLevelPermissions.getDefaultPermissions(folder?.permissions ?? []);
25
+ const permissions = await this.withCodePermissions(folder, folder?.permissions ?? []);
26
+ const permissionsWithDefaults = await this.folderLevelPermissions.getDefaultPermissions(permissions);
24
27
  return Result.ok({
25
28
  ...folder,
26
29
  permissions: permissionsWithDefaults
27
30
  });
28
31
  }
32
+ async withCodePermissions(folder, permissions) {
33
+ if (!this.codeFlpsProvider) return permissions;
34
+ const codePermissions = await this.codeFlpsProvider.getPermissions({
35
+ type: folder.type,
36
+ path: folder.path
37
+ });
38
+ return CodeFlpMerger.mergePermissions(permissions, codePermissions);
39
+ }
29
40
  }
30
41
  const CreateFolderWithFolderLevelPermissions = createDecorator({
31
42
  abstraction: CreateFolderUseCase,
32
43
  decorator: CreateFolderWithFolderLevelPermissionsImpl,
33
44
  dependencies: [
34
- FolderLevelPermissions
45
+ FolderLevelPermissions,
46
+ [
47
+ CodeFlpsProvider,
48
+ {
49
+ optional: true
50
+ }
51
+ ]
35
52
  ]
36
53
  });
37
54
  export { CreateFolderWithFolderLevelPermissions };
@@ -1 +1 @@
1
- {"version":3,"file":"features/folder/CreateFolder/decorators/CreateFolderWithFolderLevelPermissions.js","sources":["../../../../../src/features/folder/CreateFolder/decorators/CreateFolderWithFolderLevelPermissions.ts"],"sourcesContent":["import { FolderLevelPermissions } from \"~/features/flp/FolderLevelPermissions/index.js\";\nimport { CreateFolderUseCase } from \"../abstractions.js\";\nimport type { CreateFolderParams } from \"~/folder/folder.types.js\";\nimport { createDecorator, Result } from \"@webiny/feature/api\";\nimport { FolderNotAuthorizedError } from \"~/domain/folder/errors.js\";\n\nclass CreateFolderWithFolderLevelPermissionsImpl implements CreateFolderUseCase.Interface {\n private folderLevelPermissions: FolderLevelPermissions.Interface;\n private readonly decoretee: CreateFolderUseCase.Interface;\n\n constructor(\n folderLevelPermissions: FolderLevelPermissions.Interface,\n decoretee: CreateFolderUseCase.Interface\n ) {\n this.folderLevelPermissions = folderLevelPermissions;\n this.decoretee = decoretee;\n }\n\n async execute(params: CreateFolderParams): CreateFolderUseCase.Return {\n let canCreateFolder: boolean;\n if (params.parentId) {\n const permissions = await this.folderLevelPermissions.getFolderLevelPermissions(\n params.parentId\n );\n canCreateFolder = await this.folderLevelPermissions.canAccessFolder({\n permissions,\n rwd: \"w\"\n });\n } else {\n canCreateFolder = this.folderLevelPermissions.canCreateFolderInRoot();\n }\n\n if (!canCreateFolder) {\n return Result.fail(new FolderNotAuthorizedError());\n }\n\n const result = await this.decoretee.execute(params);\n\n if (result.isFail()) {\n return Result.fail(result.error);\n }\n\n const folder = result.value;\n\n // Let's set default permissions based on the current user.\n const permissionsWithDefaults = await this.folderLevelPermissions.getDefaultPermissions(\n folder?.permissions ?? []\n );\n\n return Result.ok({\n ...folder,\n permissions: permissionsWithDefaults\n });\n }\n}\n\nexport const CreateFolderWithFolderLevelPermissions = createDecorator({\n abstraction: CreateFolderUseCase,\n decorator: CreateFolderWithFolderLevelPermissionsImpl,\n dependencies: [FolderLevelPermissions]\n});\n"],"names":["CreateFolderWithFolderLevelPermissionsImpl","folderLevelPermissions","decoretee","params","canCreateFolder","permissions","Result","FolderNotAuthorizedError","result","folder","permissionsWithDefaults","CreateFolderWithFolderLevelPermissions","createDecorator","CreateFolderUseCase","FolderLevelPermissions"],"mappings":";;;;AAMA,MAAMA;IAIF,YACIC,sBAAwD,EACxDC,SAAwC,CAC1C;QACE,IAAI,CAAC,sBAAsB,GAAGD;QAC9B,IAAI,CAAC,SAAS,GAAGC;IACrB;IAEA,MAAM,QAAQC,MAA0B,EAA8B;QAClE,IAAIC;QACJ,IAAID,OAAO,QAAQ,EAAE;YACjB,MAAME,cAAc,MAAM,IAAI,CAAC,sBAAsB,CAAC,yBAAyB,CAC3EF,OAAO,QAAQ;YAEnBC,kBAAkB,MAAM,IAAI,CAAC,sBAAsB,CAAC,eAAe,CAAC;gBAChEC;gBACA,KAAK;YACT;QACJ,OACID,kBAAkB,IAAI,CAAC,sBAAsB,CAAC,qBAAqB;QAGvE,IAAI,CAACA,iBACD,OAAOE,OAAO,IAAI,CAAC,IAAIC;QAG3B,MAAMC,SAAS,MAAM,IAAI,CAAC,SAAS,CAAC,OAAO,CAACL;QAE5C,IAAIK,OAAO,MAAM,IACb,OAAOF,OAAO,IAAI,CAACE,OAAO,KAAK;QAGnC,MAAMC,SAASD,OAAO,KAAK;QAG3B,MAAME,0BAA0B,MAAM,IAAI,CAAC,sBAAsB,CAAC,qBAAqB,CACnFD,QAAQ,eAAe,EAAE;QAG7B,OAAOH,OAAO,EAAE,CAAC;YACb,GAAGG,MAAM;YACT,aAAaC;QACjB;IACJ;AACJ;AAEO,MAAMC,yCAAyCC,gBAAgB;IAClE,aAAaC;IACb,WAAWb;IACX,cAAc;QAACc;KAAuB;AAC1C"}
1
+ {"version":3,"file":"features/folder/CreateFolder/decorators/CreateFolderWithFolderLevelPermissions.js","sources":["../../../../../src/features/folder/CreateFolder/decorators/CreateFolderWithFolderLevelPermissions.ts"],"sourcesContent":["import { FolderLevelPermissions } from \"~/features/flp/FolderLevelPermissions/index.js\";\nimport { CreateFolderUseCase } from \"../abstractions.js\";\nimport type { CreateFolderParams } from \"~/folder/folder.types.js\";\nimport type { Folder } from \"~/folder/folder.types.js\";\nimport type { FolderPermission } from \"~/flp/flp.types.js\";\nimport { createDecorator, Result } from \"@webiny/feature/api\";\nimport { FolderNotAuthorizedError } from \"~/domain/folder/errors.js\";\nimport { CodeFlpMerger } from \"~/features/flp/shared/index.js\";\nimport { CodeFlpsProvider } from \"~/features/flp/shared/index.js\";\n\nclass CreateFolderWithFolderLevelPermissionsImpl implements CreateFolderUseCase.Interface {\n private folderLevelPermissions: FolderLevelPermissions.Interface;\n private readonly decoretee: CreateFolderUseCase.Interface;\n private readonly codeFlpsProvider?: CodeFlpsProvider.Interface;\n\n constructor(\n folderLevelPermissions: FolderLevelPermissions.Interface,\n codeFlpsProvider: CodeFlpsProvider.Interface | undefined,\n decoretee: CreateFolderUseCase.Interface\n ) {\n this.folderLevelPermissions = folderLevelPermissions;\n this.codeFlpsProvider = codeFlpsProvider;\n this.decoretee = decoretee;\n }\n\n async execute(params: CreateFolderParams): CreateFolderUseCase.Return {\n let canCreateFolder: boolean;\n if (params.parentId) {\n const permissions = await this.folderLevelPermissions.getFolderLevelPermissions(\n params.parentId\n );\n canCreateFolder = await this.folderLevelPermissions.canAccessFolder({\n permissions,\n rwd: \"w\"\n });\n } else {\n canCreateFolder = this.folderLevelPermissions.canCreateFolderInRoot();\n }\n\n if (!canCreateFolder) {\n return Result.fail(new FolderNotAuthorizedError());\n }\n\n const result = await this.decoretee.execute(params);\n\n if (result.isFail()) {\n return Result.fail(result.error);\n }\n\n const folder = result.value;\n\n const permissions = await this.withCodePermissions(folder, folder?.permissions ?? []);\n\n // Let's set default permissions based on the current user.\n const permissionsWithDefaults =\n await this.folderLevelPermissions.getDefaultPermissions(permissions);\n\n return Result.ok({\n ...folder,\n permissions: permissionsWithDefaults\n });\n }\n\n /**\n * Code-defined permissions are resolved from the folder's own type and path rather than the FLP\n * catalog: the record for a folder this new is written by an event handler and may not exist\n * yet. Without this the response would omit them until something refetched the folder.\n */\n private async withCodePermissions(\n folder: Pick<Folder, \"type\" | \"path\">,\n permissions: FolderPermission[]\n ): Promise<FolderPermission[]> {\n if (!this.codeFlpsProvider) {\n return permissions;\n }\n\n const codePermissions = await this.codeFlpsProvider.getPermissions({\n type: folder.type,\n path: folder.path\n });\n\n return CodeFlpMerger.mergePermissions(permissions, codePermissions);\n }\n}\n\nexport const CreateFolderWithFolderLevelPermissions = createDecorator({\n abstraction: CreateFolderUseCase,\n decorator: CreateFolderWithFolderLevelPermissionsImpl,\n // `CodeFlpsProvider` is optional: `CodeFlpsFeature` does not register it unless the project has\n // the folder-level permissions entitlement.\n dependencies: [FolderLevelPermissions, [CodeFlpsProvider, { optional: true }]]\n});\n"],"names":["CreateFolderWithFolderLevelPermissionsImpl","folderLevelPermissions","codeFlpsProvider","decoretee","params","canCreateFolder","permissions","Result","FolderNotAuthorizedError","result","folder","permissionsWithDefaults","codePermissions","CodeFlpMerger","CreateFolderWithFolderLevelPermissions","createDecorator","CreateFolderUseCase","FolderLevelPermissions","CodeFlpsProvider"],"mappings":";;;;;AAUA,MAAMA;IAKF,YACIC,sBAAwD,EACxDC,gBAAwD,EACxDC,SAAwC,CAC1C;QACE,IAAI,CAAC,sBAAsB,GAAGF;QAC9B,IAAI,CAAC,gBAAgB,GAAGC;QACxB,IAAI,CAAC,SAAS,GAAGC;IACrB;IAEA,MAAM,QAAQC,MAA0B,EAA8B;QAClE,IAAIC;QACJ,IAAID,OAAO,QAAQ,EAAE;YACjB,MAAME,cAAc,MAAM,IAAI,CAAC,sBAAsB,CAAC,yBAAyB,CAC3EF,OAAO,QAAQ;YAEnBC,kBAAkB,MAAM,IAAI,CAAC,sBAAsB,CAAC,eAAe,CAAC;gBAChEC;gBACA,KAAK;YACT;QACJ,OACID,kBAAkB,IAAI,CAAC,sBAAsB,CAAC,qBAAqB;QAGvE,IAAI,CAACA,iBACD,OAAOE,OAAO,IAAI,CAAC,IAAIC;QAG3B,MAAMC,SAAS,MAAM,IAAI,CAAC,SAAS,CAAC,OAAO,CAACL;QAE5C,IAAIK,OAAO,MAAM,IACb,OAAOF,OAAO,IAAI,CAACE,OAAO,KAAK;QAGnC,MAAMC,SAASD,OAAO,KAAK;QAE3B,MAAMH,cAAc,MAAM,IAAI,CAAC,mBAAmB,CAACI,QAAQA,QAAQ,eAAe,EAAE;QAGpF,MAAMC,0BACF,MAAM,IAAI,CAAC,sBAAsB,CAAC,qBAAqB,CAACL;QAE5D,OAAOC,OAAO,EAAE,CAAC;YACb,GAAGG,MAAM;YACT,aAAaC;QACjB;IACJ;IAOA,MAAc,oBACVD,MAAqC,EACrCJ,WAA+B,EACJ;QAC3B,IAAI,CAAC,IAAI,CAAC,gBAAgB,EACtB,OAAOA;QAGX,MAAMM,kBAAkB,MAAM,IAAI,CAAC,gBAAgB,CAAC,cAAc,CAAC;YAC/D,MAAMF,OAAO,IAAI;YACjB,MAAMA,OAAO,IAAI;QACrB;QAEA,OAAOG,cAAc,gBAAgB,CAACP,aAAaM;IACvD;AACJ;AAEO,MAAME,yCAAyCC,gBAAgB;IAClE,aAAaC;IACb,WAAWhB;IAGX,cAAc;QAACiB;QAAwB;YAACC;YAAkB;gBAAE,UAAU;YAAK;SAAE;KAAC;AAClF"}
@@ -1,12 +1,12 @@
1
1
  import { Result } from "@webiny/feature/api";
2
2
  import { DeleteFolderRepository as RepositoryAbstraction, type IDeleteFolderRepository } from "./abstractions.js";
3
3
  import { DeleteEntryUseCase } from "@webiny/api-headless-cms/features/contentEntry/DeleteEntry";
4
- import { FolderModel } from "../../../domain/folder/abstractions.js";
4
+ import { FolderModelProvider } from "../../../domain/folder/abstractions.js";
5
5
  import type { Folder } from "../../../folder/folder.types.js";
6
6
  declare class DeleteFolderRepositoryImpl implements IDeleteFolderRepository {
7
7
  private deleteEntry;
8
- private folderModel;
9
- constructor(deleteEntry: DeleteEntryUseCase.Interface, folderModel: FolderModel.Interface);
8
+ private folderModelProvider;
9
+ constructor(deleteEntry: DeleteEntryUseCase.Interface, folderModelProvider: FolderModelProvider.Interface);
10
10
  execute(folder: Folder): Promise<Result<void, RepositoryAbstraction.Error>>;
11
11
  }
12
12
  export declare const DeleteFolderRepository: typeof DeleteFolderRepositoryImpl & {
@@ -1,15 +1,16 @@
1
1
  import { Result } from "@webiny/feature/api";
2
2
  import { DeleteFolderRepository } from "./abstractions.js";
3
3
  import { DeleteEntryUseCase } from "@webiny/api-headless-cms/features/contentEntry/DeleteEntry";
4
- import { FolderModel } from "../../../domain/folder/abstractions.js";
4
+ import { FolderModelProvider } from "../../../domain/folder/abstractions.js";
5
5
  import { FolderNotAuthorizedError, FolderPersistenceError } from "../../../domain/folder/errors.js";
6
6
  class DeleteFolderRepositoryImpl {
7
- constructor(deleteEntry, folderModel){
7
+ constructor(deleteEntry, folderModelProvider){
8
8
  this.deleteEntry = deleteEntry;
9
- this.folderModel = folderModel;
9
+ this.folderModelProvider = folderModelProvider;
10
10
  }
11
11
  async execute(folder) {
12
- const result = await this.deleteEntry.execute(this.folderModel, folder.id, {
12
+ const folderModel = await this.folderModelProvider.get();
13
+ const result = await this.deleteEntry.execute(folderModel, folder.id, {
13
14
  permanently: true,
14
15
  force: true
15
16
  });
@@ -24,7 +25,7 @@ const DeleteFolderRepository_DeleteFolderRepository = DeleteFolderRepository.cre
24
25
  implementation: DeleteFolderRepositoryImpl,
25
26
  dependencies: [
26
27
  DeleteEntryUseCase,
27
- FolderModel
28
+ FolderModelProvider
28
29
  ]
29
30
  });
30
31
  export { DeleteFolderRepository_DeleteFolderRepository as DeleteFolderRepository };