@webiny/api-aco 6.4.11 → 6.6.0-alpha.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 (157) hide show
  1. package/AcoFeature.d.ts +5 -0
  2. package/AcoFeature.js +129 -0
  3. package/AcoFeature.js.map +1 -0
  4. package/AcoFolderSchemaFactory.d.ts +30 -0
  5. package/AcoFolderSchemaFactory.js +64 -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/exports/api/aco/folder.d.ts +1 -1
  14. package/exports/api/aco/folder.js +1 -1
  15. package/features/ai/CreateFolderTool.d.ts +44 -0
  16. package/features/ai/CreateFolderTool.js +49 -0
  17. package/features/ai/CreateFolderTool.js.map +1 -0
  18. package/features/ai/CreateTeamTool.d.ts +43 -0
  19. package/features/ai/CreateTeamTool.js +47 -0
  20. package/features/ai/CreateTeamTool.js.map +1 -0
  21. package/features/ai/GrantFolderAccessTool.d.ts +72 -0
  22. package/features/ai/GrantFolderAccessTool.js +71 -0
  23. package/features/ai/GrantFolderAccessTool.js.map +1 -0
  24. package/features/ai/ListFoldersTool.d.ts +42 -0
  25. package/features/ai/ListFoldersTool.js +48 -0
  26. package/features/ai/ListFoldersTool.js.map +1 -0
  27. package/features/ai/ListRolesTool.d.ts +34 -0
  28. package/features/ai/ListRolesTool.js +39 -0
  29. package/features/ai/ListRolesTool.js.map +1 -0
  30. package/features/ai/ListTeamsTool.d.ts +34 -0
  31. package/features/ai/ListTeamsTool.js +39 -0
  32. package/features/ai/ListTeamsTool.js.map +1 -0
  33. package/features/ai/RevokeFolderAccessTool.d.ts +58 -0
  34. package/features/ai/RevokeFolderAccessTool.js +60 -0
  35. package/features/ai/RevokeFolderAccessTool.js.map +1 -0
  36. package/features/ai/assertTargetIsUsable.d.ts +10 -0
  37. package/features/ai/assertTargetIsUsable.js +14 -0
  38. package/features/ai/assertTargetIsUsable.js.map +1 -0
  39. package/features/ai/feature.d.ts +12 -0
  40. package/features/ai/feature.js +23 -0
  41. package/features/ai/feature.js.map +1 -0
  42. package/features/ai/index.d.ts +8 -0
  43. package/features/ai/index.js +8 -0
  44. package/features/ai/loadFolderPermissions.d.ts +16 -0
  45. package/features/ai/loadFolderPermissions.js +14 -0
  46. package/features/ai/loadFolderPermissions.js.map +1 -0
  47. package/features/cms/decorators/MoveEntryWithFlpDecorator.d.ts +1 -1
  48. package/features/flp/CreateFlp/CreateFlpUseCase.d.ts +3 -3
  49. package/features/flp/CreateFlp/CreateFlpUseCase.js +4 -4
  50. package/features/flp/CreateFlp/CreateFlpUseCase.js.map +1 -1
  51. package/features/flp/CreateFlp/feature.d.ts +1 -6
  52. package/features/flp/CreateFlp/feature.js +3 -2
  53. package/features/flp/CreateFlp/feature.js.map +1 -1
  54. package/features/flp/DeleteFlp/DeleteFlpUseCase.d.ts +3 -3
  55. package/features/flp/DeleteFlp/DeleteFlpUseCase.js +3 -3
  56. package/features/flp/DeleteFlp/DeleteFlpUseCase.js.map +1 -1
  57. package/features/flp/DeleteFlp/feature.d.ts +1 -6
  58. package/features/flp/DeleteFlp/feature.js +3 -2
  59. package/features/flp/DeleteFlp/feature.js.map +1 -1
  60. package/features/flp/FolderLevelPermissions/FolderLevelPermissions.d.ts +3 -3
  61. package/features/flp/FolderLevelPermissions/FolderLevelPermissions.js +6 -6
  62. package/features/flp/FolderLevelPermissions/FolderLevelPermissions.js.map +1 -1
  63. package/features/flp/FolderLevelPermissions/NoopFolderLevelPermissions.d.ts +25 -0
  64. package/features/flp/FolderLevelPermissions/NoopFolderLevelPermissions.js +48 -0
  65. package/features/flp/FolderLevelPermissions/NoopFolderLevelPermissions.js.map +1 -0
  66. package/features/flp/FolderLevelPermissions/index.d.ts +1 -0
  67. package/features/flp/FolderLevelPermissions/index.js +1 -0
  68. package/features/flp/GetFlp/feature.d.ts +1 -1
  69. package/features/flp/GetFlp/feature.js +3 -2
  70. package/features/flp/GetFlp/feature.js.map +1 -1
  71. package/features/flp/ListFlps/feature.d.ts +1 -1
  72. package/features/flp/ListFlps/feature.js +3 -2
  73. package/features/flp/ListFlps/feature.js.map +1 -1
  74. package/features/flp/UpdateFlp/UpdateFlpUseCase.d.ts +11 -3
  75. package/features/flp/UpdateFlp/UpdateFlpUseCase.js +15 -13
  76. package/features/flp/UpdateFlp/UpdateFlpUseCase.js.map +1 -1
  77. package/features/flp/UpdateFlp/feature.d.ts +1 -6
  78. package/features/flp/UpdateFlp/feature.js +7 -2
  79. package/features/flp/UpdateFlp/feature.js.map +1 -1
  80. package/features/folder/CreateFolder/CreateFolderRepository.d.ts +3 -3
  81. package/features/folder/CreateFolder/CreateFolderRepository.js +10 -7
  82. package/features/folder/CreateFolder/CreateFolderRepository.js.map +1 -1
  83. package/features/folder/DeleteFolder/DeleteFolderRepository.d.ts +3 -3
  84. package/features/folder/DeleteFolder/DeleteFolderRepository.js +6 -5
  85. package/features/folder/DeleteFolder/DeleteFolderRepository.js.map +1 -1
  86. package/features/folder/DeleteFolder/decorators/DeleteFolderWithFolderLevelPermissions.d.ts +1 -1
  87. package/features/folder/EnsureFolderIsEmpty/EnsureFolderIsEmpty.d.ts +1 -3
  88. package/features/folder/EnsureFolderIsEmpty/EnsureFolderIsEmpty.js +4 -7
  89. package/features/folder/EnsureFolderIsEmpty/EnsureFolderIsEmpty.js.map +1 -1
  90. package/features/folder/EnsureHcmsFolderIsEmptyOnDelete/ModelFolderBeforeDeleteHandler.js +4 -1
  91. package/features/folder/EnsureHcmsFolderIsEmptyOnDelete/ModelFolderBeforeDeleteHandler.js.map +1 -1
  92. package/features/folder/FolderModelProvider.d.ts +26 -0
  93. package/features/folder/FolderModelProvider.js +22 -0
  94. package/features/folder/FolderModelProvider.js.map +1 -0
  95. package/features/folder/GetAncestors/GetAncestorsRepository.d.ts +3 -3
  96. package/features/folder/GetAncestors/GetAncestorsRepository.js +6 -5
  97. package/features/folder/GetAncestors/GetAncestorsRepository.js.map +1 -1
  98. package/features/folder/GetFolder/GetFolderRepository.d.ts +3 -3
  99. package/features/folder/GetFolder/GetFolderRepository.js +6 -5
  100. package/features/folder/GetFolder/GetFolderRepository.js.map +1 -1
  101. package/features/folder/GetFolder/decorators/GetFolderWithFolderLevelPermissions.d.ts +8 -8
  102. package/features/folder/GetFolderHierarchy/GetFolderHierarchyRepository.d.ts +3 -3
  103. package/features/folder/GetFolderHierarchy/GetFolderHierarchyRepository.js +10 -8
  104. package/features/folder/GetFolderHierarchy/GetFolderHierarchyRepository.js.map +1 -1
  105. package/features/folder/ListFolders/ListFoldersRepository.d.ts +3 -3
  106. package/features/folder/ListFolders/ListFoldersRepository.js +8 -7
  107. package/features/folder/ListFolders/ListFoldersRepository.js.map +1 -1
  108. package/features/folder/UpdateFolder/UpdateFolderRepository.d.ts +3 -3
  109. package/features/folder/UpdateFolder/UpdateFolderRepository.js +11 -8
  110. package/features/folder/UpdateFolder/UpdateFolderRepository.js.map +1 -1
  111. package/features/folder/shared/abstractions.d.ts +14 -0
  112. package/features/folder/shared/abstractions.js +4 -1
  113. package/features/folder/shared/abstractions.js.map +1 -1
  114. package/filter/filter.gql.d.ts +2 -3
  115. package/filter/filter.gql.js +61 -27
  116. package/filter/filter.gql.js.map +1 -1
  117. package/filter/filter.so.d.ts +10 -2
  118. package/filter/filter.so.js +2 -2
  119. package/filter/filter.so.js.map +1 -1
  120. package/flp/index.d.ts +0 -1
  121. package/flp/index.js +0 -1
  122. package/flp/tasks/createFlp.task.d.ts +2 -2
  123. package/flp/tasks/deleteFlp.task.d.ts +2 -2
  124. package/flp/tasks/index.d.ts +0 -1
  125. package/flp/tasks/index.js +1 -14
  126. package/flp/tasks/index.js.map +1 -1
  127. package/flp/tasks/syncFlp.task.d.ts +2 -2
  128. package/flp/tasks/syncFlp.task.js +7 -1
  129. package/flp/tasks/syncFlp.task.js.map +1 -1
  130. package/flp/tasks/updateFlp.task.d.ts +2 -2
  131. package/folder/folder.gql.d.ts +1 -1
  132. package/folder/folder.gql.js +10 -4
  133. package/folder/folder.gql.js.map +1 -1
  134. package/index.d.ts +1 -6
  135. package/index.js +1 -11
  136. package/package.json +24 -25
  137. package/utils/createOperationsWrapper.d.ts +5 -2
  138. package/utils/createOperationsWrapper.js +2 -2
  139. package/utils/createOperationsWrapper.js.map +1 -1
  140. package/utils/decorators/CmsEntriesCrudDecorators.js +9 -5
  141. package/utils/decorators/CmsEntriesCrudDecorators.js.map +1 -1
  142. package/utils/resolve.d.ts +2 -2
  143. package/utils/resolve.js +1 -1
  144. package/utils/resolve.js.map +1 -1
  145. package/createAcoContext.d.ts +0 -9
  146. package/createAcoContext.js +0 -108
  147. package/createAcoContext.js.map +0 -1
  148. package/createAcoStorageOperations.d.ts +0 -12
  149. package/createAcoStorageOperations.js +0 -9
  150. package/createAcoStorageOperations.js.map +0 -1
  151. package/createAcoTasks.d.ts +0 -1
  152. package/createAcoTasks.js +0 -14
  153. package/createAcoTasks.js.map +0 -1
  154. package/flp/flp.so.d.ts +0 -20
  155. package/flp/flp.so.js +0 -183
  156. package/flp/flp.so.js.map +0 -1
  157. package/index.js.map +0 -1
