@webiny/api-core 6.6.0-alpha.0 → 6.6.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. package/ApiCoreFeature.js +6 -0
  2. package/ApiCoreFeature.js.map +1 -1
  3. package/exports/api/security/api-key.d.ts +1 -0
  4. package/exports/api/security/api-key.js +1 -0
  5. package/features/ai/Ai.d.ts +3 -1
  6. package/features/ai/Ai.js +39 -4
  7. package/features/ai/Ai.js.map +1 -1
  8. package/features/ai/AnthropicSdkFactory.js +12 -0
  9. package/features/ai/AnthropicSdkFactory.js.map +1 -1
  10. package/features/ai/OpenAiSdkFactory.js +16 -0
  11. package/features/ai/OpenAiSdkFactory.js.map +1 -1
  12. package/features/ai/TextExtractor/DefaultTextExtractor.d.ts +9 -0
  13. package/features/ai/TextExtractor/DefaultTextExtractor.js +28 -0
  14. package/features/ai/TextExtractor/DefaultTextExtractor.js.map +1 -0
  15. package/features/ai/TextExtractor/abstractions.d.ts +12 -0
  16. package/features/ai/TextExtractor/abstractions.js +5 -0
  17. package/features/ai/TextExtractor/abstractions.js.map +1 -0
  18. package/features/ai/TextExtractor/index.d.ts +3 -0
  19. package/features/ai/TextExtractor/index.js +2 -0
  20. package/features/ai/TextExtractor/parsers/docxParser.d.ts +1 -0
  21. package/features/ai/TextExtractor/parsers/docxParser.js +111 -0
  22. package/features/ai/TextExtractor/parsers/docxParser.js.map +1 -0
  23. package/features/ai/abstractions.d.ts +19 -0
  24. package/features/ai/abstractions.js.map +1 -1
  25. package/features/ai/events.d.ts +59 -0
  26. package/features/ai/events.js +41 -0
  27. package/features/ai/events.js.map +1 -0
  28. package/features/ai/feature.js +2 -0
  29. package/features/ai/feature.js.map +1 -1
  30. package/features/ai/index.d.ts +5 -1
  31. package/features/ai/index.js +2 -0
  32. package/features/dateFormatter/DefaultDateFormatter.d.ts +15 -0
  33. package/features/dateFormatter/DefaultDateFormatter.js +20 -0
  34. package/features/dateFormatter/DefaultDateFormatter.js.map +1 -0
  35. package/features/dateFormatter/abstractions.d.ts +13 -0
  36. package/features/dateFormatter/abstractions.js +5 -0
  37. package/features/dateFormatter/abstractions.js.map +1 -0
  38. package/features/dateFormatter/feature.d.ts +4 -0
  39. package/features/dateFormatter/feature.js +11 -0
  40. package/features/dateFormatter/feature.js.map +1 -0
  41. package/features/dateFormatter/index.d.ts +3 -0
  42. package/features/dateFormatter/index.js +2 -0
  43. package/features/featureFlags/decorators/FeatureFlagsWithLicenseDecorator.d.ts +13 -0
  44. package/features/featureFlags/decorators/FeatureFlagsWithLicenseDecorator.js +49 -0
  45. package/features/featureFlags/decorators/FeatureFlagsWithLicenseDecorator.js.map +1 -0
  46. package/features/security/IdentityContext/IdentityContext.d.ts +3 -3
  47. package/features/security/IdentityContext/IdentityContext.js +6 -6
  48. package/features/security/IdentityContext/IdentityContext.js.map +1 -1
  49. package/features/security/apiKeys/CreateApiKey/CreateApiKeyUseCase.js +11 -6
  50. package/features/security/apiKeys/CreateApiKey/CreateApiKeyUseCase.js.map +1 -1
  51. package/features/security/apiKeys/GetApiKey/GetApiKeyUseCase.d.ts +1 -1
  52. package/features/security/apiKeys/GetApiKey/GetApiKeyUseCase.js.map +1 -1
  53. package/features/security/apiKeys/GetApiKeyBySlug/GetApiKeyBySlugUseCase.d.ts +1 -3
  54. package/features/security/apiKeys/GetApiKeyBySlug/GetApiKeyBySlugUseCase.js.map +1 -1
  55. package/features/security/apiKeys/GetApiKeyBySlug/abstractions.d.ts +1 -1
  56. package/features/security/apiKeys/GetApiKeyBySlug/abstractions.js.map +1 -1
  57. package/features/security/apiKeys/GetApiKeyByToken/GetApiKeyByTokenUseCase.d.ts +1 -3
  58. package/features/security/apiKeys/GetApiKeyByToken/GetApiKeyByTokenUseCase.js.map +1 -1
  59. package/features/security/apiKeys/GetApiKeyByToken/abstractions.d.ts +1 -1
  60. package/features/security/apiKeys/GetApiKeyByToken/abstractions.js.map +1 -1
  61. package/features/security/apiKeys/UpdateApiKey/UpdateApiKeyUseCase.js +9 -3
  62. package/features/security/apiKeys/UpdateApiKey/UpdateApiKeyUseCase.js.map +1 -1
  63. package/features/security/apiKeys/feature.js +7 -2
  64. package/features/security/apiKeys/feature.js.map +1 -1
  65. package/features/security/apiKeys/shared/ApiKeyProvider.d.ts +3 -5
  66. package/features/security/apiKeys/shared/ApiKeyProvider.js +6 -21
  67. package/features/security/apiKeys/shared/ApiKeyProvider.js.map +1 -1
  68. package/features/security/apiKeys/shared/ApiKeysRepository.d.ts +1 -0
  69. package/features/security/apiKeys/shared/ApiKeysRepository.js +19 -4
  70. package/features/security/apiKeys/shared/ApiKeysRepository.js.map +1 -1
  71. package/features/security/apiKeys/shared/generateToken.d.ts +1 -1
  72. package/features/security/apiKeys/shared/generateToken.js.map +1 -1
  73. package/features/security/apiKeys/shared/schemas.d.ts +2 -2
  74. package/features/security/apiKeys/shared/schemas.js +2 -2
  75. package/features/security/apiKeys/shared/schemas.js.map +1 -1
  76. package/features/security/apiKeys/shared/types.d.ts +1 -1
  77. package/features/security/authorization/GroupsTeamsAuthorizer/GetPermissionsFromIdentity.d.ts +3 -3
  78. package/features/security/authorization/GroupsTeamsAuthorizer/GetPermissionsFromIdentity.js +5 -5
  79. package/features/security/authorization/GroupsTeamsAuthorizer/GetPermissionsFromIdentity.js.map +1 -1
  80. package/features/security/roles/CreateRole/CreateRoleUseCase.js +11 -6
  81. package/features/security/roles/CreateRole/CreateRoleUseCase.js.map +1 -1
  82. package/features/security/roles/CreateRole/schema.d.ts +1 -1
  83. package/features/security/roles/CreateRole/schema.js +1 -1
  84. package/features/security/roles/CreateRole/schema.js.map +1 -1
  85. package/features/security/roles/UpdateRole/UpdateRoleUseCase.js +9 -3
  86. package/features/security/roles/UpdateRole/UpdateRoleUseCase.js.map +1 -1
  87. package/features/security/roles/UpdateRole/schema.d.ts +1 -1
  88. package/features/security/roles/UpdateRole/schema.js +1 -1
  89. package/features/security/roles/UpdateRole/schema.js.map +1 -1
  90. package/features/security/shared/description.d.ts +4 -0
  91. package/features/security/shared/description.js +7 -0
  92. package/features/security/shared/description.js.map +1 -0
  93. package/features/security/shared/index.d.ts +1 -0
  94. package/features/security/shared/index.js +1 -0
  95. package/features/security/teams/CreateTeam/CreateTeamUseCase.d.ts +3 -1
  96. package/features/security/teams/CreateTeam/CreateTeamUseCase.js +20 -8
  97. package/features/security/teams/CreateTeam/CreateTeamUseCase.js.map +1 -1
  98. package/features/security/teams/CreateTeam/schema.d.ts +1 -1
  99. package/features/security/teams/CreateTeam/schema.js +1 -1
  100. package/features/security/teams/CreateTeam/schema.js.map +1 -1
  101. package/features/security/teams/UpdateTeam/UpdateTeamUseCase.d.ts +3 -1
  102. package/features/security/teams/UpdateTeam/UpdateTeamUseCase.js +20 -5
  103. package/features/security/teams/UpdateTeam/UpdateTeamUseCase.js.map +1 -1
  104. package/features/security/teams/UpdateTeam/schema.d.ts +1 -1
  105. package/features/security/teams/UpdateTeam/schema.js +1 -1
  106. package/features/security/teams/UpdateTeam/schema.js.map +1 -1
  107. package/features/security/teams/shared/resolveRoleIdentifiers.d.ts +17 -0
  108. package/features/security/teams/shared/resolveRoleIdentifiers.js +32 -0
  109. package/features/security/teams/shared/resolveRoleIdentifiers.js.map +1 -0
  110. package/features/slugify/DefaultSlugify.d.ts +8 -0
  111. package/features/slugify/DefaultSlugify.js +20 -0
  112. package/features/slugify/DefaultSlugify.js.map +1 -0
  113. package/features/slugify/abstractions.d.ts +12 -0
  114. package/features/slugify/abstractions.js +5 -0
  115. package/features/slugify/abstractions.js.map +1 -0
  116. package/features/slugify/feature.d.ts +4 -0
  117. package/features/slugify/feature.js +11 -0
  118. package/features/slugify/feature.js.map +1 -0
  119. package/features/slugify/index.d.ts +3 -0
  120. package/features/slugify/index.js +2 -0
  121. package/features/stringFormatter/DefaultStringFormatter.d.ts +17 -0
  122. package/features/stringFormatter/DefaultStringFormatter.js +19 -0
  123. package/features/stringFormatter/DefaultStringFormatter.js.map +1 -0
  124. package/features/stringFormatter/abstractions.d.ts +11 -0
  125. package/features/stringFormatter/abstractions.js +5 -0
  126. package/features/stringFormatter/abstractions.js.map +1 -0
  127. package/features/stringFormatter/feature.d.ts +4 -0
  128. package/features/stringFormatter/feature.js +13 -0
  129. package/features/stringFormatter/feature.js.map +1 -0
  130. package/features/stringFormatter/index.d.ts +3 -0
  131. package/features/stringFormatter/index.js +2 -0
  132. package/features/task/TaskDefinition/abstractions.d.ts +76 -4
  133. package/features/task/TaskDefinition/abstractions.js +2 -1
  134. package/features/task/TaskDefinition/abstractions.js.map +1 -1
  135. package/features/wcp/WcpContext/WcpContext.d.ts +6 -0
  136. package/features/wcp/WcpContext/WcpContext.js +18 -0
  137. package/features/wcp/WcpContext/WcpContext.js.map +1 -1
  138. package/features/wcp/WcpContext/decorators/WcpContextWithFeatureFlagsDecorator.d.ts +18 -0
  139. package/features/wcp/WcpContext/decorators/WcpContextWithFeatureFlagsDecorator.js +57 -25
  140. package/features/wcp/WcpContext/decorators/WcpContextWithFeatureFlagsDecorator.js.map +1 -1
  141. package/features/wcp/WcpFeature.js +2 -0
  142. package/features/wcp/WcpFeature.js.map +1 -1
  143. package/features/wcp/WcpLicenseLoader.d.ts +25 -0
  144. package/features/wcp/WcpLicenseLoader.js +58 -0
  145. package/features/wcp/WcpLicenseLoader.js.map +1 -0
  146. package/features/wcp/WcpLicenseProvider.d.ts +6 -14
  147. package/features/wcp/WcpLicenseProvider.js +3 -7
  148. package/features/wcp/WcpLicenseProvider.js.map +1 -1
  149. package/features/wcp/resolveWcpProjectEnvironment.d.ts +9 -0
  150. package/features/wcp/resolveWcpProjectEnvironment.js +23 -0
  151. package/features/wcp/resolveWcpProjectEnvironment.js.map +1 -0
  152. package/graphql/featureFlags/FeatureFlagsSchemaFactory.d.ts +9 -0
  153. package/graphql/featureFlags/FeatureFlagsSchemaFactory.js +49 -0
  154. package/graphql/featureFlags/FeatureFlagsSchemaFactory.js.map +1 -0
  155. package/graphql/wcp/WcpSchemaFactory.js +2 -0
  156. package/graphql/wcp/WcpSchemaFactory.js.map +1 -1
  157. package/package.json +18 -18
  158. package/testing/environment.d.ts +14 -0
  159. package/testing/environment.js +18 -0
  160. package/testing/environment.js.map +1 -0
  161. package/types/security.d.ts +1 -1
  162. package/features/wcp/loadWcpLicense.d.ts +0 -2
  163. package/features/wcp/loadWcpLicense.js +0 -51
  164. package/features/wcp/loadWcpLicense.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"features/security/apiKeys/GetApiKeyByToken/GetApiKeyByTokenUseCase.js","sources":["../../../../../src/features/security/apiKeys/GetApiKeyByToken/GetApiKeyByTokenUseCase.ts"],"sourcesContent":["import { Result } from \"@webiny/feature/api\";\nimport { GetApiKeyByTokenUseCase as GetApiKeyByTokenUseCaseAbstraction } from \"./abstractions.js\";\nimport { ApiKeysRepository } from \"../shared/abstractions.js\";\nimport type { ApiKey } from \"../shared/types.js\";\n\nclass GetApiKeyByTokenUseCaseImpl implements GetApiKeyByTokenUseCaseAbstraction.Interface {\n private repository: ApiKeysRepository.Interface;\n\n constructor(repository: ApiKeysRepository.Interface) {\n this.repository = repository;\n }\n\n async execute(\n token: string\n ): Promise<Result<ApiKey | null, GetApiKeyByTokenUseCaseAbstraction.Error>> {\n return this.repository.getByToken(token);\n }\n}\n\nexport const GetApiKeyByTokenUseCase = GetApiKeyByTokenUseCaseAbstraction.createImplementation({\n implementation: GetApiKeyByTokenUseCaseImpl,\n dependencies: [ApiKeysRepository]\n});\n"],"names":["GetApiKeyByTokenUseCaseImpl","repository","token","GetApiKeyByTokenUseCase","GetApiKeyByTokenUseCaseAbstraction","ApiKeysRepository"],"mappings":";;AAKA,MAAMA;IAGF,YAAYC,UAAuC,CAAE;QACjD,IAAI,CAAC,UAAU,GAAGA;IACtB;IAEA,MAAM,QACFC,KAAa,EAC2D;QACxE,OAAO,IAAI,CAAC,UAAU,CAAC,UAAU,CAACA;IACtC;AACJ;AAEO,MAAMC,kDAA0BC,wBAAAA,oBAAuD,CAAC;IAC3F,gBAAgBJ;IAChB,cAAc;QAACK;KAAkB;AACrC"}
