@furystack/rest-service 11.0.6 → 12.0.0

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 (74) hide show
  1. package/CHANGELOG.md +74 -0
  2. package/README.md +3 -2
  3. package/esm/authenticate.d.ts.map +1 -1
  4. package/esm/authenticate.js +4 -1
  5. package/esm/authenticate.js.map +1 -1
  6. package/esm/authenticate.spec.js +6 -4
  7. package/esm/authenticate.spec.js.map +1 -1
  8. package/esm/authentication-providers/authentication-provider.d.ts +25 -0
  9. package/esm/authentication-providers/authentication-provider.d.ts.map +1 -0
  10. package/esm/authentication-providers/authentication-provider.js +2 -0
  11. package/esm/authentication-providers/authentication-provider.js.map +1 -0
  12. package/esm/authentication-providers/basic-auth-provider.d.ts +8 -0
  13. package/esm/authentication-providers/basic-auth-provider.d.ts.map +1 -0
  14. package/esm/authentication-providers/basic-auth-provider.js +18 -0
  15. package/esm/authentication-providers/basic-auth-provider.js.map +1 -0
  16. package/esm/authentication-providers/cookie-auth-provider.d.ts +11 -0
  17. package/esm/authentication-providers/cookie-auth-provider.d.ts.map +1 -0
  18. package/esm/authentication-providers/cookie-auth-provider.js +21 -0
  19. package/esm/authentication-providers/cookie-auth-provider.js.map +1 -0
  20. package/esm/authentication-providers/helpers.d.ts +11 -0
  21. package/esm/authentication-providers/helpers.d.ts.map +1 -0
  22. package/esm/authentication-providers/helpers.js +47 -0
  23. package/esm/authentication-providers/helpers.js.map +1 -0
  24. package/esm/authentication-providers/index.d.ts +5 -0
  25. package/esm/authentication-providers/index.d.ts.map +1 -0
  26. package/esm/authentication-providers/index.js +5 -0
  27. package/esm/authentication-providers/index.js.map +1 -0
  28. package/esm/endpoint-generators/utils.d.ts.map +1 -1
  29. package/esm/endpoint-generators/utils.js +4 -1
  30. package/esm/endpoint-generators/utils.js.map +1 -1
  31. package/esm/helpers.d.ts +5 -2
  32. package/esm/helpers.d.ts.map +1 -1
  33. package/esm/helpers.js +27 -3
  34. package/esm/helpers.js.map +1 -1
  35. package/esm/helpers.spec.js +37 -0
  36. package/esm/helpers.spec.js.map +1 -1
  37. package/esm/http-authentication-settings.d.ts +11 -4
  38. package/esm/http-authentication-settings.d.ts.map +1 -1
  39. package/esm/http-authentication-settings.js +9 -2
  40. package/esm/http-authentication-settings.js.map +1 -1
  41. package/esm/http-user-context.d.ts +9 -4
  42. package/esm/http-user-context.d.ts.map +1 -1
  43. package/esm/http-user-context.js +28 -55
  44. package/esm/http-user-context.js.map +1 -1
  45. package/esm/http-user-context.spec.d.ts +3 -1
  46. package/esm/http-user-context.spec.d.ts.map +1 -1
  47. package/esm/http-user-context.spec.js +103 -45
  48. package/esm/http-user-context.spec.js.map +1 -1
  49. package/esm/index.d.ts +1 -0
  50. package/esm/index.d.ts.map +1 -1
  51. package/esm/index.js +1 -0
  52. package/esm/index.js.map +1 -1
  53. package/esm/rest-service.integration.spec.d.ts.map +1 -1
  54. package/esm/rest-service.integration.spec.js +5 -4
  55. package/esm/rest-service.integration.spec.js.map +1 -1
  56. package/esm/validate.integration.spec.js +5 -0
  57. package/esm/validate.integration.spec.js.map +1 -1
  58. package/package.json +6 -6
  59. package/src/authenticate.spec.ts +6 -4
  60. package/src/authenticate.ts +4 -1
  61. package/src/authentication-providers/authentication-provider.ts +25 -0
  62. package/src/authentication-providers/basic-auth-provider.ts +21 -0
  63. package/src/authentication-providers/cookie-auth-provider.ts +26 -0
  64. package/src/authentication-providers/helpers.ts +73 -0
  65. package/src/authentication-providers/index.ts +4 -0
  66. package/src/endpoint-generators/utils.ts +4 -1
  67. package/src/helpers.spec.ts +40 -0
  68. package/src/helpers.ts +48 -3
  69. package/src/http-authentication-settings.ts +14 -5
  70. package/src/http-user-context.spec.ts +112 -44
  71. package/src/http-user-context.ts +27 -57
  72. package/src/index.ts +1 -0
  73. package/src/rest-service.integration.spec.ts +5 -4
  74. package/src/validate.integration.spec.ts +5 -0
