@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.
- package/LICENSE +339 -0
- package/README.md +219 -0
- package/dist/actions/error-action.d.ts +14 -0
- package/dist/actions/error-action.d.ts.map +1 -0
- package/dist/actions/error-action.js +29 -0
- package/dist/actions/error-action.js.map +1 -0
- package/dist/actions/error-action.spec.d.ts +2 -0
- package/dist/actions/error-action.spec.d.ts.map +1 -0
- package/dist/actions/error-action.spec.js +51 -0
- package/dist/actions/error-action.spec.js.map +1 -0
- package/dist/actions/get-current-user.d.ts +11 -0
- package/dist/actions/get-current-user.d.ts.map +1 -0
- package/dist/actions/get-current-user.js +15 -0
- package/dist/actions/get-current-user.js.map +1 -0
- package/dist/actions/get-current-user.spec.d.ts +2 -0
- package/dist/actions/get-current-user.spec.d.ts.map +1 -0
- package/dist/actions/get-current-user.spec.js +20 -0
- package/dist/actions/get-current-user.spec.js.map +1 -0
- package/dist/actions/index.d.ts +7 -0
- package/dist/actions/index.d.ts.map +1 -0
- package/dist/actions/index.js +10 -0
- package/dist/actions/index.js.map +1 -0
- package/dist/actions/is-authenticated.d.ts +14 -0
- package/dist/actions/is-authenticated.d.ts.map +1 -0
- package/dist/actions/is-authenticated.js +17 -0
- package/dist/actions/is-authenticated.js.map +1 -0
- package/dist/actions/is-authenticated.spec.d.ts +2 -0
- package/dist/actions/is-authenticated.spec.d.ts.map +1 -0
- package/dist/actions/is-authenticated.spec.js +19 -0
- package/dist/actions/is-authenticated.spec.js.map +1 -0
- package/dist/actions/login-action.spec.d.ts +2 -0
- package/dist/actions/login-action.spec.d.ts.map +1 -0
- package/dist/actions/login-action.spec.js +35 -0
- package/dist/actions/login-action.spec.js.map +1 -0
- package/dist/actions/login.d.ts +16 -0
- package/dist/actions/login.d.ts.map +1 -0
- package/dist/actions/login.js +26 -0
- package/dist/actions/login.js.map +1 -0
- package/dist/actions/logout-action.spec.d.ts +2 -0
- package/dist/actions/logout-action.spec.d.ts.map +1 -0
- package/dist/actions/logout-action.spec.js +23 -0
- package/dist/actions/logout-action.spec.js.map +1 -0
- package/dist/actions/logout.d.ts +14 -0
- package/dist/actions/logout.d.ts.map +1 -0
- package/dist/actions/logout.js +20 -0
- package/dist/actions/logout.js.map +1 -0
- package/dist/actions/not-found-action.d.ts +10 -0
- package/dist/actions/not-found-action.d.ts.map +1 -0
- package/dist/actions/not-found-action.js +14 -0
- package/dist/actions/not-found-action.js.map +1 -0
- package/dist/actions/not-found-action.spec.d.ts +2 -0
- package/dist/actions/not-found-action.spec.d.ts.map +1 -0
- package/dist/actions/not-found-action.spec.js +17 -0
- package/dist/actions/not-found-action.spec.js.map +1 -0
- package/dist/add-cors-header.spec.d.ts +2 -0
- package/dist/add-cors-header.spec.d.ts.map +1 -0
- package/dist/add-cors-header.spec.js +99 -0
- package/dist/add-cors-header.spec.js.map +1 -0
- package/dist/api-manager.d.ts +61 -0
- package/dist/api-manager.d.ts.map +1 -0
- package/dist/api-manager.js +144 -0
- package/dist/api-manager.js.map +1 -0
- package/dist/authenticate.d.ts +5 -0
- package/dist/authenticate.d.ts.map +1 -0
- package/dist/authenticate.js +20 -0
- package/dist/authenticate.js.map +1 -0
- package/dist/authenticate.spec.d.ts +2 -0
- package/dist/authenticate.spec.d.ts.map +1 -0
- package/dist/authenticate.spec.js +59 -0
- package/dist/authenticate.spec.js.map +1 -0
- package/dist/authorize.d.ts +5 -0
- package/dist/authorize.d.ts.map +1 -0
- package/dist/authorize.js +22 -0
- package/dist/authorize.js.map +1 -0
- package/dist/authorize.spec.d.ts +2 -0
- package/dist/authorize.spec.d.ts.map +1 -0
- package/dist/authorize.spec.js +55 -0
- package/dist/authorize.spec.js.map +1 -0
- package/dist/endpoint-generators/create-delete-endpoint.d.ts +17 -0
- package/dist/endpoint-generators/create-delete-endpoint.d.ts.map +1 -0
- package/dist/endpoint-generators/create-delete-endpoint.js +24 -0
- package/dist/endpoint-generators/create-delete-endpoint.js.map +1 -0
- package/dist/endpoint-generators/create-delete-endpoint.spec.d.ts +2 -0
- package/dist/endpoint-generators/create-delete-endpoint.spec.d.ts.map +1 -0
- package/dist/endpoint-generators/create-delete-endpoint.spec.js +33 -0
- package/dist/endpoint-generators/create-delete-endpoint.spec.js.map +1 -0
- package/dist/endpoint-generators/create-get-collection-endpoint.d.ts +17 -0
- package/dist/endpoint-generators/create-get-collection-endpoint.d.ts.map +1 -0
- package/dist/endpoint-generators/create-get-collection-endpoint.js +26 -0
- package/dist/endpoint-generators/create-get-collection-endpoint.js.map +1 -0
- package/dist/endpoint-generators/create-get-collection-endpoint.spec.d.ts +2 -0
- package/dist/endpoint-generators/create-get-collection-endpoint.spec.d.ts.map +1 -0
- package/dist/endpoint-generators/create-get-collection-endpoint.spec.js +143 -0
- package/dist/endpoint-generators/create-get-collection-endpoint.spec.js.map +1 -0
- package/dist/endpoint-generators/create-get-entity-endpoint.d.ts +17 -0
- package/dist/endpoint-generators/create-get-entity-endpoint.d.ts.map +1 -0
- package/dist/endpoint-generators/create-get-entity-endpoint.js +29 -0
- package/dist/endpoint-generators/create-get-entity-endpoint.js.map +1 -0
- package/dist/endpoint-generators/create-get-entity-endpoint.spec.d.ts +2 -0
- package/dist/endpoint-generators/create-get-entity-endpoint.spec.d.ts.map +1 -0
- package/dist/endpoint-generators/create-get-entity-endpoint.spec.js +74 -0
- package/dist/endpoint-generators/create-get-entity-endpoint.spec.js.map +1 -0
- package/dist/endpoint-generators/create-patch-endpoint.d.ts +18 -0
- package/dist/endpoint-generators/create-patch-endpoint.d.ts.map +1 -0
- package/dist/endpoint-generators/create-patch-endpoint.js +26 -0
- package/dist/endpoint-generators/create-patch-endpoint.js.map +1 -0
- package/dist/endpoint-generators/create-patch-endpoint.spec.d.ts +2 -0
- package/dist/endpoint-generators/create-patch-endpoint.spec.d.ts.map +1 -0
- package/dist/endpoint-generators/create-patch-endpoint.spec.js +36 -0
- package/dist/endpoint-generators/create-patch-endpoint.spec.js.map +1 -0
- package/dist/endpoint-generators/create-post-endpoint.d.ts +18 -0
- package/dist/endpoint-generators/create-post-endpoint.d.ts.map +1 -0
- package/dist/endpoint-generators/create-post-endpoint.js +29 -0
- package/dist/endpoint-generators/create-post-endpoint.js.map +1 -0
- package/dist/endpoint-generators/create-post-endpoint.spec.d.ts +2 -0
- package/dist/endpoint-generators/create-post-endpoint.spec.d.ts.map +1 -0
- package/dist/endpoint-generators/create-post-endpoint.spec.js +34 -0
- package/dist/endpoint-generators/create-post-endpoint.spec.js.map +1 -0
- package/dist/endpoint-generators/index.d.ts +6 -0
- package/dist/endpoint-generators/index.d.ts.map +1 -0
- package/dist/endpoint-generators/index.js +9 -0
- package/dist/endpoint-generators/index.js.map +1 -0
- package/dist/endpoint-generators/utils.d.ts +9 -0
- package/dist/endpoint-generators/utils.d.ts.map +1 -0
- package/dist/endpoint-generators/utils.js +27 -0
- package/dist/endpoint-generators/utils.js.map +1 -0
- package/dist/http-authentication-settings.d.ts +17 -0
- package/dist/http-authentication-settings.d.ts.map +1 -0
- package/dist/http-authentication-settings.js +26 -0
- package/dist/http-authentication-settings.js.map +1 -0
- package/dist/http-user-context.d.ts +54 -0
- package/dist/http-user-context.d.ts.map +1 -0
- package/dist/http-user-context.js +153 -0
- package/dist/http-user-context.js.map +1 -0
- package/dist/http-user-context.spec.d.ts +4 -0
- package/dist/http-user-context.spec.d.ts.map +1 -0
- package/dist/http-user-context.spec.js +267 -0
- package/dist/http-user-context.spec.js.map +1 -0
- package/dist/incoming-message-extensions.d.ts +8 -0
- package/dist/incoming-message-extensions.d.ts.map +1 -0
- package/dist/incoming-message-extensions.js +14 -0
- package/dist/incoming-message-extensions.js.map +1 -0
- package/dist/incoming-message-extensions.spec.d.ts +2 -0
- package/dist/incoming-message-extensions.spec.d.ts.map +1 -0
- package/dist/incoming-message-extensions.spec.js +39 -0
- package/dist/incoming-message-extensions.spec.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/injector-extensions.d.ts +21 -0
- package/dist/injector-extensions.d.ts.map +1 -0
- package/dist/injector-extensions.js +14 -0
- package/dist/injector-extensions.js.map +1 -0
- package/dist/injector-extensions.spec.d.ts +2 -0
- package/dist/injector-extensions.spec.d.ts.map +1 -0
- package/dist/injector-extensions.spec.js +19 -0
- package/dist/injector-extensions.spec.js.map +1 -0
- package/dist/models/cors-options.d.ts +22 -0
- package/dist/models/cors-options.d.ts.map +1 -0
- package/dist/models/cors-options.js +3 -0
- package/dist/models/cors-options.js.map +1 -0
- package/dist/models/default-session.d.ts +14 -0
- package/dist/models/default-session.d.ts.map +1 -0
- package/dist/models/default-session.js +10 -0
- package/dist/models/default-session.js.map +1 -0
- package/dist/request-action-implementation.d.ts +54 -0
- package/dist/request-action-implementation.d.ts.map +1 -0
- package/dist/request-action-implementation.js +42 -0
- package/dist/request-action-implementation.js.map +1 -0
- package/dist/rest-service.integration.spec.d.ts +2 -0
- package/dist/rest-service.integration.spec.d.ts.map +1 -0
- package/dist/rest-service.integration.spec.js +129 -0
- package/dist/rest-service.integration.spec.js.map +1 -0
- package/dist/rest.integration.test.d.ts +58 -0
- package/dist/rest.integration.test.d.ts.map +1 -0
- package/dist/rest.integration.test.js +94 -0
- package/dist/rest.integration.test.js.map +1 -0
- package/dist/schema-validator/index.d.ts +3 -0
- package/dist/schema-validator/index.d.ts.map +1 -0
- package/dist/schema-validator/index.js +6 -0
- package/dist/schema-validator/index.js.map +1 -0
- package/dist/schema-validator/schema-validation-error.d.ts +10 -0
- package/dist/schema-validator/schema-validation-error.d.ts.map +1 -0
- package/dist/schema-validator/schema-validation-error.js +15 -0
- package/dist/schema-validator/schema-validation-error.js.map +1 -0
- package/dist/schema-validator/schema-validator.d.ts +20 -0
- package/dist/schema-validator/schema-validator.d.ts.map +1 -0
- package/dist/schema-validator/schema-validator.js +36 -0
- package/dist/schema-validator/schema-validator.js.map +1 -0
- package/dist/schema-validator/schema-validator.test.d.ts +2 -0
- package/dist/schema-validator/schema-validator.test.d.ts.map +1 -0
- package/dist/schema-validator/schema-validator.test.js +62 -0
- package/dist/schema-validator/schema-validator.test.js.map +1 -0
- package/dist/schema-validator/validate-examples.d.ts +37 -0
- package/dist/schema-validator/validate-examples.d.ts.map +1 -0
- package/dist/schema-validator/validate-examples.js +29 -0
- package/dist/schema-validator/validate-examples.js.map +1 -0
- package/dist/server-manager.d.ts +30 -0
- package/dist/server-manager.d.ts.map +1 -0
- package/dist/server-manager.js +71 -0
- package/dist/server-manager.js.map +1 -0
- package/dist/server-response-extensions.d.ts +21 -0
- package/dist/server-response-extensions.d.ts.map +1 -0
- package/dist/server-response-extensions.js +15 -0
- package/dist/server-response-extensions.js.map +1 -0
- package/dist/server-response-extensions.spec.d.ts +2 -0
- package/dist/server-response-extensions.spec.d.ts.map +1 -0
- package/dist/server-response-extensions.spec.js +49 -0
- package/dist/server-response-extensions.spec.js.map +1 -0
- package/dist/utils.d.ts +24 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +66 -0
- package/dist/utils.js.map +1 -0
- package/dist/validate.d.ts +18 -0
- package/dist/validate.d.ts.map +1 -0
- package/dist/validate.integration.schema.d.ts +69 -0
- package/dist/validate.integration.schema.d.ts.map +1 -0
- package/dist/validate.integration.schema.js +3 -0
- package/dist/validate.integration.schema.js.map +1 -0
- package/dist/validate.integration.spec.d.ts +13 -0
- package/dist/validate.integration.spec.d.ts.map +1 -0
- package/dist/validate.integration.spec.js +223 -0
- package/dist/validate.integration.spec.js.map +1 -0
- package/dist/validate.integration.spec.schema.json +749 -0
- package/dist/validate.js +49 -0
- package/dist/validate.js.map +1 -0
- package/package.json +56 -0
- package/src/actions/error-action.spec.ts +54 -0
- package/src/actions/error-action.ts +34 -0
- package/src/actions/get-current-user.spec.ts +23 -0
- package/src/actions/get-current-user.ts +15 -0
- package/src/actions/index.ts +6 -0
- package/src/actions/is-authenticated.spec.ts +18 -0
- package/src/actions/is-authenticated.ts +13 -0
- package/src/actions/login-action.spec.ts +41 -0
- package/src/actions/login.ts +26 -0
- package/src/actions/logout-action.spec.ts +27 -0
- package/src/actions/logout.ts +16 -0
- package/src/actions/not-found-action.spec.ts +17 -0
- package/src/actions/not-found-action.ts +13 -0
- package/src/add-cors-header.spec.ts +133 -0
- package/src/api-manager.ts +222 -0
- package/src/authenticate.spec.ts +78 -0
- package/src/authenticate.ts +22 -0
- package/src/authorize.spec.ts +69 -0
- package/src/authorize.ts +19 -0
- package/src/endpoint-generators/create-delete-endpoint.spec.ts +34 -0
- package/src/endpoint-generators/create-delete-endpoint.ts +25 -0
- package/src/endpoint-generators/create-get-collection-endpoint.spec.ts +164 -0
- package/src/endpoint-generators/create-get-collection-endpoint.ts +28 -0
- package/src/endpoint-generators/create-get-entity-endpoint.spec.ts +75 -0
- package/src/endpoint-generators/create-get-entity-endpoint.ts +29 -0
- package/src/endpoint-generators/create-patch-endpoint.spec.ts +36 -0
- package/src/endpoint-generators/create-patch-endpoint.ts +27 -0
- package/src/endpoint-generators/create-post-endpoint.spec.ts +32 -0
- package/src/endpoint-generators/create-post-endpoint.ts +30 -0
- package/src/endpoint-generators/index.ts +5 -0
- package/src/endpoint-generators/utils.ts +34 -0
- package/src/http-authentication-settings.ts +23 -0
- package/src/http-user-context.spec.ts +299 -0
- package/src/http-user-context.ts +160 -0
- package/src/incoming-message-extensions.spec.ts +41 -0
- package/src/incoming-message-extensions.ts +19 -0
- package/src/index.ts +16 -0
- package/src/injector-extensions.spec.ts +19 -0
- package/src/injector-extensions.ts +35 -0
- package/src/models/cors-options.ts +21 -0
- package/src/models/default-session.ts +14 -0
- package/src/request-action-implementation.ts +70 -0
- package/src/rest-service.integration.spec.ts +166 -0
- package/src/rest.integration.test.ts +112 -0
- package/src/schema-validator/index.ts +2 -0
- package/src/schema-validator/schema-validation-error.ts +11 -0
- package/src/schema-validator/schema-validator.test.ts +72 -0
- package/src/schema-validator/schema-validator.ts +31 -0
- package/src/schema-validator/validate-examples.ts +38 -0
- package/src/server-manager.ts +88 -0
- package/src/server-response-extensions.spec.ts +53 -0
- package/src/server-response-extensions.ts +30 -0
- package/src/utils.ts +65 -0
- package/src/validate.integration.schema.ts +50 -0
- package/src/validate.integration.spec.schema.json +779 -0
- package/src/validate.integration.spec.ts +218 -0
- 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 @@
|
|
|
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
|