@furystack/rest-service 4.0.19

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 (285) hide show
  1. package/LICENSE +339 -0
  2. package/README.md +219 -0
  3. package/dist/actions/error-action.d.ts +14 -0
  4. package/dist/actions/error-action.d.ts.map +1 -0
  5. package/dist/actions/error-action.js +29 -0
  6. package/dist/actions/error-action.js.map +1 -0
  7. package/dist/actions/error-action.spec.d.ts +2 -0
  8. package/dist/actions/error-action.spec.d.ts.map +1 -0
  9. package/dist/actions/error-action.spec.js +51 -0
  10. package/dist/actions/error-action.spec.js.map +1 -0
  11. package/dist/actions/get-current-user.d.ts +11 -0
  12. package/dist/actions/get-current-user.d.ts.map +1 -0
  13. package/dist/actions/get-current-user.js +15 -0
  14. package/dist/actions/get-current-user.js.map +1 -0
  15. package/dist/actions/get-current-user.spec.d.ts +2 -0
  16. package/dist/actions/get-current-user.spec.d.ts.map +1 -0
  17. package/dist/actions/get-current-user.spec.js +20 -0
  18. package/dist/actions/get-current-user.spec.js.map +1 -0
  19. package/dist/actions/index.d.ts +7 -0
  20. package/dist/actions/index.d.ts.map +1 -0
  21. package/dist/actions/index.js +10 -0
  22. package/dist/actions/index.js.map +1 -0
  23. package/dist/actions/is-authenticated.d.ts +14 -0
  24. package/dist/actions/is-authenticated.d.ts.map +1 -0
  25. package/dist/actions/is-authenticated.js +17 -0
  26. package/dist/actions/is-authenticated.js.map +1 -0
  27. package/dist/actions/is-authenticated.spec.d.ts +2 -0
  28. package/dist/actions/is-authenticated.spec.d.ts.map +1 -0
  29. package/dist/actions/is-authenticated.spec.js +19 -0
  30. package/dist/actions/is-authenticated.spec.js.map +1 -0
  31. package/dist/actions/login-action.spec.d.ts +2 -0
  32. package/dist/actions/login-action.spec.d.ts.map +1 -0
  33. package/dist/actions/login-action.spec.js +35 -0
  34. package/dist/actions/login-action.spec.js.map +1 -0
  35. package/dist/actions/login.d.ts +16 -0
  36. package/dist/actions/login.d.ts.map +1 -0
  37. package/dist/actions/login.js +26 -0
  38. package/dist/actions/login.js.map +1 -0
  39. package/dist/actions/logout-action.spec.d.ts +2 -0
  40. package/dist/actions/logout-action.spec.d.ts.map +1 -0
  41. package/dist/actions/logout-action.spec.js +23 -0
  42. package/dist/actions/logout-action.spec.js.map +1 -0
  43. package/dist/actions/logout.d.ts +14 -0
  44. package/dist/actions/logout.d.ts.map +1 -0
  45. package/dist/actions/logout.js +20 -0
  46. package/dist/actions/logout.js.map +1 -0
  47. package/dist/actions/not-found-action.d.ts +10 -0
  48. package/dist/actions/not-found-action.d.ts.map +1 -0
  49. package/dist/actions/not-found-action.js +14 -0
  50. package/dist/actions/not-found-action.js.map +1 -0
  51. package/dist/actions/not-found-action.spec.d.ts +2 -0
  52. package/dist/actions/not-found-action.spec.d.ts.map +1 -0
  53. package/dist/actions/not-found-action.spec.js +17 -0
  54. package/dist/actions/not-found-action.spec.js.map +1 -0
  55. package/dist/add-cors-header.spec.d.ts +2 -0
  56. package/dist/add-cors-header.spec.d.ts.map +1 -0
  57. package/dist/add-cors-header.spec.js +99 -0
  58. package/dist/add-cors-header.spec.js.map +1 -0
  59. package/dist/api-manager.d.ts +61 -0
  60. package/dist/api-manager.d.ts.map +1 -0
  61. package/dist/api-manager.js +144 -0
  62. package/dist/api-manager.js.map +1 -0
  63. package/dist/authenticate.d.ts +5 -0
  64. package/dist/authenticate.d.ts.map +1 -0
  65. package/dist/authenticate.js +20 -0
  66. package/dist/authenticate.js.map +1 -0
  67. package/dist/authenticate.spec.d.ts +2 -0
  68. package/dist/authenticate.spec.d.ts.map +1 -0
  69. package/dist/authenticate.spec.js +59 -0
  70. package/dist/authenticate.spec.js.map +1 -0
  71. package/dist/authorize.d.ts +5 -0
  72. package/dist/authorize.d.ts.map +1 -0
  73. package/dist/authorize.js +22 -0
  74. package/dist/authorize.js.map +1 -0
  75. package/dist/authorize.spec.d.ts +2 -0
  76. package/dist/authorize.spec.d.ts.map +1 -0
  77. package/dist/authorize.spec.js +55 -0
  78. package/dist/authorize.spec.js.map +1 -0
  79. package/dist/endpoint-generators/create-delete-endpoint.d.ts +17 -0
  80. package/dist/endpoint-generators/create-delete-endpoint.d.ts.map +1 -0
  81. package/dist/endpoint-generators/create-delete-endpoint.js +24 -0
  82. package/dist/endpoint-generators/create-delete-endpoint.js.map +1 -0
  83. package/dist/endpoint-generators/create-delete-endpoint.spec.d.ts +2 -0
  84. package/dist/endpoint-generators/create-delete-endpoint.spec.d.ts.map +1 -0
  85. package/dist/endpoint-generators/create-delete-endpoint.spec.js +33 -0
  86. package/dist/endpoint-generators/create-delete-endpoint.spec.js.map +1 -0
  87. package/dist/endpoint-generators/create-get-collection-endpoint.d.ts +17 -0
  88. package/dist/endpoint-generators/create-get-collection-endpoint.d.ts.map +1 -0
  89. package/dist/endpoint-generators/create-get-collection-endpoint.js +26 -0
  90. package/dist/endpoint-generators/create-get-collection-endpoint.js.map +1 -0
  91. package/dist/endpoint-generators/create-get-collection-endpoint.spec.d.ts +2 -0
  92. package/dist/endpoint-generators/create-get-collection-endpoint.spec.d.ts.map +1 -0
  93. package/dist/endpoint-generators/create-get-collection-endpoint.spec.js +143 -0
  94. package/dist/endpoint-generators/create-get-collection-endpoint.spec.js.map +1 -0
  95. package/dist/endpoint-generators/create-get-entity-endpoint.d.ts +17 -0
  96. package/dist/endpoint-generators/create-get-entity-endpoint.d.ts.map +1 -0
  97. package/dist/endpoint-generators/create-get-entity-endpoint.js +29 -0
  98. package/dist/endpoint-generators/create-get-entity-endpoint.js.map +1 -0
  99. package/dist/endpoint-generators/create-get-entity-endpoint.spec.d.ts +2 -0
  100. package/dist/endpoint-generators/create-get-entity-endpoint.spec.d.ts.map +1 -0
  101. package/dist/endpoint-generators/create-get-entity-endpoint.spec.js +74 -0
  102. package/dist/endpoint-generators/create-get-entity-endpoint.spec.js.map +1 -0
  103. package/dist/endpoint-generators/create-patch-endpoint.d.ts +18 -0
  104. package/dist/endpoint-generators/create-patch-endpoint.d.ts.map +1 -0
  105. package/dist/endpoint-generators/create-patch-endpoint.js +26 -0
  106. package/dist/endpoint-generators/create-patch-endpoint.js.map +1 -0
  107. package/dist/endpoint-generators/create-patch-endpoint.spec.d.ts +2 -0
  108. package/dist/endpoint-generators/create-patch-endpoint.spec.d.ts.map +1 -0
  109. package/dist/endpoint-generators/create-patch-endpoint.spec.js +36 -0
  110. package/dist/endpoint-generators/create-patch-endpoint.spec.js.map +1 -0
  111. package/dist/endpoint-generators/create-post-endpoint.d.ts +18 -0
  112. package/dist/endpoint-generators/create-post-endpoint.d.ts.map +1 -0
  113. package/dist/endpoint-generators/create-post-endpoint.js +29 -0
  114. package/dist/endpoint-generators/create-post-endpoint.js.map +1 -0
  115. package/dist/endpoint-generators/create-post-endpoint.spec.d.ts +2 -0
  116. package/dist/endpoint-generators/create-post-endpoint.spec.d.ts.map +1 -0
  117. package/dist/endpoint-generators/create-post-endpoint.spec.js +34 -0
  118. package/dist/endpoint-generators/create-post-endpoint.spec.js.map +1 -0
  119. package/dist/endpoint-generators/index.d.ts +6 -0
  120. package/dist/endpoint-generators/index.d.ts.map +1 -0
  121. package/dist/endpoint-generators/index.js +9 -0
  122. package/dist/endpoint-generators/index.js.map +1 -0
  123. package/dist/endpoint-generators/utils.d.ts +9 -0
  124. package/dist/endpoint-generators/utils.d.ts.map +1 -0
  125. package/dist/endpoint-generators/utils.js +27 -0
  126. package/dist/endpoint-generators/utils.js.map +1 -0
  127. package/dist/http-authentication-settings.d.ts +17 -0
  128. package/dist/http-authentication-settings.d.ts.map +1 -0
  129. package/dist/http-authentication-settings.js +26 -0
  130. package/dist/http-authentication-settings.js.map +1 -0
  131. package/dist/http-user-context.d.ts +54 -0
  132. package/dist/http-user-context.d.ts.map +1 -0
  133. package/dist/http-user-context.js +153 -0
  134. package/dist/http-user-context.js.map +1 -0
  135. package/dist/http-user-context.spec.d.ts +4 -0
  136. package/dist/http-user-context.spec.d.ts.map +1 -0
  137. package/dist/http-user-context.spec.js +267 -0
  138. package/dist/http-user-context.spec.js.map +1 -0
  139. package/dist/incoming-message-extensions.d.ts +8 -0
  140. package/dist/incoming-message-extensions.d.ts.map +1 -0
  141. package/dist/incoming-message-extensions.js +14 -0
  142. package/dist/incoming-message-extensions.js.map +1 -0
  143. package/dist/incoming-message-extensions.spec.d.ts +2 -0
  144. package/dist/incoming-message-extensions.spec.d.ts.map +1 -0
  145. package/dist/incoming-message-extensions.spec.js +39 -0
  146. package/dist/incoming-message-extensions.spec.js.map +1 -0
  147. package/dist/index.d.ts +17 -0
  148. package/dist/index.d.ts.map +1 -0
  149. package/dist/index.js +20 -0
  150. package/dist/index.js.map +1 -0
  151. package/dist/injector-extensions.d.ts +21 -0
  152. package/dist/injector-extensions.d.ts.map +1 -0
  153. package/dist/injector-extensions.js +14 -0
  154. package/dist/injector-extensions.js.map +1 -0
  155. package/dist/injector-extensions.spec.d.ts +2 -0
  156. package/dist/injector-extensions.spec.d.ts.map +1 -0
  157. package/dist/injector-extensions.spec.js +19 -0
  158. package/dist/injector-extensions.spec.js.map +1 -0
  159. package/dist/models/cors-options.d.ts +22 -0
  160. package/dist/models/cors-options.d.ts.map +1 -0
  161. package/dist/models/cors-options.js +3 -0
  162. package/dist/models/cors-options.js.map +1 -0
  163. package/dist/models/default-session.d.ts +14 -0
  164. package/dist/models/default-session.d.ts.map +1 -0
  165. package/dist/models/default-session.js +10 -0
  166. package/dist/models/default-session.js.map +1 -0
  167. package/dist/request-action-implementation.d.ts +54 -0
  168. package/dist/request-action-implementation.d.ts.map +1 -0
  169. package/dist/request-action-implementation.js +42 -0
  170. package/dist/request-action-implementation.js.map +1 -0
  171. package/dist/rest-service.integration.spec.d.ts +2 -0
  172. package/dist/rest-service.integration.spec.d.ts.map +1 -0
  173. package/dist/rest-service.integration.spec.js +129 -0
  174. package/dist/rest-service.integration.spec.js.map +1 -0
  175. package/dist/rest.integration.test.d.ts +58 -0
  176. package/dist/rest.integration.test.d.ts.map +1 -0
  177. package/dist/rest.integration.test.js +94 -0
  178. package/dist/rest.integration.test.js.map +1 -0
  179. package/dist/schema-validator/index.d.ts +3 -0
  180. package/dist/schema-validator/index.d.ts.map +1 -0
  181. package/dist/schema-validator/index.js +6 -0
  182. package/dist/schema-validator/index.js.map +1 -0
  183. package/dist/schema-validator/schema-validation-error.d.ts +10 -0
  184. package/dist/schema-validator/schema-validation-error.d.ts.map +1 -0
  185. package/dist/schema-validator/schema-validation-error.js +15 -0
  186. package/dist/schema-validator/schema-validation-error.js.map +1 -0
  187. package/dist/schema-validator/schema-validator.d.ts +20 -0
  188. package/dist/schema-validator/schema-validator.d.ts.map +1 -0
  189. package/dist/schema-validator/schema-validator.js +36 -0
  190. package/dist/schema-validator/schema-validator.js.map +1 -0
  191. package/dist/schema-validator/schema-validator.test.d.ts +2 -0
  192. package/dist/schema-validator/schema-validator.test.d.ts.map +1 -0
  193. package/dist/schema-validator/schema-validator.test.js +62 -0
  194. package/dist/schema-validator/schema-validator.test.js.map +1 -0
  195. package/dist/schema-validator/validate-examples.d.ts +37 -0
  196. package/dist/schema-validator/validate-examples.d.ts.map +1 -0
  197. package/dist/schema-validator/validate-examples.js +29 -0
  198. package/dist/schema-validator/validate-examples.js.map +1 -0
  199. package/dist/server-manager.d.ts +30 -0
  200. package/dist/server-manager.d.ts.map +1 -0
  201. package/dist/server-manager.js +71 -0
  202. package/dist/server-manager.js.map +1 -0
  203. package/dist/server-response-extensions.d.ts +21 -0
  204. package/dist/server-response-extensions.d.ts.map +1 -0
  205. package/dist/server-response-extensions.js +15 -0
  206. package/dist/server-response-extensions.js.map +1 -0
  207. package/dist/server-response-extensions.spec.d.ts +2 -0
  208. package/dist/server-response-extensions.spec.d.ts.map +1 -0
  209. package/dist/server-response-extensions.spec.js +49 -0
  210. package/dist/server-response-extensions.spec.js.map +1 -0
  211. package/dist/utils.d.ts +24 -0
  212. package/dist/utils.d.ts.map +1 -0
  213. package/dist/utils.js +66 -0
  214. package/dist/utils.js.map +1 -0
  215. package/dist/validate.d.ts +18 -0
  216. package/dist/validate.d.ts.map +1 -0
  217. package/dist/validate.integration.schema.d.ts +69 -0
  218. package/dist/validate.integration.schema.d.ts.map +1 -0
  219. package/dist/validate.integration.schema.js +3 -0
  220. package/dist/validate.integration.schema.js.map +1 -0
  221. package/dist/validate.integration.spec.d.ts +13 -0
  222. package/dist/validate.integration.spec.d.ts.map +1 -0
  223. package/dist/validate.integration.spec.js +223 -0
  224. package/dist/validate.integration.spec.js.map +1 -0
  225. package/dist/validate.integration.spec.schema.json +749 -0
  226. package/dist/validate.js +49 -0
  227. package/dist/validate.js.map +1 -0
  228. package/package.json +56 -0
  229. package/src/actions/error-action.spec.ts +54 -0
  230. package/src/actions/error-action.ts +34 -0
  231. package/src/actions/get-current-user.spec.ts +23 -0
  232. package/src/actions/get-current-user.ts +15 -0
  233. package/src/actions/index.ts +6 -0
  234. package/src/actions/is-authenticated.spec.ts +18 -0
  235. package/src/actions/is-authenticated.ts +13 -0
  236. package/src/actions/login-action.spec.ts +41 -0
  237. package/src/actions/login.ts +26 -0
  238. package/src/actions/logout-action.spec.ts +27 -0
  239. package/src/actions/logout.ts +16 -0
  240. package/src/actions/not-found-action.spec.ts +17 -0
  241. package/src/actions/not-found-action.ts +13 -0
  242. package/src/add-cors-header.spec.ts +133 -0
  243. package/src/api-manager.ts +222 -0
  244. package/src/authenticate.spec.ts +78 -0
  245. package/src/authenticate.ts +22 -0
  246. package/src/authorize.spec.ts +69 -0
  247. package/src/authorize.ts +19 -0
  248. package/src/endpoint-generators/create-delete-endpoint.spec.ts +34 -0
  249. package/src/endpoint-generators/create-delete-endpoint.ts +25 -0
  250. package/src/endpoint-generators/create-get-collection-endpoint.spec.ts +164 -0
  251. package/src/endpoint-generators/create-get-collection-endpoint.ts +28 -0
  252. package/src/endpoint-generators/create-get-entity-endpoint.spec.ts +75 -0
  253. package/src/endpoint-generators/create-get-entity-endpoint.ts +29 -0
  254. package/src/endpoint-generators/create-patch-endpoint.spec.ts +36 -0
  255. package/src/endpoint-generators/create-patch-endpoint.ts +27 -0
  256. package/src/endpoint-generators/create-post-endpoint.spec.ts +32 -0
  257. package/src/endpoint-generators/create-post-endpoint.ts +30 -0
  258. package/src/endpoint-generators/index.ts +5 -0
  259. package/src/endpoint-generators/utils.ts +34 -0
  260. package/src/http-authentication-settings.ts +23 -0
  261. package/src/http-user-context.spec.ts +299 -0
  262. package/src/http-user-context.ts +160 -0
  263. package/src/incoming-message-extensions.spec.ts +41 -0
  264. package/src/incoming-message-extensions.ts +19 -0
  265. package/src/index.ts +16 -0
  266. package/src/injector-extensions.spec.ts +19 -0
  267. package/src/injector-extensions.ts +35 -0
  268. package/src/models/cors-options.ts +21 -0
  269. package/src/models/default-session.ts +14 -0
  270. package/src/request-action-implementation.ts +70 -0
  271. package/src/rest-service.integration.spec.ts +166 -0
  272. package/src/rest.integration.test.ts +112 -0
  273. package/src/schema-validator/index.ts +2 -0
  274. package/src/schema-validator/schema-validation-error.ts +11 -0
  275. package/src/schema-validator/schema-validator.test.ts +72 -0
  276. package/src/schema-validator/schema-validator.ts +31 -0
  277. package/src/schema-validator/validate-examples.ts +38 -0
  278. package/src/server-manager.ts +88 -0
  279. package/src/server-response-extensions.spec.ts +53 -0
  280. package/src/server-response-extensions.ts +30 -0
  281. package/src/utils.ts +65 -0
  282. package/src/validate.integration.schema.ts +50 -0
  283. package/src/validate.integration.spec.schema.json +779 -0
  284. package/src/validate.integration.spec.ts +218 -0
  285. package/src/validate.ts +60 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-authentication-settings.d.ts","sourceRoot":"","sources":["../src/http-authentication-settings.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AACnE,OAAO,EAAE,aAAa,EAAc,MAAM,mBAAmB,CAAA;AAE7D,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAEzD;;GAEG;AACH,qBACa,0BAA0B,CAAC,KAAK,SAAS,IAAI,EAAE,QAAQ,SAAS,cAAc;IAClF,KAAK,EAAE,aAAa,CAAC,KAAK,CAAC,CAA+B;IAE1D,YAAY,EAAE,CAAC,YAAY,EAAE,YAAY,KAAK,aAAa,CAAC,KAAK,GAAG;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,EAAE,MAAM,KAAK,CAAC,CAEtB;IAEhF,eAAe,EAAE,CAAC,YAAY,EAAE,YAAY,KAAK,aAAa,CAAC,QAAQ,EAAE,MAAM,QAAQ,CAAC,CACI;IAE5F,UAAU,SAAQ;IAClB,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAkD;IACvF,eAAe,UAAO;CAC9B"}
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HttpAuthenticationSettings = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const core_1 = require("@furystack/core");
6
+ const inject_1 = require("@furystack/inject");
7
+ const hash_js_1 = require("hash.js");
8
+ const default_session_1 = require("./models/default-session");
9
+ /**
10
+ * Authentication settings object for FuryStack HTTP Api
11
+ */
12
+ let HttpAuthenticationSettings = class HttpAuthenticationSettings {
13
+ constructor() {
14
+ this.model = core_1.User;
15
+ this.getUserStore = (sm) => sm.getStoreFor(core_1.User, 'username');
16
+ this.getSessionStore = (sm) => sm.getStoreFor(default_session_1.DefaultSession, 'sessionId');
17
+ this.cookieName = 'fss';
18
+ this.hashMethod = (plain) => (0, hash_js_1.sha256)().update(plain).digest('hex');
19
+ this.enableBasicAuth = true;
20
+ }
21
+ };
22
+ HttpAuthenticationSettings = (0, tslib_1.__decorate)([
23
+ (0, inject_1.Injectable)({ lifetime: 'singleton' })
24
+ ], HttpAuthenticationSettings);
25
+ exports.HttpAuthenticationSettings = HttpAuthenticationSettings;
26
+ //# sourceMappingURL=http-authentication-settings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-authentication-settings.js","sourceRoot":"","sources":["../src/http-authentication-settings.ts"],"names":[],"mappings":";;;;AAAA,0CAAmE;AACnE,8CAA6D;AAC7D,qCAAgC;AAChC,8DAAyD;AAEzD;;GAEG;AAEH,IAAa,0BAA0B,GAAvC,MAAa,0BAA0B;IAAvC;QACS,UAAK,GAAyB,WAA4B,CAAA;QAE1D,iBAAY,GAA6F,CAC9G,EAAE,EACF,EAAE,CAAC,EAAE,CAAC,WAAW,CAA4C,WAAW,EAAE,UAAU,CAAC,CAAA;QAEhF,oBAAe,GAA4E,CAAC,EAAE,EAAE,EAAE,CACvG,EAAE,CAAC,WAAW,CAAC,gCAAc,EAAE,WAAW,CAAuD,CAAA;QAE5F,eAAU,GAAG,KAAK,CAAA;QAClB,eAAU,GAA8B,CAAC,KAAK,EAAE,EAAE,CAAC,IAAA,gBAAM,GAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QACvF,oBAAe,GAAG,IAAI,CAAA;IAC/B,CAAC;CAAA,CAAA;AAbY,0BAA0B;IADtC,IAAA,mBAAU,EAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;GACzB,0BAA0B,CAatC;AAbY,gEAA0B"}
@@ -0,0 +1,54 @@
1
+ import { IncomingMessage, ServerResponse } from 'http';
2
+ import { User, StoreManager } from '@furystack/core';
3
+ import { HttpAuthenticationSettings } from './http-authentication-settings';
4
+ import { DefaultSession } from 'models/default-session';
5
+ /**
6
+ * Injectable UserContext for FuryStack HTTP Api
7
+ */
8
+ export declare class HttpUserContext {
9
+ readonly authentication: HttpAuthenticationSettings<User, DefaultSession>;
10
+ private readonly storeManager;
11
+ getUserStore: () => import("@furystack/core").PhysicalStore<User & {
12
+ password: string;
13
+ }, keyof User>;
14
+ getSessionStore: () => import("@furystack/core").PhysicalStore<DefaultSession, keyof DefaultSession>;
15
+ private user?;
16
+ /**
17
+ * @param request The request to be authenticated
18
+ * @returns if the current user is authenticated
19
+ */
20
+ isAuthenticated(request: IncomingMessage): Promise<boolean>;
21
+ /**
22
+ * Returns if the current user can be authorized with ALL of the specified roles
23
+ *
24
+ * @param request The request to be authenticated
25
+ * @param roles The list of roles to authorize
26
+ * @returns a boolean value that indicates if the user is authenticated
27
+ */
28
+ isAuthorized(request: IncomingMessage, ...roles: string[]): Promise<boolean>;
29
+ /**
30
+ * Checks if the system contains a user with the provided name and password, throws an error otherwise
31
+ *
32
+ * @param userName The username
33
+ * @param password The password
34
+ * @returns the authenticated User
35
+ */
36
+ authenticateUser(userName: string, password: string): Promise<{
37
+ username: string;
38
+ roles: string[];
39
+ }>;
40
+ getCurrentUser(request: IncomingMessage): Promise<User>;
41
+ getSessionIdFromRequest(request: IncomingMessage): string | null;
42
+ authenticateRequest(request: IncomingMessage): Promise<User>;
43
+ /**
44
+ * Creates and sets up a cookie-based session for the provided user
45
+ *
46
+ * @param user The user to create a session for
47
+ * @param serverResponse A serverResponse to set the cookie
48
+ * @returns the current User
49
+ */
50
+ cookieLogin(user: User, serverResponse: ServerResponse): Promise<User>;
51
+ cookieLogout(request: IncomingMessage, response: ServerResponse): Promise<void>;
52
+ constructor(authentication: HttpAuthenticationSettings<User, DefaultSession>, storeManager: StoreManager);
53
+ }
54
+ //# sourceMappingURL=http-user-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-user-context.d.ts","sourceRoot":"","sources":["../src/http-user-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,MAAM,CAAA;AACtD,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAGpD,OAAO,EAAE,0BAA0B,EAAE,MAAM,gCAAgC,CAAA;AAC3E,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAEvD;;GAEG;AACH,qBACa,eAAe;aAiJR,cAAc,EAAE,0BAA0B,CAAC,IAAI,EAAE,cAAc,CAAC;IAChF,OAAO,CAAC,QAAQ,CAAC,YAAY;IAjJxB,YAAY;;mBAA4D;IAExE,eAAe,sFAA+D;IAErF,OAAO,CAAC,IAAI,CAAC,CAAM;IAEnB;;;OAGG;IACU,eAAe,CAAC,OAAO,EAAE,eAAe;IASrD;;;;;;OAMG;IACU,YAAY,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAUzF;;;;;;OAMG;IACU,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;;;;IAkBnD,cAAc,CAAC,OAAO,EAAE,eAAe;IAQ7C,uBAAuB,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,GAAG,IAAI;IAkB1D,mBAAmB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IA8BzE;;;;;;OAMG;IACU,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,cAAc,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAQtE,YAAY,CAAC,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,cAAc;gBAY1D,cAAc,EAAE,0BAA0B,CAAC,IAAI,EAAE,cAAc,CAAC,EAC/D,YAAY,EAAE,YAAY;CAE9C"}
@@ -0,0 +1,153 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HttpUserContext = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const core_1 = require("@furystack/core");
6
+ const inject_1 = require("@furystack/inject");
7
+ const uuid_1 = require("uuid");
8
+ const http_authentication_settings_1 = require("./http-authentication-settings");
9
+ /**
10
+ * Injectable UserContext for FuryStack HTTP Api
11
+ */
12
+ let HttpUserContext = class HttpUserContext {
13
+ constructor(authentication, storeManager) {
14
+ this.authentication = authentication;
15
+ this.storeManager = storeManager;
16
+ this.getUserStore = () => this.authentication.getUserStore(this.storeManager);
17
+ this.getSessionStore = () => this.authentication.getSessionStore(this.storeManager);
18
+ }
19
+ /**
20
+ * @param request The request to be authenticated
21
+ * @returns if the current user is authenticated
22
+ */
23
+ async isAuthenticated(request) {
24
+ try {
25
+ const currentUser = await this.getCurrentUser(request);
26
+ return currentUser !== null;
27
+ }
28
+ catch (error) {
29
+ return false;
30
+ }
31
+ }
32
+ /**
33
+ * Returns if the current user can be authorized with ALL of the specified roles
34
+ *
35
+ * @param request The request to be authenticated
36
+ * @param roles The list of roles to authorize
37
+ * @returns a boolean value that indicates if the user is authenticated
38
+ */
39
+ async isAuthorized(request, ...roles) {
40
+ const currentUser = await this.getCurrentUser(request);
41
+ for (const role of roles) {
42
+ if (!currentUser || !currentUser.roles.some((c) => c === role)) {
43
+ return false;
44
+ }
45
+ }
46
+ return true;
47
+ }
48
+ /**
49
+ * Checks if the system contains a user with the provided name and password, throws an error otherwise
50
+ *
51
+ * @param userName The username
52
+ * @param password The password
53
+ * @returns the authenticated User
54
+ */
55
+ async authenticateUser(userName, password) {
56
+ const match = (password &&
57
+ password.length &&
58
+ (await this.getUserStore().find({
59
+ filter: {
60
+ username: { $eq: userName },
61
+ password: { $eq: this.authentication.hashMethod(password) },
62
+ },
63
+ }))) ||
64
+ [];
65
+ if (match.length === 1) {
66
+ const { password: pw, ...user } = match[0];
67
+ return user;
68
+ }
69
+ throw Error('Failed to authenticate.');
70
+ }
71
+ async getCurrentUser(request) {
72
+ if (!this.user) {
73
+ this.user = await this.authenticateRequest(request);
74
+ return this.user;
75
+ }
76
+ return this.user;
77
+ }
78
+ getSessionIdFromRequest(request) {
79
+ if (request.headers.cookie) {
80
+ const cookies = request.headers.cookie
81
+ .toString()
82
+ .split(';')
83
+ .filter((val) => val.length > 0)
84
+ .map((val) => {
85
+ const [name, value] = val.split('=');
86
+ return { name: name.trim(), value: value.trim() };
87
+ });
88
+ const sessionCookie = cookies.find((c) => c.name === this.authentication.cookieName);
89
+ if (sessionCookie) {
90
+ return sessionCookie.value;
91
+ }
92
+ }
93
+ return null;
94
+ }
95
+ async authenticateRequest(request) {
96
+ // Basic auth
97
+ if (this.authentication.enableBasicAuth && request.headers.authorization) {
98
+ const authData = Buffer.from(request.headers.authorization.toString().split(' ')[1], 'base64');
99
+ const [userName, password] = authData.toString().split(':');
100
+ return await this.authenticateUser(userName, password);
101
+ }
102
+ // Cookie auth
103
+ const sessionId = this.getSessionIdFromRequest(request);
104
+ if (sessionId) {
105
+ const [session] = await this.getSessionStore().find({ filter: { sessionId: { $eq: sessionId } }, top: 2 });
106
+ if (session) {
107
+ const userResult = await this.getUserStore().find({
108
+ filter: {
109
+ username: { $eq: session.username },
110
+ },
111
+ top: 2,
112
+ });
113
+ if (userResult.length === 1) {
114
+ const { password, ...user } = userResult[0];
115
+ return user;
116
+ }
117
+ throw Error('Inconsistent session result');
118
+ }
119
+ }
120
+ throw Error('Failed to authenticate request');
121
+ }
122
+ /**
123
+ * Creates and sets up a cookie-based session for the provided user
124
+ *
125
+ * @param user The user to create a session for
126
+ * @param serverResponse A serverResponse to set the cookie
127
+ * @returns the current User
128
+ */
129
+ async cookieLogin(user, serverResponse) {
130
+ const sessionId = (0, uuid_1.v1)();
131
+ await this.getSessionStore().add({ sessionId, username: user.username });
132
+ serverResponse.setHeader('Set-Cookie', `${this.authentication.cookieName}=${sessionId}; Path=/; HttpOnly`);
133
+ this.user = user;
134
+ return user;
135
+ }
136
+ async cookieLogout(request, response) {
137
+ const sessionId = this.getSessionIdFromRequest(request);
138
+ response.setHeader('Set-Cookie', `${this.authentication.cookieName}=; Path=/; HttpOnly`);
139
+ this.user = undefined;
140
+ if (sessionId) {
141
+ const sessionStore = this.getSessionStore();
142
+ const sessions = await sessionStore.find({ filter: { sessionId: { $eq: sessionId } } });
143
+ await this.getSessionStore().remove(...sessions.map((s) => s[sessionStore.primaryKey]));
144
+ }
145
+ }
146
+ };
147
+ HttpUserContext = (0, tslib_1.__decorate)([
148
+ (0, inject_1.Injectable)({ lifetime: 'scoped' }),
149
+ (0, tslib_1.__metadata)("design:paramtypes", [http_authentication_settings_1.HttpAuthenticationSettings,
150
+ core_1.StoreManager])
151
+ ], HttpUserContext);
152
+ exports.HttpUserContext = HttpUserContext;
153
+ //# sourceMappingURL=http-user-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-user-context.js","sourceRoot":"","sources":["../src/http-user-context.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { Injector } from '@furystack/inject';
2
+ import './injector-extensions';
3
+ export declare const prepareInjector: (i: Injector) => Promise<void>;
4
+ //# sourceMappingURL=http-user-context.spec.d.ts.map
@@ -0,0 +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;AAI5C,OAAO,uBAAuB,CAAA;AAE9B,eAAO,MAAM,eAAe,MAAa,QAAQ,kBAShD,CAAA"}
@@ -0,0 +1,267 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.prepareInjector = void 0;
4
+ const utils_1 = require("@furystack/utils");
5
+ const inject_1 = require("@furystack/inject");
6
+ const core_1 = require("@furystack/core");
7
+ const default_session_1 = require("./models/default-session");
8
+ const http_user_context_1 = require("./http-user-context");
9
+ require("./injector-extensions");
10
+ const prepareInjector = async (i) => {
11
+ i.setupStores((sm) => sm
12
+ .addStore(new core_1.InMemoryStore({ model: core_1.User, primaryKey: 'username' }))
13
+ .addStore(new core_1.InMemoryStore({ model: default_session_1.DefaultSession, primaryKey: 'sessionId' })));
14
+ i.useHttpAuthentication();
15
+ // await i.getInstance(ServerManager).getOrCreate({ port: 19999 })
16
+ };
17
+ exports.prepareInjector = prepareInjector;
18
+ describe('HttpUserContext', () => {
19
+ const request = { headers: {} };
20
+ const response = {};
21
+ const testUser = { username: 'testUser', roles: ['grantedRole1', 'grantedRole2'] };
22
+ it('Should be constructed with the extension method', async () => {
23
+ await (0, utils_1.usingAsync)(new inject_1.Injector(), async (i) => {
24
+ await (0, exports.prepareInjector)(i);
25
+ const ctx = i.getInstance(http_user_context_1.HttpUserContext);
26
+ expect(ctx).toBeInstanceOf(http_user_context_1.HttpUserContext);
27
+ });
28
+ });
29
+ describe('isAuthenticated', () => {
30
+ it('Should return true for authenticated users', async () => {
31
+ await (0, utils_1.usingAsync)(new inject_1.Injector(), async (i) => {
32
+ await (0, exports.prepareInjector)(i);
33
+ const ctx = i.getInstance(http_user_context_1.HttpUserContext);
34
+ ctx.getCurrentUser = jest.fn(async () => testUser);
35
+ const value = await ctx.isAuthenticated(request);
36
+ expect(value).toBe(true);
37
+ expect(ctx.getCurrentUser).toBeCalled();
38
+ });
39
+ });
40
+ it('Should return false for unauthenticated users', async () => {
41
+ await (0, utils_1.usingAsync)(new inject_1.Injector(), async (i) => {
42
+ await (0, exports.prepareInjector)(i);
43
+ const ctx = i.getInstance(http_user_context_1.HttpUserContext);
44
+ ctx.getCurrentUser = jest.fn(async () => {
45
+ throw Error(':(');
46
+ });
47
+ await expect(ctx.isAuthenticated(request)).resolves.toEqual(false);
48
+ expect(ctx.getCurrentUser).toBeCalled();
49
+ });
50
+ });
51
+ });
52
+ describe('isAuthorized', () => {
53
+ it('Should return true if all roles are authorized', async () => {
54
+ await (0, utils_1.usingAsync)(new inject_1.Injector(), async (i) => {
55
+ await (0, exports.prepareInjector)(i);
56
+ const ctx = i.getInstance(http_user_context_1.HttpUserContext);
57
+ ctx.getCurrentUser = jest.fn(async () => testUser);
58
+ const value = await ctx.isAuthorized(request, 'grantedRole1', 'grantedRole2');
59
+ expect(value).toBe(true);
60
+ expect(ctx.getCurrentUser).toBeCalled();
61
+ });
62
+ });
63
+ it('Should return false if not all roles are authorized', async () => {
64
+ await (0, utils_1.usingAsync)(new inject_1.Injector(), async (i) => {
65
+ await (0, exports.prepareInjector)(i);
66
+ const ctx = i.getInstance(http_user_context_1.HttpUserContext);
67
+ ctx.getCurrentUser = jest.fn(async () => testUser);
68
+ const value = await ctx.isAuthorized(request, 'grantedRole1', 'nonGrantedRole2');
69
+ expect(value).toBe(false);
70
+ expect(ctx.getCurrentUser).toBeCalled();
71
+ });
72
+ });
73
+ });
74
+ describe('authenticateUser', () => {
75
+ it('Should fail when the store is empty', async () => {
76
+ await (0, utils_1.usingAsync)(new inject_1.Injector(), async (i) => {
77
+ await (0, exports.prepareInjector)(i);
78
+ const ctx = i.getInstance(http_user_context_1.HttpUserContext);
79
+ await expect(ctx.authenticateUser('user', 'password')).rejects.toThrow('');
80
+ });
81
+ });
82
+ it('Should fail when the password not equals', async () => {
83
+ await (0, utils_1.usingAsync)(new inject_1.Injector(), async (i) => {
84
+ await (0, exports.prepareInjector)(i);
85
+ const ctx = i.getInstance(http_user_context_1.HttpUserContext);
86
+ ctx.authentication
87
+ .getUserStore(i.getInstance(core_1.StoreManager))
88
+ .add({ username: 'user', password: ctx.authentication.hashMethod('pass123'), roles: [] });
89
+ await expect(ctx.authenticateUser('user', 'pass321')).rejects.toThrow('');
90
+ });
91
+ });
92
+ it('Should fail when the username not equals', async () => {
93
+ await (0, utils_1.usingAsync)(new inject_1.Injector(), async (i) => {
94
+ await (0, exports.prepareInjector)(i);
95
+ const ctx = i.getInstance(http_user_context_1.HttpUserContext);
96
+ ctx.authentication
97
+ .getUserStore(i.getInstance(core_1.StoreManager))
98
+ .add({ username: 'otherUser', password: ctx.authentication.hashMethod('pass123'), roles: [] });
99
+ expect(ctx.authenticateUser('user', 'pass123')).rejects.toThrow('');
100
+ });
101
+ });
102
+ it('Should fail when password not provided', async () => {
103
+ await (0, utils_1.usingAsync)(new inject_1.Injector(), async (i) => {
104
+ await (0, exports.prepareInjector)(i);
105
+ const ctx = i.getInstance(http_user_context_1.HttpUserContext);
106
+ ctx.authentication
107
+ .getUserStore(i.getInstance(core_1.StoreManager))
108
+ .add({ username: 'otherUser', password: ctx.authentication.hashMethod('pass123'), roles: [] });
109
+ await expect(ctx.authenticateUser('user', '')).rejects.toThrow('');
110
+ });
111
+ });
112
+ it('Should return the user without the password hash when the username and password matches', async () => {
113
+ await (0, utils_1.usingAsync)(new inject_1.Injector(), async (i) => {
114
+ await (0, exports.prepareInjector)(i);
115
+ const ctx = i.getInstance(http_user_context_1.HttpUserContext);
116
+ const store = ctx.authentication.getUserStore(i.getInstance(core_1.StoreManager));
117
+ const loginUser = { username: 'user', roles: [] };
118
+ store.add({ ...loginUser, password: ctx.authentication.hashMethod('pass123') });
119
+ const value = await ctx.authenticateUser('user', 'pass123');
120
+ expect(value).toEqual(loginUser);
121
+ });
122
+ });
123
+ });
124
+ describe('getSessionIdFromRequest', () => {
125
+ it('Should return null if no headers present', async () => {
126
+ await (0, utils_1.usingAsync)(new inject_1.Injector(), async (i) => {
127
+ await (0, exports.prepareInjector)(i);
128
+ const ctx = i.getInstance(http_user_context_1.HttpUserContext);
129
+ const sid = ctx.getSessionIdFromRequest(request);
130
+ expect(sid).toBeNull();
131
+ });
132
+ });
133
+ it('Should return null if no session ID cookie present', async () => {
134
+ await (0, utils_1.usingAsync)(new inject_1.Injector(), async (i) => {
135
+ await (0, exports.prepareInjector)(i);
136
+ const requestWithCookie = { ...request, cookie: 'a=2;b=3;c=4;' };
137
+ const ctx = i.getInstance(http_user_context_1.HttpUserContext);
138
+ const sid = ctx.getSessionIdFromRequest(requestWithCookie);
139
+ expect(sid).toBeNull();
140
+ });
141
+ });
142
+ it('Should return the Session ID value if session ID cookie present', async () => {
143
+ await (0, utils_1.usingAsync)(new inject_1.Injector(), async (i) => {
144
+ await (0, exports.prepareInjector)(i);
145
+ const ctx = i.getInstance(http_user_context_1.HttpUserContext);
146
+ const requestWithAuthCookie = {
147
+ ...request,
148
+ headers: { cookie: `a=2;b=3;${ctx.authentication.cookieName}=666;c=4;` },
149
+ };
150
+ const sid = ctx.getSessionIdFromRequest(requestWithAuthCookie);
151
+ expect(sid).toBe('666');
152
+ });
153
+ });
154
+ });
155
+ describe('authenticateRequest', () => {
156
+ it('Should try to authenticate with Basic, if enabled', async () => {
157
+ await (0, utils_1.usingAsync)(new inject_1.Injector(), async (i) => {
158
+ await (0, exports.prepareInjector)(i);
159
+ const ctx = i.getInstance(http_user_context_1.HttpUserContext);
160
+ ctx.authenticateUser = jest.fn(async () => testUser);
161
+ const result = await ctx.authenticateRequest({
162
+ headers: { authorization: `Basic dGVzdHVzZXI6cGFzc3dvcmQ=` },
163
+ });
164
+ expect(ctx.authenticateUser).toBeCalledWith('testuser', 'password');
165
+ expect(result).toBe(testUser);
166
+ });
167
+ });
168
+ it('Should NOT try to authenticate with Basic, if disabled', async () => {
169
+ await (0, utils_1.usingAsync)(new inject_1.Injector(), async (i) => {
170
+ await (0, exports.prepareInjector)(i);
171
+ const ctx = i.getInstance(http_user_context_1.HttpUserContext);
172
+ ctx.authentication.enableBasicAuth = false;
173
+ ctx.authenticateUser = jest.fn(async () => testUser);
174
+ await expect(ctx.authenticateRequest({
175
+ headers: { authorization: `Basic dGVzdHVzZXI6cGFzc3dvcmQ=` },
176
+ })).rejects.toThrow('');
177
+ expect(ctx.authenticateUser).not.toBeCalled();
178
+ });
179
+ });
180
+ it('Should fail with no session in the store', async () => {
181
+ await (0, utils_1.usingAsync)(new inject_1.Injector(), async (i) => {
182
+ await (0, exports.prepareInjector)(i);
183
+ const ctx = i.getInstance(http_user_context_1.HttpUserContext);
184
+ await expect(ctx.authenticateRequest({
185
+ headers: { cookie: `${ctx.authentication.cookieName}=666;a=3` },
186
+ })).rejects.toThrow('');
187
+ });
188
+ });
189
+ it('Should fail with valid session Id but no user', async () => {
190
+ await (0, utils_1.usingAsync)(new inject_1.Injector(), async (i) => {
191
+ await (0, exports.prepareInjector)(i);
192
+ const ctx = i.getInstance(http_user_context_1.HttpUserContext);
193
+ ctx.authentication
194
+ .getSessionStore(i.getInstance(core_1.StoreManager))
195
+ .add({ sessionId: '666', username: testUser.username });
196
+ await expect(ctx.authenticateRequest({
197
+ headers: { cookie: `${ctx.authentication.cookieName}=666;a=3` },
198
+ })).rejects.toThrow('');
199
+ });
200
+ });
201
+ it('Should authenticate with cookie, if the session IDs matches', async () => {
202
+ await (0, utils_1.usingAsync)(new inject_1.Injector(), async (i) => {
203
+ await (0, exports.prepareInjector)(i);
204
+ const ctx = i.getInstance(http_user_context_1.HttpUserContext);
205
+ ctx.authentication
206
+ .getSessionStore(i.getInstance(core_1.StoreManager))
207
+ .add({ sessionId: '666', username: testUser.username });
208
+ ctx.authentication.getUserStore(i.getInstance(core_1.StoreManager)).add({ ...testUser, password: '' });
209
+ const result = await ctx.authenticateRequest({
210
+ headers: { cookie: `${ctx.authentication.cookieName}=666;a=3` },
211
+ });
212
+ expect(result).toEqual(testUser);
213
+ });
214
+ });
215
+ });
216
+ describe('getCurrentUser', () => {
217
+ it('Should return the current user from authenticateRequest() once per request', async () => {
218
+ await (0, utils_1.usingAsync)(new inject_1.Injector(), async (i) => {
219
+ await (0, exports.prepareInjector)(i);
220
+ const ctx = i.getInstance(http_user_context_1.HttpUserContext);
221
+ ctx.authenticateRequest = jest.fn(async () => testUser);
222
+ const result = await ctx.getCurrentUser(request);
223
+ const result2 = await ctx.getCurrentUser(request);
224
+ expect(ctx.authenticateRequest).toBeCalledTimes(1);
225
+ expect(result).toBe(testUser);
226
+ expect(result2).toBe(testUser);
227
+ });
228
+ });
229
+ });
230
+ describe('cookieLogin', () => {
231
+ it('Should return the current user from authenticateRequest() once per request', async () => {
232
+ await (0, utils_1.usingAsync)(new inject_1.Injector(), async (i) => {
233
+ await (0, exports.prepareInjector)(i);
234
+ const ctx = i.getInstance(http_user_context_1.HttpUserContext);
235
+ const setHeader = jest.fn();
236
+ ctx.getSessionStore().add = jest.fn(async () => {
237
+ return {};
238
+ });
239
+ const authResult = await ctx.cookieLogin(testUser, { setHeader });
240
+ expect(authResult).toBe(testUser);
241
+ expect(setHeader).toBeCalled();
242
+ expect(ctx.getSessionStore().add).toBeCalled();
243
+ });
244
+ });
245
+ });
246
+ describe('cookieLogout', () => {
247
+ it('Should invalidate the current session id cookie', async () => {
248
+ await (0, utils_1.usingAsync)(new inject_1.Injector(), async (i) => {
249
+ await (0, exports.prepareInjector)(i);
250
+ const ctx = i.getInstance(http_user_context_1.HttpUserContext);
251
+ const setHeader = jest.fn();
252
+ ctx.getSessionStore().add = jest.fn(async () => {
253
+ return {};
254
+ });
255
+ ctx.authenticateRequest = jest.fn(async () => testUser);
256
+ ctx.getSessionStore().remove = jest.fn(async () => undefined);
257
+ ctx.getSessionIdFromRequest = () => 'example-session-id';
258
+ response.setHeader = jest.fn(() => response);
259
+ await ctx.cookieLogin(testUser, { setHeader });
260
+ await ctx.cookieLogout(request, response);
261
+ expect(response.setHeader).toBeCalledWith('Set-Cookie', 'fss=; Path=/; HttpOnly');
262
+ expect(ctx.getSessionStore().remove).toBeCalled();
263
+ });
264
+ });
265
+ });
266
+ });
267
+ //# sourceMappingURL=http-user-context.spec.js.map