@twin.org/api-auth-entity-storage-service 0.0.3-next.2 → 0.0.3-next.21

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 (52) hide show
  1. package/README.md +2 -2
  2. package/dist/es/entities/authenticationUser.js +9 -1
  3. package/dist/es/entities/authenticationUser.js.map +1 -1
  4. package/dist/es/index.js +1 -1
  5. package/dist/es/index.js.map +1 -1
  6. package/dist/es/processors/authHeaderProcessor.js +23 -9
  7. package/dist/es/processors/authHeaderProcessor.js.map +1 -1
  8. package/dist/es/restEntryPoints.js +7 -0
  9. package/dist/es/restEntryPoints.js.map +1 -1
  10. package/dist/es/routes/entityStorageAuthenticationAdminRoutes.js +362 -0
  11. package/dist/es/routes/entityStorageAuthenticationAdminRoutes.js.map +1 -0
  12. package/dist/es/routes/entityStorageAuthenticationRoutes.js +12 -12
  13. package/dist/es/routes/entityStorageAuthenticationRoutes.js.map +1 -1
  14. package/dist/es/services/entityStorageAuthenticationAdminService.js +110 -41
  15. package/dist/es/services/entityStorageAuthenticationAdminService.js.map +1 -1
  16. package/dist/es/services/entityStorageAuthenticationService.js +21 -10
  17. package/dist/es/services/entityStorageAuthenticationService.js.map +1 -1
  18. package/dist/es/utils/tokenHelper.js +25 -18
  19. package/dist/es/utils/tokenHelper.js.map +1 -1
  20. package/dist/types/entities/authenticationUser.d.ts +4 -0
  21. package/dist/types/index.d.ts +1 -1
  22. package/dist/types/routes/entityStorageAuthenticationAdminRoutes.d.ts +61 -0
  23. package/dist/types/services/entityStorageAuthenticationAdminService.d.ts +21 -6
  24. package/dist/types/services/entityStorageAuthenticationService.d.ts +2 -3
  25. package/dist/types/utils/tokenHelper.d.ts +5 -2
  26. package/docs/changelog.md +338 -1
  27. package/docs/examples.md +88 -1
  28. package/docs/reference/classes/AuthenticationUser.md +8 -0
  29. package/docs/reference/classes/EntityStorageAuthenticationAdminService.md +73 -13
  30. package/docs/reference/classes/EntityStorageAuthenticationService.md +3 -9
  31. package/docs/reference/classes/TokenHelper.md +20 -2
  32. package/docs/reference/functions/authenticationAdminCreateUser.md +31 -0
  33. package/docs/reference/functions/authenticationAdminGetUser.md +31 -0
  34. package/docs/reference/functions/authenticationAdminGetUserByIdentity.md +31 -0
  35. package/docs/reference/functions/authenticationAdminRemoveUser.md +31 -0
  36. package/docs/reference/functions/authenticationAdminUpdateUser.md +31 -0
  37. package/docs/reference/functions/authenticationAdminUpdateUserPassword.md +31 -0
  38. package/docs/reference/functions/generateRestRoutesAuthenticationAdmin.md +25 -0
  39. package/docs/reference/index.md +8 -1
  40. package/docs/reference/interfaces/IAuthHeaderProcessorConfig.md +0 -12
  41. package/docs/reference/interfaces/IAuthHeaderProcessorConstructorOptions.md +0 -6
  42. package/docs/reference/interfaces/IEntityStorageAuthenticationAdminServiceConfig.md +0 -6
  43. package/docs/reference/interfaces/IEntityStorageAuthenticationAdminServiceConstructorOptions.md +0 -6
  44. package/docs/reference/interfaces/IEntityStorageAuthenticationServiceConfig.md +0 -12
  45. package/docs/reference/interfaces/IEntityStorageAuthenticationServiceConstructorOptions.md +0 -18
  46. package/docs/reference/variables/tagsAuthenticationAdmin.md +5 -0
  47. package/locales/en.json +7 -2
  48. package/package.json +5 -5
  49. package/dist/es/utils/passwordHelper.js +0 -29
  50. package/dist/es/utils/passwordHelper.js.map +0 -1
  51. package/dist/types/utils/passwordHelper.d.ts +0 -16
  52. package/docs/reference/classes/PasswordHelper.md +0 -49
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
- # TWIN Auth Entity Storage Service
1
+ # TWIN API Auth Entity Storage Service
2
2
 
3
- Auth Entity Storage contract implementation and REST endpoint definitions.
3
+ This package provides an authentication service implementation and REST routes backed by entity storage.
4
4
 
5
5
  ## Installation
6
6
 
@@ -25,6 +25,10 @@ let AuthenticationUser = class AuthenticationUser {
25
25
  * The users organization.
26
26
  */
27
27
  organization;
28
+ /**
29
+ * The scope assigned to the user, comma separated.
30
+ */
31
+ scope;
28
32
  };
