@webiny/api-aco 5.43.0-beta.2 → 5.43.0-beta.4

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 (44) hide show
  1. package/flp/FolderLevelPermissions/useCases/GetDefaultPermissions/DefaultPermissionsMerger.d.ts +6 -0
  2. package/flp/FolderLevelPermissions/useCases/GetDefaultPermissions/DefaultPermissionsMerger.js +77 -0
  3. package/flp/FolderLevelPermissions/useCases/GetDefaultPermissions/DefaultPermissionsMerger.js.map +1 -0
  4. package/flp/FolderLevelPermissions/useCases/GetDefaultPermissions/GetDefaultPermissions.d.ts +0 -1
  5. package/flp/FolderLevelPermissions/useCases/GetDefaultPermissions/GetDefaultPermissions.js +3 -35
  6. package/flp/FolderLevelPermissions/useCases/GetDefaultPermissions/GetDefaultPermissions.js.map +1 -1
  7. package/flp/FolderLevelPermissions/useCases/GetDefaultPermissions/GetDefaultPermissionsWithTeams.d.ts +1 -1
  8. package/flp/FolderLevelPermissions/useCases/GetDefaultPermissions/GetDefaultPermissionsWithTeams.js +3 -1
  9. package/flp/FolderLevelPermissions/useCases/GetDefaultPermissions/GetDefaultPermissionsWithTeams.js.map +1 -1
  10. package/flp/useCases/CreateFlp.js +1 -1
  11. package/flp/useCases/CreateFlp.js.map +1 -1
  12. package/flp/useCases/Permissions.d.ts +2 -2
  13. package/flp/useCases/Permissions.js +31 -22
  14. package/flp/useCases/Permissions.js.map +1 -1
  15. package/flp/useCases/UpdateFlp.d.ts +1 -0
  16. package/flp/useCases/UpdateFlp.js +18 -1
  17. package/flp/useCases/UpdateFlp.js.map +1 -1
  18. package/folder/createFolderTypeDefs.js +11 -0
  19. package/folder/createFolderTypeDefs.js.map +1 -1
  20. package/folder/folder.crud.js +4 -8
  21. package/folder/folder.crud.js.map +1 -1
  22. package/folder/folder.model.js +5 -1
  23. package/folder/folder.model.js.map +1 -1
  24. package/folder/folder.so.js +23 -2
  25. package/folder/folder.so.js.map +1 -1
  26. package/folder/folder.types.d.ts +9 -0
  27. package/folder/folder.types.js.map +1 -1
  28. package/folder/useCases/CreateFolder/CreateFolderWithFolderLevelPermissions.d.ts +1 -0
  29. package/folder/useCases/GetAncestors/GetAncestors.d.ts +4 -0
  30. package/folder/useCases/GetAncestors/GetAncestors.js +22 -2
  31. package/folder/useCases/GetAncestors/GetAncestors.js.map +1 -1
  32. package/folder/useCases/GetAncestors/IGetAncestors.d.ts +0 -1
  33. package/folder/useCases/GetAncestors/IGetAncestors.js.map +1 -1
  34. package/folder/useCases/GetAncestors/index.d.ts +6 -1
  35. package/folder/useCases/GetAncestors/index.js +2 -2
  36. package/folder/useCases/GetAncestors/index.js.map +1 -1
  37. package/folder/useCases/GetFolder/GetFolderWithFolderLevelPermissions.d.ts +1 -0
  38. package/folder/useCases/UpdateFolder/UpdateFolderWithFolderLevelPermissions.d.ts +1 -0
  39. package/package.json +27 -27
  40. package/record/record.so.js +25 -2
  41. package/record/record.so.js.map +1 -1
  42. package/{flp/useCases → utils}/Path.js +1 -1
  43. /package/{flp/useCases → utils}/Path.d.ts +0 -0
  44. /package/{flp/useCases → utils}/Path.js.map +0 -0
@@ -0,0 +1,6 @@
1
+ import type { FolderPermission } from "../../../flp.types";
2
+ import { Identity } from "@webiny/api-authentication/types";
3
+ import { SecurityPermission } from "@webiny/api-security/types";
4
+ export declare class DefaultPermissionsMerger {
5
+ static merge(identity: Identity, identityPermissions: SecurityPermission[], folderPermissions: FolderPermission[]): FolderPermission[];
6
+ }
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.DefaultPermissionsMerger = void 0;
7
+ class DefaultPermissionsMerger {
8
+ static merge(identity, identityPermissions, folderPermissions) {
9
+ // If the user has full access permission, add a specific "owner" permission to the list.
10
+ // This ensures the user has complete control over the folder.
11
+ const hasFullAccess = identityPermissions.some(p => p.name === "*");
12
+ if (hasFullAccess) {
13
+ return [{
14
+ target: `admin:${identity.id}`,
15
+ level: "owner",
16
+ inheritedFrom: "role:full-access"
17
+ },
18
+ // Remove any permissions related to the full access user,
19
+ // as these are always superseded by the "owner" permission defined above.
20
+ ...folderPermissions.filter(p => p.target !== `admin:${identity.id}`)];
21
+ }
22
+ if (folderPermissions.length === 0) {
23
+ // No permissions provided. This means the folder is public.
24
+ // Add a specific "public" permission to the list to ensure the folder is accessible to everyone.
25
+ return [{
26
+ target: `admin:${identity.id}`,
27
+ level: "public",
28
+ inheritedFrom: "public"
29
+ }];
30
+ }
31
+
32
+ // If there are multiple `admin:${identity.id}` permissions in the array,
33
+ // we need to pick the one with the highest access level. We also remove
34
+ // other permissions for the same identity.
35
+
36
+ // Get permissions related to the current identity (admin).
37
+ const currentAdminPermissions = folderPermissions.filter(p => p.target === `admin:${identity.id}`);
38
+ if (currentAdminPermissions.length === 0) {
39
+ return folderPermissions;
40
+ }
41
+ const noAccessPermission = currentAdminPermissions.find(p => p.level === "no-access" && p.target === `admin:${identity.id}`);
42
+ if (noAccessPermission) {
43
+ // If one of the permissions is `no-access`, then we can immediately return it. This is
44
+ // because `no-access` is the ultimate level of access, and no other permission can override it.
45
+ // Remove all permissions for the current identity and add the winning one.
46
+ const filteredPermissions = folderPermissions.filter(p => p.target !== `admin:${identity.id}`);
47
+ return [...filteredPermissions, noAccessPermission];
48
+ }
49
+ const [firstAdminPermission, ...restAdminPermissions] = currentAdminPermissions;
50
+ const resultPermission = restAdminPermissions.reduce((winner, current) => {
51
+ const winnerInherits = winner.inheritedFrom?.startsWith("parent:");
52
+ const currentInherits = current.inheritedFrom?.startsWith("parent:");
53
+ if (winnerInherits && !currentInherits) {
54
+ return current;
55
+ }
56
+ if (currentInherits && !winnerInherits) {
57
+ return winner;
58
+ }
59
+
60
+ // At this point, we're either comparing two permissions with `inheritedFrom` or two without it.
61
+ // In other words, we're now at a point where we start comparing the levels (owner > editor > viewer).
62
+ if (current.level === "owner") {
63
+ return current;
64
+ }
65
+ if (current.level === "editor" && winner.level === "viewer") {
66
+ return current;
67
+ }
68
+ return winner;
69
+ }, firstAdminPermission);
70
+
71
+ // Remove all permissions for the current identity and add the winning one.
72
+ return [resultPermission, ...folderPermissions.filter(p => p.target !== `admin:${identity.id}`)];
73
+ }
74
+ }
75
+ exports.DefaultPermissionsMerger = DefaultPermissionsMerger;
76
+
77
+ //# sourceMappingURL=DefaultPermissionsMerger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["DefaultPermissionsMerger","merge","identity","identityPermissions","folderPermissions","hasFullAccess","some","p","name","target","id","level","inheritedFrom","filter","length","currentAdminPermissions","noAccessPermission","find","filteredPermissions","firstAdminPermission","restAdminPermissions","resultPermission","reduce","winner","current","winnerInherits","startsWith","currentInherits","exports"],"sources":["DefaultPermissionsMerger.ts"],"sourcesContent":["import type { FolderAccessLevel, FolderPermission } from \"~/flp/flp.types\";\nimport { Identity } from \"@webiny/api-authentication/types\";\nimport { SecurityPermission } from \"@webiny/api-security/types\";\n\nexport class DefaultPermissionsMerger {\n static merge(\n identity: Identity,\n identityPermissions: SecurityPermission[],\n folderPermissions: FolderPermission[]\n ): FolderPermission[] {\n // If the user has full access permission, add a specific \"owner\" permission to the list.\n // This ensures the user has complete control over the folder.\n const hasFullAccess = identityPermissions.some(p => p.name === \"*\");\n if (hasFullAccess) {\n return [\n {\n target: `admin:${identity.id}`,\n level: \"owner\" as FolderAccessLevel,\n inheritedFrom: \"role:full-access\"\n },\n\n // Remove any permissions related to the full access user,\n // as these are always superseded by the \"owner\" permission defined above.\n ...folderPermissions.filter(p => p.target !== `admin:${identity.id}`)\n ];\n }\n\n if (folderPermissions.length === 0) {\n // No permissions provided. This means the folder is public.\n // Add a specific \"public\" permission to the list to ensure the folder is accessible to everyone.\n return [\n {\n target: `admin:${identity.id}`,\n level: \"public\" as FolderAccessLevel,\n inheritedFrom: \"public\"\n }\n ];\n }\n\n // If there are multiple `admin:${identity.id}` permissions in the array,\n // we need to pick the one with the highest access level. We also remove\n // other permissions for the same identity.\n\n // Get permissions related to the current identity (admin).\n const currentAdminPermissions = folderPermissions.filter(\n p => p.target === `admin:${identity.id}`\n );\n\n if (currentAdminPermissions.length === 0) {\n return folderPermissions;\n }\n\n const noAccessPermission = currentAdminPermissions.find(\n p => p.level === \"no-access\" && p.target === `admin:${identity.id}`\n );\n\n if (noAccessPermission) {\n // If one of the permissions is `no-access`, then we can immediately return it. This is\n // because `no-access` is the ultimate level of access, and no other permission can override it.\n // Remove all permissions for the current identity and add the winning one.\n const filteredPermissions = folderPermissions.filter(\n p => p.target !== `admin:${identity.id}`\n );\n\n return [...filteredPermissions, noAccessPermission];\n }\n\n const [firstAdminPermission, ...restAdminPermissions] = currentAdminPermissions;\n\n const resultPermission = restAdminPermissions.reduce((winner, current) => {\n const winnerInherits = winner.inheritedFrom?.startsWith(\"parent:\");\n const currentInherits = current.inheritedFrom?.startsWith(\"parent:\");\n\n if (winnerInherits && !currentInherits) {\n return current;\n }\n if (currentInherits && !winnerInherits) {\n return winner;\n }\n\n // At this point, we're either comparing two permissions with `inheritedFrom` or two without it.\n // In other words, we're now at a point where we start comparing the levels (owner > editor > viewer).\n if (current.level === \"owner\") {\n return current;\n }\n\n if (current.level === \"editor\" && winner.level === \"viewer\") {\n return current;\n }\n\n return winner;\n }, firstAdminPermission);\n\n // Remove all permissions for the current identity and add the winning one.\n return [\n resultPermission,\n ...folderPermissions.filter(p => p.target !== `admin:${identity.id}`)\n ];\n }\n}\n"],"mappings":";;;;;;AAIO,MAAMA,wBAAwB,CAAC;EAClC,OAAOC,KAAKA,CACRC,QAAkB,EAClBC,mBAAyC,EACzCC,iBAAqC,EACnB;IAClB;IACA;IACA,MAAMC,aAAa,GAAGF,mBAAmB,CAACG,IAAI,CAACC,CAAC,IAAIA,CAAC,CAACC,IAAI,KAAK,GAAG,CAAC;IACnE,IAAIH,aAAa,EAAE;MACf,OAAO,CACH;QACII,MAAM,EAAE,SAASP,QAAQ,CAACQ,EAAE,EAAE;QAC9BC,KAAK,EAAE,OAA4B;QACnCC,aAAa,EAAE;MACnB,CAAC;MAED;MACA;MACA,GAAGR,iBAAiB,CAACS,MAAM,CAACN,CAAC,IAAIA,CAAC,CAACE,MAAM,KAAK,SAASP,QAAQ,CAACQ,EAAE,EAAE,CAAC,CACxE;IACL;IAEA,IAAIN,iBAAiB,CAACU,MAAM,KAAK,CAAC,EAAE;MAChC;MACA;MACA,OAAO,CACH;QACIL,MAAM,EAAE,SAASP,QAAQ,CAACQ,EAAE,EAAE;QAC9BC,KAAK,EAAE,QAA6B;QACpCC,aAAa,EAAE;MACnB,CAAC,CACJ;IACL;;IAEA;IACA;IACA;;IAEA;IACA,MAAMG,uBAAuB,GAAGX,iBAAiB,CAACS,MAAM,CACpDN,CAAC,IAAIA,CAAC,CAACE,MAAM,KAAK,SAASP,QAAQ,CAACQ,EAAE,EAC1C,CAAC;IAED,IAAIK,uBAAuB,CAACD,MAAM,KAAK,CAAC,EAAE;MACtC,OAAOV,iBAAiB;IAC5B;IAEA,MAAMY,kBAAkB,GAAGD,uBAAuB,CAACE,IAAI,CACnDV,CAAC,IAAIA,CAAC,CAACI,KAAK,KAAK,WAAW,IAAIJ,CAAC,CAACE,MAAM,KAAK,SAASP,QAAQ,CAACQ,EAAE,EACrE,CAAC;IAED,IAAIM,kBAAkB,EAAE;MACpB;MACA;MACA;MACA,MAAME,mBAAmB,GAAGd,iBAAiB,CAACS,MAAM,CAChDN,CAAC,IAAIA,CAAC,CAACE,MAAM,KAAK,SAASP,QAAQ,CAACQ,EAAE,EAC1C,CAAC;MAED,OAAO,CAAC,GAAGQ,mBAAmB,EAAEF,kBAAkB,CAAC;IACvD;IAEA,MAAM,CAACG,oBAAoB,EAAE,GAAGC,oBAAoB,CAAC,GAAGL,uBAAuB;IAE/E,MAAMM,gBAAgB,GAAGD,oBAAoB,CAACE,MAAM,CAAC,CAACC,MAAM,EAAEC,OAAO,KAAK;MACtE,MAAMC,cAAc,GAAGF,MAAM,CAACX,aAAa,EAAEc,UAAU,CAAC,SAAS,CAAC;MAClE,MAAMC,eAAe,GAAGH,OAAO,CAACZ,aAAa,EAAEc,UAAU,CAAC,SAAS,CAAC;MAEpE,IAAID,cAAc,IAAI,CAACE,eAAe,EAAE;QACpC,OAAOH,OAAO;MAClB;MACA,IAAIG,eAAe,IAAI,CAACF,cAAc,EAAE;QACpC,OAAOF,MAAM;MACjB;;MAEA;MACA;MACA,IAAIC,OAAO,CAACb,KAAK,KAAK,OAAO,EAAE;QAC3B,OAAOa,OAAO;MAClB;MAEA,IAAIA,OAAO,CAACb,KAAK,KAAK,QAAQ,IAAIY,MAAM,CAACZ,KAAK,KAAK,QAAQ,EAAE;QACzD,OAAOa,OAAO;MAClB;MAEA,OAAOD,MAAM;IACjB,CAAC,EAAEJ,oBAAoB,CAAC;;IAExB;IACA,OAAO,CACHE,gBAAgB,EAChB,GAAGjB,iBAAiB,CAACS,MAAM,CAACN,CAAC,IAAIA,CAAC,CAACE,MAAM,KAAK,SAASP,QAAQ,CAACQ,EAAE,EAAE,CAAC,CACxE;EACL;AACJ;AAACkB,OAAA,CAAA5B,wBAAA,GAAAA,wBAAA","ignoreList":[]}
@@ -6,5 +6,4 @@ export declare class GetDefaultPermissions implements IGetDefaultPermissions {
6
6
  private listPermissionsGateway;
7
7
  constructor(getIdentityGateway: IGetIdentityGateway, listPermissionsGateway: IListPermissionsGateway);
8
8
  execute(permissions: FolderPermission[]): Promise<FolderPermission[]>;
9
- private hasFullAccess;
10
9
  }