@@ -0,0 +1,58 @@
1
+ import { z } from "zod";
2
+ import type { IAiSdkTool } from "@webiny/api-core/features/ai/index.js";
3
+ import { GetFolderUseCase } from "../../features/folder/GetFolder/index.js";
4
+ import { UpdateFolderUseCase } from "../../features/folder/UpdateFolder/index.js";
5
+ declare const inputSchema: z.ZodObject<{
6
+ folderId: z.ZodString;
7
+ target: z.ZodString;
8
+ }, z.core.$strip>;
9
+ type Input = z.infer<typeof inputSchema>;
10
+ interface RevokeResult {
11
+ folderId: string;
12
+ title: string;
13
+ path: string;
14
+ removed: {
15
+ target: string;
16
+ level: string;
17
+ };
18
+ /**
19
+ * Every direct rule remaining afterwards.
20
+ *
21
+ * This is the set the update was asked to store, not an independent read of it:
22
+ * `UpdateFolderWithFolderLevelPermissions` returns the permissions it derived from the input
23
+ * rather than the ones the repository wrote. Treating it as a verification would let the tool
24
+ * confirm its own request back to itself.
25
+ */
26
+ permissions: {
27
+ target: string;
28
+ level: string;
29
+ }[];
30
+ }
31
+ /**
32
+ * Removes one target's direct access to one folder.
33
+ *
34
+ * Destructive: somebody loses access, and there is no undo. Refuses when the target has no DIRECT rule
35
+ * rather than reporting a removal that changed nothing — an inherited grant cannot be revoked here,
36
+ * only where it is defined, and saying otherwise would leave the user believing access was withdrawn.
37
+ */
38
+ declare class RevokeFolderAccessToolImpl implements IAiSdkTool<Input> {
39
+ private getFolder;
40
+ private updateFolder;
41
+ readonly name = "revokeFolderAccess";
42
+ readonly title = "Revoke folder access";
43
+ readonly description = "Removes one team's or user's direct access to one folder, leaving all other permissions untouched. Cannot remove inherited access. Requires user approval.";
44
+ readonly inputSchema: z.ZodObject<{
45
+ folderId: z.ZodString;
46
+ target: z.ZodString;
47
+ }, z.core.$strip>;
48
+ readonly annotations: {
49
+ readOnlyHint: boolean;
50
+ destructiveHint: boolean;
51
+ };
52
+ constructor(getFolder: GetFolderUseCase.Interface, updateFolder: UpdateFolderUseCase.Interface);
53
+ execute(input: Input): Promise<RevokeResult>;
54
+ }
55
+ export declare const RevokeFolderAccessTool: typeof RevokeFolderAccessToolImpl & {
56
+ __abstraction: import("@webiny/di").Abstraction<IAiSdkTool<any>>;
57
+ };
58
+ export {};
@@ -0,0 +1,60 @@
1
+ import { z } from "zod";
2
+ import { AiSdkTool } from "@webiny/api-core/features/ai/index.js";
3
+ import { GetFolderUseCase } from "../folder/GetFolder/index.js";
4
+ import { UpdateFolderUseCase } from "../folder/UpdateFolder/index.js";
5
+ import { loadFolderPermissions } from "./loadFolderPermissions.js";
6
+ const inputSchema = z.object({
7
+ folderId: z.string().describe("Folder id as returned by listFolders."),
8
+ target: z.string().describe("Whose access to remove: 'team:<slug>' or 'admin:<userId>', exactly as listFolders reports it.")
9
+ });
10
+ class RevokeFolderAccessToolImpl {
11
+ constructor(getFolder, updateFolder){
12
+ this.getFolder = getFolder;
13
+ this.updateFolder = updateFolder;
14
+ this.name = "revokeFolderAccess";
15
+ this.title = "Revoke folder access";
16
+ this.description = "Removes one team's or user's direct access to one folder, leaving all other permissions untouched. Cannot remove inherited access. Requires user approval.";
17
+ this.inputSchema = inputSchema;
18
+ this.annotations = {
19
+ readOnlyHint: false,
20
+ destructiveHint: true
21
+ };
22
+ }
23
+ async execute(input) {
24
+ const loaded = await loadFolderPermissions(this.getFolder, input.folderId);
25
+ const existing = loaded.direct.find((permission)=>String(permission.target) === input.target);
26
+ if (!existing) {
27
+ if (loaded.inheritedTargets.has(input.target)) throw new Error(`"${input.target}" has inherited access to this folder, not a direct rule, so it cannot be revoked here. Change it where it is defined.`);
28
+ throw new Error(`"${input.target}" has no direct access to this folder, so there is nothing to revoke.`);
29
+ }
30
+ const permissions = loaded.direct.filter((permission)=>String(permission.target) !== input.target);
31
+ const result = await this.updateFolder.execute(input.folderId, {
32
+ permissions
33
+ });
34
+ if (result.isFail()) throw new Error(`Could not revoke access: ${result.error.message}`);
35
+ const folder = result.value;
36
+ return {
37
+ folderId: folder.id,
38
+ title: folder.title,
39
+ path: folder.path,
40
+ removed: {
41
+ target: input.target,
42
+ level: existing.level
43
+ },
44
+ permissions: (folder.permissions ?? []).filter((permission)=>!permission.inheritedFrom).map((permission)=>({
45
+ target: String(permission.target),
46
+ level: permission.level
47
+ }))
48
+ };
49
+ }
50
+ }
51
+ const RevokeFolderAccessTool = AiSdkTool.createImplementation({
52
+ implementation: RevokeFolderAccessToolImpl,
53
+ dependencies: [
54
+ GetFolderUseCase,
55
+ UpdateFolderUseCase
56
+ ]
57
+ });
58
+ export { RevokeFolderAccessTool };
59
+
60
+ //# sourceMappingURL=RevokeFolderAccessTool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"features/ai/RevokeFolderAccessTool.js","sources":["../../../src/features/ai/RevokeFolderAccessTool.ts"],"sourcesContent":["import { z } from \"zod\";\nimport { AiSdkTool } from \"@webiny/api-core/features/ai/index.js\";\nimport type { IAiSdkTool } from \"@webiny/api-core/features/ai/index.js\";\nimport { GetFolderUseCase } from \"~/features/folder/GetFolder/index.js\";\nimport { UpdateFolderUseCase } from \"~/features/folder/UpdateFolder/index.js\";\nimport { loadFolderPermissions } from \"./loadFolderPermissions.js\";\n\nconst inputSchema = z.object({\n folderId: z.string().describe(\"Folder id as returned by listFolders.\"),\n target: z\n .string()\n .describe(\n \"Whose access to remove: 'team:<slug>' or 'admin:<userId>', exactly as listFolders reports it.\"\n )\n});\n\ntype Input = z.infer<typeof inputSchema>;\n\ninterface RevokeResult {\n folderId: string;\n title: string;\n path: string;\n removed: { target: string; level: string };\n /**\n * Every direct rule remaining afterwards.\n *\n * This is the set the update was asked to store, not an independent read of it:\n * `UpdateFolderWithFolderLevelPermissions` returns the permissions it derived from the input\n * rather than the ones the repository wrote. Treating it as a verification would let the tool\n * confirm its own request back to itself.\n */\n permissions: { target: string; level: string }[];\n}\n\n/**\n * Removes one target's direct access to one folder.\n *\n * Destructive: somebody loses access, and there is no undo. Refuses when the target has no DIRECT rule\n * rather than reporting a removal that changed nothing — an inherited grant cannot be revoked here,\n * only where it is defined, and saying otherwise would leave the user believing access was withdrawn.\n */\nclass RevokeFolderAccessToolImpl implements IAiSdkTool<Input> {\n readonly name = \"revokeFolderAccess\";\n readonly title = \"Revoke folder access\";\n readonly description =\n \"Removes one team's or user's direct access to one folder, leaving all other permissions untouched. Cannot remove inherited access. Requires user approval.\";\n readonly inputSchema = inputSchema;\n readonly annotations = { readOnlyHint: false, destructiveHint: true };\n\n constructor(\n private getFolder: GetFolderUseCase.Interface,\n private updateFolder: UpdateFolderUseCase.Interface\n ) {}\n\n async execute(input: Input): Promise<RevokeResult> {\n const loaded = await loadFolderPermissions(this.getFolder, input.folderId);\n\n const existing = loaded.direct.find(\n permission => String(permission.target) === input.target\n );\n\n if (!existing) {\n if (loaded.inheritedTargets.has(input.target)) {\n throw new Error(\n `\"${input.target}\" has inherited access to this folder, not a direct rule, so it cannot be revoked here. Change it where it is defined.`\n );\n }\n\n throw new Error(\n `\"${input.target}\" has no direct access to this folder, so there is nothing to revoke.`\n );\n }\n\n const permissions = loaded.direct.filter(\n permission => String(permission.target) !== input.target\n );\n\n const result = await this.updateFolder.execute(input.folderId, { permissions });\n\n if (result.isFail()) {\n throw new Error(`Could not revoke access: ${result.error.message}`);\n }\n\n const folder = result.value;\n\n return {\n folderId: folder.id,\n title: folder.title,\n path: folder.path,\n removed: { target: input.target, level: existing.level },\n permissions: (folder.permissions ?? [])\n .filter(permission => !permission.inheritedFrom)\n .map(permission => ({ target: String(permission.target), level: permission.level }))\n };\n }\n}\n\nexport const RevokeFolderAccessTool = AiSdkTool.createImplementation({\n implementation: RevokeFolderAccessToolImpl,\n dependencies: [GetFolderUseCase, UpdateFolderUseCase]\n});\n"],"names":["inputSchema","z","RevokeFolderAccessToolImpl","getFolder","updateFolder","input","loaded","loadFolderPermissions","existing","permission","String","Error","permissions","result","folder","RevokeFolderAccessTool","AiSdkTool","GetFolderUseCase","UpdateFolderUseCase"],"mappings":";;;;;AAOA,MAAMA,cAAcC,EAAE,MAAM,CAAC;IACzB,UAAUA,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC9B,QAAQA,EAAAA,MACG,GACN,QAAQ,CACL;AAEZ;AA2BA,MAAMC;IAQF,YACYC,SAAqC,EACrCC,YAA2C,CACrD;aAFUD,SAAS,GAATA;aACAC,YAAY,GAAZA;aATH,IAAI,GAAG;aACP,KAAK,GAAG;aACR,WAAW,GAChB;aACK,WAAW,GAAGJ;aACd,WAAW,GAAG;YAAE,cAAc;YAAO,iBAAiB;QAAK;IAKjE;IAEH,MAAM,QAAQK,KAAY,EAAyB;QAC/C,MAAMC,SAAS,MAAMC,sBAAsB,IAAI,CAAC,SAAS,EAAEF,MAAM,QAAQ;QAEzE,MAAMG,WAAWF,OAAO,MAAM,CAAC,IAAI,CAC/BG,CAAAA,aAAcC,OAAOD,WAAW,MAAM,MAAMJ,MAAM,MAAM;QAG5D,IAAI,CAACG,UAAU;YACX,IAAIF,OAAO,gBAAgB,CAAC,GAAG,CAACD,MAAM,MAAM,GACxC,MAAM,IAAIM,MACN,CAAC,CAAC,EAAEN,MAAM,MAAM,CAAC,sHAAsH,CAAC;YAIhJ,MAAM,IAAIM,MACN,CAAC,CAAC,EAAEN,MAAM,MAAM,CAAC,qEAAqE,CAAC;QAE/F;QAEA,MAAMO,cAAcN,OAAO,MAAM,CAAC,MAAM,CACpCG,CAAAA,aAAcC,OAAOD,WAAW,MAAM,MAAMJ,MAAM,MAAM;QAG5D,MAAMQ,SAAS,MAAM,IAAI,CAAC,YAAY,CAAC,OAAO,CAACR,MAAM,QAAQ,EAAE;YAAEO;QAAY;QAE7E,IAAIC,OAAO,MAAM,IACb,MAAM,IAAIF,MAAM,CAAC,yBAAyB,EAAEE,OAAO,KAAK,CAAC,OAAO,EAAE;QAGtE,MAAMC,SAASD,OAAO,KAAK;QAE3B,OAAO;YACH,UAAUC,OAAO,EAAE;YACnB,OAAOA,OAAO,KAAK;YACnB,MAAMA,OAAO,IAAI;YACjB,SAAS;gBAAE,QAAQT,MAAM,MAAM;gBAAE,OAAOG,SAAS,KAAK;YAAC;YACvD,aAAcM,AAAAA,CAAAA,OAAO,WAAW,IAAI,EAAC,EAChC,MAAM,CAACL,CAAAA,aAAc,CAACA,WAAW,aAAa,EAC9C,GAAG,CAACA,CAAAA,aAAe;oBAAE,QAAQC,OAAOD,WAAW,MAAM;oBAAG,OAAOA,WAAW,KAAK;gBAAC;QACzF;IACJ;AACJ;AAEO,MAAMM,yBAAyBC,UAAU,oBAAoB,CAAC;IACjE,gBAAgBd;IAChB,cAAc;QAACe;QAAkBC;KAAoB;AACzD"}
@@ -0,0 +1,10 @@
1
+ import type { ListTeamsUseCase } from "@webiny/api-core/features/security/teams/ListTeams/index.js";
2
+ /**
3
+ * Rejects a permission target that would be stored happily and then match nobody.
4
+ *
5
+ * A folder rule identifies a team by SLUG (`team:<slug>`) and a user by id (`admin:<userId>`) — see
6
+ * ListFolderLevelPermissionsTargets. The field is only typed as a template string, so a team id where
7
+ * a slug belongs is accepted and silently grants nothing. Also refuses a target the folder inherits,
8
+ * since rewriting it as a direct rule detaches the folder from where the grant came from.
9
+ */
10
+ export declare const assertTargetIsUsable: (listTeams: ListTeamsUseCase.Interface, target: string, inheritedTargets: Set<string>) => Promise<void>;
@@ -0,0 +1,14 @@
1
+ const assertTargetIsUsable = async (listTeams, target, inheritedTargets)=>{
2
+ if (inheritedTargets.has(target)) throw new Error(`"${target}" is inherited from an ancestor folder or a role, so it cannot be changed on this folder. Change it where it is defined.`);
3
+ if (!target.startsWith("team:")) return;
4
+ const result = await listTeams.execute();
5
+ if (result.isFail()) throw new Error(`Could not verify the teams: ${result.error.message}`);
6
+ const value = target.slice(5);
7
+ if (result.value.some((team)=>team.slug === value)) return;
8
+ const byId = result.value.find((team)=>team.id === value);
9
+ if (byId) throw new Error(`"${target}" uses a team id. Use the slug instead: "team:${byId.slug}".`);
10
+ throw new Error(`"${target}" is not a known team. Call listTeams first.`);
11
+ };
12
+ export { assertTargetIsUsable };
13
+
14
+ //# sourceMappingURL=assertTargetIsUsable.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"features/ai/assertTargetIsUsable.js","sources":["../../../src/features/ai/assertTargetIsUsable.ts"],"sourcesContent":["import type { ListTeamsUseCase } from \"@webiny/api-core/features/security/teams/ListTeams/index.js\";\n\n/**\n * Rejects a permission target that would be stored happily and then match nobody.\n *\n * A folder rule identifies a team by SLUG (`team:<slug>`) and a user by id (`admin:<userId>`) — see\n * ListFolderLevelPermissionsTargets. The field is only typed as a template string, so a team id where\n * a slug belongs is accepted and silently grants nothing. Also refuses a target the folder inherits,\n * since rewriting it as a direct rule detaches the folder from where the grant came from.\n */\nexport const assertTargetIsUsable = async (\n listTeams: ListTeamsUseCase.Interface,\n target: string,\n inheritedTargets: Set<string>\n): Promise<void> => {\n if (inheritedTargets.has(target)) {\n throw new Error(\n `\"${target}\" is inherited from an ancestor folder or a role, so it cannot be changed on this folder. Change it where it is defined.`\n );\n }\n\n if (!target.startsWith(\"team:\")) {\n return;\n }\n\n const result = await listTeams.execute();\n\n if (result.isFail()) {\n throw new Error(`Could not verify the teams: ${result.error.message}`);\n }\n\n const value = target.slice(\"team:\".length);\n\n if (result.value.some(team => team.slug === value)) {\n return;\n }\n\n const byId = result.value.find(team => team.id === value);\n\n if (byId) {\n throw new Error(`\"${target}\" uses a team id. Use the slug instead: \"team:${byId.slug}\".`);\n }\n\n throw new Error(`\"${target}\" is not a known team. Call listTeams first.`);\n};\n"],"names":["assertTargetIsUsable","listTeams","target","inheritedTargets","Error","result","value","team","byId"],"mappings":"AAUO,MAAMA,uBAAuB,OAChCC,WACAC,QACAC;IAEA,IAAIA,iBAAiB,GAAG,CAACD,SACrB,MAAM,IAAIE,MACN,CAAC,CAAC,EAAEF,OAAO,wHAAwH,CAAC;IAI5I,IAAI,CAACA,OAAO,UAAU,CAAC,UACnB;IAGJ,MAAMG,SAAS,MAAMJ,UAAU,OAAO;IAEtC,IAAII,OAAO,MAAM,IACb,MAAM,IAAID,MAAM,CAAC,4BAA4B,EAAEC,OAAO,KAAK,CAAC,OAAO,EAAE;IAGzE,MAAMC,QAAQJ,OAAO,KAAK,CAAC;IAE3B,IAAIG,OAAO,KAAK,CAAC,IAAI,CAACE,CAAAA,OAAQA,KAAK,IAAI,KAAKD,QACxC;IAGJ,MAAME,OAAOH,OAAO,KAAK,CAAC,IAAI,CAACE,CAAAA,OAAQA,KAAK,EAAE,KAAKD;IAEnD,IAAIE,MACA,MAAM,IAAIJ,MAAM,CAAC,CAAC,EAAEF,OAAO,8CAA8C,EAAEM,KAAK,IAAI,CAAC,EAAE,CAAC;IAG5F,MAAM,IAAIJ,MAAM,CAAC,CAAC,EAAEF,OAAO,4CAA4C,CAAC;AAC5E"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Folder and team tools for AI callers.
3
+ *
4
+ * The list tools are read-only and run unattended. Anything that creates or changes access is a write,
5
+ * so it pauses for the user to approve the exact arguments. Access changes are deliberately one target
6
+ * per call — granting and revoking separately means the approval block shows the entire change, rather
7
+ * than a desired end state whose omissions quietly remove somebody's access.
8
+ */
9
+ export declare const AcoAiToolsFeature: {
10
+ name: string;
11
+ register(container: import("@webiny/di").Container): void;
12
+ };
@@ -0,0 +1,23 @@
1
+ import { createFeature } from "@webiny/feature/api";
2
+ import { ListTeamsTool } from "./ListTeamsTool.js";
3
+ import { ListFoldersTool } from "./ListFoldersTool.js";
4
+ import { GrantFolderAccessTool } from "./GrantFolderAccessTool.js";
5
+ import { RevokeFolderAccessTool } from "./RevokeFolderAccessTool.js";
6
+ import { CreateFolderTool } from "./CreateFolderTool.js";
7
+ import { CreateTeamTool } from "./CreateTeamTool.js";
8
+ import { ListRolesTool } from "./ListRolesTool.js";
9
+ const AcoAiToolsFeature = createFeature({
10
+ name: "Aco/AiTools",
11
+ register (container) {
12
+ container.register(ListTeamsTool);
13
+ container.register(ListFoldersTool);
14
+ container.register(GrantFolderAccessTool);
15
+ container.register(RevokeFolderAccessTool);
16
+ container.register(CreateFolderTool);
17
+ container.register(CreateTeamTool);
18
+ container.register(ListRolesTool);
19
+ }
20
+ });
21
+ export { AcoAiToolsFeature };
22
+
23
+ //# sourceMappingURL=feature.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"features/ai/feature.js","sources":["../../../src/features/ai/feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/api\";\nimport { ListTeamsTool } from \"./ListTeamsTool.js\";\nimport { ListFoldersTool } from \"./ListFoldersTool.js\";\nimport { GrantFolderAccessTool } from \"./GrantFolderAccessTool.js\";\nimport { RevokeFolderAccessTool } from \"./RevokeFolderAccessTool.js\";\nimport { CreateFolderTool } from \"./CreateFolderTool.js\";\nimport { CreateTeamTool } from \"./CreateTeamTool.js\";\nimport { ListRolesTool } from \"./ListRolesTool.js\";\n\n/**\n * Folder and team tools for AI callers.\n *\n * The list tools are read-only and run unattended. Anything that creates or changes access is a write,\n * so it pauses for the user to approve the exact arguments. Access changes are deliberately one target\n * per call — granting and revoking separately means the approval block shows the entire change, rather\n * than a desired end state whose omissions quietly remove somebody's access.\n */\nexport const AcoAiToolsFeature = createFeature({\n name: \"Aco/AiTools\",\n register(container) {\n container.register(ListTeamsTool);\n container.register(ListFoldersTool);\n container.register(GrantFolderAccessTool);\n container.register(RevokeFolderAccessTool);\n container.register(CreateFolderTool);\n container.register(CreateTeamTool);\n container.register(ListRolesTool);\n }\n});\n"],"names":["AcoAiToolsFeature","createFeature","container","ListTeamsTool","ListFoldersTool","GrantFolderAccessTool","RevokeFolderAccessTool","CreateFolderTool","CreateTeamTool","ListRolesTool"],"mappings":";;;;;;;;AAiBO,MAAMA,oBAAoBC,cAAc;IAC3C,MAAM;IACN,UAASC,SAAS;QACdA,UAAU,QAAQ,CAACC;QACnBD,UAAU,QAAQ,CAACE;QACnBF,UAAU,QAAQ,CAACG;QACnBH,UAAU,QAAQ,CAACI;QACnBJ,UAAU,QAAQ,CAACK;QACnBL,UAAU,QAAQ,CAACM;QACnBN,UAAU,QAAQ,CAACO;IACvB;AACJ"}
@@ -0,0 +1,8 @@
1
+ export { AcoAiToolsFeature } from "./feature.js";
2
+ export { ListTeamsTool } from "./ListTeamsTool.js";
3
+ export { ListFoldersTool } from "./ListFoldersTool.js";
4
+ export { ListRolesTool } from "./ListRolesTool.js";
5
+ export { GrantFolderAccessTool } from "./GrantFolderAccessTool.js";
6
+ export { RevokeFolderAccessTool } from "./RevokeFolderAccessTool.js";
7
+ export { CreateFolderTool } from "./CreateFolderTool.js";
8
+ export { CreateTeamTool } from "./CreateTeamTool.js";
@@ -0,0 +1,8 @@
1
+ export { AcoAiToolsFeature } from "./feature.js";
2
+ export { ListTeamsTool } from "./ListTeamsTool.js";
3
+ export { ListFoldersTool } from "./ListFoldersTool.js";
4
+ export { ListRolesTool } from "./ListRolesTool.js";
5
+ export { GrantFolderAccessTool } from "./GrantFolderAccessTool.js";
6
+ export { RevokeFolderAccessTool } from "./RevokeFolderAccessTool.js";
7
+ export { CreateFolderTool } from "./CreateFolderTool.js";
8
+ export { CreateTeamTool } from "./CreateTeamTool.js";
@@ -0,0 +1,16 @@
1
+ import type { GetFolderUseCase } from "../../features/folder/GetFolder/index.js";
2
+ import type { Folder, FolderPermission } from "../../types.js";
3
+ export interface LoadedFolderPermissions {
4
+ folder: Folder;
5
+ /** Rules set on this folder. The only ones it may change. */
6
+ direct: FolderPermission[];
7
+ /** Targets granted by an ancestor or a role. Writing these back would detach the inheritance. */
8
+ inheritedTargets: Set<string>;
9
+ }
10
+ /**
11
+ * Reads a folder and separates the rules it owns from the ones it merely inherits.
12
+ *
13
+ * Every permission write starts here, because the field holds both kinds and a change has to preserve
14
+ * the direct rules while leaving the inherited ones alone.
15
+ */
16
+ export declare const loadFolderPermissions: (getFolder: GetFolderUseCase.Interface, folderId: string) => Promise<LoadedFolderPermissions>;
@@ -0,0 +1,14 @@
1
+ const loadFolderPermissions = async (getFolder, folderId)=>{
2
+ const result = await getFolder.execute(folderId);
3
+ if (result.isFail()) throw new Error(`Folder "${folderId}" not found: ${result.error.message}. Call listFolders for valid ids.`);
4
+ const folder = result.value;
5
+ const permissions = folder.permissions ?? [];
6
+ return {
7
+ folder,
8
+ direct: permissions.filter((permission)=>!permission.inheritedFrom),
9
+ inheritedTargets: new Set(permissions.filter((permission)=>permission.inheritedFrom).map((p)=>String(p.target)))
10
+ };
11
+ };
12
+ export { loadFolderPermissions };
13
+
14
+ //# sourceMappingURL=loadFolderPermissions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"features/ai/loadFolderPermissions.js","sources":["../../../src/features/ai/loadFolderPermissions.ts"],"sourcesContent":["import type { GetFolderUseCase } from \"~/features/folder/GetFolder/index.js\";\nimport type { Folder, FolderPermission } from \"~/types.js\";\n\nexport interface LoadedFolderPermissions {\n folder: Folder;\n /** Rules set on this folder. The only ones it may change. */\n direct: FolderPermission[];\n /** Targets granted by an ancestor or a role. Writing these back would detach the inheritance. */\n inheritedTargets: Set<string>;\n}\n\n/**\n * Reads a folder and separates the rules it owns from the ones it merely inherits.\n *\n * Every permission write starts here, because the field holds both kinds and a change has to preserve\n * the direct rules while leaving the inherited ones alone.\n */\nexport const loadFolderPermissions = async (\n getFolder: GetFolderUseCase.Interface,\n folderId: string\n): Promise<LoadedFolderPermissions> => {\n const result = await getFolder.execute(folderId);\n\n if (result.isFail()) {\n throw new Error(\n `Folder \"${folderId}\" not found: ${result.error.message}. Call listFolders for valid ids.`\n );\n }\n\n const folder = result.value;\n const permissions = folder.permissions ?? [];\n\n return {\n folder,\n direct: permissions.filter(permission => !permission.inheritedFrom),\n inheritedTargets: new Set(\n permissions.filter(permission => permission.inheritedFrom).map(p => String(p.target))\n )\n };\n};\n"],"names":["loadFolderPermissions","getFolder","folderId","result","Error","folder","permissions","permission","Set","p","String"],"mappings":"AAiBO,MAAMA,wBAAwB,OACjCC,WACAC;IAEA,MAAMC,SAAS,MAAMF,UAAU,OAAO,CAACC;IAEvC,IAAIC,OAAO,MAAM,IACb,MAAM,IAAIC,MACN,CAAC,QAAQ,EAAEF,SAAS,aAAa,EAAEC,OAAO,KAAK,CAAC,OAAO,CAAC,iCAAiC,CAAC;IAIlG,MAAME,SAASF,OAAO,KAAK;IAC3B,MAAMG,cAAcD,OAAO,WAAW,IAAI,EAAE;IAE5C,OAAO;QACHA;QACA,QAAQC,YAAY,MAAM,CAACC,CAAAA,aAAc,CAACA,WAAW,aAAa;QAClE,kBAAkB,IAAIC,IAClBF,YAAY,MAAM,CAACC,CAAAA,aAAcA,WAAW,aAAa,EAAE,GAAG,CAACE,CAAAA,IAAKC,OAAOD,EAAE,MAAM;IAE3F;AACJ"}
@@ -9,7 +9,7 @@ declare class MoveEntryWithFlpDecoratorImpl implements MoveEntryUseCase.Interfac
9
9
  private getRevisionById;