29
33
  __decorate([
30
34
  property({ type: "string", isPrimary: true }),
@@ -39,13 +43,17 @@ __decorate([
39
43
  __metadata("design:type", String)
40
44
  ], AuthenticationUser.prototype, "salt", void 0);
41
45
  __decorate([
42
- property({ type: "string" }),
46
+ property({ type: "string", isSecondary: true }),
43
47
  __metadata("design:type", String)
44
48
  ], AuthenticationUser.prototype, "identity", void 0);
45
49
  __decorate([
46
50
  property({ type: "string" }),
47
51
  __metadata("design:type", String)
48
52
  ], AuthenticationUser.prototype, "organization", void 0);
53
+ __decorate([
54
+ property({ type: "string" }),
55
+ __metadata("design:type", String)
56
+ ], AuthenticationUser.prototype, "scope", void 0);
49
57
  AuthenticationUser = __decorate([
50
58
  entity()
51
59
  ], AuthenticationUser);
@@ -1 +1 @@
1
- {"version":3,"file":"authenticationUser.js","sourceRoot":"","sources":["../../../src/entities/authenticationUser.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEpD;;GAEG;AAEI,IAAM,kBAAkB,GAAxB,MAAM,kBAAkB;IAC9B;;OAEG;IAEI,KAAK,CAAU;IAEtB;;OAEG;IAEI,QAAQ,CAAU;IAEzB;;OAEG;IAEI,IAAI,CAAU;IAErB;;OAEG;IAEI,QAAQ,CAAU;IAEzB;;OAEG;IAEI,YAAY,CAAU;CAC7B,CAAA;AAzBO;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;;iDACxB;AAMf;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;;oDACJ;AAMlB;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;;gDACR;AAMd;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;;oDACJ;AAMlB;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;;wDACA;AA7BjB,kBAAkB;IAD9B,MAAM,EAAE;GACI,kBAAkB,CA8B9B","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { entity, property } from \"@twin.org/entity\";\n\n/**\n * Class defining the storage for user login credentials.\n */\n@entity()\nexport class AuthenticationUser {\n\t/**\n\t * The user e-mail address.\n\t */\n\t@property({ type: \"string\", isPrimary: true })\n\tpublic email!: string;\n\n\t/**\n\t * The encrypted password for the user.\n\t */\n\t@property({ type: \"string\" })\n\tpublic password!: string;\n\n\t/**\n\t * The salt for the password.\n\t */\n\t@property({ type: \"string\" })\n\tpublic salt!: string;\n\n\t/**\n\t * The user identity.\n\t */\n\t@property({ type: \"string\" })\n\tpublic identity!: string;\n\n\t/**\n\t * The users organization.\n\t */\n\t@property({ type: \"string\" })\n\tpublic organization!: string;\n}\n"]}
1
+ {"version":3,"file":"authenticationUser.js","sourceRoot":"","sources":["../../../src/entities/authenticationUser.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEpD;;GAEG;AAEI,IAAM,kBAAkB,GAAxB,MAAM,kBAAkB;IAC9B;;OAEG;IAEI,KAAK,CAAU;IAEtB;;OAEG;IAEI,QAAQ,CAAU;IAEzB;;OAEG;IAEI,IAAI,CAAU;IAErB;;OAEG;IAEI,QAAQ,CAAU;IAEzB;;OAEG;IAEI,YAAY,CAAU;IAE7B;;OAEG;IAEI,KAAK,CAAU;CACtB,CAAA;AA/BO;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;;iDACxB;AAMf;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;;oDACJ;AAMlB;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;;gDACR;AAMd;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;;oDACvB;AAMlB;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;;wDACA;AAMtB;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;;iDACP;AAnCV,kBAAkB;IAD9B,MAAM,EAAE;GACI,kBAAkB,CAoC9B","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { entity, property } from \"@twin.org/entity\";\n\n/**\n * Class defining the storage for user login credentials.\n */\n@entity()\nexport class AuthenticationUser {\n\t/**\n\t * The user e-mail address.\n\t */\n\t@property({ type: \"string\", isPrimary: true })\n\tpublic email!: string;\n\n\t/**\n\t * The encrypted password for the user.\n\t */\n\t@property({ type: \"string\" })\n\tpublic password!: string;\n\n\t/**\n\t * The salt for the password.\n\t */\n\t@property({ type: \"string\" })\n\tpublic salt!: string;\n\n\t/**\n\t * The user identity.\n\t */\n\t@property({ type: \"string\", isSecondary: true })\n\tpublic identity!: string;\n\n\t/**\n\t * The users organization.\n\t */\n\t@property({ type: \"string\" })\n\tpublic organization!: string;\n\n\t/**\n\t * The scope assigned to the user, comma separated.\n\t */\n\t@property({ type: \"string\" })\n\tpublic scope!: string;\n}\n"]}
package/dist/es/index.js CHANGED
@@ -9,10 +9,10 @@ export * from "./models/IEntityStorageAuthenticationServiceConfig.js";
9
9
  export * from "./models/IEntityStorageAuthenticationServiceConstructorOptions.js";
10
10
  export * from "./processors/authHeaderProcessor.js";
11
11
  export * from "./restEntryPoints.js";
12
+ export * from "./routes/entityStorageAuthenticationAdminRoutes.js";
12
13
  export * from "./routes/entityStorageAuthenticationRoutes.js";
13
14
  export * from "./schema.js";
14
15
  export * from "./services/entityStorageAuthenticationAdminService.js";
15
16
  export * from "./services/entityStorageAuthenticationService.js";
16
- export * from "./utils/passwordHelper.js";
17
17
  export * from "./utils/tokenHelper.js";
18
18
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,cAAc,kCAAkC,CAAC;AACjD,cAAc,wCAAwC,CAAC;AACvD,cAAc,oDAAoD,CAAC;AACnE,cAAc,4DAA4D,CAAC;AAC3E,cAAc,wEAAwE,CAAC;AACvF,cAAc,uDAAuD,CAAC;AACtE,cAAc,mEAAmE,CAAC;AAClF,cAAc,qCAAqC,CAAC;AACpD,cAAc,sBAAsB,CAAC;AACrC,cAAc,+CAA+C,CAAC;AAC9D,cAAc,aAAa,CAAC;AAC5B,cAAc,uDAAuD,CAAC;AACtE,cAAc,kDAAkD,CAAC;AACjE,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nexport * from \"./entities/authenticationUser.js\";\nexport * from \"./models/IAuthHeaderProcessorConfig.js\";\nexport * from \"./models/IAuthHeaderProcessorConstructorOptions.js\";\nexport * from \"./models/IEntityStorageAuthenticationAdminServiceConfig.js\";\nexport * from \"./models/IEntityStorageAuthenticationAdminServiceConstructorOptions.js\";\nexport * from \"./models/IEntityStorageAuthenticationServiceConfig.js\";\nexport * from \"./models/IEntityStorageAuthenticationServiceConstructorOptions.js\";\nexport * from \"./processors/authHeaderProcessor.js\";\nexport * from \"./restEntryPoints.js\";\nexport * from \"./routes/entityStorageAuthenticationRoutes.js\";\nexport * from \"./schema.js\";\nexport * from \"./services/entityStorageAuthenticationAdminService.js\";\nexport * from \"./services/entityStorageAuthenticationService.js\";\nexport * from \"./utils/passwordHelper.js\";\nexport * from \"./utils/tokenHelper.js\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,cAAc,kCAAkC,CAAC;AACjD,cAAc,wCAAwC,CAAC;AACvD,cAAc,oDAAoD,CAAC;AACnE,cAAc,4DAA4D,CAAC;AAC3E,cAAc,wEAAwE,CAAC;AACvF,cAAc,uDAAuD,CAAC;AACtE,cAAc,mEAAmE,CAAC;AAClF,cAAc,qCAAqC,CAAC;AACpD,cAAc,sBAAsB,CAAC;AACrC,cAAc,oDAAoD,CAAC;AACnE,cAAc,+CAA+C,CAAC;AAC9D,cAAc,aAAa,CAAC;AAC5B,cAAc,uDAAuD,CAAC;AACtE,cAAc,kDAAkD,CAAC;AACjE,cAAc,wBAAwB,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nexport * from \"./entities/authenticationUser.js\";\nexport * from \"./models/IAuthHeaderProcessorConfig.js\";\nexport * from \"./models/IAuthHeaderProcessorConstructorOptions.js\";\nexport * from \"./models/IEntityStorageAuthenticationAdminServiceConfig.js\";\nexport * from \"./models/IEntityStorageAuthenticationAdminServiceConstructorOptions.js\";\nexport * from \"./models/IEntityStorageAuthenticationServiceConfig.js\";\nexport * from \"./models/IEntityStorageAuthenticationServiceConstructorOptions.js\";\nexport * from \"./processors/authHeaderProcessor.js\";\nexport * from \"./restEntryPoints.js\";\nexport * from \"./routes/entityStorageAuthenticationAdminRoutes.js\";\nexport * from \"./routes/entityStorageAuthenticationRoutes.js\";\nexport * from \"./schema.js\";\nexport * from \"./services/entityStorageAuthenticationAdminService.js\";\nexport * from \"./services/entityStorageAuthenticationService.js\";\nexport * from \"./utils/tokenHelper.js\";\n"]}
@@ -2,9 +2,9 @@
2
2
  // SPDX-License-Identifier: Apache-2.0.
3
3
  import { HttpErrorHelper } from "@twin.org/api-models";
4
4
  import { ContextIdHelper, ContextIdKeys, ContextIdStore } from "@twin.org/context";
5
- import { BaseError, Is } from "@twin.org/core";
5
+ import { BaseError, Coerce, GeneralError, Is } from "@twin.org/core";
6
6
  import { VaultConnectorFactory } from "@twin.org/vault-models";
7
- import { HeaderTypes, HttpStatusCode } from "@twin.org/web";
7
+ import { CookieHelper, HeaderTypes, HttpStatusCode } from "@twin.org/web";
8
8
  import { TokenHelper } from "../utils/tokenHelper.js";
9
9
  /**
10
10
  * Handle a JWT token in the authorization header or cookies and validate it to populate request context identity.
@@ -77,8 +77,14 @@ export class AuthHeaderProcessor {
77
77
  if (!Is.empty(route) && !(route.skipAuth ?? false)) {
78
78
  try {
79
79
  const tokenAndLocation = TokenHelper.extractTokenFromHeaders(request.headers, this._cookieName);
80
- const headerAndPayload = await TokenHelper.verify(this._vaultConnector, `${this._nodeId}/${this._signingKeyName}`, tokenAndLocation?.token);
80
+ const headerAndPayload = await TokenHelper.verify(this._vaultConnector, `${this._nodeId}/${this._signingKeyName}`, tokenAndLocation?.token, route.requiredScope);
81
+ // If tenant id is defined in the context, then it must match the one in the token
82
+ // but both can be undefined in a single tenant context
83
+ if (contextIds?.[ContextIdKeys.Tenant] !== headerAndPayload?.payload?.tid) {
84
+ throw new GeneralError(AuthHeaderProcessor.CLASS_NAME, "tenantIdMismatch");
85
+ }
81
86
  contextIds[ContextIdKeys.User] = headerAndPayload.payload?.sub;
87
+ contextIds[ContextIdKeys.Organization] = Coerce.string(headerAndPayload.payload?.org);
82
88
  processorState.authToken = tokenAndLocation?.token;
83
89
  processorState.authTokenLocation = tokenAndLocation?.location;
84
90
  }
@@ -98,21 +104,29 @@ export class AuthHeaderProcessor {
98
104
  */
