@hazeljs/oauth 0.2.0-beta.58 → 0.2.0-beta.59

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.
package/dist/index.d.ts CHANGED
@@ -8,5 +8,5 @@ export { OAuthModule } from './oauth.module';
8
8
  export { OAuthService } from './oauth.service';
9
9
  export { OAuthController } from './oauth.controller';
10
10
  export { OAuthStateGuard } from './guards/oauth-state.guard';
11
- export type { OAuthModuleOptions, OAuthProvidersConfig, OAuthCallbackResult, OAuthAuthorizationResult, OAuthUser, SupportedProvider, GoogleProviderConfig, MicrosoftProviderConfig, GitHubProviderConfig, FacebookProviderConfig, TwitterProviderConfig, } from './providers/provider.types';
11
+ export type { OAuthModuleOptions, OAuthProvidersConfig, OAuthCallbackHandler, OAuthCallbackResult, OAuthAuthorizationResult, OAuthUser, SupportedProvider, GoogleProviderConfig, MicrosoftProviderConfig, GitHubProviderConfig, FacebookProviderConfig, TwitterProviderConfig, } from './providers/provider.types';
12
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,YAAY,EACV,kBAAkB,EAClB,oBAAoB,EACpB,mBAAmB,EACnB,wBAAwB,EACxB,SAAS,EACT,iBAAiB,EACjB,oBAAoB,EACpB,uBAAuB,EACvB,oBAAoB,EACpB,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,4BAA4B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,YAAY,EACV,kBAAkB,EAClB,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,EACnB,wBAAwB,EACxB,SAAS,EACT,iBAAiB,EACjB,oBAAoB,EACpB,uBAAuB,EACvB,oBAAoB,EACpB,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,4BAA4B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"oauth.controller.d.ts","sourceRoot":"","sources":["../src/oauth.controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2C,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAC;AACvF,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAmB/C;;;GAGG;AACH,qBACa,eAAe;IACd,OAAO,CAAC,QAAQ,CAAC,YAAY;gBAAZ,YAAY,EAAE,YAAY;IAEvD;;;OAGG;IAEG,KAAK,CAAoB,QAAQ,EAAE,MAAM,EAAS,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBrF;;;OAGG;IAEG,QAAQ,CACO,QAAQ,EAAE,MAAM,EAEnC,KAAK,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,eAAe,CAAC,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,EACnF,GAAG,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAA;KAAE,EAChE,GAAG,EAAE,QAAQ,GACnB,OAAO,CAAC,IAAI,CAAC;IA2ChB,OAAO,CAAC,cAAc;CAgBvB"}
1
+ {"version":3,"file":"oauth.controller.d.ts","sourceRoot":"","sources":["../src/oauth.controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2C,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAC;AACvF,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAmB/C;;;GAGG;AACH,qBACa,eAAe;IACd,OAAO,CAAC,QAAQ,CAAC,YAAY;gBAAZ,YAAY,EAAE,YAAY;IAEvD;;;OAGG;IAEG,KAAK,CAAoB,QAAQ,EAAE,MAAM,EAAS,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBrF;;;OAGG;IAEG,QAAQ,CACO,QAAQ,EAAE,MAAM,EAEnC,KAAK,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,eAAe,CAAC,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,EACnF,GAAG,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAA;KAAE,EAChE,GAAG,EAAE,QAAQ,GACnB,OAAO,CAAC,IAAI,CAAC;IA+ChB,OAAO,CAAC,cAAc;CAgBvB"}
@@ -82,13 +82,16 @@ let OAuthController = class OAuthController {
82
82
  }
83
83
  try {
84
84
  const result = await this.oauthService.handleCallback(p, code, storedState, codeVerifier);
85
+ // Pass through callbackHandler (if configured) so the app can issue a JWT,
86
+ // look up the user in its own DB, etc. before responding.
87
+ const response = await this.oauthService.executeCallback(p, result);
85
88
  if (query.successRedirect) {
86
89
  res.status(302);
87
90
  res.setHeader('Location', query.successRedirect);
88
91
  res.end();
89
92
  return;
90
93
  }
91
- res.status(200).json(result);
94
+ res.status(200).json(response);
92
95
  }
93
96
  catch (err) {
94
97
  const message = err instanceof Error ? err.message : 'OAuth callback failed';
@@ -23,6 +23,17 @@ export declare class OAuthService {
23
23
  * For PKCE providers (Google, Microsoft), codeVerifier is required.
24
24
  */
25
25
  handleCallback(provider: SupportedProvider, code: string, state: string, codeVerifier?: string): Promise<OAuthCallbackResult>;
26
+ /**
27
+ * Called by OAuthController after a successful token exchange and user-profile fetch.
28
+ *
29
+ * If the module was configured with a `callbackHandler` class, the handler is
30
+ * resolved from the global DI container and its `handle()` method is invoked.
31
+ * This is where you look up / create your application user and issue a JWT.
32
+ *
33
+ * When no handler is configured the raw OAuthCallbackResult is returned unchanged,
34
+ * which preserves backwards-compatible behaviour.
35
+ */
36
+ executeCallback(provider: SupportedProvider, result: OAuthCallbackResult): Promise<unknown>;
26
37
  /**
27
38
  * Validate that the state matches (CSRF protection).
28
39
  * Use this when handling the callback to ensure the request originated from your app.
@@ -1 +1 @@
1
- {"version":3,"file":"oauth.service.d.ts","sourceRoot":"","sources":["../src/oauth.service.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EACV,kBAAkB,EAClB,mBAAmB,EACnB,wBAAwB,EACxB,iBAAiB,EAElB,MAAM,4BAA4B,CAAC;AAIpC,qBACa,YAAY;IACvB,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,YAAY,CAAwD;IAC5E,OAAO,CAAC,eAAe,CAA2D;IAClF,OAAO,CAAC,YAAY,CAAwD;IAC5E,OAAO,CAAC,cAAc,CAA0D;IAChF,OAAO,CAAC,aAAa,CAAyD;;IAO9E,OAAO,CAAC,MAAM,CAAC,OAAO,CAAmC;IAEzD,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI;IAInD,OAAO,CAAC,MAAM,CAAC,UAAU;IASzB,OAAO,CAAC,WAAW;IAkBnB,OAAO,CAAC,SAAS;IA8BjB,OAAO,CAAC,gBAAgB;IAmBxB;;;OAGG;IACH,mBAAmB,CACjB,QAAQ,EAAE,iBAAiB,EAC3B,KAAK,CAAC,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,EAAE,GAChB,wBAAwB;IA2B3B;;;OAGG;IACG,cAAc,CAClB,QAAQ,EAAE,iBAAiB,EAC3B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,mBAAmB,CAAC;IAuF/B;;;OAGG;IACH,aAAa,CAAC,aAAa,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO;IAIlE;;OAEG;IACH,aAAa,IAAI,MAAM;CAGxB"}
1
+ {"version":3,"file":"oauth.service.d.ts","sourceRoot":"","sources":["../src/oauth.service.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EACV,kBAAkB,EAElB,mBAAmB,EACnB,wBAAwB,EACxB,iBAAiB,EAElB,MAAM,4BAA4B,CAAC;AAIpC,qBACa,YAAY;IACvB,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,YAAY,CAAwD;IAC5E,OAAO,CAAC,eAAe,CAA2D;IAClF,OAAO,CAAC,YAAY,CAAwD;IAC5E,OAAO,CAAC,cAAc,CAA0D;IAChF,OAAO,CAAC,aAAa,CAAyD;;IAO9E,OAAO,CAAC,MAAM,CAAC,OAAO,CAAmC;IAEzD,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI;IAInD,OAAO,CAAC,MAAM,CAAC,UAAU;IASzB,OAAO,CAAC,WAAW;IAkBnB,OAAO,CAAC,SAAS;IA8BjB,OAAO,CAAC,gBAAgB;IAmBxB;;;OAGG;IACH,mBAAmB,CACjB,QAAQ,EAAE,iBAAiB,EAC3B,KAAK,CAAC,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,EAAE,GAChB,wBAAwB;IA2B3B;;;OAGG;IACG,cAAc,CAClB,QAAQ,EAAE,iBAAiB,EAC3B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,mBAAmB,CAAC;IAuF/B;;;;;;;;;OASG;IACG,eAAe,CACnB,QAAQ,EAAE,iBAAiB,EAC3B,MAAM,EAAE,mBAAmB,GAC1B,OAAO,CAAC,OAAO,CAAC;IAWnB;;;OAGG;IACH,aAAa,CAAC,aAAa,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO;IAIlE;;OAEG;IACH,aAAa,IAAI,MAAM;CAGxB"}
@@ -217,6 +217,23 @@ let OAuthService = OAuthService_1 = class OAuthService {
217
217
  user,
218
218
  };
219
219
  }
220
+ /**
221
+ * Called by OAuthController after a successful token exchange and user-profile fetch.
222
+ *
223
+ * If the module was configured with a `callbackHandler` class, the handler is
224
+ * resolved from the global DI container and its `handle()` method is invoked.
225
+ * This is where you look up / create your application user and issue a JWT.
226
+ *
227
+ * When no handler is configured the raw OAuthCallbackResult is returned unchanged,
228
+ * which preserves backwards-compatible behaviour.
229
+ */
230
+ async executeCallback(provider, result) {
231
+ const handlerClass = OAuthService_1.options?.callbackHandler;
232
+ if (!handlerClass)
233
+ return result;
234
+ const handler = core_1.Container.getInstance().resolve(handlerClass);
235
+ return handler.handle(result, provider);
236
+ }
220
237
  /**
221
238
  * Validate that the state matches (CSRF protection).
222
239
  * Use this when handling the callback to ensure the request originated from your app.
@@ -54,9 +54,41 @@ export interface OAuthAuthorizationResult {
54
54
  /** Required for PKCE providers (Google, Microsoft). Store and pass to handleCallback. */
55
55
  codeVerifier?: string;
56
56
  }
57
+ /**
58
+ * Implement this interface and pass the class to OAuthModule.forRoot({ callbackHandler })
59
+ * to hook into the OAuth callback before the response is sent.
60
+ *
61
+ * The handler is resolved from the DI container, so it can inject any service
62
+ * (JwtService, a UsersRepository, etc.) through its constructor.
63
+ *
64
+ * @example
65
+ * ```ts
66
+ * @Injectable()
67
+ * export class MyOAuthHandler implements OAuthCallbackHandler {
68
+ * constructor(
69
+ * private readonly jwtService: JwtService,
70
+ * private readonly usersRepo: UsersRepository,
71
+ * ) {}
72
+ *
73
+ * async handle(result: OAuthCallbackResult, provider: SupportedProvider) {
74
+ * const user = await this.usersRepo.findOrCreate(result.user);
75
+ * return { token: this.jwtService.sign({ sub: user.id, role: user.role, tenantId: user.orgId }) };
76
+ * }
77
+ * }
78
+ * ```
79
+ */
80
+ export interface OAuthCallbackHandler {
81
+ handle(result: OAuthCallbackResult, provider: SupportedProvider): Promise<unknown> | unknown;
82
+ }
57
83
  export interface OAuthModuleOptions {
58
84
  providers: OAuthProvidersConfig;
59
85
  /** Default scopes per provider. Override via getAuthorizationUrl scopes param. */
60
86
  defaultScopes?: Partial<Record<SupportedProvider, string[]>>;
87
+ /**
88
+ * Optional class (must be registered in the DI container) whose `handle()` method is
89
+ * called after a successful OAuth callback. Use it to look up / create the user in
90
+ * your database and return a JWT. When omitted the raw OAuthCallbackResult is returned.
91
+ */
92
+ callbackHandler?: new (...args: any[]) => OAuthCallbackHandler;
61
93
  }
62
94
  //# sourceMappingURL=provider.types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"provider.types.d.ts","sourceRoot":"","sources":["../../src/providers/provider.types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,oBAAoB,GAAG,kBAAkB,CAAC;AAEtD,MAAM,WAAW,uBAAwB,SAAQ,kBAAkB;IACjE,2EAA2E;IAC3E,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,oBAAoB,GAAG,kBAAkB,CAAC;AAEtD,MAAM,MAAM,sBAAsB,GAAG,kBAAkB,CAAC;AAExD,MAAM,WAAW,qBAAsB,SAAQ,IAAI,CAAC,kBAAkB,EAAE,cAAc,CAAC;IACrF,8CAA8C;IAC9C,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,MAAM,MAAM,mBAAmB,GAC3B;IAAE,MAAM,EAAE,oBAAoB,CAAA;CAAE,GAChC;IAAE,SAAS,EAAE,uBAAuB,CAAA;CAAE,GACtC;IAAE,MAAM,EAAE,oBAAoB,CAAA;CAAE,GAChC;IAAE,QAAQ,EAAE,sBAAsB,CAAA;CAAE,GACpC;IAAE,OAAO,EAAE,qBAAqB,CAAA;CAAE,CAAC;AAEvC,MAAM,WAAW,oBAAoB;IACnC,MAAM,CAAC,EAAE,oBAAoB,CAAC;IAC9B,SAAS,CAAC,EAAE,uBAAuB,CAAC;IACpC,MAAM,CAAC,EAAE,oBAAoB,CAAC;IAC9B,QAAQ,CAAC,EAAE,sBAAsB,CAAC;IAClC,OAAO,CAAC,EAAE,qBAAqB,CAAC;CACjC;AAED,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,WAAW,GAAG,QAAQ,GAAG,UAAU,GAAG,SAAS,CAAC;AAE3F,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,IAAI,EAAE,SAAS,CAAC;CACjB;AAED,MAAM,WAAW,wBAAwB;IACvC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,yFAAyF;IACzF,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,oBAAoB,CAAC;IAChC,kFAAkF;IAClF,aAAa,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,iBAAiB,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;CAC9D"}
1
+ {"version":3,"file":"provider.types.d.ts","sourceRoot":"","sources":["../../src/providers/provider.types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,oBAAoB,GAAG,kBAAkB,CAAC;AAEtD,MAAM,WAAW,uBAAwB,SAAQ,kBAAkB;IACjE,2EAA2E;IAC3E,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,oBAAoB,GAAG,kBAAkB,CAAC;AAEtD,MAAM,MAAM,sBAAsB,GAAG,kBAAkB,CAAC;AAExD,MAAM,WAAW,qBAAsB,SAAQ,IAAI,CAAC,kBAAkB,EAAE,cAAc,CAAC;IACrF,8CAA8C;IAC9C,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,MAAM,MAAM,mBAAmB,GAC3B;IAAE,MAAM,EAAE,oBAAoB,CAAA;CAAE,GAChC;IAAE,SAAS,EAAE,uBAAuB,CAAA;CAAE,GACtC;IAAE,MAAM,EAAE,oBAAoB,CAAA;CAAE,GAChC;IAAE,QAAQ,EAAE,sBAAsB,CAAA;CAAE,GACpC;IAAE,OAAO,EAAE,qBAAqB,CAAA;CAAE,CAAC;AAEvC,MAAM,WAAW,oBAAoB;IACnC,MAAM,CAAC,EAAE,oBAAoB,CAAC;IAC9B,SAAS,CAAC,EAAE,uBAAuB,CAAC;IACpC,MAAM,CAAC,EAAE,oBAAoB,CAAC;IAC9B,QAAQ,CAAC,EAAE,sBAAsB,CAAC;IAClC,OAAO,CAAC,EAAE,qBAAqB,CAAC;CACjC;AAED,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,WAAW,GAAG,QAAQ,GAAG,UAAU,GAAG,SAAS,CAAC;AAE3F,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,IAAI,EAAE,SAAS,CAAC;CACjB;AAED,MAAM,WAAW,wBAAwB;IACvC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,yFAAyF;IACzF,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,WAAW,oBAAoB;IACnC,MAAM,CAAC,MAAM,EAAE,mBAAmB,EAAE,QAAQ,EAAE,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;CAC9F;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,oBAAoB,CAAC;IAChC,kFAAkF;IAClF,aAAa,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,iBAAiB,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;IAC7D;;;;OAIG;IAEH,eAAe,CAAC,EAAE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,oBAAoB,CAAC;CAChE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hazeljs/oauth",
3
- "version": "0.2.0-beta.58",
3
+ "version": "0.2.0-beta.59",
4
4
  "description": "OAuth 2.0 social login module for HazelJS - Microsoft, Google, GitHub and more",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -52,5 +52,5 @@
52
52
  "peerDependencies": {
53
53
  "@hazeljs/core": ">=0.2.0-beta.0"
54
54
  },
55
- "gitHead": "ce3821b373043284ac4847315371efb137dc860d"
55
+ "gitHead": "f6d8ee8162a40e2298ccce46d843269838bbe6ff"
56
56
  }