10
10
  private decoratee;
11
11
  constructor(folderLevelPermissions: FolderLevelPermissions.Interface, getRevisionById: GetRevisionByIdUseCase.Interface, decoratee: MoveEntryUseCase.Interface);
12
- execute<T extends CmsEntryValues = CmsEntryValues>(model: CmsModel, id: string, targetFolderId: string): Promise<Result<import("@webiny/api-headless-cms/types/types").CmsEntry<T>, EntryNotAuthorizedError | import("@webiny/api-headless-cms/domain/contentEntry/errors.js").EntryPersistenceError | import("@webiny/api-headless-cms/domain/contentEntry/errors.js").EntryNotFoundError>>;
12
+ execute<T extends CmsEntryValues = CmsEntryValues>(model: CmsModel, id: string, targetFolderId: string): Promise<Result<import("@webiny/api-headless-cms/types/types").CmsEntry<T>, EntryNotAuthorizedError | import("@webiny/api-headless-cms/domain/contentEntry/errors.js").EntryNotFoundError | import("@webiny/api-headless-cms/domain/contentEntry/errors.js").EntryPersistenceError>>;
13
13
  }
14
14
  export declare const MoveEntryWithFlpDecorator: typeof MoveEntryWithFlpDecoratorImpl;
15
15
  export {};