1
+ {"version":3,"file":"features/security/apiKeys/GetApiKeyByToken/GetApiKeyByTokenUseCase.js","sources":["../../../../../src/features/security/apiKeys/GetApiKeyByToken/GetApiKeyByTokenUseCase.ts"],"sourcesContent":["import { GetApiKeyByTokenUseCase as GetApiKeyByTokenUseCaseAbstraction } from \"./abstractions.js\";\nimport { ApiKeysRepository } from \"../shared/abstractions.js\";\n\nclass GetApiKeyByTokenUseCaseImpl implements GetApiKeyByTokenUseCaseAbstraction.Interface {\n constructor(private repository: ApiKeysRepository.Interface) {}\n\n async execute(token: string) {\n return this.repository.getByToken(token);\n }\n}\n\nexport const GetApiKeyByTokenUseCase = GetApiKeyByTokenUseCaseAbstraction.createImplementation({\n implementation: GetApiKeyByTokenUseCaseImpl,\n dependencies: [ApiKeysRepository]\n});\n"],"names":["GetApiKeyByTokenUseCaseImpl","repository","token","GetApiKeyByTokenUseCase","GetApiKeyByTokenUseCaseAbstraction","ApiKeysRepository"],"mappings":";;AAGA,MAAMA;IACF,YAAoBC,UAAuC,CAAE;aAAzCA,UAAU,GAAVA;IAA0C;IAE9D,MAAM,QAAQC,KAAa,EAAE;QACzB,OAAO,IAAI,CAAC,UAAU,CAAC,UAAU,CAACA;IACtC;AACJ;AAEO,MAAMC,kDAA0BC,wBAAAA,oBAAuD,CAAC;IAC3F,gBAAgBJ;IAChB,cAAc;QAACK;KAAkB;AACrC"}
@@ -5,7 +5,7 @@ export interface IGetApiKeyByTokenErrors {
5
5
  }
6
6
  type GetApiKeyByTokenError = IGetApiKeyByTokenErrors[keyof IGetApiKeyByTokenErrors] | ApiKeysRepository.Error;
7
7
  export interface IGetApiKeyByToken {
8
- execute(token: string): Promise<Result<ApiKey | null, GetApiKeyByTokenError>>;
8
+ execute(token: string): Promise<Result<ApiKey, GetApiKeyByTokenError>>;
9
9
  }
10
10
  /** Retrieve an API key by its token value. */
11
11
  export declare const GetApiKeyByTokenUseCase: import("@webiny/di").Abstraction<IGetApiKeyByToken>;
@@ -1 +1 @@
1
- {"version":3,"file":"features/security/apiKeys/GetApiKeyByToken/abstractions.js","sources":["../../../../../src/features/security/apiKeys/GetApiKeyByToken/abstractions.ts"],"sourcesContent":["import { createAbstraction } from \"@webiny/feature/api\";\nimport { Result } from \"@webiny/feature/api\";\nimport type { ApiKey } from \"../shared/types.js\";\nimport { ApiKeysRepository } from \"../shared/abstractions.js\";\n\nexport interface IGetApiKeyByTokenErrors {\n // No use-case specific errors - only repository errors can occur\n}\n\ntype GetApiKeyByTokenError =\n | IGetApiKeyByTokenErrors[keyof IGetApiKeyByTokenErrors]\n | ApiKeysRepository.Error;\n\nexport interface IGetApiKeyByToken {\n execute(token: string): Promise<Result<ApiKey | null, GetApiKeyByTokenError>>;\n}\n\n/** Retrieve an API key by its token value. */\nexport const GetApiKeyByTokenUseCase =\n createAbstraction<IGetApiKeyByToken>(\"GetApiKeyByTokenUseCase\");\n\nexport namespace GetApiKeyByTokenUseCase {\n export type Interface = IGetApiKeyByToken;\n export type Error = GetApiKeyByTokenError;\n}\n"],"names":["GetApiKeyByTokenUseCase","createAbstraction"],"mappings":";AAkBO,MAAMA,0BACTC,kBAAqC"}
1
+ {"version":3,"file":"features/security/apiKeys/GetApiKeyByToken/abstractions.js","sources":["../../../../../src/features/security/apiKeys/GetApiKeyByToken/abstractions.ts"],"sourcesContent":["import { createAbstraction } from \"@webiny/feature/api\";\nimport { Result } from \"@webiny/feature/api\";\nimport type { ApiKey } from \"../shared/types.js\";\nimport { ApiKeysRepository } from \"../shared/abstractions.js\";\n\nexport interface IGetApiKeyByTokenErrors {\n // No use-case specific errors - only repository errors can occur\n}\n\ntype GetApiKeyByTokenError =\n | IGetApiKeyByTokenErrors[keyof IGetApiKeyByTokenErrors]\n | ApiKeysRepository.Error;\n\nexport interface IGetApiKeyByToken {\n execute(token: string): Promise<Result<ApiKey, GetApiKeyByTokenError>>;\n}\n\n/** Retrieve an API key by its token value. */\nexport const GetApiKeyByTokenUseCase =\n createAbstraction<IGetApiKeyByToken>(\"GetApiKeyByTokenUseCase\");\n\nexport namespace GetApiKeyByTokenUseCase {\n export type Interface = IGetApiKeyByToken;\n export type Error = GetApiKeyByTokenError;\n}\n"],"names":["GetApiKeyByTokenUseCase","createAbstraction"],"mappings":";AAkBO,MAAMA,0BACTC,kBAAqC"}
@@ -6,6 +6,7 @@ import { EventPublisher } from "../../../eventPublisher/index.js";
6
6
  import { updateApiKeyInputSchema } from "../shared/schemas.js";
7
7
  import { ApiKeyAfterUpdateEvent, ApiKeyBeforeUpdateEvent } from "./events.js";
8
8
  import { ApiKeyNotAuthorizedError, ApiKeyValidationError } from "../shared/errors.js";