@@ -4,48 +4,16 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.GetDefaultPermissions = void 0;
7
+ var _DefaultPermissionsMerger = require("./DefaultPermissionsMerger");
7
8
  class GetDefaultPermissions {
8
9
  constructor(getIdentityGateway, listPermissionsGateway) {
9
10
  this.getIdentityGateway = getIdentityGateway;
10
11
  this.listPermissionsGateway = listPermissionsGateway;
11
12
  }
12
13
  async execute(permissions) {
13
- const hasFullAccess = await this.hasFullAccess();
14
14
  const identity = this.getIdentityGateway.execute();
15
-
16
- /**
17
- * If the user has full access to the application, add a specific "owner" permission to the list.
18
- * This ensures the user has complete control over the folder.
19
- */
20
- if (hasFullAccess) {
21
- return [{
22
- target: `admin:${identity.id}`,
23
- level: "owner",
24
- inheritedFrom: "role:full-access"
25
- },
26
- /**
27
- * Remove any permissions related to the full access user,
28
- * as these are always superseded by the "owner" permission defined above.
29
- */
30
- ...permissions.filter(p => p.target !== `admin:${identity.id}`)];
31
- }
32
- if (permissions.length > 0) {
33
- return permissions;
34
- }
35
-
36
- /**
37
- * No permissions provided. This means the folder is public.
38
- * Add a specific "public" permission to the list to ensure the folder is accessible to everyone.
39
- */
40
- return [{
41
- target: `admin:${identity.id}`,
42
- level: "public",
43
- inheritedFrom: "public"
44
- }];
45
- }
46
- async hasFullAccess() {
47
- const permissions = await this.listPermissionsGateway.execute();
48
- return permissions.some(p => p.name === "*");
15
+ const identityPermissions = await this.listPermissionsGateway.execute();
16
+ return _DefaultPermissionsMerger.DefaultPermissionsMerger.merge(identity, identityPermissions, permissions);
49
17
  }
50
18
  }
51
19
  exports.GetDefaultPermissions = GetDefaultPermissions;
@@ -1 +1 @@
1
- {"version":3,"names":["GetDefaultPermissions","constructor","getIdentityGateway","listPermissionsGateway","execute","permissions","hasFullAccess","identity","target","id","level","inheritedFrom","filter","p","length","some","name","exports"],"sources":["GetDefaultPermissions.ts"],"sourcesContent":["import type { IGetDefaultPermissions } from \"./IGetDefaultPermissions\";\nimport type { IGetIdentityGateway, IListPermissionsGateway } from \"../../gateways\";\nimport type { FolderAccessLevel, FolderPermission } from \"~/flp/flp.types\";\n\nexport class GetDefaultPermissions implements IGetDefaultPermissions {\n private getIdentityGateway: IGetIdentityGateway;\n private listPermissionsGateway: IListPermissionsGateway;\n\n constructor(\n getIdentityGateway: IGetIdentityGateway,\n listPermissionsGateway: IListPermissionsGateway\n ) {\n this.getIdentityGateway = getIdentityGateway;\n this.listPermissionsGateway = listPermissionsGateway;\n }\n\n async execute(permissions: FolderPermission[]) {\n const hasFullAccess = await this.hasFullAccess();\n const identity = this.getIdentityGateway.execute();\n\n /**\n * If the user has full access to the application, add a specific \"owner\" permission to the list.\n * This ensures the user has complete control over the folder.\n */\n if (hasFullAccess) {\n return [\n {\n target: `admin:${identity.id}`,\n level: \"owner\" as FolderAccessLevel,\n inheritedFrom: \"role:full-access\"\n },\n /**\n * Remove any permissions related to the full access user,\n * as these are always superseded by the \"owner\" permission defined above.\n */\n ...permissions.filter(p => p.target !== `admin:${identity.id}`)\n ];\n }\n\n if (permissions.length > 0) {\n return permissions;\n }\n\n /**\n * No permissions provided. This means the folder is public.\n * Add a specific \"public\" permission to the list to ensure the folder is accessible to everyone.\n */\n return [\n {\n target: `admin:${identity.id}`,\n level: \"public\" as FolderAccessLevel,\n inheritedFrom: \"public\"\n }\n ];\n }\n\n private async hasFullAccess(): Promise<boolean> {\n const permissions = await this.listPermissionsGateway.execute();\n return permissions.some(p => p.name === \"*\");\n }\n}\n"],"mappings":";;;;;;AAIO,MAAMA,qBAAqB,CAAmC;EAIjEC,WAAWA,CACPC,kBAAuC,EACvCC,sBAA+C,EACjD;IACE,IAAI,CAACD,kBAAkB,GAAGA,kBAAkB;IAC5C,IAAI,CAACC,sBAAsB,GAAGA,sBAAsB;EACxD;EAEA,MAAMC,OAAOA,CAACC,WAA+B,EAAE;IAC3C,MAAMC,aAAa,GAAG,MAAM,IAAI,CAACA,aAAa,CAAC,CAAC;IAChD,MAAMC,QAAQ,GAAG,IAAI,CAACL,kBAAkB,CAACE,OAAO,CAAC,CAAC;;IAElD;AACR;AACA;AACA;IACQ,IAAIE,aAAa,EAAE;MACf,OAAO,CACH;QACIE,MAAM,EAAE,SAASD,QAAQ,CAACE,EAAE,EAAE;QAC9BC,KAAK,EAAE,OAA4B;QACnCC,aAAa,EAAE;MACnB,CAAC;MACD;AAChB;AACA;AACA;MACgB,GAAGN,WAAW,CAACO,MAAM,CAACC,CAAC,IAAIA,CAAC,CAACL,MAAM,KAAK,SAASD,QAAQ,CAACE,EAAE,EAAE,CAAC,CAClE;IACL;IAEA,IAAIJ,WAAW,CAACS,MAAM,GAAG,CAAC,EAAE;MACxB,OAAOT,WAAW;IACtB;;IAEA;AACR;AACA;AACA;IACQ,OAAO,CACH;MACIG,MAAM,EAAE,SAASD,QAAQ,CAACE,EAAE,EAAE;MAC9BC,KAAK,EAAE,QAA6B;MACpCC,aAAa,EAAE;IACnB,CAAC,CACJ;EACL;EAEA,MAAcL,aAAaA,CAAA,EAAqB;IAC5C,MAAMD,WAAW,GAAG,MAAM,IAAI,CAACF,sBAAsB,CAACC,OAAO,CAAC,CAAC;IAC/D,OAAOC,WAAW,CAACU,IAAI,CAACF,CAAC,IAAIA,CAAC,CAACG,IAAI,KAAK,GAAG,CAAC;EAChD;AACJ;AAACC,OAAA,CAAAjB,qBAAA,GAAAA,qBAAA","ignoreList":[]}
1
+ {"version":3,"names":["_DefaultPermissionsMerger","require","GetDefaultPermissions","constructor","getIdentityGateway","listPermissionsGateway","execute","permissions","identity","identityPermissions","DefaultPermissionsMerger","merge","exports"],"sources":["GetDefaultPermissions.ts"],"sourcesContent":["import type { IGetDefaultPermissions } from \"./IGetDefaultPermissions\";\nimport type { IGetIdentityGateway, IListPermissionsGateway } from \"../../gateways\";\nimport type { FolderPermission } from \"~/flp/flp.types\";\nimport { DefaultPermissionsMerger } from \"./DefaultPermissionsMerger\";\n\nexport class GetDefaultPermissions implements IGetDefaultPermissions {\n private getIdentityGateway: IGetIdentityGateway;\n private listPermissionsGateway: IListPermissionsGateway;\n\n constructor(\n getIdentityGateway: IGetIdentityGateway,\n listPermissionsGateway: IListPermissionsGateway\n ) {\n this.getIdentityGateway = getIdentityGateway;\n this.listPermissionsGateway = listPermissionsGateway;\n }\n\n async execute(permissions: FolderPermission[]) {\n const identity = this.getIdentityGateway.execute();\n const identityPermissions = await this.listPermissionsGateway.execute();\n\n return DefaultPermissionsMerger.merge(identity, identityPermissions, permissions);\n }\n}\n"],"mappings":";;;;;;AAGA,IAAAA,yBAAA,GAAAC,OAAA;AAEO,MAAMC,qBAAqB,CAAmC;EAIjEC,WAAWA,CACPC,kBAAuC,EACvCC,sBAA+C,EACjD;IACE,IAAI,CAACD,kBAAkB,GAAGA,kBAAkB;IAC5C,IAAI,CAACC,sBAAsB,GAAGA,sBAAsB;EACxD;EAEA,MAAMC,OAAOA,CAACC,WAA+B,EAAE;IAC3C,MAAMC,QAAQ,GAAG,IAAI,CAACJ,kBAAkB,CAACE,OAAO,CAAC,CAAC;IAClD,MAAMG,mBAAmB,GAAG,MAAM,IAAI,CAACJ,sBAAsB,CAACC,OAAO,CAAC,CAAC;IAEvE,OAAOI,kDAAwB,CAACC,KAAK,CAACH,QAAQ,EAAEC,mBAAmB,EAAEF,WAAW,CAAC;EACrF;AACJ;AAACK,OAAA,CAAAV,qBAAA,GAAAA,qBAAA","ignoreList":[]}
@@ -6,5 +6,5 @@ export declare class GetDefaultPermissionsWithTeams implements IGetDefaultPermis
6
6
  private listIdentityTeamsGateway;