99
105
  async post(request, response, route, contextIds, processorState) {
100
106
  const responseAuthOperation = processorState?.authOperation;
107
+ const responseAuthToken = processorState?.authToken;
101
108
  // We don't populate the cookie if the incoming request was from an authorization header.
102
109
  if (!Is.empty(route) &&
103
110
  Is.stringValue(responseAuthOperation) &&
104
111
  processorState.authTokenLocation !== "authorization") {
105
112
  if ((responseAuthOperation === "login" || responseAuthOperation === "refresh") &&
106
- Is.stringValue(response.body?.token)) {
113
+ Is.stringValue(responseAuthToken)) {
107
114
  response.headers ??= {};
108
- response.headers[HeaderTypes.SetCookie] =
109
- `${this._cookieName}=${response.body.token}; Secure; HttpOnly; SameSite=None; Path=/`;
110
- delete response.body.token;
115
+ response.headers[HeaderTypes.SetCookie] = CookieHelper.createCookie(this._cookieName, responseAuthToken, {
116
+ secure: true,
117
+ httpOnly: true,
118
+ sameSite: "None",
119
+ path: "/"
120
+ });
111
121
  }
112
122
  else if (responseAuthOperation === "logout") {
113
123
  response.headers ??= {};
114
- response.headers[HeaderTypes.SetCookie] =
115
- `${this._cookieName}=; Max-Age=0; Secure; HttpOnly; SameSite=None; Path=/`;
124
+ response.headers[HeaderTypes.SetCookie] = CookieHelper.deleteCookie(this._cookieName, {
125
+ secure: true,
126
+ httpOnly: true,
127
+ sameSite: "None",
128
+ path: "/"
129
+ });
116
130
  }
117
131
  }
118
132
  }