9
+ import { descriptionOnUpdate } from "../../shared/description.js";
9
10
  class UpdateApiKeyUseCaseImpl {
10
11
  constructor(repository, identityContext, eventPublisher){
11
12
  this.repository = repository;
@@ -20,21 +21,26 @@ class UpdateApiKeyUseCaseImpl {
20
21
  const existingResult = await this.repository.get(id);
21
22
  if (existingResult.isFail()) return Result.fail(existingResult.error);
22
23
  const existingApiKey = existingResult.value;
24
+ const { description, ...rest } = validation.data;
25
+ const changes = {
26
+ ...rest,
27
+ ...descriptionOnUpdate(description)
28
+ };
23
29
  const updatedApiKey = {
24
30
  ...existingApiKey,
25
- ...validation.data
31
+ ...changes
26
32
  };
27
33
  await this.eventPublisher.publish(new ApiKeyBeforeUpdateEvent({
28
34
  original: existingApiKey,
29
35
  updated: updatedApiKey,
30
- input: validation.data
36
+ input: changes
31
37
  }));
32
38
  const result = await this.repository.update(updatedApiKey);
33
39
  if (result.isFail()) return Result.fail(result.error);
34
40
  await this.eventPublisher.publish(new ApiKeyAfterUpdateEvent({
35
41
  original: existingApiKey,
36
42
  updated: updatedApiKey,
37
- input: validation.data
43
+ input: changes
38
44
  }));
39
45
  return Result.ok(updatedApiKey);
40
46
  }
@@ -1 +1 @@
1
- {"version":3,"file":"features/security/apiKeys/UpdateApiKey/UpdateApiKeyUseCase.js","sources":["../../../../../src/features/security/apiKeys/UpdateApiKey/UpdateApiKeyUseCase.ts"],"sourcesContent":["import { Result } from \"@webiny/feature/api\";\nimport { UpdateApiKeyUseCase as UpdateApiKeyUseCaseAbstraction } from \"./abstractions.js\";\nimport { ApiKeysRepository } from \"../shared/abstractions.js\";\nimport { IdentityContext } from \"../../IdentityContext/abstractions.js\";\nimport { EventPublisher } from \"~/features/eventPublisher/index.js\";\nimport { updateApiKeyInputSchema } from \"../shared/schemas.js\";\nimport { ApiKeyBeforeUpdateEvent, ApiKeyAfterUpdateEvent } from \"./events.js\";\nimport type { ApiKey, UpdateApiKeyInput } from \"../shared/types.js\";\nimport { ApiKeyNotAuthorizedError, ApiKeyValidationError } from \"../shared/errors.js\";\n\nclass UpdateApiKeyUseCaseImpl implements UpdateApiKeyUseCaseAbstraction.Interface {\n private repository: ApiKeysRepository.Interface;\n private identityContext: IdentityContext.Interface;\n private eventPublisher: EventPublisher.Interface;\n\n constructor(\n repository: ApiKeysRepository.Interface,\n identityContext: IdentityContext.Interface,\n eventPublisher: EventPublisher.Interface\n ) {\n this.repository = repository;\n this.identityContext = identityContext;\n this.eventPublisher = eventPublisher;\n }\n\n async execute(\n id: string,\n input: UpdateApiKeyInput\n ): Promise<Result<ApiKey, UpdateApiKeyUseCaseAbstraction.Error>> {\n const hasPermission = await this.identityContext.getPermission(\"security.apiKey\");\n if (!hasPermission) {\n return Result.fail(new ApiKeyNotAuthorizedError());\n }\n\n const validation = updateApiKeyInputSchema.safeParse(input);\n if (!validation.success) {\n return Result.fail(new ApiKeyValidationError(validation.error.issues[0].message));\n }\n\n const existingResult = await this.repository.get(id);\n if (existingResult.isFail()) {\n return Result.fail(existingResult.error);\n }\n\n const existingApiKey = existingResult.value;\n\n const updatedApiKey: ApiKey = {\n ...existingApiKey,\n ...validation.data\n };\n\n await this.eventPublisher.publish(\n new ApiKeyBeforeUpdateEvent({\n original: existingApiKey,\n updated: updatedApiKey,\n input: validation.data\n })\n );\n\n const result = await this.repository.update(updatedApiKey);\n\n if (result.isFail()) {\n return Result.fail(result.error);\n }\n\n await this.eventPublisher.publish(\n new ApiKeyAfterUpdateEvent({\n original: existingApiKey,\n updated: updatedApiKey,\n input: validation.data\n })\n );\n\n return Result.ok(updatedApiKey);\n }\n}\n\nexport const UpdateApiKeyUseCase = UpdateApiKeyUseCaseAbstraction.createImplementation({\n implementation: UpdateApiKeyUseCaseImpl,\n dependencies: [ApiKeysRepository, IdentityContext, EventPublisher]\n});\n"],"names":["UpdateApiKeyUseCaseImpl","repository","identityContext","eventPublisher","id","input","hasPermission","Result","ApiKeyNotAuthorizedError","validation","updateApiKeyInputSchema","ApiKeyValidationError","existingResult","existingApiKey","updatedApiKey","ApiKeyBeforeUpdateEvent","result","ApiKeyAfterUpdateEvent","UpdateApiKeyUseCase","UpdateApiKeyUseCaseAbstraction","ApiKeysRepository","IdentityContext","EventPublisher"],"mappings":";;;;;;;;AAUA,MAAMA;IAKF,YACIC,UAAuC,EACvCC,eAA0C,EAC1CC,cAAwC,CAC1C;QACE,IAAI,CAAC,UAAU,GAAGF;QAClB,IAAI,CAAC,eAAe,GAAGC;QACvB,IAAI,CAAC,cAAc,GAAGC;IAC1B;IAEA,MAAM,QACFC,EAAU,EACVC,KAAwB,EACqC;QAC7D,MAAMC,gBAAgB,MAAM,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC;QAC/D,IAAI,CAACA,eACD,OAAOC,OAAO,IAAI,CAAC,IAAIC;QAG3B,MAAMC,aAAaC,wBAAwB,SAAS,CAACL;QACrD,IAAI,CAACI,WAAW,OAAO,EACnB,OAAOF,OAAO,IAAI,CAAC,IAAII,sBAAsBF,WAAW,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO;QAGnF,MAAMG,iBAAiB,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,CAACR;QACjD,IAAIQ,eAAe,MAAM,IACrB,OAAOL,OAAO,IAAI,CAACK,eAAe,KAAK;QAG3C,MAAMC,iBAAiBD,eAAe,KAAK;QAE3C,MAAME,gBAAwB;YAC1B,GAAGD,cAAc;YACjB,GAAGJ,WAAW,IAAI;QACtB;QAEA,MAAM,IAAI,CAAC,cAAc,CAAC,OAAO,CAC7B,IAAIM,wBAAwB;YACxB,UAAUF;YACV,SAASC;YACT,OAAOL,WAAW,IAAI;QAC1B;QAGJ,MAAMO,SAAS,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,CAACF;QAE5C,IAAIE,OAAO,MAAM,IACb,OAAOT,OAAO,IAAI,CAACS,OAAO,KAAK;QAGnC,MAAM,IAAI,CAAC,cAAc,CAAC,OAAO,CAC7B,IAAIC,uBAAuB;YACvB,UAAUJ;YACV,SAASC;YACT,OAAOL,WAAW,IAAI;QAC1B;QAGJ,OAAOF,OAAO,EAAE,CAACO;IACrB;AACJ;AAEO,MAAMI,0CAAsBC,oBAAAA,oBAAmD,CAAC;IACnF,gBAAgBnB;IAChB,cAAc;QAACoB;QAAmBC;QAAiBC;KAAe;AACtE"}
1
+ {"version":3,"file":"features/security/apiKeys/UpdateApiKey/UpdateApiKeyUseCase.js","sources":["../../../../../src/features/security/apiKeys/UpdateApiKey/UpdateApiKeyUseCase.ts"],"sourcesContent":["import { Result } from \"@webiny/feature/api\";\nimport { UpdateApiKeyUseCase as UpdateApiKeyUseCaseAbstraction } from \"./abstractions.js\";\nimport { ApiKeysRepository } from \"../shared/abstractions.js\";\nimport { IdentityContext } from \"../../IdentityContext/abstractions.js\";\nimport { EventPublisher } from \"~/features/eventPublisher/index.js\";\nimport { updateApiKeyInputSchema } from \"../shared/schemas.js\";\nimport { ApiKeyBeforeUpdateEvent, ApiKeyAfterUpdateEvent } from \"./events.js\";\nimport type { ApiKey, UpdateApiKeyInput } from \"../shared/types.js\";\nimport { ApiKeyNotAuthorizedError, ApiKeyValidationError } from \"../shared/errors.js\";\nimport { descriptionOnUpdate } from \"../../shared/description.js\";\n\nclass UpdateApiKeyUseCaseImpl implements UpdateApiKeyUseCaseAbstraction.Interface {\n private repository: ApiKeysRepository.Interface;\n private identityContext: IdentityContext.Interface;\n private eventPublisher: EventPublisher.Interface;\n\n constructor(\n repository: ApiKeysRepository.Interface,\n identityContext: IdentityContext.Interface,\n eventPublisher: EventPublisher.Interface\n ) {\n this.repository = repository;\n this.identityContext = identityContext;\n this.eventPublisher = eventPublisher;\n }\n\n async execute(\n id: string,\n input: UpdateApiKeyInput\n ): Promise<Result<ApiKey, UpdateApiKeyUseCaseAbstraction.Error>> {\n const hasPermission = await this.identityContext.getPermission(\"security.apiKey\");\n if (!hasPermission) {\n return Result.fail(new ApiKeyNotAuthorizedError());\n }\n\n const validation = updateApiKeyInputSchema.safeParse(input);\n if (!validation.success) {\n return Result.fail(new ApiKeyValidationError(validation.error.issues[0].message));\n }\n\n const existingResult = await this.repository.get(id);\n if (existingResult.isFail()) {\n return Result.fail(existingResult.error);\n }\n\n const existingApiKey = existingResult.value;\n\n // `description` is pulled out of the spread because it is the one field that accepts null.\n // Normalising it here keeps null out of both the entity and the published events, whose\n // input type declares `description?: string`.\n const { description, ...rest } = validation.data;\n\n const changes: UpdateApiKeyInput = {\n ...rest,\n ...descriptionOnUpdate(description)\n };\n\n const updatedApiKey: ApiKey = {\n ...existingApiKey,\n ...changes\n };\n\n await this.eventPublisher.publish(\n new ApiKeyBeforeUpdateEvent({\n original: existingApiKey,\n updated: updatedApiKey,\n input: changes\n })\n );\n\n const result = await this.repository.update(updatedApiKey);\n\n if (result.isFail()) {\n return Result.fail(result.error);\n }\n\n await this.eventPublisher.publish(\n new ApiKeyAfterUpdateEvent({\n original: existingApiKey,\n updated: updatedApiKey,\n input: changes\n })\n );\n\n return Result.ok(updatedApiKey);\n }\n}\n\nexport const UpdateApiKeyUseCase = UpdateApiKeyUseCaseAbstraction.createImplementation({\n implementation: UpdateApiKeyUseCaseImpl,\n dependencies: [ApiKeysRepository, IdentityContext, EventPublisher]\n});\n"],"names":["UpdateApiKeyUseCaseImpl","repository","identityContext","eventPublisher","id","input","hasPermission","Result","ApiKeyNotAuthorizedError","validation","updateApiKeyInputSchema","ApiKeyValidationError","existingResult","existingApiKey","description","rest","changes","descriptionOnUpdate","updatedApiKey","ApiKeyBeforeUpdateEvent","result","ApiKeyAfterUpdateEvent","UpdateApiKeyUseCase","UpdateApiKeyUseCaseAbstraction","ApiKeysRepository","IdentityContext","EventPublisher"],"mappings":";;;;;;;;;AAWA,MAAMA;IAKF,YACIC,UAAuC,EACvCC,eAA0C,EAC1CC,cAAwC,CAC1C;QACE,IAAI,CAAC,UAAU,GAAGF;QAClB,IAAI,CAAC,eAAe,GAAGC;QACvB,IAAI,CAAC,cAAc,GAAGC;IAC1B;IAEA,MAAM,QACFC,EAAU,EACVC,KAAwB,EACqC;QAC7D,MAAMC,gBAAgB,MAAM,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC;QAC/D,IAAI,CAACA,eACD,OAAOC,OAAO,IAAI,CAAC,IAAIC;QAG3B,MAAMC,aAAaC,wBAAwB,SAAS,CAACL;QACrD,IAAI,CAACI,WAAW,OAAO,EACnB,OAAOF,OAAO,IAAI,CAAC,IAAII,sBAAsBF,WAAW,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO;QAGnF,MAAMG,iBAAiB,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,CAACR;QACjD,IAAIQ,eAAe,MAAM,IACrB,OAAOL,OAAO,IAAI,CAACK,eAAe,KAAK;QAG3C,MAAMC,iBAAiBD,eAAe,KAAK;QAK3C,MAAM,EAAEE,WAAW,EAAE,GAAGC,MAAM,GAAGN,WAAW,IAAI;QAEhD,MAAMO,UAA6B;YAC/B,GAAGD,IAAI;YACP,GAAGE,oBAAoBH,YAAY;QACvC;QAEA,MAAMI,gBAAwB;YAC1B,GAAGL,cAAc;YACjB,GAAGG,OAAO;QACd;QAEA,MAAM,IAAI,CAAC,cAAc,CAAC,OAAO,CAC7B,IAAIG,wBAAwB;YACxB,UAAUN;YACV,SAASK;YACT,OAAOF;QACX;QAGJ,MAAMI,SAAS,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,CAACF;QAE5C,IAAIE,OAAO,MAAM,IACb,OAAOb,OAAO,IAAI,CAACa,OAAO,KAAK;QAGnC,MAAM,IAAI,CAAC,cAAc,CAAC,OAAO,CAC7B,IAAIC,uBAAuB;YACvB,UAAUR;YACV,SAASK;YACT,OAAOF;QACX;QAGJ,OAAOT,OAAO,EAAE,CAACW;IACrB;AACJ;AAEO,MAAMI,0CAAsBC,oBAAAA,oBAAmD,CAAC;IACnF,gBAAgBvB;IAChB,cAAc;QAACwB;QAAmBC;QAAiBC;KAAe;AACtE"}
@@ -7,14 +7,19 @@ import { ListApiKeysFeature } from "./ListApiKeys/feature.js";
7
7
  import { CreateApiKeyFeature } from "./CreateApiKey/feature.js";
8
8
  import { UpdateApiKeyFeature } from "./UpdateApiKey/feature.js";
9
9
  import { DeleteApiKeyFeature } from "./DeleteApiKey/feature.js";
10
- import { ApiKeyProvider } from "./shared/ApiKeyProvider.js";
10
+ import { ApiKeyFactory, ApiKeyProvider } from "./shared/abstractions.js";
11
+ import { ApiKeyProvider as ApiKeyProvider_js_ApiKeyProvider } from "./shared/ApiKeyProvider.js";
11
12
  import { ApiKeyAuthenticator } from "./ApiKeyAuthenticator.js";
12
13
  import { ApiKeyAuthorizer } from "./ApiKeyAuthorizer.js";
14
+ import { TenantContext } from "../../tenancy/TenantContext/index.js";
13
15
  const ApiKeysFeature = createFeature({
14
16
  name: "ApiKeys",
15
17
  register (container) {
16
18
  container.register(ApiKeysRepository).inSingletonScope();
17
- container.register(ApiKeyProvider).inSingletonScope();
19
+ container.registerFactory(ApiKeyProvider, ()=>{
20
+ const tenantContext = container.resolve(TenantContext);
21
+ return new ApiKeyProvider_js_ApiKeyProvider(tenantContext, ()=>container.resolveAll(ApiKeyFactory));
22
+ });
18
23
  container.register(ApiKeyAuthenticator);
19
24
  container.register(ApiKeyAuthorizer);
20
25
  GetApiKeyFeature.register(container);
@@ -1 +1 @@
1
- {"version":3,"file":"features/security/apiKeys/feature.js","sources":["../../../../src/features/security/apiKeys/feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/api\";\nimport { ApiKeysRepository } from \"./shared/ApiKeysRepository.js\";\nimport { GetApiKeyFeature } from \"./GetApiKey/feature.js\";\nimport { GetApiKeyByTokenFeature } from \"./GetApiKeyByToken/feature.js\";\nimport { GetApiKeyBySlugFeature } from \"./GetApiKeyBySlug/feature.js\";\nimport { ListApiKeysFeature } from \"./ListApiKeys/feature.js\";\nimport { CreateApiKeyFeature } from \"./CreateApiKey/feature.js\";\nimport { UpdateApiKeyFeature } from \"./UpdateApiKey/feature.js\";\nimport { DeleteApiKeyFeature } from \"./DeleteApiKey/feature.js\";\nimport { ApiKeyProvider } from \"./shared/ApiKeyProvider.js\";\nimport { ApiKeyAuthenticator } from \"./ApiKeyAuthenticator.js\";\nimport { ApiKeyAuthorizer } from \"./ApiKeyAuthorizer.js\";\n\nexport const ApiKeysFeature = createFeature({\n name: \"ApiKeys\",\n register(container) {\n // Register repository in singleton scope\n container.register(ApiKeysRepository).inSingletonScope();\n container.register(ApiKeyProvider).inSingletonScope();\n container.register(ApiKeyAuthenticator);\n container.register(ApiKeyAuthorizer);\n\n // Register all use cases\n GetApiKeyFeature.register(container);\n GetApiKeyByTokenFeature.register(container);\n GetApiKeyBySlugFeature.register(container);\n ListApiKeysFeature.register(container);\n CreateApiKeyFeature.register(container);\n UpdateApiKeyFeature.register(container);\n DeleteApiKeyFeature.register(container);\n }\n});\n"],"names":["ApiKeysFeature","createFeature","container","ApiKeysRepository","ApiKeyProvider","ApiKeyAuthenticator","ApiKeyAuthorizer","GetApiKeyFeature","GetApiKeyByTokenFeature","GetApiKeyBySlugFeature","ListApiKeysFeature","CreateApiKeyFeature","UpdateApiKeyFeature","DeleteApiKeyFeature"],"mappings":";;;;;;;;;;;;AAaO,MAAMA,iBAAiBC,cAAc;IACxC,MAAM;IACN,UAASC,SAAS;QAEdA,UAAU,QAAQ,CAACC,mBAAmB,gBAAgB;QACtDD,UAAU,QAAQ,CAACE,gBAAgB,gBAAgB;QACnDF,UAAU,QAAQ,CAACG;QACnBH,UAAU,QAAQ,CAACI;QAGnBC,iBAAiB,QAAQ,CAACL;QAC1BM,wBAAwB,QAAQ,CAACN;QACjCO,uBAAuB,QAAQ,CAACP;QAChCQ,mBAAmB,QAAQ,CAACR;QAC5BS,oBAAoB,QAAQ,CAACT;QAC7BU,oBAAoB,QAAQ,CAACV;QAC7BW,oBAAoB,QAAQ,CAACX;IACjC;AACJ"}
1
+ {"version":3,"file":"features/security/apiKeys/feature.js","sources":["../../../../src/features/security/apiKeys/feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/api\";\nimport { ApiKeysRepository } from \"./shared/ApiKeysRepository.js\";\nimport { GetApiKeyFeature } from \"./GetApiKey/feature.js\";\nimport { GetApiKeyByTokenFeature } from \"./GetApiKeyByToken/feature.js\";\nimport { GetApiKeyBySlugFeature } from \"./GetApiKeyBySlug/feature.js\";\nimport { ListApiKeysFeature } from \"./ListApiKeys/feature.js\";\nimport { CreateApiKeyFeature } from \"./CreateApiKey/feature.js\";\nimport { UpdateApiKeyFeature } from \"./UpdateApiKey/feature.js\";\nimport { DeleteApiKeyFeature } from \"./DeleteApiKey/feature.js\";\nimport {\n ApiKeyFactory,\n ApiKeyProvider as ApiKeyProviderAbstraction\n} from \"~/features/security/apiKeys/shared/abstractions.js\";\nimport { ApiKeyProvider } from \"./shared/ApiKeyProvider.js\";\nimport { ApiKeyAuthenticator } from \"./ApiKeyAuthenticator.js\";\nimport { ApiKeyAuthorizer } from \"./ApiKeyAuthorizer.js\";\nimport { TenantContext } from \"~/features/tenancy/TenantContext/index.js\";\n\nexport const ApiKeysFeature = createFeature({\n name: \"ApiKeys\",\n register(container) {\n // Register repository in singleton scope\n container.register(ApiKeysRepository).inSingletonScope();\n\n container.registerFactory(ApiKeyProviderAbstraction, () => {\n const tenantContext = container.resolve(TenantContext);\n return new ApiKeyProvider(tenantContext, () => {\n return container.resolveAll(ApiKeyFactory);\n });\n });\n container.register(ApiKeyAuthenticator);\n container.register(ApiKeyAuthorizer);\n\n // Register all use cases\n GetApiKeyFeature.register(container);\n GetApiKeyByTokenFeature.register(container);\n GetApiKeyBySlugFeature.register(container);\n ListApiKeysFeature.register(container);\n CreateApiKeyFeature.register(container);\n UpdateApiKeyFeature.register(container);\n DeleteApiKeyFeature.register(container);\n }\n});\n"],"names":["ApiKeysFeature","createFeature","container","ApiKeysRepository","ApiKeyProviderAbstraction","tenantContext","TenantContext","ApiKeyProvider","ApiKeyFactory","ApiKeyAuthenticator","ApiKeyAuthorizer","GetApiKeyFeature","GetApiKeyByTokenFeature","GetApiKeyBySlugFeature","ListApiKeysFeature","CreateApiKeyFeature","UpdateApiKeyFeature","DeleteApiKeyFeature"],"mappings":";;;;;;;;;;;;;;AAkBO,MAAMA,iBAAiBC,cAAc;IACxC,MAAM;IACN,UAASC,SAAS;QAEdA,UAAU,QAAQ,CAACC,mBAAmB,gBAAgB;QAEtDD,UAAU,eAAe,CAACE,gBAA2B;YACjD,MAAMC,gBAAgBH,UAAU,OAAO,CAACI;YACxC,OAAO,IAAIC,iCAAeF,eAAe,IAC9BH,UAAU,UAAU,CAACM;QAEpC;QACAN,UAAU,QAAQ,CAACO;QACnBP,UAAU,QAAQ,CAACQ;QAGnBC,iBAAiB,QAAQ,CAACT;QAC1BU,wBAAwB,QAAQ,CAACV;QACjCW,uBAAuB,QAAQ,CAACX;QAChCY,mBAAmB,QAAQ,CAACZ;QAC5Ba,oBAAoB,QAAQ,CAACb;QAC7Bc,oBAAoB,QAAQ,CAACd;QAC7Be,oBAAoB,QAAQ,CAACf;IACjC;AACJ"}
@@ -2,14 +2,12 @@ import { TenantContext } from "../../../../features/tenancy/TenantContext/index.
2
2
  import { ApiKeyFactory } from "./abstractions.js";
3
3
  import { ApiKeyProvider as ProviderAbstraction } from "./abstractions.js";
4
4
  import type { ApiKey } from "./types.js";
5
- declare class ApiKeyProviderImpl implements ProviderAbstraction.Interface {
5
+ export declare class ApiKeyProvider implements ProviderAbstraction.Interface {
6
6
  private tenantContext;
7
- private apiKeyFactories;
7
+ private getApiKeyFactories;
8
8
  private cache;
9
- constructor(tenantContext: TenantContext.Interface, apiKeyFactories: ApiKeyFactory.Interface[]);
9
+ constructor(tenantContext: TenantContext.Interface, getApiKeyFactories: () => ApiKeyFactory.Interface[]);
10
10
  getByToken(token: string): Promise<ApiKey | null>;
11
11
  getBySlug(slug: string): Promise<ApiKey | null>;
12
12
  private getCache;
13
13
  }
14
- export declare const ApiKeyProvider: import("@webiny/di").Implementation<typeof ApiKeyProviderImpl>;
15
- export {};
@@ -1,11 +1,8 @@
1
- import { createImplementation } from "@webiny/feature/api";
2
- import { TenantContext } from "../../../tenancy/TenantContext/index.js";
3
- import { ApiKeyFactory, ApiKeyProvider } from "./abstractions.js";
4
1
  import { SystemIdentityValue } from "../../../../domain/identity/SystemIdentityValue.js";
5
- class ApiKeyProviderImpl {
6
- constructor(tenantContext, apiKeyFactories){
2
+ class ApiKeyProvider {
3
+ constructor(tenantContext, getApiKeyFactories){
7
4
  this.tenantContext = tenantContext;
8
- this.apiKeyFactories = apiKeyFactories;
5
+ this.getApiKeyFactories = getApiKeyFactories;
9
6
  }
10
7
  async getByToken(token) {
11
8
  const cache = await this.getCache();
@@ -19,7 +16,8 @@ class ApiKeyProviderImpl {
19
16
  }
20
17
  async getCache() {
21
18
  if (void 0 === this.cache) {
22
- const results = await Promise.all(this.apiKeyFactories.map((factory)=>factory.execute()));
19
+ const apiKeyFactories = this.getApiKeyFactories();
20
+ const results = await Promise.all(apiKeyFactories.map((factory)=>factory.execute()));
23
21
  this.cache = results.flat().map((codeKey)=>({
24
22
  ...codeKey,
25
23
  id: codeKey.slug,
@@ -33,19 +31,6 @@ class ApiKeyProviderImpl {
33
31
  return this.cache;
34
32
  }
35
33
  }
36
- const ApiKeyProvider_ApiKeyProvider = createImplementation({
37
- abstraction: ApiKeyProvider,
38
- implementation: ApiKeyProviderImpl,
39
- dependencies: [
40
- TenantContext,
41
- [
42
- ApiKeyFactory,
43
- {
44
- multiple: true
45
- }
46
- ]
47
- ]
48
- });
49
- export { ApiKeyProvider_ApiKeyProvider as ApiKeyProvider };
34
+ export { ApiKeyProvider };
50
35
 
51
36
  //# sourceMappingURL=ApiKeyProvider.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"features/security/apiKeys/shared/ApiKeyProvider.js","sources":["../../../../../src/features/security/apiKeys/shared/ApiKeyProvider.ts"],"sourcesContent":["import { createImplementation } from \"@webiny/feature/api\";\nimport { TenantContext } from \"~/features/tenancy/TenantContext/index.js\";\nimport { ApiKeyFactory } from \"./abstractions.js\";\nimport { ApiKeyProvider as ProviderAbstraction } from \"./abstractions.js\";\nimport type { ApiKey } from \"./types.js\";\nimport { SystemIdentityValue } from \"~/domain/identity/SystemIdentityValue.js\";\n\nclass ApiKeyProviderImpl implements ProviderAbstraction.Interface {\n private cache: ApiKey[] | undefined;\n\n constructor(\n private tenantContext: TenantContext.Interface,\n private apiKeyFactories: ApiKeyFactory.Interface[]\n ) {}\n\n async getByToken(token: string): Promise<ApiKey | null> {\n const cache = await this.getCache();\n\n // Search for the API key by token in the cached array\n const apiKey = cache.find(key => key.token === token);\n return apiKey || null;\n }\n\n async getBySlug(slug: string): Promise<ApiKey | null> {\n const cache = await this.getCache();\n\n // Search for the API key by token in the cached array\n const apiKey = cache.find(key => key.slug === slug);\n return apiKey || null;\n }\n\n private async getCache(): Promise<ApiKey[]> {\n if (this.cache === undefined) {\n const results = await Promise.all(\n this.apiKeyFactories.map(factory => factory.execute())\n );\n this.cache = results.flat().map<ApiKey>(codeKey => {\n return {\n ...codeKey,\n id: codeKey.slug,\n slug: codeKey.slug,\n description: \"\",\n tenant: this.tenantContext.getTenant().id,\n createdOn: new Date().toISOString(),\n createdBy: SystemIdentityValue.create()\n };\n });\n }\n\n return this.cache;\n }\n}\n\nexport const ApiKeyProvider = createImplementation({\n abstraction: ProviderAbstraction,\n implementation: ApiKeyProviderImpl,\n dependencies: [TenantContext, [ApiKeyFactory, { multiple: true }]]\n});\n"],"names":["ApiKeyProviderImpl","tenantContext","apiKeyFactories","token","cache","apiKey","key","slug","undefined","results","Promise","factory","codeKey","Date","SystemIdentityValue","ApiKeyProvider","createImplementation","ProviderAbstraction","TenantContext","ApiKeyFactory"],"mappings":";;;;AAOA,MAAMA;IAGF,YACYC,aAAsC,EACtCC,eAA0C,CACpD;aAFUD,aAAa,GAAbA;aACAC,eAAe,GAAfA;IACT;IAEH,MAAM,WAAWC,KAAa,EAA0B;QACpD,MAAMC,QAAQ,MAAM,IAAI,CAAC,QAAQ;QAGjC,MAAMC,SAASD,MAAM,IAAI,CAACE,CAAAA,MAAOA,IAAI,KAAK,KAAKH;QAC/C,OAAOE,UAAU;IACrB;IAEA,MAAM,UAAUE,IAAY,EAA0B;QAClD,MAAMH,QAAQ,MAAM,IAAI,CAAC,QAAQ;QAGjC,MAAMC,SAASD,MAAM,IAAI,CAACE,CAAAA,MAAOA,IAAI,IAAI,KAAKC;QAC9C,OAAOF,UAAU;IACrB;IAEA,MAAc,WAA8B;QACxC,IAAI,AAAeG,WAAf,IAAI,CAAC,KAAK,EAAgB;YAC1B,MAAMC,UAAU,MAAMC,QAAQ,GAAG,CAC7B,IAAI,CAAC,eAAe,CAAC,GAAG,CAACC,CAAAA,UAAWA,QAAQ,OAAO;YAEvD,IAAI,CAAC,KAAK,GAAGF,QAAQ,IAAI,GAAG,GAAG,CAASG,CAAAA,UAC7B;oBACH,GAAGA,OAAO;oBACV,IAAIA,QAAQ,IAAI;oBAChB,MAAMA,QAAQ,IAAI;oBAClB,aAAa;oBACb,QAAQ,IAAI,CAAC,aAAa,CAAC,SAAS,GAAG,EAAE;oBACzC,WAAW,IAAIC,OAAO,WAAW;oBACjC,WAAWC,oBAAoB,MAAM;gBACzC;QAER;QAEA,OAAO,IAAI,CAAC,KAAK;IACrB;AACJ;AAEO,MAAMC,gCAAiBC,qBAAqB;IAC/C,aAAaC;IACb,gBAAgBjB;IAChB,cAAc;QAACkB;QAAe;YAACC;YAAe;gBAAE,UAAU;YAAK;SAAE;KAAC;AACtE"}
1
+ {"version":3,"file":"features/security/apiKeys/shared/ApiKeyProvider.js","sources":["../../../../../src/features/security/apiKeys/shared/ApiKeyProvider.ts"],"sourcesContent":["import { TenantContext } from \"~/features/tenancy/TenantContext/index.js\";\nimport { ApiKeyFactory } from \"./abstractions.js\";\nimport { ApiKeyProvider as ProviderAbstraction } from \"./abstractions.js\";\nimport type { ApiKey } from \"./types.js\";\nimport { SystemIdentityValue } from \"~/domain/identity/SystemIdentityValue.js\";\n\nexport class ApiKeyProvider implements ProviderAbstraction.Interface {\n private cache: ApiKey[] | undefined;\n\n constructor(\n private tenantContext: TenantContext.Interface,\n private getApiKeyFactories: () => ApiKeyFactory.Interface[]\n ) {}\n\n async getByToken(token: string): Promise<ApiKey | null> {\n const cache = await this.getCache();\n\n // Search for the API key by token in the cached array\n const apiKey = cache.find(key => key.token === token);\n return apiKey || null;\n }\n\n async getBySlug(slug: string): Promise<ApiKey | null> {\n const cache = await this.getCache();\n\n // Search for the API key by token in the cached array\n const apiKey = cache.find(key => key.slug === slug);\n return apiKey || null;\n }\n\n private async getCache(): Promise<ApiKey[]> {\n if (this.cache === undefined) {\n const apiKeyFactories = this.getApiKeyFactories();\n const results = await Promise.all(apiKeyFactories.map(factory => factory.execute()));\n this.cache = results.flat().map<ApiKey>(codeKey => {\n return {\n ...codeKey,\n id: codeKey.slug,\n slug: codeKey.slug,\n description: \"\",\n tenant: this.tenantContext.getTenant().id,\n createdOn: new Date().toISOString(),\n createdBy: SystemIdentityValue.create()\n };\n });\n }\n\n return this.cache;\n }\n}\n"],"names":["ApiKeyProvider","tenantContext","getApiKeyFactories","token","cache","apiKey","key","slug","undefined","apiKeyFactories","results","Promise","factory","codeKey","Date","SystemIdentityValue"],"mappings":";AAMO,MAAMA;IAGT,YACYC,aAAsC,EACtCC,kBAAmD,CAC7D;aAFUD,aAAa,GAAbA;aACAC,kBAAkB,GAAlBA;IACT;IAEH,MAAM,WAAWC,KAAa,EAA0B;QACpD,MAAMC,QAAQ,MAAM,IAAI,CAAC,QAAQ;QAGjC,MAAMC,SAASD,MAAM,IAAI,CAACE,CAAAA,MAAOA,IAAI,KAAK,KAAKH;QAC/C,OAAOE,UAAU;IACrB;IAEA,MAAM,UAAUE,IAAY,EAA0B;QAClD,MAAMH,QAAQ,MAAM,IAAI,CAAC,QAAQ;QAGjC,MAAMC,SAASD,MAAM,IAAI,CAACE,CAAAA,MAAOA,IAAI,IAAI,KAAKC;QAC9C,OAAOF,UAAU;IACrB;IAEA,MAAc,WAA8B;QACxC,IAAI,AAAeG,WAAf,IAAI,CAAC,KAAK,EAAgB;YAC1B,MAAMC,kBAAkB,IAAI,CAAC,kBAAkB;YAC/C,MAAMC,UAAU,MAAMC,QAAQ,GAAG,CAACF,gBAAgB,GAAG,CAACG,CAAAA,UAAWA,QAAQ,OAAO;YAChF,IAAI,CAAC,KAAK,GAAGF,QAAQ,IAAI,GAAG,GAAG,CAASG,CAAAA,UAC7B;oBACH,GAAGA,OAAO;oBACV,IAAIA,QAAQ,IAAI;oBAChB,MAAMA,QAAQ,IAAI;oBAClB,aAAa;oBACb,QAAQ,IAAI,CAAC,aAAa,CAAC,SAAS,GAAG,EAAE;oBACzC,WAAW,IAAIC,OAAO,WAAW;oBACjC,WAAWC,oBAAoB,MAAM;gBACzC;QAER;QAEA,OAAO,IAAI,CAAC,KAAK;IACrB;AACJ"}
@@ -8,6 +8,7 @@ declare class ApiKeysRepositoryImpl implements RepositoryAbstraction.Interface {
8
8
  private tenantContext;
9
9
  private storageOperations;
10
10
  private apiKeyProvider;
11
+ private resolving;
11
12
  constructor(tenantContext: TenantContext.Interface, storageOperations: SecurityStorageOperations.Interface, apiKeyProvider: ApiKeyProvider.Interface);
12
13
  get(id: string): Promise<Result<ApiKey, RepositoryAbstraction.Error>>;
13
14
  getByToken(token: string): Promise<Result<ApiKey, RepositoryAbstraction.Error>>;
@@ -8,6 +8,7 @@ class ApiKeysRepositoryImpl {
8
8
  this.tenantContext = tenantContext;
9
9
  this.storageOperations = storageOperations;
10
10
  this.apiKeyProvider = apiKeyProvider;
11
+ this.resolving = false;
11
12
  }
12
13
  async get(id) {
13
14
  try {
@@ -30,8 +31,15 @@ class ApiKeysRepositoryImpl {
30
31
  tenant: tenant.id
31
32
  });
32
33
  if (apiKey) return Result.ok(apiKey);
33
- const factoryApiKey = await this.apiKeyProvider.getByToken(token);
34
- if (factoryApiKey) return Result.ok(factoryApiKey);
34
+ if (!this.resolving) {
35
+ this.resolving = true;
36
+ try {
37
+ const factoryApiKey = await this.apiKeyProvider.getByToken(token);
38
+ if (factoryApiKey) return Result.ok(factoryApiKey);
39
+ } finally{
40
+ this.resolving = false;
41
+ }
42
+ }
35
43
  return Result.fail(new ApiKeyNotFoundError());
36
44
  } catch (error) {
37
45
  return Result.fail(new ApiKeyPersistenceError(error));
@@ -45,8 +53,15 @@ class ApiKeysRepositoryImpl {
45
53
  tenant: tenant.id
46
54
  });
47
55
  if (apiKey) return Result.ok(apiKey);
48
- const factoryApiKey = await this.apiKeyProvider.getBySlug(slug);
49
- if (factoryApiKey) return Result.ok(factoryApiKey);
56
+ if (!this.resolving) {
57
+ this.resolving = true;
58
+ try {
59
+ const factoryApiKey = await this.apiKeyProvider.getBySlug(slug);
60
+ if (factoryApiKey) return Result.ok(factoryApiKey);
61
+ } finally{
62
+ this.resolving = false;
63
+ }
64
+ }
50
65
  return Result.fail(new ApiKeyNotFoundError());
51
66
  } catch (error) {
52
67
  return Result.fail(new ApiKeyPersistenceError(error));
@@ -1 +1 @@
1
- {"version":3,"file":"features/security/apiKeys/shared/ApiKeysRepository.js","sources":["../../../../../src/features/security/apiKeys/shared/ApiKeysRepository.ts"],"sourcesContent":["import { createImplementation } from \"@webiny/feature/api\";\nimport { Result } from \"@webiny/feature/api\";\nimport { ApiKeysRepository as RepositoryAbstraction } from \"./abstractions.js\";\nimport { ApiKeyProvider } from \"./abstractions.js\";\nimport type { ApiKey, ListApiKeysInput } from \"./types.js\";\nimport { SecurityStorageOperations } from \"~/features/security/shared/abstractions.js\";\nimport { TenantContext } from \"~/features/tenancy/TenantContext/index.js\";\nimport { ApiKeyNotFoundError, ApiKeyPersistenceError, ApiKeyValidationError } from \"./errors.js\";\n\n// TODO: create an ApiKeyMapper\n\nclass ApiKeysRepositoryImpl implements RepositoryAbstraction.Interface {\n constructor(\n private tenantContext: TenantContext.Interface,\n private storageOperations: SecurityStorageOperations.Interface,\n private apiKeyProvider: ApiKeyProvider.Interface\n ) {}\n\n async get(id: string): Promise<Result<ApiKey, RepositoryAbstraction.Error>> {\n try {\n const tenant = this.tenantContext.getTenant();\n const apiKey = await this.storageOperations.getApiKey({ id, tenant: tenant.id });\n if (apiKey) {\n return Result.ok(apiKey);\n }\n\n return Result.fail(new ApiKeyNotFoundError());\n } catch (error) {\n return Result.fail(error);\n }\n }\n\n async getByToken(token: string): Promise<Result<ApiKey, RepositoryAbstraction.Error>> {\n try {\n // First, check the database (database keys have priority over factory keys)\n const tenant = this.tenantContext.getTenant();\n const apiKey = await this.storageOperations.getApiKeyByToken({\n token,\n tenant: tenant.id\n });\n\n if (apiKey) {\n return Result.ok(apiKey);\n }\n\n // If not found in database, check if the API key is provided by a factory\n const factoryApiKey = await this.apiKeyProvider.getByToken(token);\n if (factoryApiKey) {\n return Result.ok(factoryApiKey);\n }\n\n return Result.fail(new ApiKeyNotFoundError());\n } catch (error) {\n return Result.fail(new ApiKeyPersistenceError(error));\n }\n }\n\n async getBySlug(slug: string): Promise<Result<ApiKey, RepositoryAbstraction.Error>> {\n try {\n // First, check the database (database keys have priority over factory keys)\n const tenant = this.tenantContext.getTenant();\n const apiKey = await this.storageOperations.getApiKeyBySlug({\n slug,\n tenant: tenant.id\n });\n\n if (apiKey) {\n return Result.ok(apiKey);\n }\n\n // If not found in database, check if the API key is provided by a factory\n const factoryApiKey = await this.apiKeyProvider.getBySlug(slug);\n if (factoryApiKey) {\n return Result.ok(factoryApiKey);\n }\n\n return Result.fail(new ApiKeyNotFoundError());\n } catch (error) {\n return Result.fail(new ApiKeyPersistenceError(error));\n }\n }\n\n async list(params: ListApiKeysInput): Promise<Result<ApiKey[], RepositoryAbstraction.Error>> {\n try {\n const tenant = this.tenantContext.getTenant();\n const result = await this.storageOperations.listApiKeys({\n where: { tenant: tenant.id },\n ...params\n });\n return Result.ok(result);\n } catch (error) {\n return Result.fail(new ApiKeyPersistenceError(error));\n }\n }\n\n async create(apiKey: ApiKey): Promise<Result<void, RepositoryAbstraction.Error>> {\n try {\n // Check if an API key with the same slug already exists\n const existingKeyResult = await this.getBySlug(apiKey.slug);\n\n // If we found a key, it's a duplicate slug - return validation error\n if (existingKeyResult.isOk()) {\n return Result.fail(\n new ApiKeyValidationError(`API key with slug \"${apiKey.slug}\" already exists.`)\n );\n }\n\n // \"NotFound\" error is ok. Everything else is not ok.\n if (existingKeyResult.error.code !== \"ApiKey/NotFound\") {\n return Result.fail(existingKeyResult.error);\n }\n\n // Slug is unique, proceed with creation\n const tenant = this.tenantContext.getTenant();\n await this.storageOperations.createApiKey({ apiKey: { ...apiKey, tenant: tenant.id } });\n return Result.ok();\n } catch (error) {\n return Result.fail(new ApiKeyPersistenceError(error));\n }\n }\n\n async update(apiKey: ApiKey): Promise<Result<void, RepositoryAbstraction.Error>> {\n try {\n const tenant = this.tenantContext.getTenant();\n await this.storageOperations.updateApiKey({ apiKey: { ...apiKey, tenant: tenant.id } });\n\n return Result.ok();\n } catch (error) {\n return Result.fail(new ApiKeyPersistenceError(error));\n }\n }\n\n async delete(apiKey: ApiKey): Promise<Result<void, RepositoryAbstraction.Error>> {\n try {\n const tenant = this.tenantContext.getTenant();\n await this.storageOperations.deleteApiKey({ apiKey: { ...apiKey, tenant: tenant.id } });\n\n return Result.ok();\n } catch (error) {\n return Result.fail(new ApiKeyPersistenceError(error));\n }\n }\n}\n\nexport const ApiKeysRepository = createImplementation({\n abstraction: RepositoryAbstraction,\n implementation: ApiKeysRepositoryImpl,\n dependencies: [TenantContext, SecurityStorageOperations, ApiKeyProvider]\n});\n"],"names":["ApiKeysRepositoryImpl","tenantContext","storageOperations","apiKeyProvider","id","tenant","apiKey","Result","ApiKeyNotFoundError","error","token","factoryApiKey","ApiKeyPersistenceError","slug","params","result","existingKeyResult","ApiKeyValidationError","ApiKeysRepository","createImplementation","RepositoryAbstraction","TenantContext","SecurityStorageOperations","ApiKeyProvider"],"mappings":"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"}
1
+ {"version":3,"file":"features/security/apiKeys/shared/ApiKeysRepository.js","sources":["../../../../../src/features/security/apiKeys/shared/ApiKeysRepository.ts"],"sourcesContent":["import { createImplementation } from \"@webiny/feature/api\";\nimport { Result } from \"@webiny/feature/api\";\nimport { ApiKeysRepository as RepositoryAbstraction } from \"./abstractions.js\";\nimport { ApiKeyProvider } from \"./abstractions.js\";\nimport type { ApiKey, ListApiKeysInput } from \"./types.js\";\nimport { SecurityStorageOperations } from \"~/features/security/shared/abstractions.js\";\nimport { TenantContext } from \"~/features/tenancy/TenantContext/index.js\";\nimport { ApiKeyNotFoundError, ApiKeyPersistenceError, ApiKeyValidationError } from \"./errors.js\";\n\n// TODO: create an ApiKeyMapper\n\nclass ApiKeysRepositoryImpl implements RepositoryAbstraction.Interface {\n private resolving = false;\n\n constructor(\n private tenantContext: TenantContext.Interface,\n private storageOperations: SecurityStorageOperations.Interface,\n private apiKeyProvider: ApiKeyProvider.Interface\n ) {}\n\n async get(id: string): Promise<Result<ApiKey, RepositoryAbstraction.Error>> {\n try {\n const tenant = this.tenantContext.getTenant();\n const apiKey = await this.storageOperations.getApiKey({ id, tenant: tenant.id });\n if (apiKey) {\n return Result.ok(apiKey);\n }\n\n return Result.fail(new ApiKeyNotFoundError());\n } catch (error) {\n return Result.fail(error);\n }\n }\n\n async getByToken(token: string): Promise<Result<ApiKey, RepositoryAbstraction.Error>> {\n try {\n const tenant = this.tenantContext.getTenant();\n const apiKey = await this.storageOperations.getApiKeyByToken({\n token,\n tenant: tenant.id\n });\n\n if (apiKey) {\n return Result.ok(apiKey);\n }\n\n if (!this.resolving) {\n this.resolving = true;\n try {\n const factoryApiKey = await this.apiKeyProvider.getByToken(token);\n if (factoryApiKey) {\n return Result.ok(factoryApiKey);\n }\n } finally {\n this.resolving = false;\n }\n }\n\n return Result.fail(new ApiKeyNotFoundError());\n } catch (error) {\n return Result.fail(new ApiKeyPersistenceError(error));\n }\n }\n\n async getBySlug(slug: string): Promise<Result<ApiKey, RepositoryAbstraction.Error>> {\n try {\n const tenant = this.tenantContext.getTenant();\n const apiKey = await this.storageOperations.getApiKeyBySlug({\n slug,\n tenant: tenant.id\n });\n\n if (apiKey) {\n return Result.ok(apiKey);\n }\n\n if (!this.resolving) {\n this.resolving = true;\n try {\n const factoryApiKey = await this.apiKeyProvider.getBySlug(slug);\n if (factoryApiKey) {\n return Result.ok(factoryApiKey);\n }\n } finally {\n this.resolving = false;\n }\n }\n\n return Result.fail(new ApiKeyNotFoundError());\n } catch (error) {\n return Result.fail(new ApiKeyPersistenceError(error));\n }\n }\n\n async list(params: ListApiKeysInput): Promise<Result<ApiKey[], RepositoryAbstraction.Error>> {\n try {\n const tenant = this.tenantContext.getTenant();\n const result = await this.storageOperations.listApiKeys({\n where: { tenant: tenant.id },\n ...params\n });\n return Result.ok(result);\n } catch (error) {\n return Result.fail(new ApiKeyPersistenceError(error));\n }\n }\n\n async create(apiKey: ApiKey): Promise<Result<void, RepositoryAbstraction.Error>> {\n try {\n // Check if an API key with the same slug already exists\n const existingKeyResult = await this.getBySlug(apiKey.slug);\n\n // If we found a key, it's a duplicate slug - return validation error\n if (existingKeyResult.isOk()) {\n return Result.fail(\n new ApiKeyValidationError(`API key with slug \"${apiKey.slug}\" already exists.`)\n );\n }\n\n // \"NotFound\" error is ok. Everything else is not ok.\n if (existingKeyResult.error.code !== \"ApiKey/NotFound\") {\n return Result.fail(existingKeyResult.error);\n }\n\n // Slug is unique, proceed with creation\n const tenant = this.tenantContext.getTenant();\n await this.storageOperations.createApiKey({ apiKey: { ...apiKey, tenant: tenant.id } });\n return Result.ok();\n } catch (error) {\n return Result.fail(new ApiKeyPersistenceError(error));\n }\n }\n\n async update(apiKey: ApiKey): Promise<Result<void, RepositoryAbstraction.Error>> {\n try {\n const tenant = this.tenantContext.getTenant();\n await this.storageOperations.updateApiKey({ apiKey: { ...apiKey, tenant: tenant.id } });\n\n return Result.ok();\n } catch (error) {\n return Result.fail(new ApiKeyPersistenceError(error));\n }\n }\n\n async delete(apiKey: ApiKey): Promise<Result<void, RepositoryAbstraction.Error>> {\n try {\n const tenant = this.tenantContext.getTenant();\n await this.storageOperations.deleteApiKey({ apiKey: { ...apiKey, tenant: tenant.id } });\n\n return Result.ok();\n } catch (error) {\n return Result.fail(new ApiKeyPersistenceError(error));\n }\n }\n}\n\nexport const ApiKeysRepository = createImplementation({\n abstraction: RepositoryAbstraction,\n implementation: ApiKeysRepositoryImpl,\n dependencies: [TenantContext, SecurityStorageOperations, ApiKeyProvider]\n});\n"],"names":["ApiKeysRepositoryImpl","tenantContext","storageOperations","apiKeyProvider","id","tenant","apiKey","Result","ApiKeyNotFoundError","error","token","factoryApiKey","ApiKeyPersistenceError","slug","params","result","existingKeyResult","ApiKeyValidationError","ApiKeysRepository","createImplementation","RepositoryAbstraction","TenantContext","SecurityStorageOperations","ApiKeyProvider"],"mappings":"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"}
@@ -4,4 +4,4 @@
4
4
  * When authentication plugins kick in, they will be able to tell if they should handle
5
5
  * the token by checking the first letter.
6
6
  */
7
- export declare const generateToken: (tokenLength?: number) => string;
7
+ export declare const generateToken: (tokenLength?: number) => `wat_${string}`;
@@ -1 +1 @@
1
- {"version":3,"file":"features/security/apiKeys/shared/generateToken.js","sources":["../../../../../src/features/security/apiKeys/shared/generateToken.ts"],"sourcesContent":["import crypto from \"crypto\";\n\n/**\n * Generates a random token for API keys.\n * API Keys are prefixed with letter \"wat_\" to make token verification easier.\n * When authentication plugins kick in, they will be able to tell if they should handle\n * the token by checking the first letter.\n */\nexport const generateToken = (tokenLength = 40): string => {\n const token = crypto.randomBytes(Math.ceil(tokenLength / 2)).toString(\"hex\");\n\n // API Keys are prefixed with letters \"wat_\" to make token verification easier\n if (token.startsWith(\"wat_\")) {\n return token;\n }\n\n return `wat_${token.slice(0, tokenLength - 4)}`;\n};\n"],"names":["generateToken","tokenLength","token","crypto","Math"],"mappings":";AAQO,MAAMA,gBAAgB,CAACC,cAAc,EAAE;IAC1C,MAAMC,QAAQC,SAAAA,WAAkB,CAACC,KAAK,IAAI,CAACH,cAAc,IAAI,QAAQ,CAAC;IAGtE,IAAIC,MAAM,UAAU,CAAC,SACjB,OAAOA;IAGX,OAAO,CAAC,IAAI,EAAEA,MAAM,KAAK,CAAC,GAAGD,cAAc,IAAI;AACnD"}
1
+ {"version":3,"file":"features/security/apiKeys/shared/generateToken.js","sources":["../../../../../src/features/security/apiKeys/shared/generateToken.ts"],"sourcesContent":["import crypto from \"crypto\";\n\n/**\n * Generates a random token for API keys.\n * API Keys are prefixed with letter \"wat_\" to make token verification easier.\n * When authentication plugins kick in, they will be able to tell if they should handle\n * the token by checking the first letter.\n */\nexport const generateToken = (tokenLength = 40): `wat_${string}` => {\n const token = crypto.randomBytes(Math.ceil(tokenLength / 2)).toString(\"hex\");\n\n // API Keys are prefixed with letters \"wat_\" to make token verification easier\n if (token.startsWith(\"wat_\")) {\n return token as `wat_${string}`;\n }\n\n return `wat_${token.slice(0, tokenLength - 4)}`;\n};\n"],"names":["generateToken","tokenLength","token","crypto","Math"],"mappings":";AAQO,MAAMA,gBAAgB,CAACC,cAAc,EAAE;IAC1C,MAAMC,QAAQC,SAAAA,WAAkB,CAACC,KAAK,IAAI,CAACH,cAAc,IAAI,QAAQ,CAAC;IAGtE,IAAIC,MAAM,UAAU,CAAC,SACjB,OAAOA;IAGX,OAAO,CAAC,IAAI,EAAEA,MAAM,KAAK,CAAC,GAAGD,cAAc,IAAI;AACnD"}
@@ -2,14 +2,14 @@ import { z } from "zod";
2
2
  export declare const createApiKeyInputSchema: z.ZodObject<{
3
3
  name: z.ZodString;
4
4
  slug: z.ZodString;
5
- description: z.ZodString;
5
+ description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
6
6
  permissions: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodObject<{
7
7
  name: z.ZodString;
8
8
  }, z.core.$loose>>>>;
9
9
  }, z.core.$strip>;
10
10
  export declare const updateApiKeyInputSchema: z.ZodObject<{
11
11
  name: z.ZodOptional<z.ZodString>;
12
- description: z.ZodOptional<z.ZodString>;
12
+ description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
13
13
  permissions: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodObject<{
14
14
  name: z.ZodString;
15
15
  }, z.core.$loose>>>>;
@@ -2,14 +2,14 @@ import { z } from "zod";
2
2
  const createApiKeyInputSchema = z.object({
3
3
  name: z.string().min(1),
4
4
  slug: z.string().min(1),
5
- description: z.string(),
5
+ description: z.string().max(500).nullish(),
6
6
  permissions: z.array(z.looseObject({
7
7
  name: z.string()
8
8
  })).optional().default([])
9
9
  });
10
10
  const updateApiKeyInputSchema = z.object({
11
11
  name: z.string().min(1).optional(),
12
- description: z.string().optional(),
12
+ description: z.string().max(500).nullish(),
13
13
  permissions: z.array(z.looseObject({
14
14
  name: z.string()
15
15
  })).optional().default([])
@@ -1 +1 @@
1
- {"version":3,"file":"features/security/apiKeys/shared/schemas.js","sources":["../../../../../src/features/security/apiKeys/shared/schemas.ts"],"sourcesContent":["import { z } from \"zod\";\n\nexport const createApiKeyInputSchema = z.object({\n name: z.string().min(1),\n slug: z.string().min(1),\n description: z.string(),\n permissions: z\n .array(z.looseObject({ name: z.string() }))\n .optional()\n .default([])\n});\n\nexport const updateApiKeyInputSchema = z.object({\n name: z.string().min(1).optional(),\n description: z.string().optional(),\n permissions: z\n .array(z.looseObject({ name: z.string() }))\n .optional()\n .default([])\n});\n\nexport const listApiKeysInputSchema = z.object({\n where: z\n .object({\n name: z.string().optional(),\n name_contains: z.string().optional(),\n description: z.string().optional(),\n description_contains: z.string().optional()\n })\n .optional(),\n limit: z.number().int().positive().max(100).optional(),\n after: z.string().optional(),\n sort: z.array(z.enum([\"createdOn_ASC\", \"createdOn_DESC\"])).optional()\n});\n"],"names":["createApiKeyInputSchema","z","updateApiKeyInputSchema","listApiKeysInputSchema"],"mappings":";AAEO,MAAMA,0BAA0BC,EAAE,MAAM,CAAC;IAC5C,MAAMA,EAAE,MAAM,GAAG,GAAG,CAAC;IACrB,MAAMA,EAAE,MAAM,GAAG,GAAG,CAAC;IACrB,aAAaA,EAAE,MAAM;IACrB,aAAaA,EAAAA,KACH,CAACA,EAAE,WAAW,CAAC;QAAE,MAAMA,EAAE,MAAM;IAAG,IACvC,QAAQ,GACR,OAAO,CAAC,EAAE;AACnB;AAEO,MAAMC,0BAA0BD,EAAE,MAAM,CAAC;IAC5C,MAAMA,EAAE,MAAM,GAAG,GAAG,CAAC,GAAG,QAAQ;IAChC,aAAaA,EAAE,MAAM,GAAG,QAAQ;IAChC,aAAaA,EAAAA,KACH,CAACA,EAAE,WAAW,CAAC;QAAE,MAAMA,EAAE,MAAM;IAAG,IACvC,QAAQ,GACR,OAAO,CAAC,EAAE;AACnB;AAEO,MAAME,yBAAyBF,EAAE,MAAM,CAAC;IAC3C,OAAOA,EAAAA,MACI,CAAC;QACJ,MAAMA,EAAE,MAAM,GAAG,QAAQ;QACzB,eAAeA,EAAE,MAAM,GAAG,QAAQ;QAClC,aAAaA,EAAE,MAAM,GAAG,QAAQ;QAChC,sBAAsBA,EAAE,MAAM,GAAG,QAAQ;IAC7C,GACC,QAAQ;IACb,OAAOA,EAAE,MAAM,GAAG,GAAG,GAAG,QAAQ,GAAG,GAAG,CAAC,KAAK,QAAQ;IACpD,OAAOA,EAAE,MAAM,GAAG,QAAQ;IAC1B,MAAMA,EAAE,KAAK,CAACA,CAAC,CAADA,OAAM,CAAC;QAAC;QAAiB;KAAiB,GAAG,QAAQ;AACvE"}
1
+ {"version":3,"file":"features/security/apiKeys/shared/schemas.js","sources":["../../../../../src/features/security/apiKeys/shared/schemas.ts"],"sourcesContent":["import { z } from \"zod\";\n\nexport const createApiKeyInputSchema = z.object({\n name: z.string().min(1),\n slug: z.string().min(1),\n // Nullable in the GraphQL schema - see `descriptionOnCreate` for why this is `.nullish()`.\n // This was a bare `z.string()`, so an API key created without a description was rejected\n // whether the client sent null or omitted the field entirely. `max` matches teams and roles.\n description: z.string().max(500).nullish(),\n permissions: z\n .array(z.looseObject({ name: z.string() }))\n .optional()\n .default([])\n});\n\nexport const updateApiKeyInputSchema = z.object({\n name: z.string().min(1).optional(),\n // Nullable in the GraphQL schema - see `descriptionOnUpdate` for why this is `.nullish()` and\n // must not carry a `.transform()`. `max` matches teams and roles.\n description: z.string().max(500).nullish(),\n permissions: z\n .array(z.looseObject({ name: z.string() }))\n .optional()\n .default([])\n});\n\nexport const listApiKeysInputSchema = z.object({\n where: z\n .object({\n name: z.string().optional(),\n name_contains: z.string().optional(),\n description: z.string().optional(),\n description_contains: z.string().optional()\n })\n .optional(),\n limit: z.number().int().positive().max(100).optional(),\n after: z.string().optional(),\n sort: z.array(z.enum([\"createdOn_ASC\", \"createdOn_DESC\"])).optional()\n});\n"],"names":["createApiKeyInputSchema","z","updateApiKeyInputSchema","listApiKeysInputSchema"],"mappings":";AAEO,MAAMA,0BAA0BC,EAAE,MAAM,CAAC;IAC5C,MAAMA,EAAE,MAAM,GAAG,GAAG,CAAC;IACrB,MAAMA,EAAE,MAAM,GAAG,GAAG,CAAC;IAIrB,aAAaA,EAAE,MAAM,GAAG,GAAG,CAAC,KAAK,OAAO;IACxC,aAAaA,EAAAA,KACH,CAACA,EAAE,WAAW,CAAC;QAAE,MAAMA,EAAE,MAAM;IAAG,IACvC,QAAQ,GACR,OAAO,CAAC,EAAE;AACnB;AAEO,MAAMC,0BAA0BD,EAAE,MAAM,CAAC;IAC5C,MAAMA,EAAE,MAAM,GAAG,GAAG,CAAC,GAAG,QAAQ;IAGhC,aAAaA,EAAE,MAAM,GAAG,GAAG,CAAC,KAAK,OAAO;IACxC,aAAaA,EAAAA,KACH,CAACA,EAAE,WAAW,CAAC;QAAE,MAAMA,EAAE,MAAM;IAAG,IACvC,QAAQ,GACR,OAAO,CAAC,EAAE;AACnB;AAEO,MAAME,yBAAyBF,EAAE,MAAM,CAAC;IAC3C,OAAOA,EAAAA,MACI,CAAC;QACJ,MAAMA,EAAE,MAAM,GAAG,QAAQ;QACzB,eAAeA,EAAE,MAAM,GAAG,QAAQ;QAClC,aAAaA,EAAE,MAAM,GAAG,QAAQ;QAChC,sBAAsBA,EAAE,MAAM,GAAG,QAAQ;IAC7C,GACC,QAAQ;IACb,OAAOA,EAAE,MAAM,GAAG,GAAG,GAAG,QAAQ,GAAG,GAAG,CAAC,KAAK,QAAQ;IACpD,OAAOA,EAAE,MAAM,GAAG,QAAQ;IAC1B,MAAMA,EAAE,KAAK,CAACA,CAAC,CAADA,OAAM,CAAC;QAAC;QAAiB;KAAiB,GAAG,QAAQ;AACvE"}
@@ -4,7 +4,7 @@ export interface ApiKey {
4
4
  name: string;
5
5
  slug: string;
6
6
  description: string;
7
- token: string;
7
+ token: `wat_${string}`;
8
8
  permissions: SecurityPermission[];
9
9
  createdBy: CreatedBy;
10
10
  createdOn: string;
@@ -1,4 +1,4 @@
1
- import { WcpContext } from "../../../../features/wcp/WcpContext/index.js";
1
+ import { FeatureFlags } from "../../../../features/featureFlags/abstractions.js";
2
2
  import { Identity } from "../../../../features/security/IdentityContext/index.js";
3
3
  import { PermissionsProcessor } from "./abstractions.js";
4
4
  import { RolesRepository } from "../../../../features/security/roles/shared/abstractions.js";
@@ -7,11 +7,11 @@ import { AdminUsersRepository } from "../../../../features/users/shared/abstract
7
7
  export type RoleId = string | undefined;
8
8
  export type TeamId = string | undefined;
9
9
  declare class GetPermissionsFromGroupsAndTeamsImpl implements PermissionsProcessor.Interface {
10
- private wcpContext;
10
+ private featureFlags;
11
11
  private usersRepository;
12
12
  private rolesRepository;
13
13
  private teamsRepository;
14
- constructor(wcpContext: WcpContext.Interface, usersRepository: AdminUsersRepository.Interface, rolesRepository: RolesRepository.Interface, teamsRepository: TeamsRepository.Interface);
14
+ constructor(featureFlags: FeatureFlags.Interface, usersRepository: AdminUsersRepository.Interface, rolesRepository: RolesRepository.Interface, teamsRepository: TeamsRepository.Interface);
15
15
  getPermissions(identity: Identity): Promise<{
16
16
  name: string;
17
17
  _src: string;
@@ -1,12 +1,12 @@
1
- import { WcpContext } from "../../../wcp/WcpContext/index.js";
1
+ import { FeatureFlags } from "../../../featureFlags/abstractions.js";
2
2
  import { PermissionsProcessor } from "./abstractions.js";
3
3
  import { RolesRepository } from "../../roles/shared/abstractions.js";
4
4
  import { TeamsRepository } from "../../teams/shared/abstractions.js";
5
5
  import { getPermissionsFromRoles } from "../../utils/getPermissionsFromRoles.js";
6
6
  import { AdminUsersRepository } from "../../../users/shared/abstractions.js";
7
7
  class GetPermissionsFromGroupsAndTeamsImpl {
8
- constructor(wcpContext, usersRepository, rolesRepository, teamsRepository){
9
- this.wcpContext = wcpContext;
8
+ constructor(featureFlags, usersRepository, rolesRepository, teamsRepository){
9
+ this.featureFlags = featureFlags;
10
10
  this.usersRepository = usersRepository;
11
11
  this.rolesRepository = rolesRepository;
12
12
  this.teamsRepository = teamsRepository;
@@ -32,7 +32,7 @@ class GetPermissionsFromGroupsAndTeamsImpl {
32
32
  const loadedRolesByIds = rolesResult.isOk() ? rolesResult.value : [];
33
33
  loadedRoles.push(...loadedRolesByIds);
34
34
  }
35
- if (this.wcpContext.canUseTeams()) {
35
+ if (this.featureFlags.get().isEnabled("advancedAccessControlLayer.teams")) {
36
36
  teamIds.push(...user.teams ?? []);
37
37
  const filteredTeamIds = teamIds.filter(Boolean);
38
38
  const dedupedTeamIds = Array.from(new Set(filteredTeamIds));
@@ -65,7 +65,7 @@ class GetPermissionsFromGroupsAndTeamsImpl {
65
65
  const GetPermissionsFromIdentity = PermissionsProcessor.createImplementation({
66
66
  implementation: GetPermissionsFromGroupsAndTeamsImpl,
67
67
  dependencies: [
68
- WcpContext,
68
+ FeatureFlags,
69
69
  AdminUsersRepository,
70
70
  RolesRepository,
71
71
  TeamsRepository
@@ -1 +1 @@
1
- {"version":3,"file":"features/security/authorization/GroupsTeamsAuthorizer/GetPermissionsFromIdentity.js","sources":["../../../../../src/features/security/authorization/GroupsTeamsAuthorizer/GetPermissionsFromIdentity.ts"],"sourcesContent":["import { WcpContext } from \"~/features/wcp/WcpContext/index.js\";\nimport type { SecurityRole } from \"~/types/security.js\";\nimport { Identity } from \"~/features/security/IdentityContext/index.js\";\nimport { PermissionsProcessor } from \"./abstractions.js\";\nimport { RolesRepository } from \"~/features/security/roles/shared/abstractions.js\";\nimport { TeamsRepository } from \"~/features/security/teams/shared/abstractions.js\";\nimport { getPermissionsFromRoles } from \"~/features/security/utils/getPermissionsFromRoles.js\";\nimport { AdminUsersRepository } from \"~/features/users/shared/abstractions.js\";\n\nexport type RoleId = string | undefined;\nexport type TeamId = string | undefined;\n\nclass GetPermissionsFromGroupsAndTeamsImpl implements PermissionsProcessor.Interface {\n constructor(\n private wcpContext: WcpContext.Interface,\n private usersRepository: AdminUsersRepository.Interface,\n private rolesRepository: RolesRepository.Interface,\n private teamsRepository: TeamsRepository.Interface\n ) {}\n\n async getPermissions(identity: Identity) {\n const userResult = await this.usersRepository.get({ id: identity.id });\n if (userResult.isFail()) {\n return null;\n }\n\n const user = userResult.value;\n\n // Load roles that are associated with the current identity. Also load roles\n // that are assigned via one or more teams (if the Teams feature is enabled).\n const roleIds: RoleId[] = [];\n const teamIds: TeamId[] = [];\n\n roleIds.push(...(user.roles ?? []));\n\n const filteredRoleIds = roleIds.filter(Boolean) as string[];\n const dedupedRoleIds = Array.from(new Set(filteredRoleIds));\n\n const loadedRoles: SecurityRole[] = [];\n\n if (dedupedRoleIds.length > 0) {\n const rolesResult = await this.rolesRepository.list({\n where: { id_in: dedupedRoleIds }\n });\n\n const loadedRolesByIds = rolesResult.isOk() ? rolesResult.value : [];\n loadedRoles.push(...loadedRolesByIds);\n }\n\n if (this.wcpContext.canUseTeams()) {\n teamIds.push(...(user.teams ?? []));\n\n const filteredTeamIds = teamIds.filter(Boolean) as string[];\n const dedupedTeamIds = Array.from(new Set(filteredTeamIds));\n\n if (dedupedTeamIds.length > 0) {\n const teamsResult = await this.teamsRepository.list({\n where: { id_in: dedupedTeamIds }\n });\n\n const loadedTeams = teamsResult.isOk() ? teamsResult.value : [];\n\n // Upon returning teams, we're filtering out team roles that were already loaded.\n // Also note that `team.roles` contains role IDs, not slugs.\n const roleIdsFromTeams = loadedTeams\n .flatMap(team => team.roles)\n .filter(roleId => {\n const alreadyLoaded = loadedRoles.find(role => role.id === roleId);\n return !alreadyLoaded;\n });\n\n if (roleIdsFromTeams.length > 0) {\n const moreRolesResult = await this.rolesRepository.list({\n where: { id_in: roleIdsFromTeams }\n });\n\n const rolesFromTeams = moreRolesResult.isOk() ? moreRolesResult.value : [];\n loadedRoles.push(...rolesFromTeams);\n }\n }\n }\n\n if (loadedRoles.length > 0) {\n return getPermissionsFromRoles(loadedRoles);\n }\n\n return null;\n }\n}\n\nexport const GetPermissionsFromIdentity = PermissionsProcessor.createImplementation({\n implementation: GetPermissionsFromGroupsAndTeamsImpl,\n dependencies: [WcpContext, AdminUsersRepository, RolesRepository, TeamsRepository]\n});\n"],"names":["GetPermissionsFromGroupsAndTeamsImpl","wcpContext","usersRepository","rolesRepository","teamsRepository","identity","userResult","user","roleIds","teamIds","filteredRoleIds","Boolean","dedupedRoleIds","Array","Set","loadedRoles","rolesResult","loadedRolesByIds","filteredTeamIds","dedupedTeamIds","teamsResult","loadedTeams","roleIdsFromTeams","team","roleId","alreadyLoaded","role","moreRolesResult","rolesFromTeams","getPermissionsFromRoles","GetPermissionsFromIdentity","PermissionsProcessor","WcpContext","AdminUsersRepository","RolesRepository","TeamsRepository"],"mappings":";;;;;;AAYA,MAAMA;IACF,YACYC,UAAgC,EAChCC,eAA+C,EAC/CC,eAA0C,EAC1CC,eAA0C,CACpD;aAJUH,UAAU,GAAVA;aACAC,eAAe,GAAfA;aACAC,eAAe,GAAfA;aACAC,eAAe,GAAfA;IACT;IAEH,MAAM,eAAeC,QAAkB,EAAE;QACrC,MAAMC,aAAa,MAAM,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC;YAAE,IAAID,SAAS,EAAE;QAAC;QACpE,IAAIC,WAAW,MAAM,IACjB,OAAO;QAGX,MAAMC,OAAOD,WAAW,KAAK;QAI7B,MAAME,UAAoB,EAAE;QAC5B,MAAMC,UAAoB,EAAE;QAE5BD,QAAQ,IAAI,IAAKD,KAAK,KAAK,IAAI,EAAE;QAEjC,MAAMG,kBAAkBF,QAAQ,MAAM,CAACG;QACvC,MAAMC,iBAAiBC,MAAM,IAAI,CAAC,IAAIC,IAAIJ;QAE1C,MAAMK,cAA8B,EAAE;QAEtC,IAAIH,eAAe,MAAM,GAAG,GAAG;YAC3B,MAAMI,cAAc,MAAM,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC;gBAChD,OAAO;oBAAE,OAAOJ;gBAAe;YACnC;YAEA,MAAMK,mBAAmBD,YAAY,IAAI,KAAKA,YAAY,KAAK,GAAG,EAAE;YACpED,YAAY,IAAI,IAAIE;QACxB;QAEA,IAAI,IAAI,CAAC,UAAU,CAAC,WAAW,IAAI;YAC/BR,QAAQ,IAAI,IAAKF,KAAK,KAAK,IAAI,EAAE;YAEjC,MAAMW,kBAAkBT,QAAQ,MAAM,CAACE;YACvC,MAAMQ,iBAAiBN,MAAM,IAAI,CAAC,IAAIC,IAAII;YAE1C,IAAIC,eAAe,MAAM,GAAG,GAAG;gBAC3B,MAAMC,cAAc,MAAM,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC;oBAChD,OAAO;wBAAE,OAAOD;oBAAe;gBACnC;gBAEA,MAAME,cAAcD,YAAY,IAAI,KAAKA,YAAY,KAAK,GAAG,EAAE;gBAI/D,MAAME,mBAAmBD,YACpB,OAAO,CAACE,CAAAA,OAAQA,KAAK,KAAK,EAC1B,MAAM,CAACC,CAAAA;oBACJ,MAAMC,gBAAgBV,YAAY,IAAI,CAACW,CAAAA,OAAQA,KAAK,EAAE,KAAKF;oBAC3D,OAAO,CAACC;gBACZ;gBAEJ,IAAIH,iBAAiB,MAAM,GAAG,GAAG;oBAC7B,MAAMK,kBAAkB,MAAM,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC;wBACpD,OAAO;4BAAE,OAAOL;wBAAiB;oBACrC;oBAEA,MAAMM,iBAAiBD,gBAAgB,IAAI,KAAKA,gBAAgB,KAAK,GAAG,EAAE;oBAC1EZ,YAAY,IAAI,IAAIa;gBACxB;YACJ;QACJ;QAEA,IAAIb,YAAY,MAAM,GAAG,GACrB,OAAOc,wBAAwBd;QAGnC,OAAO;IACX;AACJ;AAEO,MAAMe,6BAA6BC,qBAAqB,oBAAoB,CAAC;IAChF,gBAAgB/B;IAChB,cAAc;QAACgC;QAAYC;QAAsBC;QAAiBC;KAAgB;AACtF"}
1
+ {"version":3,"file":"features/security/authorization/GroupsTeamsAuthorizer/GetPermissionsFromIdentity.js","sources":["../../../../../src/features/security/authorization/GroupsTeamsAuthorizer/GetPermissionsFromIdentity.ts"],"sourcesContent":["import { FeatureFlags } from \"~/features/featureFlags/abstractions.js\";\nimport type { SecurityRole } from \"~/types/security.js\";\nimport { Identity } from \"~/features/security/IdentityContext/index.js\";\nimport { PermissionsProcessor } from \"./abstractions.js\";\nimport { RolesRepository } from \"~/features/security/roles/shared/abstractions.js\";\nimport { TeamsRepository } from \"~/features/security/teams/shared/abstractions.js\";\nimport { getPermissionsFromRoles } from \"~/features/security/utils/getPermissionsFromRoles.js\";\nimport { AdminUsersRepository } from \"~/features/users/shared/abstractions.js\";\n\nexport type RoleId = string | undefined;\nexport type TeamId = string | undefined;\n\nclass GetPermissionsFromGroupsAndTeamsImpl implements PermissionsProcessor.Interface {\n constructor(\n private featureFlags: FeatureFlags.Interface,\n private usersRepository: AdminUsersRepository.Interface,\n private rolesRepository: RolesRepository.Interface,\n private teamsRepository: TeamsRepository.Interface\n ) {}\n\n async getPermissions(identity: Identity) {\n const userResult = await this.usersRepository.get({ id: identity.id });\n if (userResult.isFail()) {\n return null;\n }\n\n const user = userResult.value;\n\n // Load roles that are associated with the current identity. Also load roles\n // that are assigned via one or more teams (if the Teams feature is enabled).\n const roleIds: RoleId[] = [];\n const teamIds: TeamId[] = [];\n\n roleIds.push(...(user.roles ?? []));\n\n const filteredRoleIds = roleIds.filter(Boolean) as string[];\n const dedupedRoleIds = Array.from(new Set(filteredRoleIds));\n\n const loadedRoles: SecurityRole[] = [];\n\n if (dedupedRoleIds.length > 0) {\n const rolesResult = await this.rolesRepository.list({\n where: { id_in: dedupedRoleIds }\n });\n\n const loadedRolesByIds = rolesResult.isOk() ? rolesResult.value : [];\n loadedRoles.push(...loadedRolesByIds);\n }\n\n if (this.featureFlags.get().isEnabled(\"advancedAccessControlLayer.teams\")) {\n teamIds.push(...(user.teams ?? []));\n\n const filteredTeamIds = teamIds.filter(Boolean) as string[];\n const dedupedTeamIds = Array.from(new Set(filteredTeamIds));\n\n if (dedupedTeamIds.length > 0) {\n const teamsResult = await this.teamsRepository.list({\n where: { id_in: dedupedTeamIds }\n });\n\n const loadedTeams = teamsResult.isOk() ? teamsResult.value : [];\n\n // Upon returning teams, we're filtering out team roles that were already loaded.\n // Also note that `team.roles` contains role IDs, not slugs.\n const roleIdsFromTeams = loadedTeams\n .flatMap(team => team.roles)\n .filter(roleId => {\n const alreadyLoaded = loadedRoles.find(role => role.id === roleId);\n return !alreadyLoaded;\n });\n\n if (roleIdsFromTeams.length > 0) {\n const moreRolesResult = await this.rolesRepository.list({\n where: { id_in: roleIdsFromTeams }\n });\n\n const rolesFromTeams = moreRolesResult.isOk() ? moreRolesResult.value : [];\n loadedRoles.push(...rolesFromTeams);\n }\n }\n }\n\n if (loadedRoles.length > 0) {\n return getPermissionsFromRoles(loadedRoles);\n }\n\n return null;\n }\n}\n\nexport const GetPermissionsFromIdentity = PermissionsProcessor.createImplementation({\n implementation: GetPermissionsFromGroupsAndTeamsImpl,\n dependencies: [FeatureFlags, AdminUsersRepository, RolesRepository, TeamsRepository]\n});\n"],"names":["GetPermissionsFromGroupsAndTeamsImpl","featureFlags","usersRepository","rolesRepository","teamsRepository","identity","userResult","user","roleIds","teamIds","filteredRoleIds","Boolean","dedupedRoleIds","Array","Set","loadedRoles","rolesResult","loadedRolesByIds","filteredTeamIds","dedupedTeamIds","teamsResult","loadedTeams","roleIdsFromTeams","team","roleId","alreadyLoaded","role","moreRolesResult","rolesFromTeams","getPermissionsFromRoles","GetPermissionsFromIdentity","PermissionsProcessor","FeatureFlags","AdminUsersRepository","RolesRepository","TeamsRepository"],"mappings":";;;;;;AAYA,MAAMA;IACF,YACYC,YAAoC,EACpCC,eAA+C,EAC/CC,eAA0C,EAC1CC,eAA0C,CACpD;aAJUH,YAAY,GAAZA;aACAC,eAAe,GAAfA;aACAC,eAAe,GAAfA;aACAC,eAAe,GAAfA;IACT;IAEH,MAAM,eAAeC,QAAkB,EAAE;QACrC,MAAMC,aAAa,MAAM,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC;YAAE,IAAID,SAAS,EAAE;QAAC;QACpE,IAAIC,WAAW,MAAM,IACjB,OAAO;QAGX,MAAMC,OAAOD,WAAW,KAAK;QAI7B,MAAME,UAAoB,EAAE;QAC5B,MAAMC,UAAoB,EAAE;QAE5BD,QAAQ,IAAI,IAAKD,KAAK,KAAK,IAAI,EAAE;QAEjC,MAAMG,kBAAkBF,QAAQ,MAAM,CAACG;QACvC,MAAMC,iBAAiBC,MAAM,IAAI,CAAC,IAAIC,IAAIJ;QAE1C,MAAMK,cAA8B,EAAE;QAEtC,IAAIH,eAAe,MAAM,GAAG,GAAG;YAC3B,MAAMI,cAAc,MAAM,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC;gBAChD,OAAO;oBAAE,OAAOJ;gBAAe;YACnC;YAEA,MAAMK,mBAAmBD,YAAY,IAAI,KAAKA,YAAY,KAAK,GAAG,EAAE;YACpED,YAAY,IAAI,IAAIE;QACxB;QAEA,IAAI,IAAI,CAAC,YAAY,CAAC,GAAG,GAAG,SAAS,CAAC,qCAAqC;YACvER,QAAQ,IAAI,IAAKF,KAAK,KAAK,IAAI,EAAE;YAEjC,MAAMW,kBAAkBT,QAAQ,MAAM,CAACE;YACvC,MAAMQ,iBAAiBN,MAAM,IAAI,CAAC,IAAIC,IAAII;YAE1C,IAAIC,eAAe,MAAM,GAAG,GAAG;gBAC3B,MAAMC,cAAc,MAAM,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC;oBAChD,OAAO;wBAAE,OAAOD;oBAAe;gBACnC;gBAEA,MAAME,cAAcD,YAAY,IAAI,KAAKA,YAAY,KAAK,GAAG,EAAE;gBAI/D,MAAME,mBAAmBD,YACpB,OAAO,CAACE,CAAAA,OAAQA,KAAK,KAAK,EAC1B,MAAM,CAACC,CAAAA;oBACJ,MAAMC,gBAAgBV,YAAY,IAAI,CAACW,CAAAA,OAAQA,KAAK,EAAE,KAAKF;oBAC3D,OAAO,CAACC;gBACZ;gBAEJ,IAAIH,iBAAiB,MAAM,GAAG,GAAG;oBAC7B,MAAMK,kBAAkB,MAAM,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC;wBACpD,OAAO;4BAAE,OAAOL;wBAAiB;oBACrC;oBAEA,MAAMM,iBAAiBD,gBAAgB,IAAI,KAAKA,gBAAgB,KAAK,GAAG,EAAE;oBAC1EZ,YAAY,IAAI,IAAIa;gBACxB;YACJ;QACJ;QAEA,IAAIb,YAAY,MAAM,GAAG,GACrB,OAAOc,wBAAwBd;QAGnC,OAAO;IACX;AACJ;AAEO,MAAMe,6BAA6BC,qBAAqB,oBAAoB,CAAC;IAChF,gBAAgB/B;IAChB,cAAc;QAACgC;QAAcC;QAAsBC;QAAiBC;KAAgB;AACxF"}
@@ -7,6 +7,7 @@ import { IdentityContext } from "../../IdentityContext/abstractions.js";
7
7
  import { createRoleValidation } from "./schema.js";
8
8
  import { RoleAfterCreateEvent, RoleBeforeCreateEvent } from "./events.js";
9
9
  import { NotAuthorizedError, RoleExistsError, RoleValidationError } from "../shared/errors.js";
10
+ import { descriptionOnCreate } from "../../shared/description.js";
10
11
  class CreateRoleUseCaseImpl {
11
12
  constructor(identityContext, eventPublisher, repository){
12
13
  this.identityContext = identityContext;
@@ -24,12 +25,16 @@ class CreateRoleUseCaseImpl {
24
25
  slug: data.slug
25
26
  });
26
27
  if (existingRoleResult.isOk()) return Result.fail(new RoleExistsError(data.slug));
28
+ const createInput = {
29
+ ...data,
30
+ description: descriptionOnCreate(data.description)
31
+ };
27
32
  const role = {
28
33
  id: mdbid(),
29
- name: data.name,
30
- slug: data.slug,
31
- description: data.description,
32
- permissions: data.permissions,
34
+ name: createInput.name,
35
+ slug: createInput.slug,
36
+ description: descriptionOnCreate(createInput.description),
37
+ permissions: createInput.permissions,
33
38
  system: input.system || false,
34
39
  createdOn: new Date().toISOString(),
35
40
  createdBy: {
@@ -41,13 +46,13 @@ class CreateRoleUseCaseImpl {
41
46
  };
42
47
  await this.eventPublisher.publish(new RoleBeforeCreateEvent({
43
48
  role,
44
- input: validation.data
49
+ input: createInput
45
50
  }));
46
51
  const result = await this.repository.create(role);
47
52
  if (result.isFail()) return Result.fail(result.error);
48
53
  await this.eventPublisher.publish(new RoleAfterCreateEvent({
49
54
  role,
50
- input: validation.data
55
+ input: createInput
51
56
  }));
52
57
  return Result.ok(role);
53
58
  }
@@ -1 +1 @@
1
- {"version":3,"file":"features/security/roles/CreateRole/CreateRoleUseCase.js","sources":["../../../../../src/features/security/roles/CreateRole/CreateRoleUseCase.ts"],"sourcesContent":["import { mdbid } from \"@webiny/utils\";\nimport { createImplementation } from \"@webiny/feature/api\";\nimport { Result } from \"@webiny/feature/api\";\nimport { EventPublisher } from \"~/features/eventPublisher/index.js\";\nimport { CreateRoleUseCase as UseCaseAbstraction } from \"./abstractions.js\";\nimport { RolesRepository } from \"../shared/abstractions.js\";\nimport { IdentityContext } from \"../../IdentityContext/abstractions.js\";\nimport { createRoleValidation } from \"./schema.js\";\nimport { RoleBeforeCreateEvent, RoleAfterCreateEvent } from \"./events.js\";\nimport type { Role, CreateRoleInput } from \"../shared/types.js\";\nimport { NotAuthorizedError, RoleExistsError, RoleValidationError } from \"../shared/errors.js\";\n\nclass CreateRoleUseCaseImpl implements UseCaseAbstraction.Interface {\n constructor(\n private identityContext: IdentityContext.Interface,\n private eventPublisher: EventPublisher.Interface,\n private repository: RolesRepository.Interface\n ) {}\n\n async execute(input: CreateRoleInput): Promise<Result<Role, UseCaseAbstraction.Error>> {\n const hasPermission = await this.identityContext.getPermission(\"security.role\");\n\n if (!hasPermission) {\n return Result.fail(new NotAuthorizedError());\n }\n\n const validation = createRoleValidation.safeParse(input);\n if (!validation.success) {\n return Result.fail(new RoleValidationError(validation.error.issues[0].message));\n }\n\n const identity = this.identityContext.getIdentity();\n const data = validation.data;\n\n // Check if role with same slug already exists\n const existingRoleResult = await this.repository.get({ slug: data.slug });\n if (existingRoleResult.isOk()) {\n return Result.fail(new RoleExistsError(data.slug));\n }\n\n const role: Role = {\n id: mdbid(),\n name: data.name,\n slug: data.slug,\n description: data.description,\n permissions: data.permissions,\n system: input.system || false,\n createdOn: new Date().toISOString(),\n createdBy: {\n id: identity.id,\n displayName: identity.displayName,\n type: identity.type\n },\n plugin: false\n };\n\n await this.eventPublisher.publish(\n new RoleBeforeCreateEvent({ role, input: validation.data })\n );\n\n const result = await this.repository.create(role);\n\n if (result.isFail()) {\n return Result.fail(result.error);\n }\n\n await this.eventPublisher.publish(\n new RoleAfterCreateEvent({ role, input: validation.data })\n );\n\n return Result.ok(role);\n }\n}\n\nexport const CreateRoleUseCase = createImplementation({\n abstraction: UseCaseAbstraction,\n implementation: CreateRoleUseCaseImpl,\n dependencies: [IdentityContext, EventPublisher, RolesRepository]\n});\n"],"names":["CreateRoleUseCaseImpl","identityContext","eventPublisher","repository","input","hasPermission","Result","NotAuthorizedError","validation","createRoleValidation","RoleValidationError","identity","data","existingRoleResult","RoleExistsError","role","mdbid","Date","RoleBeforeCreateEvent","result","RoleAfterCreateEvent","CreateRoleUseCase","createImplementation","UseCaseAbstraction","IdentityContext","EventPublisher","RolesRepository"],"mappings":";;;;;;;;;AAYA,MAAMA;IACF,YACYC,eAA0C,EAC1CC,cAAwC,EACxCC,UAAqC,CAC/C;aAHUF,eAAe,GAAfA;aACAC,cAAc,GAAdA;aACAC,UAAU,GAAVA;IACT;IAEH,MAAM,QAAQC,KAAsB,EAAmD;QACnF,MAAMC,gBAAgB,MAAM,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC;QAE/D,IAAI,CAACA,eACD,OAAOC,OAAO,IAAI,CAAC,IAAIC;QAG3B,MAAMC,aAAaC,qBAAqB,SAAS,CAACL;QAClD,IAAI,CAACI,WAAW,OAAO,EACnB,OAAOF,OAAO,IAAI,CAAC,IAAII,oBAAoBF,WAAW,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO;QAGjF,MAAMG,WAAW,IAAI,CAAC,eAAe,CAAC,WAAW;QACjD,MAAMC,OAAOJ,WAAW,IAAI;QAG5B,MAAMK,qBAAqB,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,MAAMD,KAAK,IAAI;QAAC;QACvE,IAAIC,mBAAmB,IAAI,IACvB,OAAOP,OAAO,IAAI,CAAC,IAAIQ,gBAAgBF,KAAK,IAAI;QAGpD,MAAMG,OAAa;YACf,IAAIC;YACJ,MAAMJ,KAAK,IAAI;YACf,MAAMA,KAAK,IAAI;YACf,aAAaA,KAAK,WAAW;YAC7B,aAAaA,KAAK,WAAW;YAC7B,QAAQR,MAAM,MAAM,IAAI;YACxB,WAAW,IAAIa,OAAO,WAAW;YACjC,WAAW;gBACP,IAAIN,SAAS,EAAE;gBACf,aAAaA,SAAS,WAAW;gBACjC,MAAMA,SAAS,IAAI;YACvB;YACA,QAAQ;QACZ;QAEA,MAAM,IAAI,CAAC,cAAc,CAAC,OAAO,CAC7B,IAAIO,sBAAsB;YAAEH;YAAM,OAAOP,WAAW,IAAI;QAAC;QAG7D,MAAMW,SAAS,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,CAACJ;QAE5C,IAAII,OAAO,MAAM,IACb,OAAOb,OAAO,IAAI,CAACa,OAAO,KAAK;QAGnC,MAAM,IAAI,CAAC,cAAc,CAAC,OAAO,CAC7B,IAAIC,qBAAqB;YAAEL;YAAM,OAAOP,WAAW,IAAI;QAAC;QAG5D,OAAOF,OAAO,EAAE,CAACS;IACrB;AACJ;AAEO,MAAMM,sCAAoBC,qBAAqB;IAClD,aAAaC;IACb,gBAAgBvB;IAChB,cAAc;QAACwB;QAAiBC;QAAgBC;KAAgB;AACpE"}
1
+ {"version":3,"file":"features/security/roles/CreateRole/CreateRoleUseCase.js","sources":["../../../../../src/features/security/roles/CreateRole/CreateRoleUseCase.ts"],"sourcesContent":["import { mdbid } from \"@webiny/utils\";\nimport { createImplementation } from \"@webiny/feature/api\";\nimport { Result } from \"@webiny/feature/api\";\nimport { EventPublisher } from \"~/features/eventPublisher/index.js\";\nimport { CreateRoleUseCase as UseCaseAbstraction } from \"./abstractions.js\";\nimport { RolesRepository } from \"../shared/abstractions.js\";\nimport { IdentityContext } from \"../../IdentityContext/abstractions.js\";\nimport { createRoleValidation } from \"./schema.js\";\nimport { RoleBeforeCreateEvent, RoleAfterCreateEvent } from \"./events.js\";\nimport type { Role, CreateRoleInput } from \"../shared/types.js\";\nimport { NotAuthorizedError, RoleExistsError, RoleValidationError } from \"../shared/errors.js\";\nimport { descriptionOnCreate } from \"../../shared/description.js\";\n\nclass CreateRoleUseCaseImpl implements UseCaseAbstraction.Interface {\n constructor(\n private identityContext: IdentityContext.Interface,\n private eventPublisher: EventPublisher.Interface,\n private repository: RolesRepository.Interface\n ) {}\n\n async execute(input: CreateRoleInput): Promise<Result<Role, UseCaseAbstraction.Error>> {\n const hasPermission = await this.identityContext.getPermission(\"security.role\");\n\n if (!hasPermission) {\n return Result.fail(new NotAuthorizedError());\n }\n\n const validation = createRoleValidation.safeParse(input);\n if (!validation.success) {\n return Result.fail(new RoleValidationError(validation.error.issues[0].message));\n }\n\n const identity = this.identityContext.getIdentity();\n const data = validation.data;\n\n // Check if role with same slug already exists\n const existingRoleResult = await this.repository.get({ slug: data.slug });\n if (existingRoleResult.isOk()) {\n return Result.fail(new RoleExistsError(data.slug));\n }\n\n // Normalised up front so that null reaches neither the entity nor the published events.\n const createInput: CreateRoleInput = {\n ...data,\n description: descriptionOnCreate(data.description)\n };\n\n const role: Role = {\n id: mdbid(),\n name: createInput.name,\n slug: createInput.slug,\n description: descriptionOnCreate(createInput.description),\n permissions: createInput.permissions,\n system: input.system || false,\n createdOn: new Date().toISOString(),\n createdBy: {\n id: identity.id,\n displayName: identity.displayName,\n type: identity.type\n },\n plugin: false\n };\n\n await this.eventPublisher.publish(new RoleBeforeCreateEvent({ role, input: createInput }));\n\n const result = await this.repository.create(role);\n\n if (result.isFail()) {\n return Result.fail(result.error);\n }\n\n await this.eventPublisher.publish(new RoleAfterCreateEvent({ role, input: createInput }));\n\n return Result.ok(role);\n }\n}\n\nexport const CreateRoleUseCase = createImplementation({\n abstraction: UseCaseAbstraction,\n implementation: CreateRoleUseCaseImpl,\n dependencies: [IdentityContext, EventPublisher, RolesRepository]\n});\n"],"names":["CreateRoleUseCaseImpl","identityContext","eventPublisher","repository","input","hasPermission","Result","NotAuthorizedError","validation","createRoleValidation","RoleValidationError","identity","data","existingRoleResult","RoleExistsError","createInput","descriptionOnCreate","role","mdbid","Date","RoleBeforeCreateEvent","result","RoleAfterCreateEvent","CreateRoleUseCase","createImplementation","UseCaseAbstraction","IdentityContext","EventPublisher","RolesRepository"],"mappings":";;;;;;;;;;AAaA,MAAMA;IACF,YACYC,eAA0C,EAC1CC,cAAwC,EACxCC,UAAqC,CAC/C;aAHUF,eAAe,GAAfA;aACAC,cAAc,GAAdA;aACAC,UAAU,GAAVA;IACT;IAEH,MAAM,QAAQC,KAAsB,EAAmD;QACnF,MAAMC,gBAAgB,MAAM,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC;QAE/D,IAAI,CAACA,eACD,OAAOC,OAAO,IAAI,CAAC,IAAIC;QAG3B,MAAMC,aAAaC,qBAAqB,SAAS,CAACL;QAClD,IAAI,CAACI,WAAW,OAAO,EACnB,OAAOF,OAAO,IAAI,CAAC,IAAII,oBAAoBF,WAAW,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO;QAGjF,MAAMG,WAAW,IAAI,CAAC,eAAe,CAAC,WAAW;QACjD,MAAMC,OAAOJ,WAAW,IAAI;QAG5B,MAAMK,qBAAqB,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,MAAMD,KAAK,IAAI;QAAC;QACvE,IAAIC,mBAAmB,IAAI,IACvB,OAAOP,OAAO,IAAI,CAAC,IAAIQ,gBAAgBF,KAAK,IAAI;QAIpD,MAAMG,cAA+B;YACjC,GAAGH,IAAI;YACP,aAAaI,oBAAoBJ,KAAK,WAAW;QACrD;QAEA,MAAMK,OAAa;YACf,IAAIC;YACJ,MAAMH,YAAY,IAAI;YACtB,MAAMA,YAAY,IAAI;YACtB,aAAaC,oBAAoBD,YAAY,WAAW;YACxD,aAAaA,YAAY,WAAW;YACpC,QAAQX,MAAM,MAAM,IAAI;YACxB,WAAW,IAAIe,OAAO,WAAW;YACjC,WAAW;gBACP,IAAIR,SAAS,EAAE;gBACf,aAAaA,SAAS,WAAW;gBACjC,MAAMA,SAAS,IAAI;YACvB;YACA,QAAQ;QACZ;QAEA,MAAM,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,IAAIS,sBAAsB;YAAEH;YAAM,OAAOF;QAAY;QAEvF,MAAMM,SAAS,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,CAACJ;QAE5C,IAAII,OAAO,MAAM,IACb,OAAOf,OAAO,IAAI,CAACe,OAAO,KAAK;QAGnC,MAAM,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,IAAIC,qBAAqB;YAAEL;YAAM,OAAOF;QAAY;QAEtF,OAAOT,OAAO,EAAE,CAACW;IACrB;AACJ;AAEO,MAAMM,sCAAoBC,qBAAqB;IAClD,aAAaC;IACb,gBAAgBzB;IAChB,cAAc;QAAC0B;QAAiBC;QAAgBC;KAAgB;AACpE"}
@@ -2,7 +2,7 @@ import { z } from "zod";
2
2
  export declare const createRoleValidation: z.ZodObject<{
3
3
  name: z.ZodString;
4
4
  slug: z.ZodString;
5
- description: z.ZodDefault<z.ZodOptional<z.ZodString>>;
5
+ description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
6
6
  permissions: z.ZodArray<z.ZodObject<{
7
7
  name: z.ZodString;
8
8
  }, z.core.$loose>>;
@@ -2,7 +2,7 @@ import { z } from "zod";
2
2
  const createRoleValidation = z.object({
3
3
  name: z.string().min(3),
4
4
  slug: z.string().min(3),
5
- description: z.string().max(500).optional().default(""),
5
+ description: z.string().max(500).nullish(),
6
6
  permissions: z.array(z.looseObject({
7
7
  name: z.string()
8
8
  }))