@@ -1,8 +1,8 @@
1
1
  import type { CreateFlpUseCase as UseCaseAbstraction } from "./abstractions.js";
2
2
  import type { Folder } from "../../../folder/folder.types.js";
3
- import type { AcoContext } from "../../../types.js";
3
+ import type { AcoFlpCrud } from "../../../features/folder/shared/abstractions.js";
4
4
  export declare class CreateFlpUseCase implements UseCaseAbstraction.Interface {
5
- private context;
6
- constructor(context: AcoContext);
5
+ private flpCrud;
6
+ constructor(flpCrud: AcoFlpCrud.Interface);
7
7
  execute(folder: Folder): Promise<void>;
8
8
  }
@@ -2,18 +2,18 @@ import { WebinyError } from "@webiny/error";
2
2
  import { Path } from "../../../utils/Path.js";
3
3
  import { Permissions, ROOT_FOLDER } from "@webiny/shared-aco";
4
4
  class CreateFlpUseCase {
5
- constructor(context){
6
- this.context = context;
5
+ constructor(flpCrud){
6
+ this.flpCrud = flpCrud;
7
7
  }
8
8
  async execute(folder) {
9
9
  try {
10
10
  const { id, type, slug, parentId, permissions } = folder;
11
11
  let parentFlp = null;
12
12
  if (parentId) {
13
- parentFlp = await this.context.aco.flp.get(parentId);
13
+ parentFlp = await this.flpCrud.get(parentId);
14
14
  if (!parentFlp) throw new WebinyError("Parent folder level permission not found. Unable to create a new record in the FLP catalog.", "ERROR_CREATE_FLP_USE_CASE_PARENT_FLP_NOT_FOUND");
15
15
  }
16
- await this.context.aco.flp.create({
16
+ await this.flpCrud.create({
17
17
  id,
18
18
  type,
19
19
  slug,
@@ -1 +1 @@
1
- {"version":3,"file":"features/flp/CreateFlp/CreateFlpUseCase.js","sources":["../../../../src/features/flp/CreateFlp/CreateFlpUseCase.ts"],"sourcesContent":["import { WebinyError } from \"@webiny/error\";\nimport { Path } from \"~/utils/Path.js\";\nimport { Permissions, ROOT_FOLDER } from \"@webiny/shared-aco\";\nimport type { CreateFlpUseCase as UseCaseAbstraction } from \"./abstractions.js\";\nimport type { FolderLevelPermission as IFolderLevelPermission } from \"~/flp/flp.types.js\";\nimport type { Folder } from \"~/folder/folder.types.js\";\nimport type { AcoContext } from \"~/types.js\";\n\nexport class CreateFlpUseCase implements UseCaseAbstraction.Interface {\n constructor(private context: AcoContext) {}\n\n async execute(folder: Folder): Promise<void> {\n try {\n const { id, type, slug, parentId, permissions } = folder;\n let parentFlp: IFolderLevelPermission | null = null;\n\n if (parentId) {\n parentFlp = await this.context.aco.flp.get(parentId);\n\n if (!parentFlp) {\n throw new WebinyError(\n \"Parent folder level permission not found. Unable to create a new record in the FLP catalog.\",\n \"ERROR_CREATE_FLP_USE_CASE_PARENT_FLP_NOT_FOUND\"\n );\n }\n }\n\n await this.context.aco.flp.create({\n id,\n type,\n slug,\n parentId: parentId ?? ROOT_FOLDER,\n path: Path.create(slug, parentFlp?.path),\n permissions: Permissions.create(permissions, parentFlp)\n });\n } catch (error) {\n throw WebinyError.from(error, {\n message: \"Error while creating FLP\",\n code: \"ERROR_CREATE_FLP_USE_CASE\"\n });\n }\n }\n}\n"],"names":["CreateFlpUseCase","context","folder","id","type","slug","parentId","permissions","parentFlp","WebinyError","ROOT_FOLDER","Path","Permissions","error"],"mappings":";;;AAQO,MAAMA;IACT,YAAoBC,OAAmB,CAAE;aAArBA,OAAO,GAAPA;IAAsB;IAE1C,MAAM,QAAQC,MAAc,EAAiB;QACzC,IAAI;YACA,MAAM,EAAEC,EAAE,EAAEC,IAAI,EAAEC,IAAI,EAAEC,QAAQ,EAAEC,WAAW,EAAE,GAAGL;YAClD,IAAIM,YAA2C;YAE/C,IAAIF,UAAU;gBACVE,YAAY,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAACF;gBAE3C,IAAI,CAACE,WACD,MAAM,IAAIC,YACN,+FACA;YAGZ;YAEA,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC;gBAC9BN;gBACAC;gBACAC;gBACA,UAAUC,YAAYI;gBACtB,MAAMC,KAAK,MAAM,CAACN,MAAMG,WAAW;gBACnC,aAAaI,YAAY,MAAM,CAACL,aAAaC;YACjD;QACJ,EAAE,OAAOK,OAAO;YACZ,MAAMJ,YAAY,IAAI,CAACI,OAAO;gBAC1B,SAAS;gBACT,MAAM;YACV;QACJ;IACJ;AACJ"}
1
+ {"version":3,"file":"features/flp/CreateFlp/CreateFlpUseCase.js","sources":["../../../../src/features/flp/CreateFlp/CreateFlpUseCase.ts"],"sourcesContent":["import { WebinyError } from \"@webiny/error\";\nimport { Path } from \"~/utils/Path.js\";\nimport { Permissions, ROOT_FOLDER } from \"@webiny/shared-aco\";\nimport type { CreateFlpUseCase as UseCaseAbstraction } from \"./abstractions.js\";\nimport type { FolderLevelPermission as IFolderLevelPermission } from \"~/flp/flp.types.js\";\nimport type { Folder } from \"~/folder/folder.types.js\";\nimport type { AcoFlpCrud } from \"~/features/folder/shared/abstractions.js\";\n\nexport class CreateFlpUseCase implements UseCaseAbstraction.Interface {\n constructor(private flpCrud: AcoFlpCrud.Interface) {}\n\n async execute(folder: Folder): Promise<void> {\n try {\n const { id, type, slug, parentId, permissions } = folder;\n let parentFlp: IFolderLevelPermission | null = null;\n\n if (parentId) {\n parentFlp = await this.flpCrud.get(parentId);\n\n if (!parentFlp) {\n throw new WebinyError(\n \"Parent folder level permission not found. Unable to create a new record in the FLP catalog.\",\n \"ERROR_CREATE_FLP_USE_CASE_PARENT_FLP_NOT_FOUND\"\n );\n }\n }\n\n await this.flpCrud.create({\n id,\n type,\n slug,\n parentId: parentId ?? ROOT_FOLDER,\n path: Path.create(slug, parentFlp?.path),\n permissions: Permissions.create(permissions, parentFlp)\n });\n } catch (error) {\n throw WebinyError.from(error, {\n message: \"Error while creating FLP\",\n code: \"ERROR_CREATE_FLP_USE_CASE\"\n });\n }\n }\n}\n"],"names":["CreateFlpUseCase","flpCrud","folder","id","type","slug","parentId","permissions","parentFlp","WebinyError","ROOT_FOLDER","Path","Permissions","error"],"mappings":";;;AAQO,MAAMA;IACT,YAAoBC,OAA6B,CAAE;aAA/BA,OAAO,GAAPA;IAAgC;IAEpD,MAAM,QAAQC,MAAc,EAAiB;QACzC,IAAI;YACA,MAAM,EAAEC,EAAE,EAAEC,IAAI,EAAEC,IAAI,EAAEC,QAAQ,EAAEC,WAAW,EAAE,GAAGL;YAClD,IAAIM,YAA2C;YAE/C,IAAIF,UAAU;gBACVE,YAAY,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAACF;gBAEnC,IAAI,CAACE,WACD,MAAM,IAAIC,YACN,+FACA;YAGZ;YAEA,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;gBACtBN;gBACAC;gBACAC;gBACA,UAAUC,YAAYI;gBACtB,MAAMC,KAAK,MAAM,CAACN,MAAMG,WAAW;gBACnC,aAAaI,YAAY,MAAM,CAACL,aAAaC;YACjD;QACJ,EAAE,OAAOK,OAAO;YACZ,MAAMJ,YAAY,IAAI,CAACI,OAAO;gBAC1B,SAAS;gBACT,MAAM;YACV;QACJ;IACJ;AACJ"}
@@ -1,10 +1,5 @@
1
1
  import type { Container } from "@webiny/di";
2
- import type { AcoContext } from "../../../types.js";
3
- interface LegacyDeps {
4
- context: AcoContext;
5
- }
6
2
  export declare const CreateFlpFeature: {
7
3
  name: string;
8
- register(container: Container, context: LegacyDeps): void;
4
+ register(container: Container): void;
9
5
  };
10
- export {};
@@ -1,10 +1,11 @@
1
1
  import { createFeature } from "@webiny/feature/api";
2
2
  import { CreateFlpUseCase } from "./CreateFlpUseCase.js";
3
3
  import { CreateFlpUseCase as external_abstractions_js_CreateFlpUseCase } from "./abstractions.js";
4
+ import { AcoFlpCrud } from "../../folder/shared/abstractions.js";
4
5
  const CreateFlpFeature = createFeature({
5
6
  name: "CreateFlp",
6
- register (container, deps) {
7
- container.registerFactory(external_abstractions_js_CreateFlpUseCase, ()=>new CreateFlpUseCase(deps.context));
7
+ register (container) {
8
+ container.registerFactory(external_abstractions_js_CreateFlpUseCase, ()=>new CreateFlpUseCase(container.resolve(AcoFlpCrud)));
8
9
  }
9
10
  });
10
11
  export { CreateFlpFeature };
@@ -1 +1 @@
1
- {"version":3,"file":"features/flp/CreateFlp/feature.js","sources":["../../../../src/features/flp/CreateFlp/feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/api\";\nimport type { Container } from \"@webiny/di\";\nimport { CreateFlpUseCase } from \"./CreateFlpUseCase.js\";\nimport { CreateFlpUseCase as UseCaseAbstraction } from \"./abstractions.js\";\nimport type { AcoContext } from \"~/types.js\";\n\ninterface LegacyDeps {\n context: AcoContext;\n}\n\nexport const CreateFlpFeature = createFeature({\n name: \"CreateFlp\",\n register(container: Container, deps: LegacyDeps) {\n container.registerFactory(UseCaseAbstraction, () => {\n return new CreateFlpUseCase(deps.context);\n });\n }\n});\n"],"names":["CreateFlpFeature","createFeature","container","deps","UseCaseAbstraction","CreateFlpUseCase"],"mappings":";;;AAUO,MAAMA,mBAAmBC,cAAc;IAC1C,MAAM;IACN,UAASC,SAAoB,EAAEC,IAAgB;QAC3CD,UAAU,eAAe,CAACE,2CAAoB,IACnC,IAAIC,iBAAiBF,KAAK,OAAO;IAEhD;AACJ"}
1
+ {"version":3,"file":"features/flp/CreateFlp/feature.js","sources":["../../../../src/features/flp/CreateFlp/feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/api\";\nimport type { Container } from \"@webiny/di\";\nimport { CreateFlpUseCase } from \"./CreateFlpUseCase.js\";\nimport { CreateFlpUseCase as UseCaseAbstraction } from \"./abstractions.js\";\nimport { AcoFlpCrud } from \"~/features/folder/shared/abstractions.js\";\n\nexport const CreateFlpFeature = createFeature({\n name: \"CreateFlp\",\n register(container: Container) {\n container.registerFactory(UseCaseAbstraction, () => {\n return new CreateFlpUseCase(container.resolve(AcoFlpCrud));\n });\n }\n});\n"],"names":["CreateFlpFeature","createFeature","container","UseCaseAbstraction","CreateFlpUseCase","AcoFlpCrud"],"mappings":";;;;AAMO,MAAMA,mBAAmBC,cAAc;IAC1C,MAAM;IACN,UAASC,SAAoB;QACzBA,UAAU,eAAe,CAACC,2CAAoB,IACnC,IAAIC,iBAAiBF,UAAU,OAAO,CAACG;IAEtD;AACJ"}
@@ -1,8 +1,8 @@
1
1
  import type { DeleteFlpUseCase as UseCaseAbstraction } from "./abstractions.js";
2
2
  import type { Folder } from "../../../folder/folder.types.js";
3
- import type { AcoContext } from "../../../types.js";
3
+ import type { AcoFlpCrud } from "../../../features/folder/shared/abstractions.js";
4
4
  export declare class DeleteFlpUseCase implements UseCaseAbstraction.Interface {
5
- private context;
6
- constructor(context: AcoContext);
5
+ private flpCrud;
6
+ constructor(flpCrud: AcoFlpCrud.Interface);
7
7
  execute(folder: Folder): Promise<void>;
8
8
  }
@@ -1,14 +1,14 @@
1
1
  import { WebinyError } from "@webiny/error";
2
2
  class DeleteFlpUseCase {
3
- constructor(context){
4
- this.context = context;
3
+ constructor(flpCrud){
4
+ this.flpCrud = flpCrud;
5
5
  }
6
6
  async execute(folder) {
7
7
  try {
8
8
  if (!folder) throw new WebinyError("Missing `folder` from the task input, I can't delete the record from the FLP catalog.", "ERROR_DELETE_FLP_USE_CASE_FOLDER_NOT_PROVIDED", {
9
9
  folder
10
10
  });
11
- await this.context.aco.flp.delete(folder.id);
11
+ await this.flpCrud.delete(folder.id);
12
12
  } catch (error) {
13
13
  throw WebinyError.from(error, {
14
14
  message: "Error while deleting FLP",
@@ -1 +1 @@
1
- {"version":3,"file":"features/flp/DeleteFlp/DeleteFlpUseCase.js","sources":["../../../../src/features/flp/DeleteFlp/DeleteFlpUseCase.ts"],"sourcesContent":["import { WebinyError } from \"@webiny/error\";\nimport type { DeleteFlpUseCase as UseCaseAbstraction } from \"./abstractions.js\";\nimport type { Folder } from \"~/folder/folder.types.js\";\nimport type { AcoContext } from \"~/types.js\";\n\nexport class DeleteFlpUseCase implements UseCaseAbstraction.Interface {\n constructor(private context: AcoContext) {}\n\n async execute(folder: Folder): Promise<void> {\n try {\n if (!folder) {\n throw new WebinyError(\n \"Missing `folder` from the task input, I can't delete the record from the FLP catalog.\",\n \"ERROR_DELETE_FLP_USE_CASE_FOLDER_NOT_PROVIDED\",\n { folder }\n );\n }\n await this.context.aco.flp.delete(folder.id);\n } catch (error) {\n throw WebinyError.from(error, {\n message: \"Error while deleting FLP\",\n code: \"ERROR_DELETE_FLP_USE_CASE\"\n });\n }\n }\n}\n"],"names":["DeleteFlpUseCase","context","folder","WebinyError","error"],"mappings":";AAKO,MAAMA;IACT,YAAoBC,OAAmB,CAAE;aAArBA,OAAO,GAAPA;IAAsB;IAE1C,MAAM,QAAQC,MAAc,EAAiB;QACzC,IAAI;YACA,IAAI,CAACA,QACD,MAAM,IAAIC,YACN,yFACA,iDACA;gBAAED;YAAO;YAGjB,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAACA,OAAO,EAAE;QAC/C,EAAE,OAAOE,OAAO;YACZ,MAAMD,YAAY,IAAI,CAACC,OAAO;gBAC1B,SAAS;gBACT,MAAM;YACV;QACJ;IACJ;AACJ"}
1
+ {"version":3,"file":"features/flp/DeleteFlp/DeleteFlpUseCase.js","sources":["../../../../src/features/flp/DeleteFlp/DeleteFlpUseCase.ts"],"sourcesContent":["import { WebinyError } from \"@webiny/error\";\nimport type { DeleteFlpUseCase as UseCaseAbstraction } from \"./abstractions.js\";\nimport type { Folder } from \"~/folder/folder.types.js\";\nimport type { AcoFlpCrud } from \"~/features/folder/shared/abstractions.js\";\n\nexport class DeleteFlpUseCase implements UseCaseAbstraction.Interface {\n constructor(private flpCrud: AcoFlpCrud.Interface) {}\n\n async execute(folder: Folder): Promise<void> {\n try {\n if (!folder) {\n throw new WebinyError(\n \"Missing `folder` from the task input, I can't delete the record from the FLP catalog.\",\n \"ERROR_DELETE_FLP_USE_CASE_FOLDER_NOT_PROVIDED\",\n { folder }\n );\n }\n await this.flpCrud.delete(folder.id);\n } catch (error) {\n throw WebinyError.from(error, {\n message: \"Error while deleting FLP\",\n code: \"ERROR_DELETE_FLP_USE_CASE\"\n });\n }\n }\n}\n"],"names":["DeleteFlpUseCase","flpCrud","folder","WebinyError","error"],"mappings":";AAKO,MAAMA;IACT,YAAoBC,OAA6B,CAAE;aAA/BA,OAAO,GAAPA;IAAgC;IAEpD,MAAM,QAAQC,MAAc,EAAiB;QACzC,IAAI;YACA,IAAI,CAACA,QACD,MAAM,IAAIC,YACN,yFACA,iDACA;gBAAED;YAAO;YAGjB,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAACA,OAAO,EAAE;QACvC,EAAE,OAAOE,OAAO;YACZ,MAAMD,YAAY,IAAI,CAACC,OAAO;gBAC1B,SAAS;gBACT,MAAM;YACV;QACJ;IACJ;AACJ"}
@@ -1,10 +1,5 @@
1
1
  import type { Container } from "@webiny/di";
2
- import type { AcoContext } from "../../../types.js";
3
- interface LegacyDeps {
4
- context: AcoContext;
5
- }
6
2
  export declare const DeleteFlpFeature: {
7
3
  name: string;
8
- register(container: Container, context: LegacyDeps): void;
4
+ register(container: Container): void;
9
5
  };
10
- export {};
@@ -1,10 +1,11 @@
1
1
  import { createFeature } from "@webiny/feature/api";
2
2
  import { DeleteFlpUseCase } from "./DeleteFlpUseCase.js";
3
3
  import { DeleteFlpUseCase as external_abstractions_js_DeleteFlpUseCase } from "./abstractions.js";
4
+ import { AcoFlpCrud } from "../../folder/shared/abstractions.js";
4
5
  const DeleteFlpFeature = createFeature({
5
6
  name: "DeleteFlp",
6
- register (container, deps) {
7
- container.registerFactory(external_abstractions_js_DeleteFlpUseCase, ()=>new DeleteFlpUseCase(deps.context));
7
+ register (container) {
8
+ container.registerFactory(external_abstractions_js_DeleteFlpUseCase, ()=>new DeleteFlpUseCase(container.resolve(AcoFlpCrud)));
8
9
  }
9
10
  });
10
11
  export { DeleteFlpFeature };
@@ -1 +1 @@
1
- {"version":3,"file":"features/flp/DeleteFlp/feature.js","sources":["../../../../src/features/flp/DeleteFlp/feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/api\";\nimport type { Container } from \"@webiny/di\";\nimport { DeleteFlpUseCase } from \"./DeleteFlpUseCase.js\";\nimport { DeleteFlpUseCase as UseCaseAbstraction } from \"./abstractions.js\";\nimport type { AcoContext } from \"~/types.js\";\n\ninterface LegacyDeps {\n context: AcoContext;\n}\n\nexport const DeleteFlpFeature = createFeature({\n name: \"DeleteFlp\",\n register(container: Container, deps: LegacyDeps) {\n container.registerFactory(UseCaseAbstraction, () => {\n return new DeleteFlpUseCase(deps.context);\n });\n }\n});\n"],"names":["DeleteFlpFeature","createFeature","container","deps","UseCaseAbstraction","DeleteFlpUseCase"],"mappings":";;;AAUO,MAAMA,mBAAmBC,cAAc;IAC1C,MAAM;IACN,UAASC,SAAoB,EAAEC,IAAgB;QAC3CD,UAAU,eAAe,CAACE,2CAAoB,IACnC,IAAIC,iBAAiBF,KAAK,OAAO;IAEhD;AACJ"}
1
+ {"version":3,"file":"features/flp/DeleteFlp/feature.js","sources":["../../../../src/features/flp/DeleteFlp/feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/api\";\nimport type { Container } from \"@webiny/di\";\nimport { DeleteFlpUseCase } from \"./DeleteFlpUseCase.js\";\nimport { DeleteFlpUseCase as UseCaseAbstraction } from \"./abstractions.js\";\nimport { AcoFlpCrud } from \"~/features/folder/shared/abstractions.js\";\n\nexport const DeleteFlpFeature = createFeature({\n name: \"DeleteFlp\",\n register(container: Container) {\n container.registerFactory(UseCaseAbstraction, () => {\n return new DeleteFlpUseCase(container.resolve(AcoFlpCrud));\n });\n }\n});\n"],"names":["DeleteFlpFeature","createFeature","container","UseCaseAbstraction","DeleteFlpUseCase","AcoFlpCrud"],"mappings":";;;;AAMO,MAAMA,mBAAmBC,cAAc;IAC1C,MAAM;IACN,UAASC,SAAoB;QACzBA,UAAU,eAAe,CAACC,2CAAoB,IACnC,IAAIC,iBAAiBF,UAAU,OAAO,CAACG;IAEtD;AACJ"}
@@ -1,5 +1,5 @@
1
1
  import { IdentityContext } from "@webiny/api-core/features/security/IdentityContext/index.js";
2
- import { WcpContext } from "@webiny/api-core/features/wcp/WcpContext/index.js";
2
+ import { FeatureFlags } from "@webiny/api-core/features/featureFlags/abstractions.js";
3
3
  import { ListUserTeamsUseCase } from "@webiny/api-core/features/users/ListUserTeams/index.js";
4
4
  import { type CanAccessFolderContentParams, type CanAccessFolderParams } from "./useCases/index.js";
5
5
  import { FolderLevelPermissions as FolderLevelPermissionsAbstraction } from "./abstractions.js";
@@ -8,11 +8,11 @@ import { ListFlpsUseCase } from "../../../features/flp/ListFlps/index.js";
8
8
  import { GetFlpUseCase } from "../../../features/flp/GetFlp/index.js";
9
9
  declare class FolderLevelPermissionsImpl implements FolderLevelPermissionsAbstraction.Interface {
10
10
  private identityContext;
11
- private wcpContext;
11
+ private featureFlags;
12
12
  private listUserTeamsUseCase;
13
13
  private getFlpUseCase;
14
14
  private listFlpsUseCase;
15
- constructor(identityContext: IdentityContext.Interface, wcpContext: WcpContext.Interface, listUserTeamsUseCase: ListUserTeamsUseCase.Interface, getFlpUseCase: GetFlpUseCase.Interface, listFlpsUseCase: ListFlpsUseCase.Interface);
15
+ constructor(identityContext: IdentityContext.Interface, featureFlags: FeatureFlags.Interface, listUserTeamsUseCase: ListUserTeamsUseCase.Interface, getFlpUseCase: GetFlpUseCase.Interface, listFlpsUseCase: ListFlpsUseCase.Interface);
16
16
  canUseFolderLevelPermissions(enabled?: boolean): boolean;
17
17
  canUseTeams(): boolean;
18
18
  canCreateFolderInRoot(): boolean;
@@ -1,6 +1,6 @@
1
1
  import { createImplementation } from "@webiny/di";
2
2
  import { IdentityContext } from "@webiny/api-core/features/security/IdentityContext/index.js";
3
- import { WcpContext } from "@webiny/api-core/features/wcp/WcpContext/index.js";
3
+ import { FeatureFlags } from "@webiny/api-core/features/featureFlags/abstractions.js";
4
4
  import { ListUserTeamsUseCase } from "@webiny/api-core/features/users/ListUserTeams/index.js";
5
5
  import { NotAuthorizedError } from "@webiny/api-core/features/security/shared/index.js";
6
6
  import { CanAccessFolder, CanAccessFolderContent, CanCreateFolderInRoot, CheckNotInheritedPermissions, GetDefaultPermissions, GetDefaultPermissionsWithTeams } from "./useCases/index.js";
@@ -8,9 +8,9 @@ import { FolderLevelPermissions } from "./abstractions.js";
8
8
  import { ListFlpsUseCase } from "../ListFlps/index.js";
9
9
  import { GetFlpUseCase } from "../GetFlp/index.js";
10
10
  class FolderLevelPermissionsImpl {
11
- constructor(identityContext, wcpContext, listUserTeamsUseCase, getFlpUseCase, listFlpsUseCase){
11
+ constructor(identityContext, featureFlags, listUserTeamsUseCase, getFlpUseCase, listFlpsUseCase){
12
12
  this.identityContext = identityContext;
13
- this.wcpContext = wcpContext;
13
+ this.featureFlags = featureFlags;
14
14
  this.listUserTeamsUseCase = listUserTeamsUseCase;
15
15
  this.getFlpUseCase = getFlpUseCase;
16
16
  this.listFlpsUseCase = listFlpsUseCase;
@@ -20,10 +20,10 @@ class FolderLevelPermissionsImpl {
20
20
  const identity = this.identityContext.getIdentity();
21
21
  if (!identity) return false;
22
22
  if ("admin" !== identity.type) return false;
23
- return this.wcpContext.canUseFolderLevelPermissions();
23
+ return this.featureFlags.get().isEnabled("advancedAccessControlLayer.folderLevelPermissions");
24
24
  }
25
25
  canUseTeams() {
26
- return this.wcpContext.canUseTeams();
26
+ return this.featureFlags.get().isEnabled("advancedAccessControlLayer.teams");
27
27
  }
28
28
  canCreateFolderInRoot() {
29
29
  const canCreateFolderInRootUseCase = new CanCreateFolderInRoot();
@@ -101,7 +101,7 @@ const FolderLevelPermissions_FolderLevelPermissions = createImplementation({
101
101
  implementation: FolderLevelPermissionsImpl,
102
102
  dependencies: [
103
103
  IdentityContext,
104
- WcpContext,
104
+ FeatureFlags,
105
105
  ListUserTeamsUseCase,
106
106
  GetFlpUseCase,
107
107
  ListFlpsUseCase
@@ -1 +1 @@
1
- {"version":3,"file":"features/flp/FolderLevelPermissions/FolderLevelPermissions.js","sources":["../../../../src/features/flp/FolderLevelPermissions/FolderLevelPermissions.ts"],"sourcesContent":["import { createImplementation } from \"@webiny/di\";\nimport { IdentityContext } from \"@webiny/api-core/features/security/IdentityContext/index.js\";\nimport { WcpContext } from \"@webiny/api-core/features/wcp/WcpContext/index.js\";\nimport { ListUserTeamsUseCase } from \"@webiny/api-core/features/users/ListUserTeams/index.js\";\nimport { NotAuthorizedError } from \"@webiny/api-core/features/security/shared/index.js\";\nimport {\n CanAccessFolder,\n CanAccessFolderContent,\n type CanAccessFolderContentParams,\n type CanAccessFolderParams,\n CanCreateFolderInRoot,\n CheckNotInheritedPermissions,\n GetDefaultPermissions,\n GetDefaultPermissionsWithTeams\n} from \"./useCases/index.js\";\nimport { FolderLevelPermissions as FolderLevelPermissionsAbstraction } from \"./abstractions.js\";\nimport type { FolderLevelPermission, FolderPermission, ListFlpsParams } from \"~/types.js\";\nimport { ListFlpsUseCase } from \"~/features/flp/ListFlps/index.js\";\nimport { GetFlpUseCase } from \"~/features/flp/GetFlp/index.js\";\n\nclass FolderLevelPermissionsImpl implements FolderLevelPermissionsAbstraction.Interface {\n constructor(\n private identityContext: IdentityContext.Interface,\n private wcpContext: WcpContext.Interface,\n private listUserTeamsUseCase: ListUserTeamsUseCase.Interface,\n private getFlpUseCase: GetFlpUseCase.Interface,\n private listFlpsUseCase: ListFlpsUseCase.Interface\n ) {}\n\n public canUseFolderLevelPermissions(enabled?: boolean): boolean {\n if (enabled === false) {\n return false;\n }\n\n const identity = this.identityContext.getIdentity();\n\n // FLPs only work with authenticated identities (logged-in users).\n if (!identity) {\n return false;\n }\n\n // At the moment, we only want FLP to be used with identities of type \"admin\".\n // This temporarily addresses the issue of API keys not being able to access content, because\n // FLPs doesn't work with them. Once we start adding FLPs to API keys, we can remove this check.\n if (identity.type !== \"admin\") {\n return false;\n }\n\n return this.wcpContext.canUseFolderLevelPermissions();\n }\n\n public canUseTeams(): boolean {\n return this.wcpContext.canUseTeams();\n }\n\n public canCreateFolderInRoot(): boolean {\n const canCreateFolderInRootUseCase = new CanCreateFolderInRoot();\n return canCreateFolderInRootUseCase.execute();\n }\n\n public permissionsIncludeNonInheritedPermissions(permissions: FolderPermission[]): boolean {\n const checkNotInheritedPermissionsUseCase = new CheckNotInheritedPermissions();\n return checkNotInheritedPermissionsUseCase.execute(permissions);\n }\n\n public async canAccessFolder(params: CanAccessFolderParams): Promise<boolean> {\n if (\n !this.canUseFolderLevelPermissions() ||\n !this.identityContext.isAuthorizationEnabled()\n ) {\n return true;\n }\n\n const canAccessFolderUseCase = new CanAccessFolder(this.identityContext);\n return await canAccessFolderUseCase.execute(params);\n }\n\n public async canAccessFolderContent(params: CanAccessFolderContentParams): Promise<boolean> {\n const canUseFlp = this.canUseFolderLevelPermissions();\n const authEnabled = this.identityContext.isAuthorizationEnabled();\n\n if (!canUseFlp || !authEnabled) {\n return true;\n }\n\n const canAccessFolderContentUseCase = new CanAccessFolderContent(this.identityContext);\n return await canAccessFolderContentUseCase.execute(params);\n }\n\n public async ensureCanAccessFolder(params: CanAccessFolderParams): Promise<void> {\n const result = await this.canAccessFolder(params);\n if (!result) {\n throw new NotAuthorizedError();\n }\n }\n\n public async ensureCanAccessFolderContent(params: CanAccessFolderContentParams): Promise<void> {\n const result = await this.canAccessFolderContent(params);\n if (!result) {\n throw new NotAuthorizedError();\n }\n }\n\n public async canManageFolderContent(flp: FolderLevelPermission): Promise<boolean> {\n if (\n !this.canUseFolderLevelPermissions() ||\n !this.identityContext.isAuthorizationEnabled()\n ) {\n return true;\n }\n\n return await this.canAccessFolderContent({ permissions: flp.permissions, rwd: \"w\" });\n }\n\n public async canManageFolderStructure(flp: FolderLevelPermission): Promise<boolean> {\n if (\n !this.canUseFolderLevelPermissions() ||\n !this.identityContext.isAuthorizationEnabled()\n ) {\n return true;\n }\n\n return await this.canAccessFolder({ permissions: flp.permissions, rwd: \"w\" });\n }\n\n public async canManageFolderPermissions(flp: FolderLevelPermission): Promise<boolean> {\n if (!this.canUseFolderLevelPermissions()) {\n return false;\n }\n\n if (!this.identityContext.isAuthorizationEnabled()) {\n return true;\n }\n\n return await this.canAccessFolder({\n permissions: flp.permissions,\n rwd: \"w\",\n managePermissions: true\n });\n }\n\n public getDefaultPermissions(permissions: FolderPermission[]): Promise<FolderPermission[]> {\n const getDefaultPermissionsUseCase = new GetDefaultPermissions(this.identityContext);\n\n if (this.canUseTeams()) {\n const getDefaultPermissionsWithTeams = new GetDefaultPermissionsWithTeams(\n this.identityContext,\n this.listUserTeamsUseCase,\n getDefaultPermissionsUseCase\n );\n\n return getDefaultPermissionsWithTeams.execute(permissions);\n }\n\n return getDefaultPermissionsUseCase.execute(permissions);\n }\n\n public async listFolderLevelPermissions(params: ListFlpsParams): Promise<\n Array<{\n id: string;\n permissions: FolderPermission[];\n }>\n > {\n const flps = await this.listFlpsUseCase.execute(params);\n\n return Promise.all(\n flps.map(async flp => ({\n id: flp.id,\n permissions: await this.getDefaultPermissions(flp.permissions)\n }))\n );\n }\n\n public async getFolderLevelPermissions(id: string): Promise<FolderPermission[]> {\n const flp = await this.getFlpUseCase.execute(id);\n return await this.getDefaultPermissions(flp?.permissions ?? []);\n }\n}\n\nexport const FolderLevelPermissions = createImplementation({\n abstraction: FolderLevelPermissionsAbstraction,\n implementation: FolderLevelPermissionsImpl,\n dependencies: [\n IdentityContext,\n WcpContext,\n ListUserTeamsUseCase,\n GetFlpUseCase,\n ListFlpsUseCase\n ]\n});\n"],"names":["FolderLevelPermissionsImpl","identityContext","wcpContext","listUserTeamsUseCase","getFlpUseCase","listFlpsUseCase","enabled","identity","canCreateFolderInRootUseCase","CanCreateFolderInRoot","permissions","checkNotInheritedPermissionsUseCase","CheckNotInheritedPermissions","params","canAccessFolderUseCase","CanAccessFolder","canUseFlp","authEnabled","canAccessFolderContentUseCase","CanAccessFolderContent","result","NotAuthorizedError","flp","getDefaultPermissionsUseCase","GetDefaultPermissions","getDefaultPermissionsWithTeams","GetDefaultPermissionsWithTeams","flps","Promise","id","FolderLevelPermissions","createImplementation","FolderLevelPermissionsAbstraction","IdentityContext","WcpContext","ListUserTeamsUseCase","GetFlpUseCase","ListFlpsUseCase"],"mappings":"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"}
1
+ {"version":3,"file":"features/flp/FolderLevelPermissions/FolderLevelPermissions.js","sources":["../../../../src/features/flp/FolderLevelPermissions/FolderLevelPermissions.ts"],"sourcesContent":["import { createImplementation } from \"@webiny/di\";\nimport { IdentityContext } from \"@webiny/api-core/features/security/IdentityContext/index.js\";\nimport { FeatureFlags } from \"@webiny/api-core/features/featureFlags/abstractions.js\";\nimport { ListUserTeamsUseCase } from \"@webiny/api-core/features/users/ListUserTeams/index.js\";\nimport { NotAuthorizedError } from \"@webiny/api-core/features/security/shared/index.js\";\nimport {\n CanAccessFolder,\n CanAccessFolderContent,\n type CanAccessFolderContentParams,\n type CanAccessFolderParams,\n CanCreateFolderInRoot,\n CheckNotInheritedPermissions,\n GetDefaultPermissions,\n GetDefaultPermissionsWithTeams\n} from \"./useCases/index.js\";\nimport { FolderLevelPermissions as FolderLevelPermissionsAbstraction } from \"./abstractions.js\";\nimport type { FolderLevelPermission, FolderPermission, ListFlpsParams } from \"~/types.js\";\nimport { ListFlpsUseCase } from \"~/features/flp/ListFlps/index.js\";\nimport { GetFlpUseCase } from \"~/features/flp/GetFlp/index.js\";\n\nclass FolderLevelPermissionsImpl implements FolderLevelPermissionsAbstraction.Interface {\n constructor(\n private identityContext: IdentityContext.Interface,\n private featureFlags: FeatureFlags.Interface,\n private listUserTeamsUseCase: ListUserTeamsUseCase.Interface,\n private getFlpUseCase: GetFlpUseCase.Interface,\n private listFlpsUseCase: ListFlpsUseCase.Interface\n ) {}\n\n public canUseFolderLevelPermissions(enabled?: boolean): boolean {\n if (enabled === false) {\n return false;\n }\n\n const identity = this.identityContext.getIdentity();\n\n // FLPs only work with authenticated identities (logged-in users).\n if (!identity) {\n return false;\n }\n\n // At the moment, we only want FLP to be used with identities of type \"admin\".\n // This temporarily addresses the issue of API keys not being able to access content, because\n // FLPs doesn't work with them. Once we start adding FLPs to API keys, we can remove this check.\n if (identity.type !== \"admin\") {\n return false;\n }\n\n return this.featureFlags\n .get()\n .isEnabled(\"advancedAccessControlLayer.folderLevelPermissions\");\n }\n\n public canUseTeams(): boolean {\n return this.featureFlags.get().isEnabled(\"advancedAccessControlLayer.teams\");\n }\n\n public canCreateFolderInRoot(): boolean {\n const canCreateFolderInRootUseCase = new CanCreateFolderInRoot();\n return canCreateFolderInRootUseCase.execute();\n }\n\n public permissionsIncludeNonInheritedPermissions(permissions: FolderPermission[]): boolean {\n const checkNotInheritedPermissionsUseCase = new CheckNotInheritedPermissions();\n return checkNotInheritedPermissionsUseCase.execute(permissions);\n }\n\n public async canAccessFolder(params: CanAccessFolderParams): Promise<boolean> {\n if (\n !this.canUseFolderLevelPermissions() ||\n !this.identityContext.isAuthorizationEnabled()\n ) {\n return true;\n }\n\n const canAccessFolderUseCase = new CanAccessFolder(this.identityContext);\n return await canAccessFolderUseCase.execute(params);\n }\n\n public async canAccessFolderContent(params: CanAccessFolderContentParams): Promise<boolean> {\n const canUseFlp = this.canUseFolderLevelPermissions();\n const authEnabled = this.identityContext.isAuthorizationEnabled();\n\n if (!canUseFlp || !authEnabled) {\n return true;\n }\n\n const canAccessFolderContentUseCase = new CanAccessFolderContent(this.identityContext);\n return await canAccessFolderContentUseCase.execute(params);\n }\n\n public async ensureCanAccessFolder(params: CanAccessFolderParams): Promise<void> {\n const result = await this.canAccessFolder(params);\n if (!result) {\n throw new NotAuthorizedError();\n }\n }\n\n public async ensureCanAccessFolderContent(params: CanAccessFolderContentParams): Promise<void> {\n const result = await this.canAccessFolderContent(params);\n if (!result) {\n throw new NotAuthorizedError();\n }\n }\n\n public async canManageFolderContent(flp: FolderLevelPermission): Promise<boolean> {\n if (\n !this.canUseFolderLevelPermissions() ||\n !this.identityContext.isAuthorizationEnabled()\n ) {\n return true;\n }\n\n return await this.canAccessFolderContent({ permissions: flp.permissions, rwd: \"w\" });\n }\n\n public async canManageFolderStructure(flp: FolderLevelPermission): Promise<boolean> {\n if (\n !this.canUseFolderLevelPermissions() ||\n !this.identityContext.isAuthorizationEnabled()\n ) {\n return true;\n }\n\n return await this.canAccessFolder({ permissions: flp.permissions, rwd: \"w\" });\n }\n\n public async canManageFolderPermissions(flp: FolderLevelPermission): Promise<boolean> {\n if (!this.canUseFolderLevelPermissions()) {\n return false;\n }\n\n if (!this.identityContext.isAuthorizationEnabled()) {\n return true;\n }\n\n return await this.canAccessFolder({\n permissions: flp.permissions,\n rwd: \"w\",\n managePermissions: true\n });\n }\n\n public getDefaultPermissions(permissions: FolderPermission[]): Promise<FolderPermission[]> {\n const getDefaultPermissionsUseCase = new GetDefaultPermissions(this.identityContext);\n\n if (this.canUseTeams()) {\n const getDefaultPermissionsWithTeams = new GetDefaultPermissionsWithTeams(\n this.identityContext,\n this.listUserTeamsUseCase,\n getDefaultPermissionsUseCase\n );\n\n return getDefaultPermissionsWithTeams.execute(permissions);\n }\n\n return getDefaultPermissionsUseCase.execute(permissions);\n }\n\n public async listFolderLevelPermissions(params: ListFlpsParams): Promise<\n Array<{\n id: string;\n permissions: FolderPermission[];\n }>\n > {\n const flps = await this.listFlpsUseCase.execute(params);\n\n return Promise.all(\n flps.map(async flp => ({\n id: flp.id,\n permissions: await this.getDefaultPermissions(flp.permissions)\n }))\n );\n }\n\n public async getFolderLevelPermissions(id: string): Promise<FolderPermission[]> {\n const flp = await this.getFlpUseCase.execute(id);\n return await this.getDefaultPermissions(flp?.permissions ?? []);\n }\n}\n\nexport const FolderLevelPermissions = createImplementation({\n abstraction: FolderLevelPermissionsAbstraction,\n implementation: FolderLevelPermissionsImpl,\n dependencies: [\n IdentityContext,\n FeatureFlags,\n ListUserTeamsUseCase,\n GetFlpUseCase,\n ListFlpsUseCase\n ]\n});\n"],"names":["FolderLevelPermissionsImpl","identityContext","featureFlags","listUserTeamsUseCase","getFlpUseCase","listFlpsUseCase","enabled","identity","canCreateFolderInRootUseCase","CanCreateFolderInRoot","permissions","checkNotInheritedPermissionsUseCase","CheckNotInheritedPermissions","params","canAccessFolderUseCase","CanAccessFolder","canUseFlp","authEnabled","canAccessFolderContentUseCase","CanAccessFolderContent","result","NotAuthorizedError","flp","getDefaultPermissionsUseCase","GetDefaultPermissions","getDefaultPermissionsWithTeams","GetDefaultPermissionsWithTeams","flps","Promise","id","FolderLevelPermissions","createImplementation","FolderLevelPermissionsAbstraction","IdentityContext","FeatureFlags","ListUserTeamsUseCase","GetFlpUseCase","ListFlpsUseCase"],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import { type IFolderLevelPermissions } from "./abstractions.js";
2
+ import type { FolderPermission } from "../../../types.js";
3
+ declare class NoopFolderLevelPermissionsImpl implements IFolderLevelPermissions {
4
+ canUseFolderLevelPermissions(): boolean;
5
+ canUseTeams(): boolean;
6
+ canCreateFolderInRoot(): boolean;
7
+ permissionsIncludeNonInheritedPermissions(): boolean;
8
+ canAccessFolder(): Promise<boolean>;
9
+ canAccessFolderContent(): Promise<boolean>;
10
+ ensureCanAccessFolder(): Promise<void>;
11
+ ensureCanAccessFolderContent(): Promise<void>;
12
+ canManageFolderContent(): Promise<boolean>;
13
+ canManageFolderStructure(): Promise<boolean>;
14
+ canManageFolderPermissions(): Promise<boolean>;
15
+ getDefaultPermissions(permissions: FolderPermission[]): Promise<FolderPermission[]>;
16
+ listFolderLevelPermissions(): Promise<Array<{
17
+ id: string;
18
+ permissions: FolderPermission[];
19
+ }>>;
20
+ getFolderLevelPermissions(): Promise<FolderPermission[]>;
21
+ }
22
+ export declare const NoopFolderLevelPermissions: typeof NoopFolderLevelPermissionsImpl & {
23
+ __abstraction: import("@webiny/di").Abstraction<IFolderLevelPermissions>;
24
+ };
25
+ export {};