@@ -1 +1 @@
1
- {"version":3,"file":"authHeaderProcessor.js","sourceRoot":"","sources":["../../../src/processors/authHeaderProcessor.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport {\n\tHttpErrorHelper,\n\ttype IBaseRoute,\n\ttype IBaseRouteProcessor,\n\ttype IHttpResponse,\n\ttype IHttpServerRequest\n} from \"@twin.org/api-models\";\nimport {\n\tContextIdHelper,\n\tContextIdKeys,\n\tContextIdStore,\n\ttype IContextIds\n} from \"@twin.org/context\";\nimport { BaseError, Is } from \"@twin.org/core\";\nimport { nameof } from \"@twin.org/nameof\";\nimport { VaultConnectorFactory, type IVaultConnector } from \"@twin.org/vault-models\";\nimport { HeaderTypes, HttpStatusCode } from \"@twin.org/web\";\nimport type { IAuthHeaderProcessorConstructorOptions } from \"../models/IAuthHeaderProcessorConstructorOptions.js\";\nimport { TokenHelper } from \"../utils/tokenHelper.js\";\n\n/**\n * Handle a JWT token in the authorization header or cookies and validate it to populate request context identity.\n */\nexport class AuthHeaderProcessor implements IBaseRouteProcessor {\n\t/**\n\t * The default name for the access token as a cookie.\n\t * @internal\n\t */\n\tpublic static readonly DEFAULT_COOKIE_NAME: string = \"access_token\";\n\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<AuthHeaderProcessor>();\n\n\t/**\n\t * The vault for the keys.\n\t * @internal\n\t */\n\tprivate readonly _vaultConnector: IVaultConnector;\n\n\t/**\n\t * The name of the key to retrieve from the vault for signing JWT.\n\t * @internal\n\t */\n\tprivate readonly _signingKeyName: string;\n\n\t/**\n\t * The name of the cookie to use for the token.\n\t * @internal\n\t */\n\tprivate readonly _cookieName: string;\n\n\t/**\n\t * The node identity.\n\t * @internal\n\t */\n\tprivate _nodeId?: string;\n\n\t/**\n\t * Create a new instance of AuthCookiePreProcessor.\n\t * @param options Options for the processor.\n\t */\n\tconstructor(options?: IAuthHeaderProcessorConstructorOptions) {\n\t\tthis._vaultConnector = VaultConnectorFactory.get(options?.vaultConnectorType ?? \"vault\");\n\t\tthis._signingKeyName = options?.config?.signingKeyName ?? \"auth-signing\";\n\t\tthis._cookieName = options?.config?.cookieName ?? AuthHeaderProcessor.DEFAULT_COOKIE_NAME;\n\t}\n\n\t/**\n\t * Returns the class name of the component.\n\t * @returns The class name of the component.\n\t */\n\tpublic className(): string {\n\t\treturn AuthHeaderProcessor.CLASS_NAME;\n\t}\n\n\t/**\n\t * The service needs to be started when the application is initialized.\n\t * @param nodeLoggingComponentType The node logging component type.\n\t * @returns Nothing.\n\t */\n\tpublic async start(nodeLoggingComponentType?: string): Promise<void> {\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tContextIdHelper.guard(contextIds, ContextIdKeys.Node);\n\t\tthis._nodeId = contextIds[ContextIdKeys.Node];\n\t}\n\n\t/**\n\t * Pre process the REST request for the specified route.\n\t * @param request The incoming request.\n\t * @param response The outgoing response.\n\t * @param route The route to process.\n\t * @param contextIds The context IDs of the request.\n\t * @param processorState The state handed through the processors.\n\t */\n\tpublic async pre(\n\t\trequest: IHttpServerRequest,\n\t\tresponse: IHttpResponse,\n\t\troute: IBaseRoute | undefined,\n\t\tcontextIds: IContextIds,\n\t\tprocessorState: { [id: string]: unknown }\n\t): Promise<void> {\n\t\tif (!Is.empty(route) && !(route.skipAuth ?? false)) {\n\t\t\ttry {\n\t\t\t\tconst tokenAndLocation = TokenHelper.extractTokenFromHeaders(\n\t\t\t\t\trequest.headers,\n\t\t\t\t\tthis._cookieName\n\t\t\t\t);\n\n\t\t\t\tconst headerAndPayload = await TokenHelper.verify(\n\t\t\t\t\tthis._vaultConnector,\n\t\t\t\t\t`${this._nodeId}/${this._signingKeyName}`,\n\t\t\t\t\ttokenAndLocation?.token\n\t\t\t\t);\n\n\t\t\t\tcontextIds[ContextIdKeys.User] = headerAndPayload.payload?.sub;\n\t\t\t\tprocessorState.authToken = tokenAndLocation?.token;\n\t\t\t\tprocessorState.authTokenLocation = tokenAndLocation?.location;\n\t\t\t} catch (err) {\n\t\t\t\tconst error = BaseError.fromError(err);\n\t\t\t\tHttpErrorHelper.buildResponse(response, error, HttpStatusCode.unauthorized);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Post process the REST request for the specified route.\n\t * @param request The incoming request.\n\t * @param response The outgoing response.\n\t * @param route The route to process.\n\t * @param contextIds The context IDs of the request.\n\t * @param processorState The state handed through the processors.\n\t */\n\tpublic async post(\n\t\trequest: IHttpServerRequest,\n\t\tresponse: IHttpResponse,\n\t\troute: IBaseRoute | undefined,\n\t\tcontextIds: IContextIds,\n\t\tprocessorState: { [id: string]: unknown }\n\t): Promise<void> {\n\t\tconst responseAuthOperation = processorState?.authOperation;\n\n\t\t// We don't populate the cookie if the incoming request was from an authorization header.\n\t\tif (\n\t\t\t!Is.empty(route) &&\n\t\t\tIs.stringValue(responseAuthOperation) &&\n\t\t\tprocessorState.authTokenLocation !== \"authorization\"\n\t\t) {\n\t\t\tif (\n\t\t\t\t(responseAuthOperation === \"login\" || responseAuthOperation === \"refresh\") &&\n\t\t\t\tIs.stringValue(response.body?.token)\n\t\t\t) {\n\t\t\t\tresponse.headers ??= {};\n\t\t\t\tresponse.headers[HeaderTypes.SetCookie] =\n\t\t\t\t\t`${this._cookieName}=${response.body.token}; Secure; HttpOnly; SameSite=None; Path=/`;\n\t\t\t\tdelete response.body.token;\n\t\t\t} else if (responseAuthOperation === \"logout\") {\n\t\t\t\tresponse.headers ??= {};\n\t\t\t\tresponse.headers[HeaderTypes.SetCookie] =\n\t\t\t\t\t`${this._cookieName}=; Max-Age=0; Secure; HttpOnly; SameSite=None; Path=/`;\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"authHeaderProcessor.js","sourceRoot":"","sources":["../../../src/processors/authHeaderProcessor.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport {\n\tHttpErrorHelper,\n\ttype IBaseRoute,\n\ttype IBaseRouteProcessor,\n\ttype IHttpResponse,\n\ttype IHttpServerRequest\n} from \"@twin.org/api-models\";\nimport {\n\tContextIdHelper,\n\tContextIdKeys,\n\tContextIdStore,\n\ttype IContextIds\n} from \"@twin.org/context\";\nimport { BaseError, Coerce, GeneralError, Is } from \"@twin.org/core\";\nimport { nameof } from \"@twin.org/nameof\";\nimport { VaultConnectorFactory, type IVaultConnector } from \"@twin.org/vault-models\";\nimport { CookieHelper, HeaderTypes, HttpStatusCode } from \"@twin.org/web\";\nimport type { IAuthHeaderProcessorConstructorOptions } from \"../models/IAuthHeaderProcessorConstructorOptions.js\";\nimport { TokenHelper } from \"../utils/tokenHelper.js\";\n\n/**\n * Handle a JWT token in the authorization header or cookies and validate it to populate request context identity.\n */\nexport class AuthHeaderProcessor implements IBaseRouteProcessor {\n\t/**\n\t * The default name for the access token as a cookie.\n\t * @internal\n\t */\n\tpublic static readonly DEFAULT_COOKIE_NAME: string = \"access_token\";\n\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<AuthHeaderProcessor>();\n\n\t/**\n\t * The vault for the keys.\n\t * @internal\n\t */\n\tprivate readonly _vaultConnector: IVaultConnector;\n\n\t/**\n\t * The name of the key to retrieve from the vault for signing JWT.\n\t * @internal\n\t */\n\tprivate readonly _signingKeyName: string;\n\n\t/**\n\t * The name of the cookie to use for the token.\n\t * @internal\n\t */\n\tprivate readonly _cookieName: string;\n\n\t/**\n\t * The node identity.\n\t * @internal\n\t */\n\tprivate _nodeId?: string;\n\n\t/**\n\t * Create a new instance of AuthCookiePreProcessor.\n\t * @param options Options for the processor.\n\t */\n\tconstructor(options?: IAuthHeaderProcessorConstructorOptions) {\n\t\tthis._vaultConnector = VaultConnectorFactory.get(options?.vaultConnectorType ?? \"vault\");\n\t\tthis._signingKeyName = options?.config?.signingKeyName ?? \"auth-signing\";\n\t\tthis._cookieName = options?.config?.cookieName ?? AuthHeaderProcessor.DEFAULT_COOKIE_NAME;\n\t}\n\n\t/**\n\t * Returns the class name of the component.\n\t * @returns The class name of the component.\n\t */\n\tpublic className(): string {\n\t\treturn AuthHeaderProcessor.CLASS_NAME;\n\t}\n\n\t/**\n\t * The service needs to be started when the application is initialized.\n\t * @param nodeLoggingComponentType The node logging component type.\n\t * @returns Nothing.\n\t */\n\tpublic async start(nodeLoggingComponentType?: string): Promise<void> {\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tContextIdHelper.guard(contextIds, ContextIdKeys.Node);\n\t\tthis._nodeId = contextIds[ContextIdKeys.Node];\n\t}\n\n\t/**\n\t * Pre process the REST request for the specified route.\n\t * @param request The incoming request.\n\t * @param response The outgoing response.\n\t * @param route The route to process.\n\t * @param contextIds The context IDs of the request.\n\t * @param processorState The state handed through the processors.\n\t */\n\tpublic async pre(\n\t\trequest: IHttpServerRequest,\n\t\tresponse: IHttpResponse,\n\t\troute: IBaseRoute | undefined,\n\t\tcontextIds: IContextIds,\n\t\tprocessorState: { [id: string]: unknown }\n\t): Promise<void> {\n\t\tif (!Is.empty(route) && !(route.skipAuth ?? false)) {\n\t\t\ttry {\n\t\t\t\tconst tokenAndLocation = TokenHelper.extractTokenFromHeaders(\n\t\t\t\t\trequest.headers,\n\t\t\t\t\tthis._cookieName\n\t\t\t\t);\n\n\t\t\t\tconst headerAndPayload = await TokenHelper.verify(\n\t\t\t\t\tthis._vaultConnector,\n\t\t\t\t\t`${this._nodeId}/${this._signingKeyName}`,\n\t\t\t\t\ttokenAndLocation?.token,\n\t\t\t\t\troute.requiredScope\n\t\t\t\t);\n\n\t\t\t\t// If tenant id is defined in the context, then it must match the one in the token\n\t\t\t\t// but both can be undefined in a single tenant context\n\t\t\t\tif (contextIds?.[ContextIdKeys.Tenant] !== headerAndPayload?.payload?.tid) {\n\t\t\t\t\tthrow new GeneralError(AuthHeaderProcessor.CLASS_NAME, \"tenantIdMismatch\");\n\t\t\t\t}\n\n\t\t\t\tcontextIds[ContextIdKeys.User] = headerAndPayload.payload?.sub;\n\t\t\t\tcontextIds[ContextIdKeys.Organization] = Coerce.string(headerAndPayload.payload?.org);\n\n\t\t\t\tprocessorState.authToken = tokenAndLocation?.token;\n\t\t\t\tprocessorState.authTokenLocation = tokenAndLocation?.location;\n\t\t\t} catch (err) {\n\t\t\t\tconst error = BaseError.fromError(err);\n\t\t\t\tHttpErrorHelper.buildResponse(response, error, HttpStatusCode.unauthorized);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Post process the REST request for the specified route.\n\t * @param request The incoming request.\n\t * @param response The outgoing response.\n\t * @param route The route to process.\n\t * @param contextIds The context IDs of the request.\n\t * @param processorState The state handed through the processors.\n\t */\n\tpublic async post(\n\t\trequest: IHttpServerRequest,\n\t\tresponse: IHttpResponse,\n\t\troute: IBaseRoute | undefined,\n\t\tcontextIds: IContextIds,\n\t\tprocessorState: { [id: string]: unknown }\n\t): Promise<void> {\n\t\tconst responseAuthOperation = processorState?.authOperation;\n\t\tconst responseAuthToken = processorState?.authToken;\n\n\t\t// We don't populate the cookie if the incoming request was from an authorization header.\n\t\tif (\n\t\t\t!Is.empty(route) &&\n\t\t\tIs.stringValue(responseAuthOperation) &&\n\t\t\tprocessorState.authTokenLocation !== \"authorization\"\n\t\t) {\n\t\t\tif (\n\t\t\t\t(responseAuthOperation === \"login\" || responseAuthOperation === \"refresh\") &&\n\t\t\t\tIs.stringValue(responseAuthToken)\n\t\t\t) {\n\t\t\t\tresponse.headers ??= {};\n\t\t\t\tresponse.headers[HeaderTypes.SetCookie] = CookieHelper.createCookie(\n\t\t\t\t\tthis._cookieName,\n\t\t\t\t\tresponseAuthToken,\n\t\t\t\t\t{\n\t\t\t\t\t\tsecure: true,\n\t\t\t\t\t\thttpOnly: true,\n\t\t\t\t\t\tsameSite: \"None\",\n\t\t\t\t\t\tpath: \"/\"\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t} else if (responseAuthOperation === \"logout\") {\n\t\t\t\tresponse.headers ??= {};\n\t\t\t\tresponse.headers[HeaderTypes.SetCookie] = CookieHelper.deleteCookie(this._cookieName, {\n\t\t\t\t\tsecure: true,\n\t\t\t\t\thttpOnly: true,\n\t\t\t\t\tsameSite: \"None\",\n\t\t\t\t\tpath: \"/\"\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
@@ -1,3 +1,4 @@
1
+ import { generateRestRoutesAuthenticationAdmin, tagsAuthenticationAdmin } from "./routes/entityStorageAuthenticationAdminRoutes.js";
1
2
  import { generateRestRoutesAuthentication, tagsAuthentication } from "./routes/entityStorageAuthenticationRoutes.js";
2
3
  export const restEntryPoints = [
3
4
  {
@@ -5,6 +6,12 @@ export const restEntryPoints = [
5
6
  defaultBaseRoute: "authentication",
6
7
  tags: tagsAuthentication,
7
8
  generateRoutes: generateRestRoutesAuthentication
9
+ },
10
+ {
11
+ name: "authenticationAdmin",
12
+ defaultBaseRoute: "authentication/admin",
13
+ tags: tagsAuthenticationAdmin,
14
+ generateRoutes: generateRestRoutesAuthenticationAdmin
8
15
  }
9
16
  ];
10
17
  //# sourceMappingURL=restEntryPoints.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"restEntryPoints.js","sourceRoot":"","sources":["../../src/restEntryPoints.ts"],"names":[],"mappings":"AAGA,OAAO,EACN,gCAAgC,EAChC,kBAAkB,EAClB,MAAM,+CAA+C,CAAC;AAEvD,MAAM,CAAC,MAAM,eAAe,GAA2B;IACtD;QACC,IAAI,EAAE,gBAAgB;QACtB,gBAAgB,EAAE,gBAAgB;QAClC,IAAI,EAAE,kBAAkB;QACxB,cAAc,EAAE,gCAAgC;KAChD;CACD,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { IRestRouteEntryPoint } from \"@twin.org/api-models\";\nimport {\n\tgenerateRestRoutesAuthentication,\n\ttagsAuthentication\n} from \"./routes/entityStorageAuthenticationRoutes.js\";\n\nexport const restEntryPoints: IRestRouteEntryPoint[] = [\n\t{\n\t\tname: \"authentication\",\n\t\tdefaultBaseRoute: \"authentication\",\n\t\ttags: tagsAuthentication,\n\t\tgenerateRoutes: generateRestRoutesAuthentication\n\t}\n];\n"]}
1
+ {"version":3,"file":"restEntryPoints.js","sourceRoot":"","sources":["../../src/restEntryPoints.ts"],"names":[],"mappings":"AAGA,OAAO,EACN,qCAAqC,EACrC,uBAAuB,EACvB,MAAM,oDAAoD,CAAC;AAC5D,OAAO,EACN,gCAAgC,EAChC,kBAAkB,EAClB,MAAM,+CAA+C,CAAC;AAEvD,MAAM,CAAC,MAAM,eAAe,GAA2B;IACtD;QACC,IAAI,EAAE,gBAAgB;QACtB,gBAAgB,EAAE,gBAAgB;QAClC,IAAI,EAAE,kBAAkB;QACxB,cAAc,EAAE,gCAAgC;KAChD;IACD;QACC,IAAI,EAAE,qBAAqB;QAC3B,gBAAgB,EAAE,sBAAsB;QACxC,IAAI,EAAE,uBAAuB;QAC7B,cAAc,EAAE,qCAAqC;KACrD;CACD,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { IRestRouteEntryPoint } from \"@twin.org/api-models\";\nimport {\n\tgenerateRestRoutesAuthenticationAdmin,\n\ttagsAuthenticationAdmin\n} from \"./routes/entityStorageAuthenticationAdminRoutes.js\";\nimport {\n\tgenerateRestRoutesAuthentication,\n\ttagsAuthentication\n} from \"./routes/entityStorageAuthenticationRoutes.js\";\n\nexport const restEntryPoints: IRestRouteEntryPoint[] = [\n\t{\n\t\tname: \"authentication\",\n\t\tdefaultBaseRoute: \"authentication\",\n\t\ttags: tagsAuthentication,\n\t\tgenerateRoutes: generateRestRoutesAuthentication\n\t},\n\t{\n\t\tname: \"authenticationAdmin\",\n\t\tdefaultBaseRoute: \"authentication/admin\",\n\t\ttags: tagsAuthenticationAdmin,\n\t\tgenerateRoutes: generateRestRoutesAuthenticationAdmin\n\t}\n];\n"]}
@@ -0,0 +1,362 @@
1
+ import { ComponentFactory, Guards } from "@twin.org/core";
2
+ import { HeaderTypes, HttpStatusCode } from "@twin.org/web";
3
+ /**
4
+ * The source used when communicating about these routes.
5
+ */
6
+ const ROUTES_SOURCE = "authenticationAdminRoutes";
7
+ /**
8
+ * The tag to associate with the routes.
9
+ */
10
+ export const tagsAuthenticationAdmin = [
11
+ {
12
+ name: "Authentication Admin",
13
+ description: "Authentication Admin endpoints for the REST server."
14
+ }
15
+ ];
16
+ /**
17
+ * The REST routes for authentication admin.
18
+ * @param baseRouteName Prefix to prepend to the paths.
19
+ * @param componentName The name of the component to use in the routes stored in the ComponentFactory.
20
+ * @returns The generated routes.
21
+ */
22
+ export function generateRestRoutesAuthenticationAdmin(baseRouteName, componentName) {
23
+ const createUserRoute = {
24
+ operationId: "authenticationAdminCreateUser",
25
+ summary: "Create a new user",
26
+ tag: tagsAuthenticationAdmin[0].name,
27
+ method: "POST",
28
+ path: `${baseRouteName}/users`,
29
+ handler: async (httpRequestContext, request) => authenticationAdminCreateUser(httpRequestContext, componentName, request),
30
+ requestType: {
31
+ type: "IAdminUserCreateRequest",
32
+ examples: [
33
+ {
34
+ id: "createUserRequestExample",
35
+ description: "The request to create a new user.",
36
+ request: {
37
+ body: {
38
+ email: "user@example.com",
39
+ password: "MyPassword123!",
40
+ userIdentity: "did:example:123456789abcdefghi",
41
+ organizationIdentity: "did:example:123456789abcdefghi",
42
+ scope: ["scope1", "scope2"]
43
+ }
44
+ }
45
+ }
46
+ ]
47
+ },
48
+ responseType: [
49
+ {
50
+ type: "INoContentResponse"
51
+ },
52
+ {
53
+ type: "IUnauthorizedResponse"
54
+ }
55
+ ],
56
+ requiredScope: ["user-admin"]
57
+ };
58
+ const updateUserRoute = {
59
+ operationId: "authenticationAdminUpdateUser",
60
+ summary: "Update an existing user",
61
+ tag: tagsAuthenticationAdmin[0].name,
62
+ method: "PUT",
63
+ path: `${baseRouteName}/users/:email`,
64
+ handler: async (httpRequestContext, request) => authenticationAdminUpdateUser(httpRequestContext, componentName, request),
65
+ requestType: {
66
+ type: "IAdminUserUpdateRequest",
67
+ examples: [
68
+ {
69
+ id: "updateUserRequestExample",
70
+ description: "The request to update an existing user.",
71
+ request: {
72
+ pathParams: {
73
+ email: "user@example.com"
74
+ },
75
+ body: {
76
+ userIdentity: "did:example:123456789abcdefghi",
77
+ organizationIdentity: "did:example:123456789abcdefghi",
78
+ scope: ["scope1", "scope2"]
79
+ }
80
+ }
81
+ }
82
+ ]
83
+ },
84
+ responseType: [
85
+ {
86
+ type: "INoContentResponse"
87
+ },
88
+ {
89
+ type: "IUnauthorizedResponse"
90
+ }
91
+ ],
92
+ requiredScope: ["user-admin"]
93
+ };
94
+ const updateUserPasswordRoute = {
95
+ operationId: "authenticationAdminUpdateUserPassword",
96
+ summary: "Update an existing user password",
97
+ tag: tagsAuthenticationAdmin[0].name,
98
+ method: "PUT",
99
+ path: `${baseRouteName}/users/:email/password`,
100
+ handler: async (httpRequestContext, request) => authenticationAdminUpdateUserPassword(httpRequestContext, componentName, request),
101
+ requestType: {
102
+ type: "IAdminUserUpdatePasswordRequest",
103
+ examples: [
104
+ {
105
+ id: "updateUserPasswordRequestExample",
106
+ description: "The request to update an existing user password.",
107
+ request: {
108
+ pathParams: {
109
+ email: "user@example.com"
110
+ },
111
+ body: {
112
+ newPassword: "MyNewPassword123!"
113
+ }
114
+ }
115
+ }
116
+ ]
117
+ },
118
+ responseType: [
119
+ {
120
+ type: "INoContentResponse"
121
+ },
122
+ {
123
+ type: "IUnauthorizedResponse"
124
+ }
125
+ ],
126
+ requiredScope: ["user-admin"]
127
+ };
128
+ const getUserRoute = {
129
+ operationId: "authenticationAdminGetUser",
130
+ summary: "Get existing user",
131
+ tag: tagsAuthenticationAdmin[0].name,
132
+ method: "GET",
133
+ path: `${baseRouteName}/users/:email`,
134
+ handler: async (httpRequestContext, request) => authenticationAdminGetUser(httpRequestContext, componentName, request),
135
+ requestType: {
136
+ type: "IAdminUserGetRequest",
137
+ examples: [
138
+ {
139
+ id: "getUserRequestExample",
140
+ description: "The request to get an existing user.",
141
+ request: {
142
+ pathParams: {
143
+ email: "user@example.com"
144
+ }
145
+ }
146
+ }
147
+ ]
148
+ },
149
+ responseType: [
150
+ {
151
+ type: "IAdminUserGetResponse",
152
+ examples: [
153
+ {
154
+ id: "getUserResponseExample",
155
+ description: "The response to get an existing user.",
156
+ response: {
157
+ body: {
158
+ email: "user@example.com",
159
+ userIdentity: "did:example:123456789abcdefghi",
160
+ organizationIdentity: "did:example:123456789abcdefghi",
161
+ scope: ["scope1", "scope2"]
162
+ }
163
+ }
164
+ }
165
+ ]
166
+ },
167
+ {
168
+ type: "IUnauthorizedResponse"
169
+ }
170
+ ],
171
+ requiredScope: ["user-admin"]
172
+ };
173
+ const getByIdentityUserRoute = {
174
+ operationId: "authenticationAdminGetByIdentityUser",
175
+ summary: "Get existing user by identity",
176
+ tag: tagsAuthenticationAdmin[0].name,
177
+ method: "GET",
178
+ path: `${baseRouteName}/users/identity/:identity`,
179
+ handler: async (httpRequestContext, request) => authenticationAdminGetUserByIdentity(httpRequestContext, componentName, request),
180
+ requestType: {
181
+ type: "IAdminUserGetByIdentityRequest",
182
+ examples: [
183
+ {
184
+ id: "getUserByIdentityRequestExample",
185
+ description: "The request to get an existing user by identity.",
186
+ request: {
187
+ pathParams: {
188
+ identity: "did:example:123456789abcdefghi"
189
+ }
190
+ }
191
+ }
192
+ ]
193
+ },
194
+ responseType: [
195
+ {
196
+ type: "IAdminUserGetResponse",
197
+ examples: [
198
+ {
199
+ id: "getUserResponseExample",
200
+ description: "The response to get an existing user.",
201
+ response: {
202
+ body: {
203
+ email: "user@example.com",
204
+ userIdentity: "did:example:123456789abcdefghi",
205
+ organizationIdentity: "did:example:123456789abcdefghi",
206
+ scope: ["scope1", "scope2"]
207
+ }
208
+ }
209
+ }
210
+ ]
211
+ },
212
+ {
213
+ type: "IUnauthorizedResponse"
214
+ }
215
+ ],
216
+ requiredScope: ["user-admin"]
217
+ };
218
+ const removeUserRoute = {
219
+ operationId: "authenticationAdminRemoveUser",
220
+ summary: "Remove existing user",
221
+ tag: tagsAuthenticationAdmin[0].name,
222
+ method: "DELETE",
223
+ path: `${baseRouteName}/users/:email`,
224
+ handler: async (httpRequestContext, request) => authenticationAdminRemoveUser(httpRequestContext, componentName, request),
225
+ requestType: {
226
+ type: "IAdminUserRemoveRequest",
227
+ examples: [
228
+ {
229
+ id: "removeUserRequestExample",
230
+ description: "The request to remove an existing user.",
231
+ request: {
232
+ pathParams: {
233
+ email: "user@example.com"
234
+ }
235
+ }
236
+ }
237
+ ]
238
+ },
239
+ responseType: [
240
+ {
241
+ type: "INoContentResponse"
242
+ },
243
+ {
244
+ type: "IUnauthorizedResponse"
245
+ }
246
+ ],
247
+ requiredScope: ["user-admin"]
248
+ };
249
+ return [
250
+ createUserRoute,
251
+ updateUserRoute,
252
+ updateUserPasswordRoute,
253
+ getUserRoute,
254
+ getByIdentityUserRoute,
255
+ removeUserRoute
256
+ ];
257
+ }
258
+ /**
259
+ * Create a new user.
260
+ * @param httpRequestContext The request context for the API.
261
+ * @param componentName The name of the component to use in the routes.
262
+ * @param request The request.
263
+ * @returns The response object with additional http response properties.
264
+ */
265
+ export async function authenticationAdminCreateUser(httpRequestContext, componentName, request) {
266
+ Guards.object(ROUTES_SOURCE, "request", request);
267
+ Guards.object(ROUTES_SOURCE, "request.body", request.body);
268
+ const component = ComponentFactory.get(componentName);
269
+ await component.create(request.body);
270
+ return {
271
+ statusCode: HttpStatusCode.created,
272
+ headers: {
273
+ [HeaderTypes.Location]: request.body.email
274
+ }
275
+ };
276
+ }
277
+ /**
278
+ * Update an existing user.
279
+ * @param httpRequestContext The request context for the API.
280
+ * @param componentName The name of the component to use in the routes.
281
+ * @param request The request.
282
+ * @returns The response object with additional http response properties.
283
+ */
284
+ export async function authenticationAdminUpdateUser(httpRequestContext, componentName, request) {
285
+ Guards.object(ROUTES_SOURCE, "request", request);
286
+ Guards.object(ROUTES_SOURCE, "request.pathParams", request.pathParams);
287
+ Guards.object(ROUTES_SOURCE, "request.body", request.body);
288
+ const component = ComponentFactory.get(componentName);
289
+ await component.update({
290
+ ...request.body,
291
+ email: request.pathParams.email
292
+ });
293
+ return {
294
+ statusCode: HttpStatusCode.noContent
295
+ };
296
+ }
297
+ /**
298
+ * Update an existing user password.
299
+ * @param httpRequestContext The request context for the API.
300
+ * @param componentName The name of the component to use in the routes.
301
+ * @param request The request.
302
+ * @returns The response object with additional http response properties.
303
+ */
304
+ export async function authenticationAdminUpdateUserPassword(httpRequestContext, componentName, request) {
305
+ Guards.object(ROUTES_SOURCE, "request", request);
306
+ Guards.object(ROUTES_SOURCE, "request.pathParams", request.pathParams);
307
+ Guards.object(ROUTES_SOURCE, "request.body", request.body);
308
+ const component = ComponentFactory.get(componentName);
309
+ await component.updatePassword(request.pathParams.email, request.body.newPassword);
310
+ return {
311
+ statusCode: HttpStatusCode.noContent
312
+ };
313
+ }
314
+ /**
315
+ * Get an existing user.
316
+ * @param httpRequestContext The request context for the API.
317
+ * @param componentName The name of the component to use in the routes.
318
+ * @param request The request.
319
+ * @returns The response object with additional http response properties.
320
+ */
321
+ export async function authenticationAdminGetUser(httpRequestContext, componentName, request) {
322
+ Guards.object(ROUTES_SOURCE, "request", request);
323
+ Guards.object(ROUTES_SOURCE, "request.pathParams", request.pathParams);
324
+ const component = ComponentFactory.get(componentName);
325
+ const result = await component.get(request.pathParams.email);
326
+ return {
327
+ body: result
328
+ };
329
+ }
330
+ /**
331
+ * Get an existing user by identity.
332
+ * @param httpRequestContext The request context for the API.
333
+ * @param componentName The name of the component to use in the routes.
334
+ * @param request The request.
335
+ * @returns The response object with additional http response properties.
336
+ */
337
+ export async function authenticationAdminGetUserByIdentity(httpRequestContext, componentName, request) {
338
+ Guards.object(ROUTES_SOURCE, "request", request);
339
+ Guards.object(ROUTES_SOURCE, "request.pathParams", request.pathParams);
340
+ const component = ComponentFactory.get(componentName);
341
+ const result = await component.getByIdentity(request.pathParams.identity);
342
+ return {
343
+ body: result
344
+ };
345
+ }
346
+ /**
347
+ * Remove an existing user.
348
+ * @param httpRequestContext The request context for the API.
349
+ * @param componentName The name of the component to use in the routes.
350
+ * @param request The request.
351
+ * @returns The response object with additional http response properties.
352
+ */
353
+ export async function authenticationAdminRemoveUser(httpRequestContext, componentName, request) {
354
+ Guards.object(ROUTES_SOURCE, "request", request);
355
+ Guards.object(ROUTES_SOURCE, "request.pathParams", request.pathParams);
356
+ const component = ComponentFactory.get(componentName);
357
+ await component.remove(request.pathParams.email);
358
+ return {
359
+ statusCode: HttpStatusCode.noContent
360
+ };
361
+ }
362
+ //# sourceMappingURL=entityStorageAuthenticationAdminRoutes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entityStorageAuthenticationAdminRoutes.js","sourceRoot":"","sources":["../../../src/routes/entityStorageAuthenticationAdminRoutes.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type {\n\tIAdminUserCreateRequest,\n\tIAdminUserGetByIdentityRequest,\n\tIAdminUserGetRequest,\n\tIAdminUserGetResponse,\n\tIAdminUserRemoveRequest,\n\tIAdminUserUpdatePasswordRequest,\n\tIAdminUserUpdateRequest,\n\tIAuthenticationAdminComponent\n} from \"@twin.org/api-auth-entity-storage-models\";\nimport type {\n\tICreatedResponse,\n\tIHttpRequestContext,\n\tINoContentResponse,\n\tIRestRoute,\n\tITag,\n\tIUnauthorizedResponse\n} from \"@twin.org/api-models\";\nimport { ComponentFactory, Guards } from \"@twin.org/core\";\nimport { nameof } from \"@twin.org/nameof\";\nimport { HeaderTypes, HttpStatusCode } from \"@twin.org/web\";\n\n/**\n * The source used when communicating about these routes.\n */\nconst ROUTES_SOURCE = \"authenticationAdminRoutes\";\n\n/**\n * The tag to associate with the routes.\n */\nexport const tagsAuthenticationAdmin: ITag[] = [\n\t{\n\t\tname: \"Authentication Admin\",\n\t\tdescription: \"Authentication Admin endpoints for the REST server.\"\n\t}\n];\n\n/**\n * The REST routes for authentication admin.\n * @param baseRouteName Prefix to prepend to the paths.\n * @param componentName The name of the component to use in the routes stored in the ComponentFactory.\n * @returns The generated routes.\n */\nexport function generateRestRoutesAuthenticationAdmin(\n\tbaseRouteName: string,\n\tcomponentName: string\n): IRestRoute[] {\n\tconst createUserRoute: IRestRoute<IAdminUserCreateRequest, ICreatedResponse> = {\n\t\toperationId: \"authenticationAdminCreateUser\",\n\t\tsummary: \"Create a new user\",\n\t\ttag: tagsAuthenticationAdmin[0].name,\n\t\tmethod: \"POST\",\n\t\tpath: `${baseRouteName}/users`,\n\t\thandler: async (httpRequestContext, request) =>\n\t\t\tauthenticationAdminCreateUser(httpRequestContext, componentName, request),\n\t\trequestType: {\n\t\t\ttype: nameof<IAdminUserCreateRequest>(),\n\t\t\texamples: [\n\t\t\t\t{\n\t\t\t\t\tid: \"createUserRequestExample\",\n\t\t\t\t\tdescription: \"The request to create a new user.\",\n\t\t\t\t\trequest: {\n\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\temail: \"user@example.com\",\n\t\t\t\t\t\t\tpassword: \"MyPassword123!\",\n\t\t\t\t\t\t\tuserIdentity: \"did:example:123456789abcdefghi\",\n\t\t\t\t\t\t\torganizationIdentity: \"did:example:123456789abcdefghi\",\n\t\t\t\t\t\t\tscope: [\"scope1\", \"scope2\"]\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\tresponseType: [\n\t\t\t{\n\t\t\t\ttype: nameof<INoContentResponse>()\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: nameof<IUnauthorizedResponse>()\n\t\t\t}\n\t\t],\n\t\trequiredScope: [\"user-admin\"]\n\t};\n\n\tconst updateUserRoute: IRestRoute<IAdminUserUpdateRequest, INoContentResponse> = {\n\t\toperationId: \"authenticationAdminUpdateUser\",\n\t\tsummary: \"Update an existing user\",\n\t\ttag: tagsAuthenticationAdmin[0].name,\n\t\tmethod: \"PUT\",\n\t\tpath: `${baseRouteName}/users/:email`,\n\t\thandler: async (httpRequestContext, request) =>\n\t\t\tauthenticationAdminUpdateUser(httpRequestContext, componentName, request),\n\t\trequestType: {\n\t\t\ttype: nameof<IAdminUserUpdateRequest>(),\n\t\t\texamples: [\n\t\t\t\t{\n\t\t\t\t\tid: \"updateUserRequestExample\",\n\t\t\t\t\tdescription: \"The request to update an existing user.\",\n\t\t\t\t\trequest: {\n\t\t\t\t\t\tpathParams: {\n\t\t\t\t\t\t\temail: \"user@example.com\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\tuserIdentity: \"did:example:123456789abcdefghi\",\n\t\t\t\t\t\t\torganizationIdentity: \"did:example:123456789abcdefghi\",\n\t\t\t\t\t\t\tscope: [\"scope1\", \"scope2\"]\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\tresponseType: [\n\t\t\t{\n\t\t\t\ttype: nameof<INoContentResponse>()\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: nameof<IUnauthorizedResponse>()\n\t\t\t}\n\t\t],\n\t\trequiredScope: [\"user-admin\"]\n\t};\n\n\tconst updateUserPasswordRoute: IRestRoute<IAdminUserUpdatePasswordRequest, INoContentResponse> = {\n\t\toperationId: \"authenticationAdminUpdateUserPassword\",\n\t\tsummary: \"Update an existing user password\",\n\t\ttag: tagsAuthenticationAdmin[0].name,\n\t\tmethod: \"PUT\",\n\t\tpath: `${baseRouteName}/users/:email/password`,\n\t\thandler: async (httpRequestContext, request) =>\n\t\t\tauthenticationAdminUpdateUserPassword(httpRequestContext, componentName, request),\n\t\trequestType: {\n\t\t\ttype: nameof<IAdminUserUpdatePasswordRequest>(),\n\t\t\texamples: [\n\t\t\t\t{\n\t\t\t\t\tid: \"updateUserPasswordRequestExample\",\n\t\t\t\t\tdescription: \"The request to update an existing user password.\",\n\t\t\t\t\trequest: {\n\t\t\t\t\t\tpathParams: {\n\t\t\t\t\t\t\temail: \"user@example.com\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\tnewPassword: \"MyNewPassword123!\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\tresponseType: [\n\t\t\t{\n\t\t\t\ttype: nameof<INoContentResponse>()\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: nameof<IUnauthorizedResponse>()\n\t\t\t}\n\t\t],\n\t\trequiredScope: [\"user-admin\"]\n\t};\n\n\tconst getUserRoute: IRestRoute<IAdminUserGetRequest, IAdminUserGetResponse> = {\n\t\toperationId: \"authenticationAdminGetUser\",\n\t\tsummary: \"Get existing user\",\n\t\ttag: tagsAuthenticationAdmin[0].name,\n\t\tmethod: \"GET\",\n\t\tpath: `${baseRouteName}/users/:email`,\n\t\thandler: async (httpRequestContext, request) =>\n\t\t\tauthenticationAdminGetUser(httpRequestContext, componentName, request),\n\t\trequestType: {\n\t\t\ttype: nameof<IAdminUserGetRequest>(),\n\t\t\texamples: [\n\t\t\t\t{\n\t\t\t\t\tid: \"getUserRequestExample\",\n\t\t\t\t\tdescription: \"The request to get an existing user.\",\n\t\t\t\t\trequest: {\n\t\t\t\t\t\tpathParams: {\n\t\t\t\t\t\t\temail: \"user@example.com\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\tresponseType: [\n\t\t\t{\n\t\t\t\ttype: nameof<IAdminUserGetResponse>(),\n\t\t\t\texamples: [\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"getUserResponseExample\",\n\t\t\t\t\t\tdescription: \"The response to get an existing user.\",\n\t\t\t\t\t\tresponse: {\n\t\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\t\temail: \"user@example.com\",\n\t\t\t\t\t\t\t\tuserIdentity: \"did:example:123456789abcdefghi\",\n\t\t\t\t\t\t\t\torganizationIdentity: \"did:example:123456789abcdefghi\",\n\t\t\t\t\t\t\t\tscope: [\"scope1\", \"scope2\"]\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: nameof<IUnauthorizedResponse>()\n\t\t\t}\n\t\t],\n\t\trequiredScope: [\"user-admin\"]\n\t};\n\n\tconst getByIdentityUserRoute: IRestRoute<IAdminUserGetByIdentityRequest, IAdminUserGetResponse> =\n\t\t{\n\t\t\toperationId: \"authenticationAdminGetByIdentityUser\",\n\t\t\tsummary: \"Get existing user by identity\",\n\t\t\ttag: tagsAuthenticationAdmin[0].name,\n\t\t\tmethod: \"GET\",\n\t\t\tpath: `${baseRouteName}/users/identity/:identity`,\n\t\t\thandler: async (httpRequestContext, request) =>\n\t\t\t\tauthenticationAdminGetUserByIdentity(httpRequestContext, componentName, request),\n\t\t\trequestType: {\n\t\t\t\ttype: nameof<IAdminUserGetByIdentityRequest>(),\n\t\t\t\texamples: [\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"getUserByIdentityRequestExample\",\n\t\t\t\t\t\tdescription: \"The request to get an existing user by identity.\",\n\t\t\t\t\t\trequest: {\n\t\t\t\t\t\t\tpathParams: {\n\t\t\t\t\t\t\t\tidentity: \"did:example:123456789abcdefghi\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t},\n\t\t\tresponseType: [\n\t\t\t\t{\n\t\t\t\t\ttype: nameof<IAdminUserGetResponse>(),\n\t\t\t\t\texamples: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tid: \"getUserResponseExample\",\n\t\t\t\t\t\t\tdescription: \"The response to get an existing user.\",\n\t\t\t\t\t\t\tresponse: {\n\t\t\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\t\t\temail: \"user@example.com\",\n\t\t\t\t\t\t\t\t\tuserIdentity: \"did:example:123456789abcdefghi\",\n\t\t\t\t\t\t\t\t\torganizationIdentity: \"did:example:123456789abcdefghi\",\n\t\t\t\t\t\t\t\t\tscope: [\"scope1\", \"scope2\"]\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: nameof<IUnauthorizedResponse>()\n\t\t\t\t}\n\t\t\t],\n\t\t\trequiredScope: [\"user-admin\"]\n\t\t};\n\n\tconst removeUserRoute: IRestRoute<IAdminUserRemoveRequest, INoContentResponse> = {\n\t\toperationId: \"authenticationAdminRemoveUser\",\n\t\tsummary: \"Remove existing user\",\n\t\ttag: tagsAuthenticationAdmin[0].name,\n\t\tmethod: \"DELETE\",\n\t\tpath: `${baseRouteName}/users/:email`,\n\t\thandler: async (httpRequestContext, request) =>\n\t\t\tauthenticationAdminRemoveUser(httpRequestContext, componentName, request),\n\t\trequestType: {\n\t\t\ttype: nameof<IAdminUserRemoveRequest>(),\n\t\t\texamples: [\n\t\t\t\t{\n\t\t\t\t\tid: \"removeUserRequestExample\",\n\t\t\t\t\tdescription: \"The request to remove an existing user.\",\n\t\t\t\t\trequest: {\n\t\t\t\t\t\tpathParams: {\n\t\t\t\t\t\t\temail: \"user@example.com\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\tresponseType: [\n\t\t\t{\n\t\t\t\ttype: nameof<INoContentResponse>()\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: nameof<IUnauthorizedResponse>()\n\t\t\t}\n\t\t],\n\t\trequiredScope: [\"user-admin\"]\n\t};\n\n\treturn [\n\t\tcreateUserRoute,\n\t\tupdateUserRoute,\n\t\tupdateUserPasswordRoute,\n\t\tgetUserRoute,\n\t\tgetByIdentityUserRoute,\n\t\tremoveUserRoute\n\t];\n}\n\n/**\n * Create a new user.\n * @param httpRequestContext The request context for the API.\n * @param componentName The name of the component to use in the routes.\n * @param request The request.\n * @returns The response object with additional http response properties.\n */\nexport async function authenticationAdminCreateUser(\n\thttpRequestContext: IHttpRequestContext,\n\tcomponentName: string,\n\trequest: IAdminUserCreateRequest\n): Promise<ICreatedResponse> {\n\tGuards.object<IAdminUserCreateRequest>(ROUTES_SOURCE, nameof(request), request);\n\tGuards.object<IAdminUserCreateRequest[\"body\"]>(ROUTES_SOURCE, nameof(request.body), request.body);\n\n\tconst component = ComponentFactory.get<IAuthenticationAdminComponent>(componentName);\n\tawait component.create(request.body);\n\n\treturn {\n\t\tstatusCode: HttpStatusCode.created,\n\t\theaders: {\n\t\t\t[HeaderTypes.Location]: request.body.email\n\t\t}\n\t};\n}\n\n/**\n * Update an existing user.\n * @param httpRequestContext The request context for the API.\n * @param componentName The name of the component to use in the routes.\n * @param request The request.\n * @returns The response object with additional http response properties.\n */\nexport async function authenticationAdminUpdateUser(\n\thttpRequestContext: IHttpRequestContext,\n\tcomponentName: string,\n\trequest: IAdminUserUpdateRequest\n): Promise<INoContentResponse> {\n\tGuards.object<IAdminUserUpdateRequest>(ROUTES_SOURCE, nameof(request), request);\n\tGuards.object<IAdminUserUpdateRequest[\"pathParams\"]>(\n\t\tROUTES_SOURCE,\n\t\tnameof(request.pathParams),\n\t\trequest.pathParams\n\t);\n\tGuards.object<IAdminUserUpdateRequest[\"body\"]>(ROUTES_SOURCE, nameof(request.body), request.body);\n\n\tconst component = ComponentFactory.get<IAuthenticationAdminComponent>(componentName);\n\tawait component.update({\n\t\t...request.body,\n\t\temail: request.pathParams.email\n\t});\n\n\treturn {\n\t\tstatusCode: HttpStatusCode.noContent\n\t};\n}\n\n/**\n * Update an existing user password.\n * @param httpRequestContext The request context for the API.\n * @param componentName The name of the component to use in the routes.\n * @param request The request.\n * @returns The response object with additional http response properties.\n */\nexport async function authenticationAdminUpdateUserPassword(\n\thttpRequestContext: IHttpRequestContext,\n\tcomponentName: string,\n\trequest: IAdminUserUpdatePasswordRequest\n): Promise<INoContentResponse> {\n\tGuards.object<IAdminUserUpdatePasswordRequest>(ROUTES_SOURCE, nameof(request), request);\n\tGuards.object<IAdminUserUpdatePasswordRequest[\"pathParams\"]>(\n\t\tROUTES_SOURCE,\n\t\tnameof(request.pathParams),\n\t\trequest.pathParams\n\t);\n\tGuards.object<IAdminUserUpdatePasswordRequest[\"body\"]>(\n\t\tROUTES_SOURCE,\n\t\tnameof(request.body),\n\t\trequest.body\n\t);\n\n\tconst component = ComponentFactory.get<IAuthenticationAdminComponent>(componentName);\n\tawait component.updatePassword(request.pathParams.email, request.body.newPassword);\n\n\treturn {\n\t\tstatusCode: HttpStatusCode.noContent\n\t};\n}\n\n/**\n * Get an existing user.\n * @param httpRequestContext The request context for the API.\n * @param componentName The name of the component to use in the routes.\n * @param request The request.\n * @returns The response object with additional http response properties.\n */\nexport async function authenticationAdminGetUser(\n\thttpRequestContext: IHttpRequestContext,\n\tcomponentName: string,\n\trequest: IAdminUserGetRequest\n): Promise<IAdminUserGetResponse> {\n\tGuards.object<IAdminUserGetRequest>(ROUTES_SOURCE, nameof(request), request);\n\tGuards.object<IAdminUserGetRequest[\"pathParams\"]>(\n\t\tROUTES_SOURCE,\n\t\tnameof(request.pathParams),\n\t\trequest.pathParams\n\t);\n\n\tconst component = ComponentFactory.get<IAuthenticationAdminComponent>(componentName);\n\tconst result = await component.get(request.pathParams.email);\n\n\treturn {\n\t\tbody: result\n\t};\n}\n\n/**\n * Get an existing user by identity.\n * @param httpRequestContext The request context for the API.\n * @param componentName The name of the component to use in the routes.\n * @param request The request.\n * @returns The response object with additional http response properties.\n */\nexport async function authenticationAdminGetUserByIdentity(\n\thttpRequestContext: IHttpRequestContext,\n\tcomponentName: string,\n\trequest: IAdminUserGetByIdentityRequest\n): Promise<IAdminUserGetResponse> {\n\tGuards.object<IAdminUserGetByIdentityRequest>(ROUTES_SOURCE, nameof(request), request);\n\tGuards.object<IAdminUserGetByIdentityRequest[\"pathParams\"]>(\n\t\tROUTES_SOURCE,\n\t\tnameof(request.pathParams),\n\t\trequest.pathParams\n\t);\n\n\tconst component = ComponentFactory.get<IAuthenticationAdminComponent>(componentName);\n\tconst result = await component.getByIdentity(request.pathParams.identity);\n\n\treturn {\n\t\tbody: result\n\t};\n}\n\n/**\n * Remove an existing user.\n * @param httpRequestContext The request context for the API.\n * @param componentName The name of the component to use in the routes.\n * @param request The request.\n * @returns The response object with additional http response properties.\n */\nexport async function authenticationAdminRemoveUser(\n\thttpRequestContext: IHttpRequestContext,\n\tcomponentName: string,\n\trequest: IAdminUserRemoveRequest\n): Promise<INoContentResponse> {\n\tGuards.object<IAdminUserRemoveRequest>(ROUTES_SOURCE, nameof(request), request);\n\tGuards.object<IAdminUserRemoveRequest[\"pathParams\"]>(\n\t\tROUTES_SOURCE,\n\t\tnameof(request.pathParams),\n\t\trequest.pathParams\n\t);\n\n\tconst component = ComponentFactory.get<IAuthenticationAdminComponent>(componentName);\n\tawait component.remove(request.pathParams.email);\n\n\treturn {\n\t\tstatusCode: HttpStatusCode.noContent\n\t};\n}\n"]}