7
7
  private decoretee;
8
8
  constructor(getIdentityGateway: IGetIdentityGateway, listIdentityTeamsGateway: IListIdentityTeamsGateway, decoretee: IGetDefaultPermissions);
9
- execute(permissions: FolderPermission[]): Promise<FolderPermission[]>;
9
+ execute(originalPermissions: FolderPermission[]): Promise<FolderPermission[]>;
10
10
  }
@@ -10,7 +10,7 @@ class GetDefaultPermissionsWithTeams {
10
10
  this.listIdentityTeamsGateway = listIdentityTeamsGateway;
11
11
  this.decoretee = decoretee;
12
12
  }
13
- async execute(permissions) {
13
+ async execute(originalPermissions) {
14
14
  /**
15
15
  * Retrieves the list of teams the current identity belongs to and checks if any of these teams
16
16
  * have permissions for the folder. If a team has permissions, the current identity is granted
@@ -18,6 +18,8 @@ class GetDefaultPermissionsWithTeams {
18
18
  */
19
19
  const identity = this.getIdentityGateway.execute();
20
20
  const identityTeams = (await this.listIdentityTeamsGateway.execute()) ?? [];
21
+ const permissions = [...originalPermissions]; // Clone the original permissions to avoid mutation.
22
+
21
23
  if (identityTeams.length) {
22
24
  for (const identityTeam of identityTeams) {
23
25
  // Check if the team has permissions for the folder.
@@ -1 +1 @@
1
- {"version":3,"names":["GetDefaultPermissionsWithTeams","constructor","getIdentityGateway","listIdentityTeamsGateway","decoretee","execute","permissions","identity","identityTeams","length","identityTeam","teamPermission","find","p","target","id","push","level","inheritedFrom","exports"],"sources":["GetDefaultPermissionsWithTeams.ts"],"sourcesContent":["import type { IGetDefaultPermissions } from \"./IGetDefaultPermissions\";\nimport type {\n IGetIdentityGateway,\n IListIdentityTeamsGateway\n} from \"~/flp/FolderLevelPermissions/gateways\";\nimport type { FolderPermission } from \"~/flp/flp.types\";\nimport { Team } from \"@webiny/api-security/types\";\n\nexport class GetDefaultPermissionsWithTeams implements IGetDefaultPermissions {\n private getIdentityGateway: IGetIdentityGateway;\n private listIdentityTeamsGateway: IListIdentityTeamsGateway;\n private decoretee: IGetDefaultPermissions;\n\n constructor(\n getIdentityGateway: IGetIdentityGateway,\n listIdentityTeamsGateway: IListIdentityTeamsGateway,\n decoretee: IGetDefaultPermissions\n ) {\n this.getIdentityGateway = getIdentityGateway;\n this.listIdentityTeamsGateway = listIdentityTeamsGateway;\n this.decoretee = decoretee;\n }\n\n async execute(permissions: FolderPermission[]) {\n /**\n * Retrieves the list of teams the current identity belongs to and checks if any of these teams\n * have permissions for the folder. If a team has permissions, the current identity is granted\n * the same permissions, inheriting them from the team.\n */\n const identity = this.getIdentityGateway.execute();\n const identityTeams: Team[] = (await this.listIdentityTeamsGateway.execute()) ?? [];\n\n if (identityTeams.length) {\n for (const identityTeam of identityTeams) {\n // Check if the team has permissions for the folder.\n const teamPermission = permissions.find(\n p => p.target === `team:${identityTeam.id}`\n );\n\n if (teamPermission) {\n // Grant the current identity the same permissions as the team, marking them as inherited.\n permissions.push({\n target: `admin:${identity.id}`,\n level: teamPermission.level,\n inheritedFrom: \"team:\" + identityTeam.id\n });\n }\n }\n }\n\n return await this.decoretee.execute(permissions);\n }\n}\n"],"mappings":";;;;;;AAQO,MAAMA,8BAA8B,CAAmC;EAK1EC,WAAWA,CACPC,kBAAuC,EACvCC,wBAAmD,EACnDC,SAAiC,EACnC;IACE,IAAI,CAACF,kBAAkB,GAAGA,kBAAkB;IAC5C,IAAI,CAACC,wBAAwB,GAAGA,wBAAwB;IACxD,IAAI,CAACC,SAAS,GAAGA,SAAS;EAC9B;EAEA,MAAMC,OAAOA,CAACC,WAA+B,EAAE;IAC3C;AACR;AACA;AACA;AACA;IACQ,MAAMC,QAAQ,GAAG,IAAI,CAACL,kBAAkB,CAACG,OAAO,CAAC,CAAC;IAClD,MAAMG,aAAqB,GAAG,CAAC,MAAM,IAAI,CAACL,wBAAwB,CAACE,OAAO,CAAC,CAAC,KAAK,EAAE;IAEnF,IAAIG,aAAa,CAACC,MAAM,EAAE;MACtB,KAAK,MAAMC,YAAY,IAAIF,aAAa,EAAE;QACtC;QACA,MAAMG,cAAc,GAAGL,WAAW,CAACM,IAAI,CACnCC,CAAC,IAAIA,CAAC,CAACC,MAAM,KAAK,QAAQJ,YAAY,CAACK,EAAE,EAC7C,CAAC;QAED,IAAIJ,cAAc,EAAE;UAChB;UACAL,WAAW,CAACU,IAAI,CAAC;YACbF,MAAM,EAAE,SAASP,QAAQ,CAACQ,EAAE,EAAE;YAC9BE,KAAK,EAAEN,cAAc,CAACM,KAAK;YAC3BC,aAAa,EAAE,OAAO,GAAGR,YAAY,CAACK;UAC1C,CAAC,CAAC;QACN;MACJ;IACJ;IAEA,OAAO,MAAM,IAAI,CAACX,SAAS,CAACC,OAAO,CAACC,WAAW,CAAC;EACpD;AACJ;AAACa,OAAA,CAAAnB,8BAAA,GAAAA,8BAAA","ignoreList":[]}
1
+ {"version":3,"names":["GetDefaultPermissionsWithTeams","constructor","getIdentityGateway","listIdentityTeamsGateway","decoretee","execute","originalPermissions","identity","identityTeams","permissions","length","identityTeam","teamPermission","find","p","target","id","push","level","inheritedFrom","exports"],"sources":["GetDefaultPermissionsWithTeams.ts"],"sourcesContent":["import type { IGetDefaultPermissions } from \"./IGetDefaultPermissions\";\nimport type {\n IGetIdentityGateway,\n IListIdentityTeamsGateway\n} from \"~/flp/FolderLevelPermissions/gateways\";\nimport type { FolderPermission } from \"~/flp/flp.types\";\nimport { Team } from \"@webiny/api-security/types\";\n\nexport class GetDefaultPermissionsWithTeams implements IGetDefaultPermissions {\n private getIdentityGateway: IGetIdentityGateway;\n private listIdentityTeamsGateway: IListIdentityTeamsGateway;\n private decoretee: IGetDefaultPermissions;\n\n constructor(\n getIdentityGateway: IGetIdentityGateway,\n listIdentityTeamsGateway: IListIdentityTeamsGateway,\n decoretee: IGetDefaultPermissions\n ) {\n this.getIdentityGateway = getIdentityGateway;\n this.listIdentityTeamsGateway = listIdentityTeamsGateway;\n this.decoretee = decoretee;\n }\n\n async execute(originalPermissions: FolderPermission[]) {\n /**\n * Retrieves the list of teams the current identity belongs to and checks if any of these teams\n * have permissions for the folder. If a team has permissions, the current identity is granted\n * the same permissions, inheriting them from the team.\n */\n const identity = this.getIdentityGateway.execute();\n const identityTeams: Team[] = (await this.listIdentityTeamsGateway.execute()) ?? [];\n\n const permissions = [...originalPermissions]; // Clone the original permissions to avoid mutation.\n\n if (identityTeams.length) {\n for (const identityTeam of identityTeams) {\n // Check if the team has permissions for the folder.\n const teamPermission = permissions.find(\n p => p.target === `team:${identityTeam.id}`\n );\n\n if (teamPermission) {\n // Grant the current identity the same permissions as the team, marking them as inherited.\n permissions.push({\n target: `admin:${identity.id}`,\n level: teamPermission.level,\n inheritedFrom: \"team:\" + identityTeam.id\n });\n }\n }\n }\n\n return await this.decoretee.execute(permissions);\n }\n}\n"],"mappings":";;;;;;AAQO,MAAMA,8BAA8B,CAAmC;EAK1EC,WAAWA,CACPC,kBAAuC,EACvCC,wBAAmD,EACnDC,SAAiC,EACnC;IACE,IAAI,CAACF,kBAAkB,GAAGA,kBAAkB;IAC5C,IAAI,CAACC,wBAAwB,GAAGA,wBAAwB;IACxD,IAAI,CAACC,SAAS,GAAGA,SAAS;EAC9B;EAEA,MAAMC,OAAOA,CAACC,mBAAuC,EAAE;IACnD;AACR;AACA;AACA;AACA;IACQ,MAAMC,QAAQ,GAAG,IAAI,CAACL,kBAAkB,CAACG,OAAO,CAAC,CAAC;IAClD,MAAMG,aAAqB,GAAG,CAAC,MAAM,IAAI,CAACL,wBAAwB,CAACE,OAAO,CAAC,CAAC,KAAK,EAAE;IAEnF,MAAMI,WAAW,GAAG,CAAC,GAAGH,mBAAmB,CAAC,CAAC,CAAC;;IAE9C,IAAIE,aAAa,CAACE,MAAM,EAAE;MACtB,KAAK,MAAMC,YAAY,IAAIH,aAAa,EAAE;QACtC;QACA,MAAMI,cAAc,GAAGH,WAAW,CAACI,IAAI,CACnCC,CAAC,IAAIA,CAAC,CAACC,MAAM,KAAK,QAAQJ,YAAY,CAACK,EAAE,EAC7C,CAAC;QAED,IAAIJ,cAAc,EAAE;UAChB;UACAH,WAAW,CAACQ,IAAI,CAAC;YACbF,MAAM,EAAE,SAASR,QAAQ,CAACS,EAAE,EAAE;YAC9BE,KAAK,EAAEN,cAAc,CAACM,KAAK;YAC3BC,aAAa,EAAE,OAAO,GAAGR,YAAY,CAACK;UAC1C,CAAC,CAAC;QACN;MACJ;IACJ;IAEA,OAAO,MAAM,IAAI,CAACZ,SAAS,CAACC,OAAO,CAACI,WAAW,CAAC;EACpD;AACJ;AAACW,OAAA,CAAApB,8BAAA,GAAAA,8BAAA","ignoreList":[]}
@@ -5,7 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.CreateFlp = void 0;
7
7
  var _error = require("@webiny/error");
8
- var _Path = require("./Path");
8
+ var _Path = require("../../utils/Path");
9
9
  var _Permissions = require("./Permissions");
10
10
  var _constants = require("../../constants");
11
11
  class CreateFlp {
@@ -1 +1 @@
1
- {"version":3,"names":["_error","require","_Path","_Permissions","_constants","CreateFlp","constructor","context","execute","folder","WebinyError","id","type","slug","parentId","permissions","parentFlp","aco","flp","get","create","ROOT_FOLDER","path","Path","Permissions","error","from","message","code","exports"],"sources":["CreateFlp.ts"],"sourcesContent":["import { WebinyError } from \"@webiny/error\";\nimport { Path } from \"./Path\";\nimport { Permissions } from \"./Permissions\";\nimport type { FolderLevelPermission as IFolderLevelPermission } from \"~/flp/flp.types\";\nimport type { Folder } from \"~/folder/folder.types\";\nimport type { AcoContext } from \"~/types\";\nimport { ROOT_FOLDER } from \"~/constants\";\n\nexport class CreateFlp {\n private context: AcoContext;\n\n constructor(context: AcoContext) {\n this.context = context;\n }\n\n async execute(folder: Folder) {\n try {\n if (!folder) {\n throw new WebinyError(\n \"Missing `folder`, I can't create a new record into the FLP catalog.\",\n \"ERROR_CREATE_FLP_USE_CASE_FOLDER_NOT_PROVIDED\"\n );\n }\n\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"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AACA,IAAAC,KAAA,GAAAD,OAAA;AACA,IAAAE,YAAA,GAAAF,OAAA;AAIA,IAAAG,UAAA,GAAAH,OAAA;AAEO,MAAMI,SAAS,CAAC;EAGnBC,WAAWA,CAACC,OAAmB,EAAE;IAC7B,IAAI,CAACA,OAAO,GAAGA,OAAO;EAC1B;EAEA,MAAMC,OAAOA,CAACC,MAAc,EAAE;IAC1B,IAAI;MACA,IAAI,CAACA,MAAM,EAAE;QACT,MAAM,IAAIC,kBAAW,CACjB,qEAAqE,EACrE,+CACJ,CAAC;MACL;MAEA,MAAM;QAAEC,EAAE;QAAEC,IAAI;QAAEC,IAAI;QAAEC,QAAQ;QAAEC;MAAY,CAAC,GAAGN,MAAM;MACxD,IAAIO,SAAwC,GAAG,IAAI;MAEnD,IAAIF,QAAQ,EAAE;QACVE,SAAS,GAAG,MAAM,IAAI,CAACT,OAAO,CAACU,GAAG,CAACC,GAAG,CAACC,GAAG,CAACL,QAAQ,CAAC;QAEpD,IAAI,CAACE,SAAS,EAAE;UACZ,MAAM,IAAIN,kBAAW,CACjB,6FAA6F,EAC7F,gDACJ,CAAC;QACL;MACJ;MAEA,MAAM,IAAI,CAACH,OAAO,CAACU,GAAG,CAACC,GAAG,CAACE,MAAM,CAAC;QAC9BT,EAAE;QACFC,IAAI;QACJC,IAAI;QACJC,QAAQ,EAAEA,QAAQ,IAAIO,sBAAW;QACjCC,IAAI,EAAEC,UAAI,CAACH,MAAM,CAACP,IAAI,EAAEG,SAAS,EAAEM,IAAI,CAAC;QACxCP,WAAW,EAAES,wBAAW,CAACJ,MAAM,CAACL,WAAW,EAAEC,SAAS;MAC1D,CAAC,CAAC;IACN,CAAC,CAAC,OAAOS,KAAK,EAAE;MACZ,MAAMf,kBAAW,CAACgB,IAAI,CAACD,KAAK,EAAE;QAC1BE,OAAO,EAAE,0BAA0B;QACnCC,IAAI,EAAE;MACV,CAAC,CAAC;IACN;EACJ;AACJ;AAACC,OAAA,CAAAxB,SAAA,GAAAA,SAAA","ignoreList":[]}
1
+ {"version":3,"names":["_error","require","_Path","_Permissions","_constants","CreateFlp","constructor","context","execute","folder","WebinyError","id","type","slug","parentId","permissions","parentFlp","aco","flp","get","create","ROOT_FOLDER","path","Path","Permissions","error","from","message","code","exports"],"sources":["CreateFlp.ts"],"sourcesContent":["import { WebinyError } from \"@webiny/error\";\nimport { Path } from \"~/utils/Path\";\nimport { Permissions } from \"./Permissions\";\nimport type { FolderLevelPermission as IFolderLevelPermission } from \"~/flp/flp.types\";\nimport type { Folder } from \"~/folder/folder.types\";\nimport type { AcoContext } from \"~/types\";\nimport { ROOT_FOLDER } from \"~/constants\";\n\nexport class CreateFlp {\n private context: AcoContext;\n\n constructor(context: AcoContext) {\n this.context = context;\n }\n\n async execute(folder: Folder) {\n try {\n if (!folder) {\n throw new WebinyError(\n \"Missing `folder`, I can't create a new record into the FLP catalog.\",\n \"ERROR_CREATE_FLP_USE_CASE_FOLDER_NOT_PROVIDED\"\n );\n }\n\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"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AACA,IAAAC,KAAA,GAAAD,OAAA;AACA,IAAAE,YAAA,GAAAF,OAAA;AAIA,IAAAG,UAAA,GAAAH,OAAA;AAEO,MAAMI,SAAS,CAAC;EAGnBC,WAAWA,CAACC,OAAmB,EAAE;IAC7B,IAAI,CAACA,OAAO,GAAGA,OAAO;EAC1B;EAEA,MAAMC,OAAOA,CAACC,MAAc,EAAE;IAC1B,IAAI;MACA,IAAI,CAACA,MAAM,EAAE;QACT,MAAM,IAAIC,kBAAW,CACjB,qEAAqE,EACrE,+CACJ,CAAC;MACL;MAEA,MAAM;QAAEC,EAAE;QAAEC,IAAI;QAAEC,IAAI;QAAEC,QAAQ;QAAEC;MAAY,CAAC,GAAGN,MAAM;MACxD,IAAIO,SAAwC,GAAG,IAAI;MAEnD,IAAIF,QAAQ,EAAE;QACVE,SAAS,GAAG,MAAM,IAAI,CAACT,OAAO,CAACU,GAAG,CAACC,GAAG,CAACC,GAAG,CAACL,QAAQ,CAAC;QAEpD,IAAI,CAACE,SAAS,EAAE;UACZ,MAAM,IAAIN,kBAAW,CACjB,6FAA6F,EAC7F,gDACJ,CAAC;QACL;MACJ;MAEA,MAAM,IAAI,CAACH,OAAO,CAACU,GAAG,CAACC,GAAG,CAACE,MAAM,CAAC;QAC9BT,EAAE;QACFC,IAAI;QACJC,IAAI;QACJC,QAAQ,EAAEA,QAAQ,IAAIO,sBAAW;QACjCC,IAAI,EAAEC,UAAI,CAACH,MAAM,CAACP,IAAI,EAAEG,SAAS,EAAEM,IAAI,CAAC;QACxCP,WAAW,EAAES,wBAAW,CAACJ,MAAM,CAACL,WAAW,EAAEC,SAAS;MAC1D,CAAC,CAAC;IACN,CAAC,CAAC,OAAOS,KAAK,EAAE;MACZ,MAAMf,kBAAW,CAACgB,IAAI,CAACD,KAAK,EAAE;QAC1BE,OAAO,EAAE,0BAA0B;QACnCC,IAAI,EAAE;MACV,CAAC,CAAC;IACN;EACJ;AACJ;AAACC,OAAA,CAAAxB,SAAA,GAAAA,SAAA","ignoreList":[]}
@@ -1,4 +1,4 @@
1
- import type { FolderLevelPermission as IFolderLevelPermission, FolderPermission } from "../flp.types";
1
+ import type { FolderLevelPermission, FolderPermission } from "../flp.types";
2
2
  export declare class Permissions {
3
- static create(permissions?: FolderPermission[], parentFlp?: Pick<IFolderLevelPermission, "id" | "permissions"> | null): FolderPermission[];
3
+ static create(permissions?: FolderPermission[], parentFlp?: FolderLevelPermission | null): FolderPermission[];
4
4
  }
@@ -6,31 +6,40 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.Permissions = void 0;
7
7
  class Permissions {
8
8
  static create(permissions, parentFlp) {
9
- const folderPermissions = permissions ?? [];
10
-
11
- // No permissions from the parent, let's return the permissions provided by the folder.
12
- if (!parentFlp || !parentFlp.permissions?.length) {
13
- return folderPermissions;
9
+ const parentFolderPermissions = parentFlp?.permissions || [];
10
+ const currentFolderPermissions = permissions?.filter(p => p.inheritedFrom !== `parent:${parentFlp?.id}`) || [];
11
+ if (!parentFolderPermissions.length) {
12
+ return currentFolderPermissions;
14
13
  }
15
- const {
16
- id: parentId,
17
- permissions: parentPermissions
18
- } = parentFlp;
19
-
20
- // Remove all previously inherited permissions
21
- const cleanedPermissions = folderPermissions.filter(p => p.inheritedFrom !== `parent:${parentId}`);
22
14
 
23
- // Store the `target` values from the current cleaned permissions.
24
- // These will be used to exclude inherited permissions that target the same entities as the current folder's permissions.
25
- const permissionsTargets = new Set(cleanedPermissions.map(p => p.target));
15
+ // Merge parent and current folder permissions:
16
+ // - current folder permissions take precedence over parent permissions
17
+ // - only if parent permission's level is set to `no-access`, then we ignore the current folder permission
18
+ const permissionsInheritedFromParentFolder = [];
19
+ for (const parentFolderPermission of parentFolderPermissions) {
20
+ if (parentFolderPermission.level === "no-access") {
21
+ permissionsInheritedFromParentFolder.push({
22
+ ...parentFolderPermission,
23
+ inheritedFrom: `parent:${parentFlp.id}`
24
+ });
25
+ continue;
26
+ }
27
+ const currentFolderHasOverridePermission = currentFolderPermissions.some(permission => permission.target === parentFolderPermission.target);
28
+ if (currentFolderHasOverridePermission) {
29
+ continue;
30
+ }
31
+ permissionsInheritedFromParentFolder.push({
32
+ ...parentFolderPermission,
33
+ inheritedFrom: `parent:${parentFlp.id}`
34
+ });
35
+ }
26
36
 
27
- // Get inherited permissions from parent, preserving the original inheritance chain
28
- const inheritedPermissions = parentPermissions.filter(p => !permissionsTargets.has(p.target)).map(p => ({
29
- ...p,
30
- // If the permission was already inherited, keep its original source
31
- inheritedFrom: `parent:${parentId}`
32
- }));
33
- return [...cleanedPermissions, ...inheritedPermissions];
37
+ // Add current folder permissions that are not present in the parent folder permissions.
38
+ const applicableCurrentFolderPermissions = currentFolderPermissions.filter(permission => {
39
+ const alreadyInInheritedPermissions = permissionsInheritedFromParentFolder.some(p => p.target === permission.target);
40
+ return !alreadyInInheritedPermissions;
41
+ });
42
+ return [...applicableCurrentFolderPermissions, ...permissionsInheritedFromParentFolder];
34
43
  }
35
44
  }
36
45
  exports.Permissions = Permissions;
@@ -1 +1 @@
1
- {"version":3,"names":["Permissions","create","permissions","parentFlp","folderPermissions","length","id","parentId","parentPermissions","cleanedPermissions","filter","p","inheritedFrom","permissionsTargets","Set","map","target","inheritedPermissions","has","exports"],"sources":["Permissions.ts"],"sourcesContent":["import type {\n FolderLevelPermission as IFolderLevelPermission,\n FolderPermission\n} from \"~/flp/flp.types\";\n\nexport class Permissions {\n public static create(\n permissions?: FolderPermission[],\n parentFlp?: Pick<IFolderLevelPermission, \"id\" | \"permissions\"> | null\n ): FolderPermission[] {\n const folderPermissions = permissions ?? [];\n\n // No permissions from the parent, let's return the permissions provided by the folder.\n if (!parentFlp || !parentFlp.permissions?.length) {\n return folderPermissions;\n }\n\n const { id: parentId, permissions: parentPermissions } = parentFlp;\n\n // Remove all previously inherited permissions\n const cleanedPermissions = folderPermissions.filter(\n p => p.inheritedFrom !== `parent:${parentId}`\n );\n\n // Store the `target` values from the current cleaned permissions.\n // These will be used to exclude inherited permissions that target the same entities as the current folder's permissions.\n const permissionsTargets = new Set(cleanedPermissions.map(p => p.target));\n\n // Get inherited permissions from parent, preserving the original inheritance chain\n const inheritedPermissions = parentPermissions\n .filter(p => !permissionsTargets.has(p.target))\n .map(p => ({\n ...p,\n // If the permission was already inherited, keep its original source\n inheritedFrom: `parent:${parentId}`\n }));\n\n return [...cleanedPermissions, ...inheritedPermissions];\n }\n}\n"],"mappings":";;;;;;AAKO,MAAMA,WAAW,CAAC;EACrB,OAAcC,MAAMA,CAChBC,WAAgC,EAChCC,SAAqE,EACnD;IAClB,MAAMC,iBAAiB,GAAGF,WAAW,IAAI,EAAE;;IAE3C;IACA,IAAI,CAACC,SAAS,IAAI,CAACA,SAAS,CAACD,WAAW,EAAEG,MAAM,EAAE;MAC9C,OAAOD,iBAAiB;IAC5B;IAEA,MAAM;MAAEE,EAAE,EAAEC,QAAQ;MAAEL,WAAW,EAAEM;IAAkB,CAAC,GAAGL,SAAS;;IAElE;IACA,MAAMM,kBAAkB,GAAGL,iBAAiB,CAACM,MAAM,CAC/CC,CAAC,IAAIA,CAAC,CAACC,aAAa,KAAK,UAAUL,QAAQ,EAC/C,CAAC;;IAED;IACA;IACA,MAAMM,kBAAkB,GAAG,IAAIC,GAAG,CAACL,kBAAkB,CAACM,GAAG,CAACJ,CAAC,IAAIA,CAAC,CAACK,MAAM,CAAC,CAAC;;IAEzE;IACA,MAAMC,oBAAoB,GAAGT,iBAAiB,CACzCE,MAAM,CAACC,CAAC,IAAI,CAACE,kBAAkB,CAACK,GAAG,CAACP,CAAC,CAACK,MAAM,CAAC,CAAC,CAC9CD,GAAG,CAACJ,CAAC,KAAK;MACP,GAAGA,CAAC;MACJ;MACAC,aAAa,EAAE,UAAUL,QAAQ;IACrC,CAAC,CAAC,CAAC;IAEP,OAAO,CAAC,GAAGE,kBAAkB,EAAE,GAAGQ,oBAAoB,CAAC;EAC3D;AACJ;AAACE,OAAA,CAAAnB,WAAA,GAAAA,WAAA","ignoreList":[]}
1
+ {"version":3,"names":["Permissions","create","permissions","parentFlp","parentFolderPermissions","currentFolderPermissions","filter","p","inheritedFrom","id","length","permissionsInheritedFromParentFolder","parentFolderPermission","level","push","currentFolderHasOverridePermission","some","permission","target","applicableCurrentFolderPermissions","alreadyInInheritedPermissions","exports"],"sources":["Permissions.ts"],"sourcesContent":["import type { FolderLevelPermission, FolderPermission } from \"~/flp/flp.types\";\n\nexport class Permissions {\n public static create(\n permissions?: FolderPermission[],\n parentFlp?: FolderLevelPermission | null\n ): FolderPermission[] {\n const parentFolderPermissions = parentFlp?.permissions || [];\n const currentFolderPermissions =\n permissions?.filter(p => p.inheritedFrom !== `parent:${parentFlp?.id}`) || [];\n\n if (!parentFolderPermissions.length) {\n return currentFolderPermissions;\n }\n\n // Merge parent and current folder permissions:\n // - current folder permissions take precedence over parent permissions\n // - only if parent permission's level is set to `no-access`, then we ignore the current folder permission\n const permissionsInheritedFromParentFolder: FolderPermission[] = [];\n\n for (const parentFolderPermission of parentFolderPermissions) {\n if (parentFolderPermission.level === \"no-access\") {\n permissionsInheritedFromParentFolder.push({\n ...parentFolderPermission,\n inheritedFrom: `parent:${parentFlp!.id}`\n });\n continue;\n }\n\n const currentFolderHasOverridePermission = currentFolderPermissions.some(\n permission => permission.target === parentFolderPermission.target\n );\n\n if (currentFolderHasOverridePermission) {\n continue;\n }\n\n permissionsInheritedFromParentFolder.push({\n ...parentFolderPermission,\n inheritedFrom: `parent:${parentFlp!.id}`\n });\n }\n\n // Add current folder permissions that are not present in the parent folder permissions.\n const applicableCurrentFolderPermissions = currentFolderPermissions.filter(permission => {\n const alreadyInInheritedPermissions = permissionsInheritedFromParentFolder.some(\n p => p.target === permission.target\n );\n\n return !alreadyInInheritedPermissions;\n });\n\n return [...applicableCurrentFolderPermissions, ...permissionsInheritedFromParentFolder];\n }\n}\n"],"mappings":";;;;;;AAEO,MAAMA,WAAW,CAAC;EACrB,OAAcC,MAAMA,CAChBC,WAAgC,EAChCC,SAAwC,EACtB;IAClB,MAAMC,uBAAuB,GAAGD,SAAS,EAAED,WAAW,IAAI,EAAE;IAC5D,MAAMG,wBAAwB,GAC1BH,WAAW,EAAEI,MAAM,CAACC,CAAC,IAAIA,CAAC,CAACC,aAAa,KAAK,UAAUL,SAAS,EAAEM,EAAE,EAAE,CAAC,IAAI,EAAE;IAEjF,IAAI,CAACL,uBAAuB,CAACM,MAAM,EAAE;MACjC,OAAOL,wBAAwB;IACnC;;IAEA;IACA;IACA;IACA,MAAMM,oCAAwD,GAAG,EAAE;IAEnE,KAAK,MAAMC,sBAAsB,IAAIR,uBAAuB,EAAE;MAC1D,IAAIQ,sBAAsB,CAACC,KAAK,KAAK,WAAW,EAAE;QAC9CF,oCAAoC,CAACG,IAAI,CAAC;UACtC,GAAGF,sBAAsB;UACzBJ,aAAa,EAAE,UAAUL,SAAS,CAAEM,EAAE;QAC1C,CAAC,CAAC;QACF;MACJ;MAEA,MAAMM,kCAAkC,GAAGV,wBAAwB,CAACW,IAAI,CACpEC,UAAU,IAAIA,UAAU,CAACC,MAAM,KAAKN,sBAAsB,CAACM,MAC/D,CAAC;MAED,IAAIH,kCAAkC,EAAE;QACpC;MACJ;MAEAJ,oCAAoC,CAACG,IAAI,CAAC;QACtC,GAAGF,sBAAsB;QACzBJ,aAAa,EAAE,UAAUL,SAAS,CAAEM,EAAE;MAC1C,CAAC,CAAC;IACN;;IAEA;IACA,MAAMU,kCAAkC,GAAGd,wBAAwB,CAACC,MAAM,CAACW,UAAU,IAAI;MACrF,MAAMG,6BAA6B,GAAGT,oCAAoC,CAACK,IAAI,CAC3ET,CAAC,IAAIA,CAAC,CAACW,MAAM,KAAKD,UAAU,CAACC,MACjC,CAAC;MAED,OAAO,CAACE,6BAA6B;IACzC,CAAC,CAAC;IAEF,OAAO,CAAC,GAAGD,kCAAkC,EAAE,GAAGR,oCAAoC,CAAC;EAC3F;AACJ;AAACU,OAAA,CAAArB,WAAA,GAAAA,WAAA","ignoreList":[]}
@@ -21,5 +21,6 @@ export declare class UpdateFlp {
21
21
  private clearQueuedList;
22
22
  private listDirectChildren;
23
23
  private getFlp;
24
+ private getFolderModel;
24
25
  }
25
26
  export {};
@@ -5,9 +5,10 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.UpdateFlp = void 0;
7
7
  var _error = require("@webiny/error");
8
- var _Path = require("./Path");
8
+ var _Path = require("../../utils/Path");
9
9
  var _Permissions = require("./Permissions");
10
10
  var _constants = require("../../constants");
11
+ var _folder = require("../../folder/folder.model");
11
12
  class UpdateFlp {
12
13
  queued = new Set();
13
14
  flpsToUpdate = new Map();
@@ -117,6 +118,19 @@ class UpdateFlp {
117
118
  };
118
119
  });
119
120
  await this.context.aco.flp.batchUpdate(items);
121
+
122
+ // Update all folders with the new path
123
+ const folderModel = await this.getFolderModel();
124
+ for (const item of items) {
125
+ const {
126
+ id,
127
+ data
128
+ } = item;
129
+ // Directly update the folder in CMS storage to bypass any folder update event triggers.
130
+ await this.context.cms.updateEntry(folderModel, id, {
131
+ path: data.path
132
+ });
133
+ }
120
134
  } catch (error) {
121
135
  throw _error.WebinyError.from(error, {
122
136
  message: "Error while executing batch update of FLPs",
@@ -176,6 +190,9 @@ class UpdateFlp {
176
190
  }
177
191
  return flp;
178
192
  }
193
+ async getFolderModel() {
194
+ return await this.context.cms.getModel(_folder.FOLDER_MODEL_ID);
195
+ }
179
196
  }
180
197
  exports.UpdateFlp = UpdateFlp;
181
198
 
@@ -1 +1 @@
1
- {"version":3,"names":["_error","require","_Path","_Permissions","_constants","UpdateFlp","queued","Set","flpsToUpdate","Map","constructor","params","context","isCloseToTimeout","handleTimeout","execute","folder","WebinyError","flp","getFlp","parentFlp","parentId","aco","get","set","id","slug","ROOT_FOLDER","path","Path","create","permissions","Permissions","setQueued","directChildren","listDirectChildren","child","executeBatchUpdate","getQueuedList","collectBranchForUpdate","error","clear","from","message","code","isQueued","parentFlpData","currentParentFlp","children","items","Array","entries","map","data","batchUpdate","keys","clearQueuedList","add","has","folders","listAll","where","type","disablePermissions","Promise","all","exports"],"sources":["UpdateFlp.ts"],"sourcesContent":["import { WebinyError } from \"@webiny/error\";\nimport { Path } from \"./Path\";\nimport { Permissions } from \"./Permissions\";\nimport { ROOT_FOLDER } from \"~/constants\";\nimport type { AcoContext, Folder, FolderLevelPermission, FolderPermission } from \"~/types\";\n\ninterface UpdateFlpParams {\n context: AcoContext;\n queued?: string[];\n isCloseToTimeout?: () => boolean;\n handleTimeout?: (queued: string[]) => void;\n}\n\ninterface FlpUpdateData {\n parentId: string;\n slug: string;\n path: string;\n permissions: FolderPermission[];\n}\n\nexport class UpdateFlp {\n private context: AcoContext;\n private readonly isCloseToTimeout?: () => boolean;\n private readonly handleTimeout?: (updated: string[]) => void;\n\n private readonly queued: Set<string> = new Set();\n private readonly flpsToUpdate: Map<string, FlpUpdateData> = new Map();\n\n constructor(params: UpdateFlpParams) {\n this.context = params.context;\n this.queued = new Set(params.queued);\n this.isCloseToTimeout = params.isCloseToTimeout;\n this.handleTimeout = params.handleTimeout;\n }\n\n async execute(folder: Folder) {\n try {\n if (!folder) {\n throw new WebinyError(\n \"Missing `folder`, I can't update the FLP record.\",\n \"ERROR_UPDATING_FLP_USE_CASE_FOLDER_NOT_PROVIDED\",\n { folder }\n );\n }\n\n const flp = await this.getFlp(folder);\n const parentFlp = folder.parentId\n ? await this.context.aco.flp.get(folder.parentId)\n : null;\n\n // Add the root folder to the update collection\n this.flpsToUpdate.set(folder.id, {\n slug: folder.slug,\n parentId: folder.parentId ?? ROOT_FOLDER,\n path: Path.create(folder.slug, parentFlp?.path),\n permissions: Permissions.create(folder.permissions, parentFlp)\n });\n\n // Let's set the FLP as in queue\n this.setQueued(flp.id);\n\n // Get direct children and process each branch completely\n const directChildren = await this.listDirectChildren(flp);\n\n for (const child of directChildren) {\n if (this.isCloseToTimeout?.()) {\n await this.executeBatchUpdate();\n this.handleTimeout?.(this.getQueuedList());\n return;\n }\n await this.collectBranchForUpdate(child, flp);\n }\n\n // Execute batch update\n await this.executeBatchUpdate();\n } catch (error) {\n // Clear the update collection in case of error\n this.flpsToUpdate.clear();\n this.queued.clear();\n throw WebinyError.from(error, {\n message: \"Error while updating FLP\",\n code: \"ERROR_UPDATING_FLP_USE_CASE\"\n });\n }\n }\n\n private async collectBranchForUpdate(\n flp: FolderLevelPermission,\n parentFlp: FolderLevelPermission\n ) {\n if (this.isQueued(flp.id)) {\n return;\n }\n\n // Get the parent's permissions from the update collection if available\n const parentFlpData = this.flpsToUpdate.get(parentFlp.id);\n const currentParentFlp = {\n ...parentFlp,\n ...(parentFlpData && { ...parentFlpData })\n };\n\n // Add the FLP to the update collection with inherited permissions\n this.flpsToUpdate.set(flp.id, {\n slug: flp.slug,\n parentId: flp.parentId,\n path: Path.create(flp.slug, currentParentFlp.path),\n permissions: Permissions.create(flp.permissions, currentParentFlp)\n });\n\n // Add the FLP to the queue list so we don't fetch it again\n this.setQueued(flp.id);\n\n // Process all children of this folder before moving to siblings\n const children = await this.listDirectChildren(flp);\n\n for (const child of children) {\n if (this.isCloseToTimeout?.()) {\n await this.executeBatchUpdate();\n this.handleTimeout?.(this.getQueuedList());\n return;\n }\n // Pass the current FLP as the parent for the child\n await this.collectBranchForUpdate(child, flp);\n }\n }\n\n private async executeBatchUpdate() {\n try {\n const items = Array.from(this.flpsToUpdate.entries()).map(\n ([id, { slug, parentId, path, permissions }]) => {\n return {\n id,\n data: {\n slug,\n parentId,\n path,\n permissions\n }\n };\n }\n );\n\n await this.context.aco.flp.batchUpdate(items);\n } catch (error) {\n throw WebinyError.from(error, {\n message: \"Error while executing batch update of FLPs\",\n code: \"BATCH_UPDATE_FLP_ERROR\",\n data: {\n items: Array.from(this.flpsToUpdate.keys())\n }\n });\n } finally {\n // Clear the update collection after the batch update\n this.flpsToUpdate.clear();\n\n //Let's remove all the updated FLPs ids from the queue cache\n this.clearQueuedList();\n }\n }\n\n private getQueuedList() {\n return Array.from(this.queued);\n }\n\n private setQueued(id: string) {\n this.queued.add(id);\n }\n\n private isQueued(id: string) {\n return this.queued.has(id);\n }\n\n private clearQueuedList() {\n return this.queued.clear();\n }\n\n private async listDirectChildren(flp: FolderLevelPermission): Promise<FolderLevelPermission[]> {\n const [folders] = await this.context.aco.folder.listAll({\n where: {\n type: flp.type,\n parentId: flp.id\n },\n disablePermissions: true\n });\n\n return await Promise.all(folders.map(folder => this.getFlp(folder)));\n }\n\n private async getFlp({ id, type, parentId, slug, permissions }: Folder) {\n const flp = await this.context.aco.flp.get(id);\n\n if (!flp) {\n const parentFlp = parentId ? await this.context.aco.flp.get(parentId) : null;\n\n return 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 }\n\n return flp;\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["_error","require","_Path","_Permissions","_constants","_folder","UpdateFlp","queued","Set","flpsToUpdate","Map","constructor","params","context","isCloseToTimeout","handleTimeout","execute","folder","WebinyError","flp","getFlp","parentFlp","parentId","aco","get","set","id","slug","ROOT_FOLDER","path","Path","create","permissions","Permissions","setQueued","directChildren","listDirectChildren","child","executeBatchUpdate","getQueuedList","collectBranchForUpdate","error","clear","from","message","code","isQueued","parentFlpData","currentParentFlp","children","items","Array","entries","map","data","batchUpdate","folderModel","getFolderModel","item","cms","updateEntry","keys","clearQueuedList","add","has","folders","listAll","where","type","disablePermissions","Promise","all","getModel","FOLDER_MODEL_ID","exports"],"sources":["UpdateFlp.ts"],"sourcesContent":["import { WebinyError } from \"@webiny/error\";\nimport { Path } from \"~/utils/Path\";\nimport { Permissions } from \"./Permissions\";\nimport { ROOT_FOLDER } from \"~/constants\";\nimport type { AcoContext, Folder, FolderLevelPermission, FolderPermission } from \"~/types\";\nimport { FOLDER_MODEL_ID } from \"~/folder/folder.model\";\n\ninterface UpdateFlpParams {\n context: AcoContext;\n queued?: string[];\n isCloseToTimeout?: () => boolean;\n handleTimeout?: (queued: string[]) => void;\n}\n\ninterface FlpUpdateData {\n parentId: string;\n slug: string;\n path: string;\n permissions: FolderPermission[];\n}\n\nexport class UpdateFlp {\n private context: AcoContext;\n private readonly isCloseToTimeout?: () => boolean;\n private readonly handleTimeout?: (updated: string[]) => void;\n\n private readonly queued: Set<string> = new Set();\n private readonly flpsToUpdate: Map<string, FlpUpdateData> = new Map();\n\n constructor(params: UpdateFlpParams) {\n this.context = params.context;\n this.queued = new Set(params.queued);\n this.isCloseToTimeout = params.isCloseToTimeout;\n this.handleTimeout = params.handleTimeout;\n }\n\n async execute(folder: Folder) {\n try {\n if (!folder) {\n throw new WebinyError(\n \"Missing `folder`, I can't update the FLP record.\",\n \"ERROR_UPDATING_FLP_USE_CASE_FOLDER_NOT_PROVIDED\",\n { folder }\n );\n }\n\n const flp = await this.getFlp(folder);\n const parentFlp = folder.parentId\n ? await this.context.aco.flp.get(folder.parentId)\n : null;\n\n // Add the root folder to the update collection\n this.flpsToUpdate.set(folder.id, {\n slug: folder.slug,\n parentId: folder.parentId ?? ROOT_FOLDER,\n path: Path.create(folder.slug, parentFlp?.path),\n permissions: Permissions.create(folder.permissions, parentFlp)\n });\n\n // Let's set the FLP as in queue\n this.setQueued(flp.id);\n\n // Get direct children and process each branch completely\n const directChildren = await this.listDirectChildren(flp);\n\n for (const child of directChildren) {\n if (this.isCloseToTimeout?.()) {\n await this.executeBatchUpdate();\n this.handleTimeout?.(this.getQueuedList());\n return;\n }\n await this.collectBranchForUpdate(child, flp);\n }\n\n // Execute batch update\n await this.executeBatchUpdate();\n } catch (error) {\n // Clear the update collection in case of error\n this.flpsToUpdate.clear();\n this.queued.clear();\n throw WebinyError.from(error, {\n message: \"Error while updating FLP\",\n code: \"ERROR_UPDATING_FLP_USE_CASE\"\n });\n }\n }\n\n private async collectBranchForUpdate(\n flp: FolderLevelPermission,\n parentFlp: FolderLevelPermission\n ) {\n if (this.isQueued(flp.id)) {\n return;\n }\n\n // Get the parent's permissions from the update collection if available\n const parentFlpData = this.flpsToUpdate.get(parentFlp.id);\n const currentParentFlp = {\n ...parentFlp,\n ...(parentFlpData && { ...parentFlpData })\n };\n\n // Add the FLP to the update collection with inherited permissions\n this.flpsToUpdate.set(flp.id, {\n slug: flp.slug,\n parentId: flp.parentId,\n path: Path.create(flp.slug, currentParentFlp.path),\n permissions: Permissions.create(flp.permissions, currentParentFlp)\n });\n\n // Add the FLP to the queue list so we don't fetch it again\n this.setQueued(flp.id);\n\n // Process all children of this folder before moving to siblings\n const children = await this.listDirectChildren(flp);\n\n for (const child of children) {\n if (this.isCloseToTimeout?.()) {\n await this.executeBatchUpdate();\n this.handleTimeout?.(this.getQueuedList());\n return;\n }\n // Pass the current FLP as the parent for the child\n await this.collectBranchForUpdate(child, flp);\n }\n }\n\n private async executeBatchUpdate() {\n try {\n const items = Array.from(this.flpsToUpdate.entries()).map(\n ([id, { slug, parentId, path, permissions }]) => {\n return {\n id,\n data: {\n slug,\n parentId,\n path,\n permissions\n }\n };\n }\n );\n\n await this.context.aco.flp.batchUpdate(items);\n\n // Update all folders with the new path\n const folderModel = await this.getFolderModel();\n for (const item of items) {\n const { id, data } = item;\n // Directly update the folder in CMS storage to bypass any folder update event triggers.\n await this.context.cms.updateEntry(folderModel, id, { path: data.path });\n }\n } catch (error) {\n throw WebinyError.from(error, {\n message: \"Error while executing batch update of FLPs\",\n code: \"BATCH_UPDATE_FLP_ERROR\",\n data: {\n items: Array.from(this.flpsToUpdate.keys())\n }\n });\n } finally {\n // Clear the update collection after the batch update\n this.flpsToUpdate.clear();\n\n //Let's remove all the updated FLPs ids from the queue cache\n this.clearQueuedList();\n }\n }\n\n private getQueuedList() {\n return Array.from(this.queued);\n }\n\n private setQueued(id: string) {\n this.queued.add(id);\n }\n\n private isQueued(id: string) {\n return this.queued.has(id);\n }\n\n private clearQueuedList() {\n return this.queued.clear();\n }\n\n private async listDirectChildren(flp: FolderLevelPermission): Promise<FolderLevelPermission[]> {\n const [folders] = await this.context.aco.folder.listAll({\n where: {\n type: flp.type,\n parentId: flp.id\n },\n disablePermissions: true\n });\n\n return await Promise.all(folders.map(folder => this.getFlp(folder)));\n }\n\n private async getFlp({ id, type, parentId, slug, permissions }: Folder) {\n const flp = await this.context.aco.flp.get(id);\n\n if (!flp) {\n const parentFlp = parentId ? await this.context.aco.flp.get(parentId) : null;\n\n return 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 }\n\n return flp;\n }\n\n private async getFolderModel() {\n return await this.context.cms.getModel(FOLDER_MODEL_ID);\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -86,6 +86,9 @@ const createFolderTypeDefs = params => {
86
86
  ${inputCreateFields.map(f => f.typeDefs).join("\n")}
87
87
 
88
88
  input FolderCreateInput {
89
+ # Pass an ID if you want to create a folder with a specific ID.
90
+ id: ID
91
+
89
92
  ${inputCreateFields.map(f => f.fields).join("\n")}
90
93
  }
91
94
 
@@ -97,6 +100,14 @@ const createFolderTypeDefs = params => {
97
100
  type: String!
98
101
  parentId: ID
99
102
  parentId_in: [ID]
103
+ path: String
104
+ path_not: String
105
+ path_contains: String
106
+ path_not_contains: String
107
+ path_in: [String]
108
+ path_not_in: [String]
109
+ path_startsWith: String
110
+ path_not_startsWith: String
100
111
  createdBy: ID
101
112
  }
102
113
 
@@ -1 +1 @@
1
- {"version":3,"names":["_renderFields","require","_renderInputFields","removeFieldRequiredValidation","field","validation","filter","name","listValidation","v","createUpdateFields","fields","reduce","collection","push","createFolderTypeDefs","params","model","models","plugins","fieldTypePlugins","fieldTypes","renderFields","type","inputCreateFields","renderInputFields","inputUpdateFields","map","f","typeDefs","join","exports"],"sources":["createFolderTypeDefs.ts"],"sourcesContent":["import { CmsFieldTypePlugins, CmsModel, CmsModelField } from \"@webiny/api-headless-cms/types\";\nimport { renderFields } from \"@webiny/api-headless-cms/utils/renderFields\";\nimport { renderInputFields } from \"@webiny/api-headless-cms/utils/renderInputFields\";\n\nexport interface CreateFolderTypeDefsParams {\n model: CmsModel;\n models: CmsModel[];\n plugins: CmsFieldTypePlugins;\n}\n\nconst removeFieldRequiredValidation = (field: CmsModelField) => {\n if (field.validation) {\n field.validation = field.validation.filter(validation => validation.name !== \"required\");\n }\n if (field.listValidation) {\n field.listValidation = field.listValidation.filter(v => v.name !== \"required\");\n }\n return field;\n};\n\nconst createUpdateFields = (fields: CmsModelField[]): CmsModelField[] => {\n return fields.reduce<CmsModelField[]>((collection, field) => {\n collection.push(removeFieldRequiredValidation({ ...field }));\n return collection;\n }, []);\n};\n\nexport const createFolderTypeDefs = (params: CreateFolderTypeDefsParams): string => {\n const { model, models, plugins: fieldTypePlugins } = params;\n const { fields } = model;\n\n const fieldTypes = renderFields({\n models,\n model,\n fields,\n type: \"manage\",\n fieldTypePlugins\n });\n const inputCreateFields = renderInputFields({\n models,\n model,\n fields,\n fieldTypePlugins\n });\n const inputUpdateFields = renderInputFields({\n models,\n model,\n fields: createUpdateFields(fields),\n fieldTypePlugins\n });\n\n return /* GraphQL */ `\n ${fieldTypes.map(f => f.typeDefs).join(\"\\n\")}\n \n type CompressedResponse {\n compression: String\n value: String\n }\n\n type Folder {\n id: ID!\n # Tells us if the current user can manage folder structure.\n canManageStructure: Boolean\n\n # Tells us if the current user can manage folder permissions.\n canManagePermissions: Boolean\n\n # Tells us if the current user can manage folder content.\n canManageContent: Boolean\n\n # Tells us if the folder contains non-inherited permissions.\n hasNonInheritedPermissions: Boolean\n\n createdOn: DateTime\n modifiedOn: DateTime\n savedOn: DateTime\n createdBy: AcoUser\n modifiedBy: AcoUser\n savedBy: AcoUser\n \n ${fieldTypes.map(f => f.fields).join(\"\\n\")}\n }\n\n ${inputCreateFields.map(f => f.typeDefs).join(\"\\n\")}\n \n input FolderCreateInput {\n ${inputCreateFields.map(f => f.fields).join(\"\\n\")}\n }\n \n input FolderUpdateInput {\n ${inputUpdateFields.map(f => f.fields).join(\"\\n\")}\n }\n \n input FoldersListWhereInput {\n type: String!\n parentId: ID\n parentId_in: [ID]\n createdBy: ID\n }\n \n type FolderResponse {\n data: Folder\n error: AcoError\n }\n\n type FoldersListResponse {\n data: [Folder]\n error: AcoError\n meta: AcoMeta\n }\n\n type FoldersListCompressedResponse {\n data: CompressedResponse\n error: AcoError\n }\n \n type FoldersHierarchyData {\n parents: [Folder]\n siblings: [Folder]\n }\n\n type FoldersHierarchyResponse {\n data: FoldersHierarchyData\n error: AcoError\n }\n\n type FolderLevelPermissionsTarget {\n id: ID!\n type: String!\n target: ID!\n name: String!\n meta: JSON\n }\n\n type FolderLevelPermissionsTargetsListMeta {\n totalCount: Int!\n }\n\n type FolderLevelPermissionsTargetsListResponse {\n data: [FolderLevelPermissionsTarget]\n meta: FolderLevelPermissionsTargetsListMeta\n error: AcoError\n }\n \n type FolderModelResponse {\n data: JSON\n error: AcoError\n }\n\n extend type AcoQuery {\n getFolderModel: FolderModelResponse!\n getFolder(id: ID!): FolderResponse\n listFolders(\n where: FoldersListWhereInput!\n limit: Int\n after: String\n sort: AcoSort\n ): FoldersListResponse\n listFoldersCompressed(\n where: FoldersListWhereInput!\n limit: Int\n after: String\n sort: AcoSort\n ): FoldersListCompressedResponse\n getFolderHierarchy(type: String!, id: ID!): FoldersHierarchyResponse\n listFolderLevelPermissionsTargets: FolderLevelPermissionsTargetsListResponse\n }\n\n extend type AcoMutation {\n createFolder(data: FolderCreateInput!): FolderResponse\n updateFolder(id: ID!, data: FolderUpdateInput!): FolderResponse\n deleteFolder(id: ID!): AcoBooleanResponse\n }\n \n extend type AcoFolder_Permissions {\n inheritedFrom: ID\n }\n \n extend input AcoFolder_PermissionsInput {\n inheritedFrom: ID\n }\n `;\n};\n"],"mappings":";;;;;;AACA,IAAAA,aAAA,GAAAC,OAAA;AACA,IAAAC,kBAAA,GAAAD,OAAA;AAQA,MAAME,6BAA6B,GAAIC,KAAoB,IAAK;EAC5D,IAAIA,KAAK,CAACC,UAAU,EAAE;IAClBD,KAAK,CAACC,UAAU,GAAGD,KAAK,CAACC,UAAU,CAACC,MAAM,CAACD,UAAU,IAAIA,UAAU,CAACE,IAAI,KAAK,UAAU,CAAC;EAC5F;EACA,IAAIH,KAAK,CAACI,cAAc,EAAE;IACtBJ,KAAK,CAACI,cAAc,GAAGJ,KAAK,CAACI,cAAc,CAACF,MAAM,CAACG,CAAC,IAAIA,CAAC,CAACF,IAAI,KAAK,UAAU,CAAC;EAClF;EACA,OAAOH,KAAK;AAChB,CAAC;AAED,MAAMM,kBAAkB,GAAIC,MAAuB,IAAsB;EACrE,OAAOA,MAAM,CAACC,MAAM,CAAkB,CAACC,UAAU,EAAET,KAAK,KAAK;IACzDS,UAAU,CAACC,IAAI,CAACX,6BAA6B,CAAC;MAAE,GAAGC;IAAM,CAAC,CAAC,CAAC;IAC5D,OAAOS,UAAU;EACrB,CAAC,EAAE,EAAE,CAAC;AACV,CAAC;AAEM,MAAME,oBAAoB,GAAIC,MAAkC,IAAa;EAChF,MAAM;IAAEC,KAAK;IAAEC,MAAM;IAAEC,OAAO,EAAEC;EAAiB,CAAC,GAAGJ,MAAM;EAC3D,MAAM;IAAEL;EAAO,CAAC,GAAGM,KAAK;EAExB,MAAMI,UAAU,GAAG,IAAAC,0BAAY,EAAC;IAC5BJ,MAAM;IACND,KAAK;IACLN,MAAM;IACNY,IAAI,EAAE,QAAQ;IACdH;EACJ,CAAC,CAAC;EACF,MAAMI,iBAAiB,GAAG,IAAAC,oCAAiB,EAAC;IACxCP,MAAM;IACND,KAAK;IACLN,MAAM;IACNS;EACJ,CAAC,CAAC;EACF,MAAMM,iBAAiB,GAAG,IAAAD,oCAAiB,EAAC;IACxCP,MAAM;IACND,KAAK;IACLN,MAAM,EAAED,kBAAkB,CAACC,MAAM,CAAC;IAClCS;EACJ,CAAC,CAAC;EAEF,OAAO,aAAc;AACzB,UAAUC,UAAU,CAACM,GAAG,CAACC,CAAC,IAAIA,CAAC,CAACC,QAAQ,CAAC,CAACC,IAAI,CAAC,IAAI,CAAC;AACpD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAcT,UAAU,CAACM,GAAG,CAACC,CAAC,IAAIA,CAAC,CAACjB,MAAM,CAAC,CAACmB,IAAI,CAAC,IAAI,CAAC;AACtD;AACA;AACA,UAAUN,iBAAiB,CAACG,GAAG,CAACC,CAAC,IAAIA,CAAC,CAACC,QAAQ,CAAC,CAACC,IAAI,CAAC,IAAI,CAAC;AAC3D;AACA;AACA,eAAeN,iBAAiB,CAACG,GAAG,CAACC,CAAC,IAAIA,CAAC,CAACjB,MAAM,CAAC,CAACmB,IAAI,CAAC,IAAI,CAAC;AAC9D;AACA;AACA;AACA,cAAcJ,iBAAiB,CAACC,GAAG,CAACC,CAAC,IAAIA,CAAC,CAACjB,MAAM,CAAC,CAACmB,IAAI,CAAC,IAAI,CAAC;AAC7D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL,CAAC;AAACC,OAAA,CAAAhB,oBAAA,GAAAA,oBAAA","ignoreList":[]}
1
+ {"version":3,"names":["_renderFields","require","_renderInputFields","removeFieldRequiredValidation","field","validation","filter","name","listValidation","v","createUpdateFields","fields","reduce","collection","push","createFolderTypeDefs","params","model","models","plugins","fieldTypePlugins","fieldTypes","renderFields","type","inputCreateFields","renderInputFields","inputUpdateFields","map","f","typeDefs","join","exports"],"sources":["createFolderTypeDefs.ts"],"sourcesContent":["import { CmsFieldTypePlugins, CmsModel, CmsModelField } from \"@webiny/api-headless-cms/types\";\nimport { renderFields } from \"@webiny/api-headless-cms/utils/renderFields\";\nimport { renderInputFields } from \"@webiny/api-headless-cms/utils/renderInputFields\";\n\nexport interface CreateFolderTypeDefsParams {\n model: CmsModel;\n models: CmsModel[];\n plugins: CmsFieldTypePlugins;\n}\n\nconst removeFieldRequiredValidation = (field: CmsModelField) => {\n if (field.validation) {\n field.validation = field.validation.filter(validation => validation.name !== \"required\");\n }\n if (field.listValidation) {\n field.listValidation = field.listValidation.filter(v => v.name !== \"required\");\n }\n return field;\n};\n\nconst createUpdateFields = (fields: CmsModelField[]): CmsModelField[] => {\n return fields.reduce<CmsModelField[]>((collection, field) => {\n collection.push(removeFieldRequiredValidation({ ...field }));\n return collection;\n }, []);\n};\n\nexport const createFolderTypeDefs = (params: CreateFolderTypeDefsParams): string => {\n const { model, models, plugins: fieldTypePlugins } = params;\n const { fields } = model;\n\n const fieldTypes = renderFields({\n models,\n model,\n fields,\n type: \"manage\",\n fieldTypePlugins\n });\n const inputCreateFields = renderInputFields({\n models,\n model,\n fields,\n fieldTypePlugins\n });\n const inputUpdateFields = renderInputFields({\n models,\n model,\n fields: createUpdateFields(fields),\n fieldTypePlugins\n });\n\n return /* GraphQL */ `\n ${fieldTypes.map(f => f.typeDefs).join(\"\\n\")}\n \n type CompressedResponse {\n compression: String\n value: String\n }\n\n type Folder {\n id: ID!\n # Tells us if the current user can manage folder structure.\n canManageStructure: Boolean\n\n # Tells us if the current user can manage folder permissions.\n canManagePermissions: Boolean\n\n # Tells us if the current user can manage folder content.\n canManageContent: Boolean\n\n # Tells us if the folder contains non-inherited permissions.\n hasNonInheritedPermissions: Boolean\n\n createdOn: DateTime\n modifiedOn: DateTime\n savedOn: DateTime\n createdBy: AcoUser\n modifiedBy: AcoUser\n savedBy: AcoUser\n \n ${fieldTypes.map(f => f.fields).join(\"\\n\")}\n }\n\n ${inputCreateFields.map(f => f.typeDefs).join(\"\\n\")}\n \n input FolderCreateInput {\n # Pass an ID if you want to create a folder with a specific ID.\n id: ID \n \n ${inputCreateFields.map(f => f.fields).join(\"\\n\")}\n }\n \n input FolderUpdateInput {\n ${inputUpdateFields.map(f => f.fields).join(\"\\n\")}\n }\n \n input FoldersListWhereInput {\n type: String!\n parentId: ID\n parentId_in: [ID]\n path: String\n path_not: String\n path_contains: String\n path_not_contains: String\n path_in: [String]\n path_not_in: [String]\n path_startsWith: String\n path_not_startsWith: String\n createdBy: ID\n }\n \n type FolderResponse {\n data: Folder\n error: AcoError\n }\n\n type FoldersListResponse {\n data: [Folder]\n error: AcoError\n meta: AcoMeta\n }\n\n type FoldersListCompressedResponse {\n data: CompressedResponse\n error: AcoError\n }\n \n type FoldersHierarchyData {\n parents: [Folder]\n siblings: [Folder]\n }\n\n type FoldersHierarchyResponse {\n data: FoldersHierarchyData\n error: AcoError\n }\n\n type FolderLevelPermissionsTarget {\n id: ID!\n type: String!\n target: ID!\n name: String!\n meta: JSON\n }\n\n type FolderLevelPermissionsTargetsListMeta {\n totalCount: Int!\n }\n\n type FolderLevelPermissionsTargetsListResponse {\n data: [FolderLevelPermissionsTarget]\n meta: FolderLevelPermissionsTargetsListMeta\n error: AcoError\n }\n \n type FolderModelResponse {\n data: JSON\n error: AcoError\n }\n\n extend type AcoQuery {\n getFolderModel: FolderModelResponse!\n getFolder(id: ID!): FolderResponse\n listFolders(\n where: FoldersListWhereInput!\n limit: Int\n after: String\n sort: AcoSort\n ): FoldersListResponse\n listFoldersCompressed(\n where: FoldersListWhereInput!\n limit: Int\n after: String\n sort: AcoSort\n ): FoldersListCompressedResponse\n getFolderHierarchy(type: String!, id: ID!): FoldersHierarchyResponse\n listFolderLevelPermissionsTargets: FolderLevelPermissionsTargetsListResponse\n }\n\n extend type AcoMutation {\n createFolder(data: FolderCreateInput!): FolderResponse\n updateFolder(id: ID!, data: FolderUpdateInput!): FolderResponse\n deleteFolder(id: ID!): AcoBooleanResponse\n }\n \n extend type AcoFolder_Permissions {\n inheritedFrom: ID\n }\n \n extend input AcoFolder_PermissionsInput {\n inheritedFrom: ID\n }\n `;\n};\n"],"mappings":";;;;;;AACA,IAAAA,aAAA,GAAAC,OAAA;AACA,IAAAC,kBAAA,GAAAD,OAAA;AAQA,MAAME,6BAA6B,GAAIC,KAAoB,IAAK;EAC5D,IAAIA,KAAK,CAACC,UAAU,EAAE;IAClBD,KAAK,CAACC,UAAU,GAAGD,KAAK,CAACC,UAAU,CAACC,MAAM,CAACD,UAAU,IAAIA,UAAU,CAACE,IAAI,KAAK,UAAU,CAAC;EAC5F;EACA,IAAIH,KAAK,CAACI,cAAc,EAAE;IACtBJ,KAAK,CAACI,cAAc,GAAGJ,KAAK,CAACI,cAAc,CAACF,MAAM,CAACG,CAAC,IAAIA,CAAC,CAACF,IAAI,KAAK,UAAU,CAAC;EAClF;EACA,OAAOH,KAAK;AAChB,CAAC;AAED,MAAMM,kBAAkB,GAAIC,MAAuB,IAAsB;EACrE,OAAOA,MAAM,CAACC,MAAM,CAAkB,CAACC,UAAU,EAAET,KAAK,KAAK;IACzDS,UAAU,CAACC,IAAI,CAACX,6BAA6B,CAAC;MAAE,GAAGC;IAAM,CAAC,CAAC,CAAC;IAC5D,OAAOS,UAAU;EACrB,CAAC,EAAE,EAAE,CAAC;AACV,CAAC;AAEM,MAAME,oBAAoB,GAAIC,MAAkC,IAAa;EAChF,MAAM;IAAEC,KAAK;IAAEC,MAAM;IAAEC,OAAO,EAAEC;EAAiB,CAAC,GAAGJ,MAAM;EAC3D,MAAM;IAAEL;EAAO,CAAC,GAAGM,KAAK;EAExB,MAAMI,UAAU,GAAG,IAAAC,0BAAY,EAAC;IAC5BJ,MAAM;IACND,KAAK;IACLN,MAAM;IACNY,IAAI,EAAE,QAAQ;IACdH;EACJ,CAAC,CAAC;EACF,MAAMI,iBAAiB,GAAG,IAAAC,oCAAiB,EAAC;IACxCP,MAAM;IACND,KAAK;IACLN,MAAM;IACNS;EACJ,CAAC,CAAC;EACF,MAAMM,iBAAiB,GAAG,IAAAD,oCAAiB,EAAC;IACxCP,MAAM;IACND,KAAK;IACLN,MAAM,EAAED,kBAAkB,CAACC,MAAM,CAAC;IAClCS;EACJ,CAAC,CAAC;EAEF,OAAO,aAAc;AACzB,UAAUC,UAAU,CAACM,GAAG,CAACC,CAAC,IAAIA,CAAC,CAACC,QAAQ,CAAC,CAACC,IAAI,CAAC,IAAI,CAAC;AACpD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAcT,UAAU,CAACM,GAAG,CAACC,CAAC,IAAIA,CAAC,CAACjB,MAAM,CAAC,CAACmB,IAAI,CAAC,IAAI,CAAC;AACtD;AACA;AACA,UAAUN,iBAAiB,CAACG,GAAG,CAACC,CAAC,IAAIA,CAAC,CAACC,QAAQ,CAAC,CAACC,IAAI,CAAC,IAAI,CAAC;AAC3D;AACA;AACA;AACA;AACA;AACA,eAAeN,iBAAiB,CAACG,GAAG,CAACC,CAAC,IAAIA,CAAC,CAACjB,MAAM,CAAC,CAACmB,IAAI,CAAC,IAAI,CAAC;AAC9D;AACA;AACA;AACA,cAAcJ,iBAAiB,CAACC,GAAG,CAACC,CAAC,IAAIA,CAAC,CAACjB,MAAM,CAAC,CAACmB,IAAI,CAAC,IAAI,CAAC;AAC7D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL,CAAC;AAACC,OAAA,CAAAhB,oBAAA,GAAAA,oBAAA","ignoreList":[]}
@@ -76,7 +76,9 @@ const createFolderCrudMethods = ({
76
76
  });
77
77
  const {
78
78
  getAncestorsUseCase
79
- } = (0, _useCases.getGetAncestors)();
79
+ } = (0, _useCases.getGetAncestors)({
80
+ listFoldersUseCase: listFoldersUseCase
81
+ });
80
82
  const {
81
83
  listFolderLevelPermissionsTargetsUseCase
82
84
  } = (0, _useCases.getListFolderLevelPermissionsTargets)({
@@ -134,14 +136,8 @@ const createFolderCrudMethods = ({
134
136
  return await updateFolderUseCase.execute(id, data);
135
137
  },
136
138
  async getAncestors(folder) {
137
- const [folders] = await this.listAll({
138
- where: {
139
- type: folder.type
140
- }
141
- });
142
139
  return getAncestorsUseCase.execute({
143
- folder,
144
- folders
140
+ folder
145
141
  });
146
142
  },
147
143
  /**