@@ -1 +1 @@
1
- {"version":3,"file":"http-authentication-settings.d.ts","sourceRoot":"","sources":["../src/http-authentication-settings.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAClE,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AACtC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAEtD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAE5D;;GAEG;AACH,qBACa,0BAA0B,CAAC,KAAK,SAAS,IAAI,EAAE,QAAQ,SAAS,cAAc;IAClF,KAAK,EAAE,aAAa,CAAC,KAAK,CAAC,CAA+B;IAE1D,YAAY,GAAI,IAAI,YAAY,iGAAqC;IAErE,eAAe,EAAE,CAAC,YAAY,EAAE,YAAY,KAAK,aAAa,CAAC,QAAQ,EAAE,MAAM,QAAQ,CAAC,CACI;IAE5F,UAAU,SAAQ;IAClB,eAAe,UAAO;CAC9B"}
1
+ {"version":3,"file":"http-authentication-settings.d.ts","sourceRoot":"","sources":["../src/http-authentication-settings.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AACtC,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAEhE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAA;AAEpD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,uDAAuD,CAAA;AACnG,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAE5D;;GAEG;AACH,qBACa,0BAA0B,CAAC,KAAK,SAAS,IAAI,EAAE,QAAQ,SAAS,cAAc;IAClF,KAAK,EAAE,aAAa,CAAC,KAAK,CAAC,CAA+B;IAE1D,cAAc,GAAI,UAAU,QAAQ,2FAA8C;IAElF,iBAAiB,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,OAAO,CAAC,QAAQ,EAAE,MAAM,QAAQ,CAAC,CACmB;IAE/F,UAAU,SAAQ;IAClB,eAAe,UAAO;IAE7B;;;;OAIG;IACI,uBAAuB,EAAE,sBAAsB,EAAE,CAAK;CAC9D"}
@@ -6,16 +6,23 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
6
6
  };
7
7
  import { User } from '@furystack/core';
8
8
  import { Injectable } from '@furystack/inject';
9
+ import { getDataSetFor } from '@furystack/repository';
9
10
  import { DefaultSession } from './models/default-session.js';
10
11
  /**
11
12
  * Authentication settings object for FuryStack HTTP Api
12
13
  */
13
14
  let HttpAuthenticationSettings = class HttpAuthenticationSettings {
14
15
  model = User;
15
- getUserStore = (sm) => sm.getStoreFor(User, 'username');
16
- getSessionStore = (sm) => sm.getStoreFor(DefaultSession, 'sessionId');
16
+ getUserDataSet = (injector) => getDataSetFor(injector, User, 'username');
17
+ getSessionDataSet = (injector) => getDataSetFor(injector, DefaultSession, 'sessionId');
17
18
  cookieName = 'fss';
18
19
  enableBasicAuth = true;
20
+ /**
21
+ * Ordered list of authentication providers. Populated by {@link useHttpAuthentication}
22
+ * and extended by `useJwtAuthentication()` or other auth plugins.
23
+ * Safe to mutate only during setup, before the first request is served.
24
+ */
25
+ authenticationProviders = [];
19
26
  };
20
27
  HttpAuthenticationSettings = __decorate([
21
28
  Injectable({ lifetime: 'singleton' })
@@ -1 +1 @@
1
- {"version":3,"file":"http-authentication-settings.js","sourceRoot":"","sources":["../src/http-authentication-settings.ts"],"names":[],"mappings":";;;;;;AACA,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAEtC,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAE5D;;GAEG;AAEI,IAAM,0BAA0B,GAAhC,MAAM,0BAA0B;IAC9B,KAAK,GAAyB,IAA4B,CAAA;IAE1D,YAAY,GAAG,CAAC,EAAgB,EAAE,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,IAAI,EAAE,UAAU,CAAC,CAAA;IAErE,eAAe,GAA4E,CAAC,EAAE,EAAE,EAAE,CACvG,EAAE,CAAC,WAAW,CAAC,cAAc,EAAE,WAAW,CAAuD,CAAA;IAE5F,UAAU,GAAG,KAAK,CAAA;IAClB,eAAe,GAAG,IAAI,CAAA;CAC9B,CAAA;AAVY,0BAA0B;IADtC,UAAU,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;GACzB,0BAA0B,CAUtC"}
1
+ {"version":3,"file":"http-authentication-settings.js","sourceRoot":"","sources":["../src/http-authentication-settings.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAEtC,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAE9C,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAErD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAE5D;;GAEG;AAEI,IAAM,0BAA0B,GAAhC,MAAM,0BAA0B;IAC9B,KAAK,GAAyB,IAA4B,CAAA;IAE1D,cAAc,GAAG,CAAC,QAAkB,EAAE,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,IAAI,EAAE,UAAU,CAAC,CAAA;IAElF,iBAAiB,GAA8D,CAAC,QAAQ,EAAE,EAAE,CACjG,aAAa,CAAC,QAAQ,EAAE,cAAc,EAAE,WAAW,CAAiD,CAAA;IAE/F,UAAU,GAAG,KAAK,CAAA;IAClB,eAAe,GAAG,IAAI,CAAA;IAE7B;;;;OAIG;IACI,uBAAuB,GAA6B,EAAE,CAAA;CAC9D,CAAA;AAjBY,0BAA0B;IADtC,UAAU,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;GACzB,0BAA0B,CAiBtC"}
@@ -6,10 +6,9 @@ import type { DefaultSession } from './models/default-session.js';
6
6
  * Injectable UserContext for FuryStack HTTP Api
7
7
  */
8
8
  export declare class HttpUserContext {
9
- getUserStore: () => import("@furystack/core").PhysicalStore<User, "username", import("@furystack/core").WithOptionalId<User, "username">>;
10
- getSessionStore: () => import("@furystack/core").PhysicalStore<DefaultSession, keyof DefaultSession, import("@furystack/core").WithOptionalId<DefaultSession, keyof DefaultSession>>;
9
+ getUserDataSet: () => import("@furystack/repository").DataSet<User, "username", import("@furystack/core").WithOptionalId<User, "username">>;
10
+ getSessionDataSet: () => import("@furystack/repository").DataSet<DefaultSession, keyof DefaultSession, import("@furystack/core").WithOptionalId<DefaultSession, keyof DefaultSession>>;
11
11
  private getUserByName;
12
- private getSessionById;
13
12
  private user?;
14
13
  /**
15
14
  * @param request The request to be authenticated
@@ -32,6 +31,12 @@ export declare class HttpUserContext {
32
31
  authenticateUser(userName: string, password: string): Promise<import("@furystack/core").PartialResult<User, (keyof User)[]>>;
33
32
  getCurrentUser(request: Pick<IncomingMessage, 'headers'>): Promise<User>;
34
33
  getSessionIdFromRequest(request: Pick<IncomingMessage, 'headers'>): string | null;
34
+ /**
35
+ * Iterates registered authentication providers in order.
36
+ * - A provider returning `User` means authentication succeeded.
37
+ * - A provider returning `null` means it does not apply; try the next one.
38
+ * - A provider throwing means it owns the request but auth failed; propagate the error.
39
+ */
35
40
  authenticateRequest(request: Pick<IncomingMessage, 'headers'>): Promise<User>;
36
41
  /**
37
42
  * Creates and sets up a cookie-based session for the provided user
@@ -46,7 +51,7 @@ export declare class HttpUserContext {
46
51
  setHeader: (header: string, value: string) => void;
47
52
  }): Promise<void>;
48
53
  readonly authentication: HttpAuthenticationSettings<User, DefaultSession>;
49
- private readonly storeManager;
54
+ private readonly systemInjector;
50
55
  private readonly authenticator;
51
56
  init(): void;
52
57
  }
@@ -1 +1 @@
1
- {"version":3,"file":"http-user-context.d.ts","sourceRoot":"","sources":["../src/http-user-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAK3C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,MAAM,CAAA;AAC3C,OAAO,EAAE,0BAA0B,EAAE,MAAM,mCAAmC,CAAA;AAC9E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAEjE;;GAEG;AACH,qBACa,eAAe;IACnB,YAAY,8HAA4D;IAExE,eAAe,sKAA+D;IAErF,OAAO,CAAC,aAAa,CAOpB;IAED,OAAO,CAAC,cAAc,CAOrB;IAED,OAAO,CAAC,IAAI,CAAC,CAAM;IAEnB;;;OAGG;IACU,eAAe,CAAC,OAAO,EAAE,eAAe;IASrD;;;;;OAKG;IACU,YAAY,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAUzF;;;;;OAKG;IACU,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;IAanD,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,eAAe,EAAE,SAAS,CAAC;IAQ9D,uBAAuB,CAAC,OAAO,EAAE,IAAI,CAAC,eAAe,EAAE,SAAS,CAAC,GAAG,MAAM,GAAG,IAAI;IAkB3E,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAAC,eAAe,EAAE,SAAS,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAuB1F;;;;;OAKG;IACU,WAAW,CACtB,IAAI,EAAE,IAAI,EACV,cAAc,EAAE;QAAE,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE,GACrE,OAAO,CAAC,IAAI,CAAC;IAQH,YAAY,CACvB,OAAO,EAAE,IAAI,CAAC,eAAe,EAAE,SAAS,CAAC,EACzC,QAAQ,EAAE;QAAE,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE;IAalE,SACwB,cAAc,EAAE,0BAA0B,CAAC,IAAI,EAAE,cAAc,CAAC,CAAA;IAExF,iBACyB,YAAY,CAAc;IAEnD,iBACyB,aAAa,CAAuB;IAEtD,IAAI;CAiBZ"}
1
+ {"version":3,"file":"http-user-context.d.ts","sourceRoot":"","sources":["../src/http-user-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAM3C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,MAAM,CAAA;AAE3C,OAAO,EAAE,0BAA0B,EAAE,MAAM,mCAAmC,CAAA;AAC9E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAEjE;;GAEG;AACH,qBACa,eAAe;IACnB,cAAc,8HAAgE;IAE9E,iBAAiB,sKAAmE;IAE3F,OAAO,CAAC,aAAa,CAOpB;IAED,OAAO,CAAC,IAAI,CAAC,CAAM;IAEnB;;;OAGG;IACU,eAAe,CAAC,OAAO,EAAE,eAAe;IASrD;;;;;OAKG;IACU,YAAY,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAUzF;;;;;OAKG;IACU,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;IAanD,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,eAAe,EAAE,SAAS,CAAC;IAQ9D,uBAAuB,CAAC,OAAO,EAAE,IAAI,CAAC,eAAe,EAAE,SAAS,CAAC,GAAG,MAAM,GAAG,IAAI;IAIxF;;;;;OAKG;IACU,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAAC,eAAe,EAAE,SAAS,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ1F;;;;;OAKG;IACU,WAAW,CACtB,IAAI,EAAE,IAAI,EACV,cAAc,EAAE;QAAE,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE,GACrE,OAAO,CAAC,IAAI,CAAC;IAQH,YAAY,CACvB,OAAO,EAAE,IAAI,CAAC,eAAe,EAAE,SAAS,CAAC,EACzC,QAAQ,EAAE;QAAE,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE;IAalE,SACwB,cAAc,EAAE,0BAA0B,CAAC,IAAI,EAAE,cAAc,CAAC,CAAA;IAExF,iBACyB,cAAc,CAAU;IAEjD,iBACyB,aAAa,CAAuB;IAEtD,IAAI;CAiBZ"}
@@ -7,33 +7,26 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
7
7
  var __metadata = (this && this.__metadata) || function (k, v) {
8
8
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
9
  };
10
- import { StoreManager } from '@furystack/core';
10
+ import { useSystemIdentityContext } from '@furystack/core';
11
11
  import { Injectable, Injected } from '@furystack/inject';
12
12
  import { PasswordAuthenticator, UnauthenticatedError } from '@furystack/security';
13
13
  import { randomBytes } from 'crypto';
14
+ import { extractSessionIdFromCookies } from './authentication-providers/helpers.js';
14
15
  import { HttpAuthenticationSettings } from './http-authentication-settings.js';
15
16
  /**
16
17
  * Injectable UserContext for FuryStack HTTP Api
17
18
  */
18
19
  let HttpUserContext = class HttpUserContext {
19
- getUserStore = () => this.authentication.getUserStore(this.storeManager);
20
- getSessionStore = () => this.authentication.getSessionStore(this.storeManager);
20
+ getUserDataSet = () => this.authentication.getUserDataSet(this.systemInjector);
21
+ getSessionDataSet = () => this.authentication.getSessionDataSet(this.systemInjector);
21
22
  getUserByName = async (userName) => {
22
- const userStore = this.getUserStore();
23
- const users = await userStore.find({ filter: { username: { $eq: userName } }, top: 2 });
23
+ const userDataSet = this.getUserDataSet();
24
+ const users = await userDataSet.find(this.systemInjector, { filter: { username: { $eq: userName } }, top: 2 });
24
25
  if (users.length !== 1) {
25
26
  throw new UnauthenticatedError();
26
27
  }
27
28
  return users[0];
28
29
  };
29
- getSessionById = async (sessionId) => {
30
- const sessionStore = this.getSessionStore();
31
- const sessions = await sessionStore.find({ filter: { sessionId: { $eq: sessionId } }, top: 2 });
32
- if (sessions.length !== 1) {
33
- throw new UnauthenticatedError();
34
- }
35
- return sessions[0];
36
- };
37
30
  user;
38
31
  /**
39
32
  * @param request The request to be authenticated
@@ -88,39 +81,19 @@ let HttpUserContext = class HttpUserContext {
88
81
  return this.user;
89
82
  }
90
83
  getSessionIdFromRequest(request) {
91
- if (request.headers.cookie) {
92
- const cookies = request.headers.cookie
93
- .toString()
94
- .split(';')
95
- .filter((val) => val.length > 0)
96
- .map((val) => {
97
- const [name, value] = val.split('=');
98
- return { name: name?.trim(), value: value?.trim() };
99
- });
100
- const sessionCookie = cookies.find((c) => c.name === this.authentication.cookieName);
101
- if (sessionCookie) {
102
- return sessionCookie.value;
103
- }
104
- }
105
- return null;
84
+ return extractSessionIdFromCookies(request, this.authentication.cookieName);
106
85
  }
86
+ /**
87
+ * Iterates registered authentication providers in order.
88
+ * - A provider returning `User` means authentication succeeded.
89
+ * - A provider returning `null` means it does not apply; try the next one.
90
+ * - A provider throwing means it owns the request but auth failed; propagate the error.
91
+ */
107
92
  async authenticateRequest(request) {
108
- // Basic auth
109
- if (this.authentication.enableBasicAuth && request.headers.authorization) {
110
- const authData = Buffer.from(request.headers.authorization.toString().split(' ')[1], 'base64');
111
- const [userName, password] = authData.toString().split(':');
112
- return await this.authenticateUser(userName, password);
113
- }
114
- // Cookie auth
115
- const sessionId = this.getSessionIdFromRequest(request);
116
- if (sessionId) {
117
- const session = await this.getSessionById(sessionId);
118
- if (session) {
119
- const user = await this.getUserByName(session.username);
120
- if (user) {
121
- return user;
122
- }
123
- }
93
+ for (const provider of this.authentication.authenticationProviders) {
94
+ const user = await provider.authenticate(request);
95
+ if (user)
96
+ return user;
124
97
  }
125
98
  throw new UnauthenticatedError();
126
99
  }
@@ -132,7 +105,7 @@ let HttpUserContext = class HttpUserContext {
132
105
  */
133
106
  async cookieLogin(user, serverResponse) {
134
107
  const sessionId = randomBytes(32).toString('hex');
135
- await this.getSessionStore().add({ sessionId, username: user.username });
108
+ await this.getSessionDataSet().add(this.systemInjector, { sessionId, username: user.username });
136
109
  serverResponse.setHeader('Set-Cookie', `${this.authentication.cookieName}=${sessionId}; Path=/; HttpOnly`);
137
110
  this.user = user;
138
111
  return user;
@@ -142,24 +115,24 @@ let HttpUserContext = class HttpUserContext {
142
115
  const sessionId = this.getSessionIdFromRequest(request);
143
116
  response.setHeader('Set-Cookie', `${this.authentication.cookieName}=; Path=/; HttpOnly`);
144
117
  if (sessionId) {
145
- const sessionStore = this.getSessionStore();
146
- const sessions = await sessionStore.find({ filter: { sessionId: { $eq: sessionId } } });
147
- await this.getSessionStore().remove(...sessions.map((s) => s[sessionStore.primaryKey]));
118
+ const sessionDataSet = this.getSessionDataSet();
119
+ const sessions = await sessionDataSet.find(this.systemInjector, { filter: { sessionId: { $eq: sessionId } } });
120
+ await sessionDataSet.remove(this.systemInjector, ...sessions.map((s) => s[sessionDataSet.primaryKey]));
148
121
  }
149
122
  }
150
123
  init() {
151
- this.getUserStore().addListener('onEntityUpdated', ({ id, change }) => {
124
+ this.getUserDataSet().addListener('onEntityUpdated', ({ id, change }) => {
152
125
  if (this.user?.username === id) {
153
126
  this.user = { ...this.user, ...change };
154
127
  }
155
128
  });
156
- this.getUserStore().addListener('onEntityRemoved', ({ key }) => {
129
+ this.getUserDataSet().addListener('onEntityRemoved', ({ key }) => {
157
130
  if (this.user?.username === key) {
158
131
  this.user = undefined;
159
132
  }
160
133
  });
161
- this.getSessionStore().addListener('onEntityRemoved', () => {
162
- this.user = undefined; // as user cannot be determined by the session id anymore
134
+ this.getSessionDataSet().addListener('onEntityRemoved', () => {
135
+ this.user = undefined;
163
136
  });
164
137
  }
165
138
  };
@@ -168,9 +141,9 @@ __decorate([
168
141
  __metadata("design:type", HttpAuthenticationSettings)
169
142
  ], HttpUserContext.prototype, "authentication", void 0);
170
143
  __decorate([
171
- Injected(StoreManager),
172
- __metadata("design:type", StoreManager)
173
- ], HttpUserContext.prototype, "storeManager", void 0);
144
+ Injected((injector) => useSystemIdentityContext({ injector, username: 'HttpUserContext' })),
145
+ __metadata("design:type", Function)
146
+ ], HttpUserContext.prototype, "systemInjector", void 0);
174
147
  __decorate([
175
148
  Injected(PasswordAuthenticator),
176
149
  __metadata("design:type", PasswordAuthenticator)
@@ -1 +1 @@
1
- {"version":3,"file":"http-user-context.js","sourceRoot":"","sources":["../src/http-user-context.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"http-user-context.js","sourceRoot":"","sources":["../src/http-user-context.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,5 @@
1
1
  import { Injector } from '@furystack/inject';
2
- export declare const prepareInjector: (i: Injector) => Promise<void>;
2
+ export declare const prepareInjector: (i: Injector, options?: {
3
+ enableBasicAuth?: boolean;
4
+ }) => Promise<void>;
3
5
  //# sourceMappingURL=http-user-context.spec.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"http-user-context.spec.d.ts","sourceRoot":"","sources":["../src/http-user-context.spec.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAS5C,eAAO,MAAM,eAAe,GAAU,GAAG,QAAQ,kBAMhD,CAAA"}
1
+ {"version":3,"file":"http-user-context.spec.d.ts","sourceRoot":"","sources":["../src/http-user-context.spec.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAgB5C,eAAO,MAAM,eAAe,GAAU,GAAG,QAAQ,EAAE,UAAU;IAAE,eAAe,CAAC,EAAE,OAAO,CAAA;CAAE,kBAczF,CAAA"}
@@ -1,17 +1,25 @@
1
1
  /* eslint-disable @typescript-eslint/ban-ts-comment */
2
- import { InMemoryStore, StoreManager, User, addStore } from '@furystack/core';
2
+ import { InMemoryStore, StoreManager, User, addStore, useSystemIdentityContext } from '@furystack/core';
3
3
  import { Injector } from '@furystack/inject';
4
- import { PasswordAuthenticator, PasswordCredential, UnauthenticatedError } from '@furystack/security';
4
+ import { getDataSetFor, getRepository } from '@furystack/repository';
5
+ import { PasswordAuthenticator, PasswordCredential, PasswordResetToken, UnauthenticatedError, usePasswordPolicy, } from '@furystack/security';
5
6
  import { usingAsync } from '@furystack/utils';
6
7
  import { describe, expect, it, vi } from 'vitest';
7
8
  import { useHttpAuthentication } from './helpers.js';
8
9
  import { HttpUserContext } from './http-user-context.js';
9
10
  import { DefaultSession } from './models/default-session.js';
10
- export const prepareInjector = async (i) => {
11
+ export const prepareInjector = async (i, options) => {
11
12
  addStore(i, new InMemoryStore({ model: User, primaryKey: 'username' }))
12
13
  .addStore(new InMemoryStore({ model: DefaultSession, primaryKey: 'sessionId' }))
13
- .addStore(new InMemoryStore({ model: PasswordCredential, primaryKey: 'userName' }));
14
- useHttpAuthentication(i);
14
+ .addStore(new InMemoryStore({ model: PasswordCredential, primaryKey: 'userName' }))
15
+ .addStore(new InMemoryStore({ model: PasswordResetToken, primaryKey: 'token' }));
16
+ const repo = getRepository(i);
17
+ repo.createDataSet(User, 'username');
18
+ repo.createDataSet(DefaultSession, 'sessionId');
19
+ repo.createDataSet(PasswordCredential, 'userName');
20
+ repo.createDataSet(PasswordResetToken, 'token');
21
+ usePasswordPolicy(i);
22
+ useHttpAuthentication(i, { enableBasicAuth: options?.enableBasicAuth ?? true });
15
23
  };
16
24
  const setupUser = async (i, userName, password) => {
17
25
  const sm = i.getInstance(StoreManager);
@@ -155,28 +163,25 @@ describe('HttpUserContext', () => {
155
163
  });
156
164
  });
157
165
  describe('authenticateRequest', () => {
158
- it('Should try to authenticate with Basic, if enabled', async () => {
166
+ it('Should authenticate with Basic Auth when enabled and valid credentials provided', async () => {
159
167
  await usingAsync(new Injector(), async (i) => {
160
168
  await prepareInjector(i);
169
+ await setupUser(i, 'testuser', 'password');
161
170
  const ctx = i.getInstance(HttpUserContext);
162
- ctx.authenticateUser = vi.fn(async () => testUser);
163
171
  const result = await ctx.authenticateRequest({
164
172
  headers: { authorization: `Basic dGVzdHVzZXI6cGFzc3dvcmQ=` },
165
173
  });
166
- expect(ctx.authenticateUser).toBeCalledWith('testuser', 'password');
167
- expect(result).toBe(testUser);
174
+ expect(result.username).toBe('testuser');
168
175
  });
169
176
  });
170
- it('Should NOT try to authenticate with Basic, if disabled', async () => {
177
+ it('Should NOT try to authenticate with Basic when disabled', async () => {
171
178
  await usingAsync(new Injector(), async (i) => {
172
- await prepareInjector(i);
179
+ await prepareInjector(i, { enableBasicAuth: false });
180
+ await setupUser(i, 'testuser', 'password');
173
181
  const ctx = i.getInstance(HttpUserContext);
174
- ctx.authentication.enableBasicAuth = false;
175
- ctx.authenticateUser = vi.fn(async () => testUser);
176
182
  await expect(ctx.authenticateRequest({
177
183
  headers: { authorization: `Basic dGVzdHVzZXI6cGFzc3dvcmQ=` },
178
184
  })).rejects.toThrowError(UnauthenticatedError);
179
- expect(ctx.authenticateUser).not.toBeCalled();
180
185
  });
181
186
  });
182
187
  it('Should fail with no session in the store', async () => {
@@ -192,9 +197,10 @@ describe('HttpUserContext', () => {
192
197
  await usingAsync(new Injector(), async (i) => {
193
198
  await prepareInjector(i);
194
199
  const ctx = i.getInstance(HttpUserContext);
195
- await ctx.authentication
196
- .getSessionStore(i.getInstance(StoreManager))
197
- .add({ sessionId: '666', username: testUser.username });
200
+ await i.getInstance(StoreManager).getStoreFor(DefaultSession, 'sessionId').add({
201
+ sessionId: '666',
202
+ username: testUser.username,
203
+ });
198
204
  await expect(ctx.authenticateRequest({
199
205
  headers: { cookie: `${ctx.authentication.cookieName}=666;a=3` },
200
206
  })).rejects.toThrowError(UnauthenticatedError);
@@ -204,16 +210,60 @@ describe('HttpUserContext', () => {
204
210
  await usingAsync(new Injector(), async (i) => {
205
211
  await prepareInjector(i);
206
212
  const ctx = i.getInstance(HttpUserContext);
207
- await ctx.authentication
208
- .getSessionStore(i.getInstance(StoreManager))
209
- .add({ sessionId: '666', username: testUser.username });
210
- await ctx.authentication.getUserStore(i.getInstance(StoreManager)).add({ ...testUser });
213
+ await i.getInstance(StoreManager).getStoreFor(DefaultSession, 'sessionId').add({
214
+ sessionId: '666',
215
+ username: testUser.username,
216
+ });
217
+ await i
218
+ .getInstance(StoreManager)
219
+ .getStoreFor(User, 'username')
220
+ .add({ ...testUser });
211
221
  const result = await ctx.authenticateRequest({
212
222
  headers: { cookie: `${ctx.authentication.cookieName}=666;a=3` },
213
223
  });
214
224
  expect(result).toEqual(testUser);
215
225
  });
216
226
  });
227
+ it('Should iterate providers and return null results pass to next', async () => {
228
+ await usingAsync(new Injector(), async (i) => {
229
+ await prepareInjector(i);
230
+ const ctx = i.getInstance(HttpUserContext);
231
+ const provider1 = vi.fn(async () => null);
232
+ const provider2 = vi.fn(async () => testUser);
233
+ ctx.authentication.authenticationProviders = [
234
+ { name: 'test-1', authenticate: provider1 },
235
+ { name: 'test-2', authenticate: provider2 },
236
+ ];
237
+ const result = await ctx.authenticateRequest(request);
238
+ expect(provider1).toHaveBeenCalledOnce();
239
+ expect(provider2).toHaveBeenCalledOnce();
240
+ expect(result).toBe(testUser);
241
+ });
242
+ });
243
+ it('Should throw if provider throws (skipping remaining providers)', async () => {
244
+ await usingAsync(new Injector(), async (i) => {
245
+ await prepareInjector(i);
246
+ const ctx = i.getInstance(HttpUserContext);
247
+ const provider1 = vi.fn(async () => {
248
+ throw new UnauthenticatedError();
249
+ });
250
+ const provider2 = vi.fn(async () => testUser);
251
+ ctx.authentication.authenticationProviders = [
252
+ { name: 'test-1', authenticate: provider1 },
253
+ { name: 'test-2', authenticate: provider2 },
254
+ ];
255
+ await expect(ctx.authenticateRequest(request)).rejects.toThrowError(UnauthenticatedError);
256
+ expect(provider2).not.toHaveBeenCalled();
257
+ });
258
+ });
259
+ it('Should throw UnauthenticatedError if no provider returns a user', async () => {
260
+ await usingAsync(new Injector(), async (i) => {
261
+ await prepareInjector(i);
262
+ const ctx = i.getInstance(HttpUserContext);
263
+ ctx.authentication.authenticationProviders = [{ name: 'test-1', authenticate: async () => null }];
264
+ await expect(ctx.authenticateRequest(request)).rejects.toThrowError(UnauthenticatedError);
265
+ });
266
+ });
217
267
  });
218
268
  describe('getCurrentUser', () => {
219
269
  it('Should return the current user from authenticateRequest() once per request', async () => {
@@ -235,14 +285,13 @@ describe('HttpUserContext', () => {
235
285
  await prepareInjector(i);
236
286
  const ctx = i.getInstance(HttpUserContext);
237
287
  const setHeader = vi.fn();
288
+ const addMock = vi.fn(async () => ({}));
238
289
  // @ts-expect-error
239
- ctx.getSessionStore().add = vi.fn(async () => {
240
- return {};
241
- });
290
+ ctx.getSessionDataSet = vi.fn(() => ({ add: addMock }));
242
291
  const authResult = await ctx.cookieLogin(testUser, { setHeader });
243
292
  expect(authResult).toBe(testUser);
244
293
  expect(setHeader).toBeCalled();
245
- expect(ctx.getSessionStore().add).toBeCalled();
294
+ expect(addMock).toBeCalled();
246
295
  });
247
296
  });
248
297
  });
@@ -252,18 +301,22 @@ describe('HttpUserContext', () => {
252
301
  await prepareInjector(i);
253
302
  const ctx = i.getInstance(HttpUserContext);
254
303
  const setHeader = vi.fn();
304
+ const removeMock = vi.fn(async () => undefined);
305
+ const sessionDataSetMock = {
306
+ add: vi.fn(async () => ({})),
307
+ find: vi.fn(async () => [{ sessionId: 'example-session-id' }]),
308
+ remove: removeMock,
309
+ primaryKey: 'sessionId',
310
+ };
255
311
  // @ts-expect-error
256
- ctx.getSessionStore().add = vi.fn(async () => {
257
- return {};
258
- });
312
+ ctx.getSessionDataSet = vi.fn(() => sessionDataSetMock);
259
313
  ctx.authenticateRequest = vi.fn(async () => testUser);
260
- ctx.getSessionStore().remove = vi.fn(async () => undefined);
261
314
  ctx.getSessionIdFromRequest = () => 'example-session-id';
262
315
  response.setHeader = vi.fn(() => response);
263
316
  await ctx.cookieLogin(testUser, { setHeader });
264
317
  await ctx.cookieLogout(request, response);
265
318
  expect(response.setHeader).toBeCalledWith('Set-Cookie', 'fss=; Path=/; HttpOnly');
266
- expect(ctx.getSessionStore().remove).toBeCalled();
319
+ expect(removeMock).toBeCalled();
267
320
  });
268
321
  });
269
322
  });
@@ -272,18 +325,20 @@ describe('HttpUserContext', () => {
272
325
  return usingAsync(new Injector(), async (i) => {
273
326
  await prepareInjector(i);
274
327
  const ctx = i.getInstance(HttpUserContext);
275
- const userStore = i.getInstance(StoreManager).getStoreFor(User, 'username');
276
- await userStore.add(testUser);
328
+ const sm = i.getInstance(StoreManager);
329
+ await sm.getStoreFor(User, 'username').add(testUser);
277
330
  const pw = await i.getInstance(PasswordAuthenticator).hasher.createCredential(testUser.username, 'test');
278
- await i.getInstance(StoreManager).getStoreFor(PasswordCredential, 'userName').add(pw);
331
+ await sm.getStoreFor(PasswordCredential, 'userName').add(pw);
279
332
  await ctx.cookieLogin(testUser, { setHeader: vi.fn() });
280
333
  const originalUser = await ctx.getCurrentUser(request);
281
334
  expect(originalUser).toEqual(testUser);
335
+ const systemInjector = useSystemIdentityContext({ injector: i, username: 'test' });
336
+ const userDataSet = getDataSetFor(systemInjector, User, 'username');
282
337
  const updatedUser = { ...testUser, roles: ['newFancyRole'] };
283
- await userStore.update(testUser.username, updatedUser);
338
+ await userDataSet.update(systemInjector, testUser.username, updatedUser);
284
339
  const updatedUserFromContext = await ctx.getCurrentUser(request);
285
340
  expect(updatedUserFromContext.roles).toEqual(['newFancyRole']);
286
- await userStore.update(testUser.username, { ...updatedUser, roles: [] });
341
+ await userDataSet.update(systemInjector, testUser.username, { ...updatedUser, roles: [] });
287
342
  const reloadedUserFromContext = await ctx.getCurrentUser(request);
288
343
  expect(reloadedUserFromContext.roles).toEqual([]);
289
344
  });
@@ -292,14 +347,16 @@ describe('HttpUserContext', () => {
292
347
  return usingAsync(new Injector(), async (i) => {
293
348
  await prepareInjector(i);
294
349
  const ctx = i.getInstance(HttpUserContext);
295
- const userStore = i.getInstance(StoreManager).getStoreFor(User, 'username');
296
- await userStore.add(testUser);
350
+ const sm = i.getInstance(StoreManager);
351
+ await sm.getStoreFor(User, 'username').add(testUser);
297
352
  const pw = await i.getInstance(PasswordAuthenticator).hasher.createCredential(testUser.username, 'test');
298
- await i.getInstance(StoreManager).getStoreFor(PasswordCredential, 'userName').add(pw);
353
+ await sm.getStoreFor(PasswordCredential, 'userName').add(pw);
299
354
  await ctx.cookieLogin(testUser, { setHeader: vi.fn() });
300
355
  const originalUser = await ctx.getCurrentUser(request);
301
356
  expect(originalUser).toEqual(testUser);
302
- await userStore.remove(testUser.username);
357
+ const systemInjector = useSystemIdentityContext({ injector: i, username: 'test' });
358
+ const userDataSet = getDataSetFor(systemInjector, User, 'username');
359
+ await userDataSet.remove(systemInjector, testUser.username);
303
360
  await expect(() => ctx.getCurrentUser(request)).rejects.toThrowError(UnauthenticatedError);
304
361
  });
305
362
  });
@@ -307,21 +364,22 @@ describe('HttpUserContext', () => {
307
364
  return usingAsync(new Injector(), async (i) => {
308
365
  await prepareInjector(i);
309
366
  const ctx = i.getInstance(HttpUserContext);
310
- const userStore = i.getInstance(StoreManager).getStoreFor(User, 'username');
311
- await userStore.add(testUser);
367
+ const sm = i.getInstance(StoreManager);
368
+ await sm.getStoreFor(User, 'username').add(testUser);
312
369
  let sessionId = '';
313
370
  const pw = await i.getInstance(PasswordAuthenticator).hasher.createCredential(testUser.username, 'test');
314
- await i.getInstance(StoreManager).getStoreFor(PasswordCredential, 'userName').add(pw);
371
+ await sm.getStoreFor(PasswordCredential, 'userName').add(pw);
315
372
  await ctx.cookieLogin(testUser, {
316
373
  setHeader: (_headerName, headerValue) => {
317
- sessionId = headerValue;
374
+ sessionId = headerValue.split('=')[1].split(';')[0];
318
375
  return {};
319
376
  },
320
377
  });
321
378
  const originalUser = await ctx.getCurrentUser(request);
322
379
  expect(originalUser).toEqual(testUser);
323
- const sessionStore = ctx.getSessionStore();
324
- await sessionStore.remove(sessionId);
380
+ const systemInjector = useSystemIdentityContext({ injector: i, username: 'test' });
381
+ const sessionDataSet = getDataSetFor(systemInjector, DefaultSession, 'sessionId');
382
+ await sessionDataSet.remove(systemInjector, sessionId);
325
383
  await expect(() => ctx.getCurrentUser(request)).rejects.toThrowError(UnauthenticatedError);
326
384
  });
327
385
  });