@furystack/websocket-api 11.0.0 → 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.
- package/esm/actions/whoami.d.ts +2 -2
- package/esm/actions/whoami.d.ts.map +1 -1
- package/esm/actions/whoami.js +2 -9
- package/esm/actions/whoami.js.map +1 -1
- package/esm/actions/whoami.spec.js +1 -1
- package/esm/actions/whoami.spec.js.map +1 -1
- package/esm/models/websocket-action.d.ts +9 -1
- package/esm/models/websocket-action.d.ts.map +1 -1
- package/esm/websocket-api.d.ts +5 -4
- package/esm/websocket-api.d.ts.map +1 -1
- package/esm/websocket-api.js +11 -17
- package/esm/websocket-api.js.map +1 -1
- package/package.json +6 -6
- package/src/actions/whoami.spec.ts +1 -2
- package/src/actions/whoami.ts +5 -9
- package/src/models/websocket-action.ts +4 -3
- package/src/websocket-api.ts +16 -15
- package/esm/websocket-user-context.d.ts +0 -8
- package/esm/websocket-user-context.d.ts.map +0 -1
- package/esm/websocket-user-context.js +0 -52
- package/esm/websocket-user-context.js.map +0 -1
- package/esm/websocket-user-context.spec.d.ts +0 -2
- package/esm/websocket-user-context.spec.d.ts.map +0 -1
- package/esm/websocket-user-context.spec.js +0 -68
- package/esm/websocket-user-context.spec.js.map +0 -1
- package/src/websocket-user-context.spec.ts +0 -73
- package/src/websocket-user-context.ts +0 -37
package/esm/actions/whoami.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/// <reference path="../../../rest-service/esm/incoming-message-extensions.d.ts" />
|
|
2
2
|
/// <reference path="../../../rest-service/esm/server-response-extensions.d.ts" />
|
|
3
3
|
/// <reference types="node/http.js" />
|
|
4
|
-
import type { Data } from 'ws';
|
|
4
|
+
import type { Data, WebSocket } from 'ws';
|
|
5
5
|
import type { WebSocketAction } from '../models/websocket-action.js';
|
|
6
6
|
import type { IncomingMessage } from 'http';
|
|
7
7
|
/**
|
|
@@ -16,8 +16,8 @@ export declare class WhoAmI implements WebSocketAction {
|
|
|
16
16
|
execute(options: {
|
|
17
17
|
data: Data;
|
|
18
18
|
request: IncomingMessage;
|
|
19
|
+
socket: WebSocket;
|
|
19
20
|
}): Promise<void>;
|
|
20
21
|
private readonly httpUserContext;
|
|
21
|
-
private readonly websocket;
|
|
22
22
|
}
|
|
23
23
|
//# sourceMappingURL=whoami.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"whoami.d.ts","sourceRoot":"","sources":["../../src/actions/whoami.ts"],"names":[],"mappings":";;;AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"whoami.d.ts","sourceRoot":"","sources":["../../src/actions/whoami.ts"],"names":[],"mappings":";;;AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,IAAI,CAAA;AACzC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AACpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,MAAM,CAAA;AAE3C;;GAEG;AACH,qBACa,MAAO,YAAW,eAAe;IACrC,OAAO;WAGA,UAAU,CAAC,OAAO,EAAE;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,OAAO,EAAE,eAAe,CAAA;KAAE,GAAG,OAAO;IAIvE,OAAO,CAAC,OAAO,EAAE;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,OAAO,EAAE,eAAe,CAAC;QAAC,MAAM,EAAE,SAAS,CAAA;KAAE;IASzF,iBACyB,eAAe,CAAiB;CAC1D"}
|
package/esm/actions/whoami.js
CHANGED
|
@@ -9,7 +9,6 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
9
9
|
};
|
|
10
10
|
import { HttpUserContext } from '@furystack/rest-service';
|
|
11
11
|
import { Injectable, Injected } from '@furystack/inject';
|
|
12
|
-
import ws from 'ws';
|
|
13
12
|
/**
|
|
14
13
|
* Example action that returns the current user instance
|
|
15
14
|
*/
|
|
@@ -23,23 +22,17 @@ let WhoAmI = class WhoAmI {
|
|
|
23
22
|
async execute(options) {
|
|
24
23
|
try {
|
|
25
24
|
const currentUser = await this.httpUserContext.getCurrentUser(options.request);
|
|
26
|
-
|
|
25
|
+
options.socket.send(JSON.stringify({ currentUser }));
|
|
27
26
|
}
|
|
28
27
|
catch (error) {
|
|
29
|
-
|
|
28
|
+
options.socket.send(JSON.stringify({ currentUser: null }));
|
|
30
29
|
}
|
|
31
30
|
}
|
|
32
|
-
httpUserContext;
|
|
33
|
-
websocket;
|
|
34
31
|
};
|
|
35
32
|
__decorate([
|
|
36
33
|
Injected(HttpUserContext),
|
|
37
34
|
__metadata("design:type", HttpUserContext)
|
|
38
35
|
], WhoAmI.prototype, "httpUserContext", void 0);
|
|
39
|
-
__decorate([
|
|
40
|
-
Injected(ws),
|
|
41
|
-
__metadata("design:type", ws)
|
|
42
|
-
], WhoAmI.prototype, "websocket", void 0);
|
|
43
36
|
WhoAmI = __decorate([
|
|
44
37
|
Injectable({ lifetime: 'transient' })
|
|
45
38
|
], WhoAmI);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"whoami.js","sourceRoot":"","sources":["../../src/actions/whoami.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AACzD,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"whoami.js","sourceRoot":"","sources":["../../src/actions/whoami.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AACzD,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAKxD;;GAEG;AAEI,IAAM,MAAM,GAAZ,MAAM,MAAM;IACV,OAAO;QACZ,MAAM;IACR,CAAC;IACM,MAAM,CAAC,UAAU,CAAC,OAAiD;QACxE,OAAO,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,gBAAgB,CAAA;IAC7F,CAAC;IAEM,KAAK,CAAC,OAAO,CAAC,OAAoE;QACvF,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,cAAc,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;YAC9E,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAA;QACtD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;QAC5D,CAAC;IACH,CAAC;CAIF,CAAA;AAD0B;IADxB,QAAQ,CAAC,eAAe,CAAC;8BACgB,eAAe;+CAAA;AAlB9C,MAAM;IADlB,UAAU,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;GACzB,MAAM,CAmBlB"}
|
|
@@ -25,7 +25,7 @@ describe('Whoami action', () => {
|
|
|
25
25
|
injector.setExplicitInstance(contextMock, HttpUserContext);
|
|
26
26
|
injector.setExplicitInstance(wsMock, ws);
|
|
27
27
|
const instance = injector.getInstance(WhoAmI);
|
|
28
|
-
await instance.execute({ request, data: '' });
|
|
28
|
+
await instance.execute({ request, data: '', socket: wsMock });
|
|
29
29
|
expect(wsMock.send).toBeCalledWith(JSON.stringify({ currentUser }));
|
|
30
30
|
});
|
|
31
31
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"whoami.spec.js","sourceRoot":"","sources":["../../src/actions/whoami.spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AACzD,OAAO,EAAE,MAAM,IAAI,CAAA;AACnB,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAE7C,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC5C,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAEjD,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,MAAM,WAAW,GAAG,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAA;IAC5C,MAAM,WAAW,GAAoB,EAAE,cAAc,EAAE,KAAK,IAAI,EAAE,CAAC,WAAW,EAAgC,CAAA;IAE9G,MAAM,OAAO,GAAG,EAAE,GAAG,EAAE,oBAAoB,EAAqB,CAAA;IAEhE,MAAM,MAAM,GAAO;QACjB,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC;KACZ,CAAA;IAElB,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,EAAE,CAAA;IACjE,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,UAAU,EAAE,CAAA;IACrE,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC,CAAC,CAAC,UAAU,EAAE,CAAA;IAC7E,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;QAC9C,MAAM,UAAU,CAAC,IAAI,QAAQ,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;YAClD,QAAQ,CAAC,mBAAmB,CAAC,WAAW,EAAE,eAAe,CAAC,CAAA;YAC1D,QAAQ,CAAC,mBAAmB,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;YACxC,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"whoami.spec.js","sourceRoot":"","sources":["../../src/actions/whoami.spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AACzD,OAAO,EAAE,MAAM,IAAI,CAAA;AACnB,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAE7C,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC5C,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAEjD,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,MAAM,WAAW,GAAG,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAA;IAC5C,MAAM,WAAW,GAAoB,EAAE,cAAc,EAAE,KAAK,IAAI,EAAE,CAAC,WAAW,EAAgC,CAAA;IAE9G,MAAM,OAAO,GAAG,EAAE,GAAG,EAAE,oBAAoB,EAAqB,CAAA;IAEhE,MAAM,MAAM,GAAO;QACjB,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC;KACZ,CAAA;IAElB,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,EAAE,CAAA;IACjE,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,UAAU,EAAE,CAAA;IACrE,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC,CAAC,CAAC,UAAU,EAAE,CAAA;IAC7E,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;QAC9C,MAAM,UAAU,CAAC,IAAI,QAAQ,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;YAClD,QAAQ,CAAC,mBAAmB,CAAC,WAAW,EAAE,eAAe,CAAC,CAAA;YAC1D,QAAQ,CAAC,mBAAmB,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;YACxC,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;YAC7C,MAAM,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;YAC7D,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAA;QACrE,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
|
|
@@ -1,11 +1,17 @@
|
|
|
1
|
+
/// <reference path="../../../rest-service/esm/incoming-message-extensions.d.ts" />
|
|
2
|
+
/// <reference path="../../../rest-service/esm/server-response-extensions.d.ts" />
|
|
3
|
+
/// <reference types="node/http.js" />
|
|
1
4
|
import type { Disposable } from '@furystack/utils';
|
|
2
|
-
import type { Data } from 'ws';
|
|
5
|
+
import type { Data, WebSocket } from 'ws';
|
|
6
|
+
import type { IncomingMessage } from 'http';
|
|
3
7
|
/**
|
|
4
8
|
* Static methods of a WebSocket Action
|
|
5
9
|
*/
|
|
6
10
|
export interface WebSocketActionStatic {
|
|
7
11
|
canExecute(options: {
|
|
8
12
|
data: Data;
|
|
13
|
+
request: IncomingMessage;
|
|
14
|
+
socket: WebSocket;
|
|
9
15
|
}): boolean;
|
|
10
16
|
}
|
|
11
17
|
/**
|
|
@@ -14,6 +20,8 @@ export interface WebSocketActionStatic {
|
|
|
14
20
|
export interface WebSocketAction extends Disposable {
|
|
15
21
|
execute(options: {
|
|
16
22
|
data: Data;
|
|
23
|
+
request: IncomingMessage;
|
|
24
|
+
socket: WebSocket;
|
|
17
25
|
}): void;
|
|
18
26
|
}
|
|
19
27
|
//# sourceMappingURL=websocket-action.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"websocket-action.d.ts","sourceRoot":"","sources":["../../src/models/websocket-action.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"websocket-action.d.ts","sourceRoot":"","sources":["../../src/models/websocket-action.ts"],"names":[],"mappings":";;;AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,IAAI,CAAA;AACzC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,MAAM,CAAA;AAE3C;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,UAAU,CAAC,OAAO,EAAE;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,OAAO,EAAE,eAAe,CAAC;QAAC,MAAM,EAAE,SAAS,CAAA;KAAE,GAAG,OAAO,CAAA;CAC1F;AAED;;GAEG;AACH,MAAM,WAAW,eAAgB,SAAQ,UAAU;IACjD,OAAO,CAAC,OAAO,EAAE;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,OAAO,EAAE,eAAe,CAAC;QAAC,MAAM,EAAE,SAAS,CAAA;KAAE,GAAG,IAAI,CAAA;CACpF"}
|
package/esm/websocket-api.d.ts
CHANGED
|
@@ -3,15 +3,16 @@
|
|
|
3
3
|
/// <reference types="node/http.js" />
|
|
4
4
|
/// <reference types="node/http.js" />
|
|
5
5
|
import { IncomingMessage } from 'http';
|
|
6
|
-
import { Injector } from '@furystack/inject';
|
|
7
|
-
import type
|
|
6
|
+
import type { Injector } from '@furystack/inject';
|
|
7
|
+
import { type Disposable } from '@furystack/utils';
|
|
8
8
|
import type { Data } from 'ws';
|
|
9
|
+
import type WebSocket from 'ws';
|
|
9
10
|
import ws from 'ws';
|
|
10
11
|
/**
|
|
11
12
|
* A WebSocket API implementation for FuryStack
|
|
12
13
|
*/
|
|
13
14
|
export declare class WebSocketApi implements Disposable {
|
|
14
|
-
readonly socket:
|
|
15
|
+
readonly socket: WebSocket.Server<typeof WebSocket, typeof IncomingMessage>;
|
|
15
16
|
private clients;
|
|
16
17
|
private readonly settings;
|
|
17
18
|
private readonly serverManager;
|
|
@@ -24,6 +25,6 @@ export declare class WebSocketApi implements Disposable {
|
|
|
24
25
|
ws: ws;
|
|
25
26
|
message: IncomingMessage;
|
|
26
27
|
}) => void | Promise<void>): Promise<void>;
|
|
27
|
-
execute(data: Data, injector: Injector): void
|
|
28
|
+
execute(data: Data, request: IncomingMessage, injector: Injector, socket: WebSocket): Promise<void>;
|
|
28
29
|
}
|
|
29
30
|
//# sourceMappingURL=websocket-api.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"websocket-api.d.ts","sourceRoot":"","sources":["../src/websocket-api.ts"],"names":[],"mappings":";;;;AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,MAAM,CAAA;AAEtC,OAAO,
|
|
1
|
+
{"version":3,"file":"websocket-api.d.ts","sourceRoot":"","sources":["../src/websocket-api.ts"],"names":[],"mappings":";;;;AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,MAAM,CAAA;AAEtC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAEjD,OAAO,EAAc,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC9D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,IAAI,CAAA;AAC9B,OAAO,KAAK,SAAS,MAAM,IAAI,CAAA;AAE/B,OAAO,EAAE,MAAM,IAAI,CAAA;AAKnB;;GAEG;AACH,qBACa,YAAa,YAAW,UAAU;IAC7C,SAAgB,MAAM,6DAA0C;IAEhE,OAAO,CAAC,OAAO,CAA0E;IAEzF,iBACyB,QAAQ,CAAsB;IAEvD,iBACyB,aAAa,CAAe;IAErD,iBAAyB,QAAQ,CAAU;IAE3C,OAAO,CAAC,aAAa,CAAQ;IACtB,IAAI;IA+BE,OAAO;IAMP,SAAS,CACpB,QAAQ,EAAE,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,QAAQ,CAAC;QAAC,EAAE,EAAE,EAAE,CAAC;QAAC,OAAO,EAAE,eAAe,CAAA;KAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAmB1F,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS;CAQjG"}
|
package/esm/websocket-api.js
CHANGED
|
@@ -9,22 +9,19 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
9
9
|
};
|
|
10
10
|
import { URL } from 'url';
|
|
11
11
|
import { IncomingMessage } from 'http';
|
|
12
|
-
import { ServerManager } from '@furystack/rest-service';
|
|
13
|
-
import { Injectable, Injected
|
|
12
|
+
import { HttpUserContext, ServerManager } from '@furystack/rest-service';
|
|
13
|
+
import { Injectable, Injected } from '@furystack/inject';
|
|
14
|
+
import { usingAsync } from '@furystack/utils';
|
|
14
15
|
import { WebSocketServer } from 'ws';
|
|
15
16
|
import ws from 'ws';
|
|
16
17
|
import { WebSocketApiSettings } from './websocket-api-settings.js';
|
|
17
18
|
import { AggregatedError, IdentityContext } from '@furystack/core';
|
|
18
|
-
import { WebsocketUserContext } from './websocket-user-context.js';
|
|
19
19
|
/**
|
|
20
20
|
* A WebSocket API implementation for FuryStack
|
|
21
21
|
*/
|
|
22
22
|
let WebSocketApi = class WebSocketApi {
|
|
23
23
|
socket = new WebSocketServer({ noServer: true });
|
|
24
24
|
clients = new Map();
|
|
25
|
-
settings;
|
|
26
|
-
serverManager;
|
|
27
|
-
injector;
|
|
28
25
|
isInitialized = false;
|
|
29
26
|
init() {
|
|
30
27
|
if (!this.isInitialized) {
|
|
@@ -32,10 +29,10 @@ let WebSocketApi = class WebSocketApi {
|
|
|
32
29
|
const connectionInjector = this.injector.createChild({ owner: msg });
|
|
33
30
|
connectionInjector.setExplicitInstance(websocket, ws);
|
|
34
31
|
connectionInjector.setExplicitInstance(msg, IncomingMessage);
|
|
35
|
-
connectionInjector.setExplicitInstance(connectionInjector.getInstance(
|
|
32
|
+
connectionInjector.setExplicitInstance(connectionInjector.getInstance(HttpUserContext), IdentityContext);
|
|
36
33
|
this.clients.set(websocket, { injector: connectionInjector, message: msg, ws: websocket });
|
|
37
34
|
websocket.on('message', (message) => {
|
|
38
|
-
this.execute(message, connectionInjector);
|
|
35
|
+
this.execute(message, msg, connectionInjector, websocket);
|
|
39
36
|
});
|
|
40
37
|
websocket.on('close', () => {
|
|
41
38
|
this.clients.delete(websocket);
|
|
@@ -77,11 +74,12 @@ let WebSocketApi = class WebSocketApi {
|
|
|
77
74
|
throw new AggregatedError('The Broadcast operation encountered some errors', errors);
|
|
78
75
|
}
|
|
79
76
|
}
|
|
80
|
-
execute(data, injector) {
|
|
81
|
-
const
|
|
82
|
-
if (
|
|
83
|
-
|
|
84
|
-
|
|
77
|
+
async execute(data, request, injector, socket) {
|
|
78
|
+
const Action = this.settings.actions.find((a) => a.canExecute({ data, request, socket }));
|
|
79
|
+
if (Action) {
|
|
80
|
+
await usingAsync(injector.getInstance(Action), async (action) => {
|
|
81
|
+
await action.execute({ data, request, socket });
|
|
82
|
+
});
|
|
85
83
|
}
|
|
86
84
|
}
|
|
87
85
|
};
|
|
@@ -93,10 +91,6 @@ __decorate([
|
|
|
93
91
|
Injected(ServerManager),
|
|
94
92
|
__metadata("design:type", ServerManager)
|
|
95
93
|
], WebSocketApi.prototype, "serverManager", void 0);
|
|
96
|
-
__decorate([
|
|
97
|
-
Injected(Injector),
|
|
98
|
-
__metadata("design:type", Injector)
|
|
99
|
-
], WebSocketApi.prototype, "injector", void 0);
|
|
100
94
|
WebSocketApi = __decorate([
|
|
101
95
|
Injectable({ lifetime: 'scoped' })
|
|
102
96
|
], WebSocketApi);
|
package/esm/websocket-api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"websocket-api.js","sourceRoot":"","sources":["../src/websocket-api.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAEzB,OAAO,EAAE,eAAe,EAAE,MAAM,MAAM,CAAA;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;
|
|
1
|
+
{"version":3,"file":"websocket-api.js","sourceRoot":"","sources":["../src/websocket-api.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@furystack/websocket-api",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "12.0.0",
|
|
4
4
|
"description": "HTTP Api FuryStack package",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -34,15 +34,15 @@
|
|
|
34
34
|
},
|
|
35
35
|
"homepage": "https://github.com/furystack/furystack",
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@furystack/core": "^14.0.
|
|
38
|
-
"@furystack/inject": "^
|
|
39
|
-
"@furystack/rest-service": "^9.0.
|
|
40
|
-
"@furystack/utils": "^6.0.
|
|
37
|
+
"@furystack/core": "^14.0.1",
|
|
38
|
+
"@furystack/inject": "^11.0.0",
|
|
39
|
+
"@furystack/rest-service": "^9.0.1",
|
|
40
|
+
"@furystack/utils": "^6.0.1",
|
|
41
41
|
"ws": "^8.16.0"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@types/ws": "^8.5.10",
|
|
45
|
-
"typescript": "^5.4.
|
|
45
|
+
"typescript": "^5.4.3",
|
|
46
46
|
"vitest": "^1.4.0"
|
|
47
47
|
},
|
|
48
48
|
"gitHead": "1045d854bfd8c475b7035471d130d401417a2321"
|
|
@@ -33,8 +33,7 @@ describe('Whoami action', () => {
|
|
|
33
33
|
injector.setExplicitInstance(contextMock, HttpUserContext)
|
|
34
34
|
injector.setExplicitInstance(wsMock, ws)
|
|
35
35
|
const instance = injector.getInstance(WhoAmI)
|
|
36
|
-
|
|
37
|
-
await instance.execute({ request, data: '' })
|
|
36
|
+
await instance.execute({ request, data: '', socket: wsMock })
|
|
38
37
|
expect(wsMock.send).toBeCalledWith(JSON.stringify({ currentUser }))
|
|
39
38
|
})
|
|
40
39
|
})
|
package/src/actions/whoami.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { HttpUserContext } from '@furystack/rest-service'
|
|
2
2
|
import { Injectable, Injected } from '@furystack/inject'
|
|
3
|
-
import type { Data } from 'ws'
|
|
4
|
-
import ws from 'ws'
|
|
3
|
+
import type { Data, WebSocket } from 'ws'
|
|
5
4
|
import type { WebSocketAction } from '../models/websocket-action.js'
|
|
6
5
|
import type { IncomingMessage } from 'http'
|
|
7
6
|
|
|
@@ -17,18 +16,15 @@ export class WhoAmI implements WebSocketAction {
|
|
|
17
16
|
return options.data.toString() === 'whoami' || options.data.toString() === 'whoami /claims'
|
|
18
17
|
}
|
|
19
18
|
|
|
20
|
-
public async execute(options: { data: Data; request: IncomingMessage }) {
|
|
19
|
+
public async execute(options: { data: Data; request: IncomingMessage; socket: WebSocket }) {
|
|
21
20
|
try {
|
|
22
21
|
const currentUser = await this.httpUserContext.getCurrentUser(options.request)
|
|
23
|
-
|
|
22
|
+
options.socket.send(JSON.stringify({ currentUser }))
|
|
24
23
|
} catch (error) {
|
|
25
|
-
|
|
24
|
+
options.socket.send(JSON.stringify({ currentUser: null }))
|
|
26
25
|
}
|
|
27
26
|
}
|
|
28
27
|
|
|
29
28
|
@Injected(HttpUserContext)
|
|
30
|
-
private readonly httpUserContext
|
|
31
|
-
|
|
32
|
-
@Injected(ws)
|
|
33
|
-
private readonly websocket!: ws
|
|
29
|
+
private declare readonly httpUserContext: HttpUserContext
|
|
34
30
|
}
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import type { Disposable } from '@furystack/utils'
|
|
2
|
-
import type { Data } from 'ws'
|
|
2
|
+
import type { Data, WebSocket } from 'ws'
|
|
3
|
+
import type { IncomingMessage } from 'http'
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Static methods of a WebSocket Action
|
|
6
7
|
*/
|
|
7
8
|
export interface WebSocketActionStatic {
|
|
8
|
-
canExecute(options: { data: Data }): boolean
|
|
9
|
+
canExecute(options: { data: Data; request: IncomingMessage; socket: WebSocket }): boolean
|
|
9
10
|
}
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* A WebSocket action implementaion
|
|
13
14
|
*/
|
|
14
15
|
export interface WebSocketAction extends Disposable {
|
|
15
|
-
execute(options: { data: Data }): void
|
|
16
|
+
execute(options: { data: Data; request: IncomingMessage; socket: WebSocket }): void
|
|
16
17
|
}
|
package/src/websocket-api.ts
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import { URL } from 'url'
|
|
2
2
|
import type { Socket } from 'net'
|
|
3
3
|
import { IncomingMessage } from 'http'
|
|
4
|
-
import { ServerManager } from '@furystack/rest-service'
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
4
|
+
import { HttpUserContext, ServerManager } from '@furystack/rest-service'
|
|
5
|
+
import type { Injector } from '@furystack/inject'
|
|
6
|
+
import { Injectable, Injected } from '@furystack/inject'
|
|
7
|
+
import { usingAsync, type Disposable } from '@furystack/utils'
|
|
7
8
|
import type { Data } from 'ws'
|
|
9
|
+
import type WebSocket from 'ws'
|
|
8
10
|
import { WebSocketServer } from 'ws'
|
|
9
11
|
import ws from 'ws'
|
|
10
12
|
import { WebSocketApiSettings } from './websocket-api-settings.js'
|
|
11
13
|
import type { WebSocketAction } from './models/websocket-action.js'
|
|
12
14
|
import { AggregatedError, IdentityContext } from '@furystack/core'
|
|
13
|
-
import { WebsocketUserContext } from './websocket-user-context.js'
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
* A WebSocket API implementation for FuryStack
|
|
@@ -22,13 +23,12 @@ export class WebSocketApi implements Disposable {
|
|
|
22
23
|
private clients = new Map<ws, { injector: Injector; ws: ws; message: IncomingMessage }>()
|
|
23
24
|
|
|
24
25
|
@Injected(WebSocketApiSettings)
|
|
25
|
-
private readonly settings
|
|
26
|
+
private declare readonly settings: WebSocketApiSettings
|
|
26
27
|
|
|
27
28
|
@Injected(ServerManager)
|
|
28
|
-
private readonly serverManager
|
|
29
|
+
private declare readonly serverManager: ServerManager
|
|
29
30
|
|
|
30
|
-
|
|
31
|
-
private readonly injector!: Injector
|
|
31
|
+
private declare readonly injector: Injector
|
|
32
32
|
|
|
33
33
|
private isInitialized = false
|
|
34
34
|
public init() {
|
|
@@ -37,10 +37,10 @@ export class WebSocketApi implements Disposable {
|
|
|
37
37
|
const connectionInjector = this.injector.createChild({ owner: msg })
|
|
38
38
|
connectionInjector.setExplicitInstance(websocket, ws)
|
|
39
39
|
connectionInjector.setExplicitInstance(msg, IncomingMessage)
|
|
40
|
-
connectionInjector.setExplicitInstance(connectionInjector.getInstance(
|
|
40
|
+
connectionInjector.setExplicitInstance(connectionInjector.getInstance(HttpUserContext), IdentityContext)
|
|
41
41
|
this.clients.set(websocket, { injector: connectionInjector, message: msg, ws: websocket })
|
|
42
42
|
websocket.on('message', (message) => {
|
|
43
|
-
this.execute(message, connectionInjector)
|
|
43
|
+
this.execute(message, msg, connectionInjector, websocket)
|
|
44
44
|
})
|
|
45
45
|
|
|
46
46
|
websocket.on('close', () => {
|
|
@@ -88,11 +88,12 @@ export class WebSocketApi implements Disposable {
|
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
public execute(data: Data, injector: Injector) {
|
|
92
|
-
const
|
|
93
|
-
if (
|
|
94
|
-
|
|
95
|
-
|
|
91
|
+
public async execute(data: Data, request: IncomingMessage, injector: Injector, socket: WebSocket) {
|
|
92
|
+
const Action = this.settings.actions.find((a) => a.canExecute({ data, request, socket }))
|
|
93
|
+
if (Action) {
|
|
94
|
+
await usingAsync(injector.getInstance<WebSocketAction>(Action), async (action) => {
|
|
95
|
+
await action.execute({ data, request, socket })
|
|
96
|
+
})
|
|
96
97
|
}
|
|
97
98
|
}
|
|
98
99
|
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import type { IdentityContext, User } from '@furystack/core';
|
|
2
|
-
export declare class WebsocketUserContext implements IdentityContext {
|
|
3
|
-
isAuthenticated(): Promise<boolean>;
|
|
4
|
-
isAuthorized(...roles: string[]): Promise<boolean>;
|
|
5
|
-
getCurrentUser<TUser extends User>(): Promise<TUser>;
|
|
6
|
-
private readonly injector;
|
|
7
|
-
}
|
|
8
|
-
//# sourceMappingURL=websocket-user-context.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"websocket-user-context.d.ts","sourceRoot":"","sources":["../src/websocket-user-context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAI5D,qBACa,oBAAqB,YAAW,eAAe;IAC7C,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC;IAOnC,YAAY,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAalD,cAAc,CAAC,KAAK,SAAS,IAAI,KAAK,OAAO,CAAC,KAAK,CAAC;IAQjE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAW;CACrC"}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
-
};
|
|
7
|
-
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
-
};
|
|
10
|
-
import { IncomingMessage } from 'http';
|
|
11
|
-
import { Injectable, Injected, Injector } from '@furystack/inject';
|
|
12
|
-
import { HttpUserContext } from '@furystack/rest-service';
|
|
13
|
-
let WebsocketUserContext = class WebsocketUserContext {
|
|
14
|
-
async isAuthenticated() {
|
|
15
|
-
try {
|
|
16
|
-
return (await this.getCurrentUser()) ? true : false;
|
|
17
|
-
}
|
|
18
|
-
catch (error) {
|
|
19
|
-
return false;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
async isAuthorized(...roles) {
|
|
23
|
-
try {
|
|
24
|
-
const currentUser = await this.getCurrentUser();
|
|
25
|
-
for (const role of roles) {
|
|
26
|
-
if (!currentUser || !currentUser.roles.some((c) => c === role)) {
|
|
27
|
-
return false;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
return true;
|
|
31
|
-
}
|
|
32
|
-
catch (error) {
|
|
33
|
-
return false;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
async getCurrentUser() {
|
|
37
|
-
const user = await this.injector
|
|
38
|
-
.getInstance(HttpUserContext)
|
|
39
|
-
.authenticateRequest(this.injector.getInstance(IncomingMessage));
|
|
40
|
-
return user;
|
|
41
|
-
}
|
|
42
|
-
injector;
|
|
43
|
-
};
|
|
44
|
-
__decorate([
|
|
45
|
-
Injected(Injector),
|
|
46
|
-
__metadata("design:type", Injector)
|
|
47
|
-
], WebsocketUserContext.prototype, "injector", void 0);
|
|
48
|
-
WebsocketUserContext = __decorate([
|
|
49
|
-
Injectable({ lifetime: 'scoped' })
|
|
50
|
-
], WebsocketUserContext);
|
|
51
|
-
export { WebsocketUserContext };
|
|
52
|
-
//# sourceMappingURL=websocket-user-context.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"websocket-user-context.js","sourceRoot":"","sources":["../src/websocket-user-context.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,MAAM,CAAA;AAEtC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAGlD,IAAM,oBAAoB,GAA1B,MAAM,oBAAoB;IACxB,KAAK,CAAC,eAAe;QAC1B,IAAI,CAAC;YACH,OAAO,CAAC,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAA;QACrD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAA;QACd,CAAC;IACH,CAAC;IACM,KAAK,CAAC,YAAY,CAAC,GAAG,KAAe;QAC1C,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE,CAAA;YAC/C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,IAAI,CAAC,WAAW,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,EAAE,CAAC;oBAC/D,OAAO,KAAK,CAAA;gBACd,CAAC;YACH,CAAC;YACD,OAAO,IAAI,CAAA;QACb,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAA;QACd,CAAC;IACH,CAAC;IACM,KAAK,CAAC,cAAc;QACzB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ;aAC7B,WAAW,CAAC,eAAe,CAAC;aAC5B,mBAAmB,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,eAAe,CAAC,CAAC,CAAA;QAClE,OAAO,IAAa,CAAA;IACtB,CAAC;IAGgB,QAAQ,CAAW;CACrC,CAAA;AADkB;IADhB,QAAQ,CAAC,QAAQ,CAAC;8BACS,QAAQ;sDAAA;AA7BzB,oBAAoB;IADhC,UAAU,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;GACtB,oBAAoB,CA8BhC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"websocket-user-context.spec.d.ts","sourceRoot":"","sources":["../src/websocket-user-context.spec.ts"],"names":[],"mappings":"AAEA,OAAO,GAAG,CAAA"}
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { Injector } from '@furystack/inject';
|
|
2
|
-
import { IncomingMessage } from 'http';
|
|
3
|
-
import '.';
|
|
4
|
-
import { HttpUserContext } from '@furystack/rest-service';
|
|
5
|
-
import { usingAsync } from '@furystack/utils';
|
|
6
|
-
import { WebsocketUserContext } from './websocket-user-context.js';
|
|
7
|
-
import { describe, it, expect, vi } from 'vitest';
|
|
8
|
-
describe('WebSocket User Context', () => {
|
|
9
|
-
const mockUser = { username: 'mock@gmail.com', roles: [] };
|
|
10
|
-
const mockAdmin = { username: 'mock@gmail.com', roles: ['admin'] };
|
|
11
|
-
describe('isAuthenticated', () => {
|
|
12
|
-
it('should authenticate with HttpUserContext and the IncomingMessage', async () => {
|
|
13
|
-
await usingAsync(new Injector(), async (i) => {
|
|
14
|
-
const authFn = vi.fn(async () => mockUser);
|
|
15
|
-
const incomingMessage = {};
|
|
16
|
-
i.setExplicitInstance(incomingMessage, IncomingMessage);
|
|
17
|
-
i.setExplicitInstance({ authenticateRequest: authFn }, HttpUserContext);
|
|
18
|
-
const authResult = await i.getInstance(WebsocketUserContext).isAuthenticated();
|
|
19
|
-
expect(authResult).toBeTruthy();
|
|
20
|
-
expect(authFn).toBeCalledWith(incomingMessage);
|
|
21
|
-
});
|
|
22
|
-
});
|
|
23
|
-
it('should return false if HttpUserContext throws', async () => {
|
|
24
|
-
await usingAsync(new Injector(), async (i) => {
|
|
25
|
-
const authFn = vi.fn(() => Promise.reject('Hey! No user here!'));
|
|
26
|
-
const incomingMessage = {};
|
|
27
|
-
i.setExplicitInstance(incomingMessage, IncomingMessage);
|
|
28
|
-
i.setExplicitInstance({ authenticateRequest: authFn }, HttpUserContext);
|
|
29
|
-
const authResult = await i.getInstance(WebsocketUserContext).isAuthenticated();
|
|
30
|
-
expect(authResult).toBeFalsy();
|
|
31
|
-
expect(authFn).toBeCalledWith(incomingMessage);
|
|
32
|
-
});
|
|
33
|
-
});
|
|
34
|
-
});
|
|
35
|
-
describe('isAuthorized', () => {
|
|
36
|
-
it('should return true if the user has the role', async () => {
|
|
37
|
-
await usingAsync(new Injector(), async (i) => {
|
|
38
|
-
const authFn = vi.fn(async () => mockAdmin);
|
|
39
|
-
const incomingMessage = {};
|
|
40
|
-
i.setExplicitInstance(incomingMessage, IncomingMessage);
|
|
41
|
-
i.setExplicitInstance({ authenticateRequest: authFn }, HttpUserContext);
|
|
42
|
-
const authResult = await i.getInstance(WebsocketUserContext).isAuthorized('admin');
|
|
43
|
-
expect(authResult).toBe(true);
|
|
44
|
-
});
|
|
45
|
-
});
|
|
46
|
-
it('should return false if the user does not have the role', async () => {
|
|
47
|
-
await usingAsync(new Injector(), async (i) => {
|
|
48
|
-
const authFn = vi.fn(async () => mockUser);
|
|
49
|
-
const incomingMessage = {};
|
|
50
|
-
i.setExplicitInstance(incomingMessage, IncomingMessage);
|
|
51
|
-
i.setExplicitInstance({ authenticateRequest: authFn }, HttpUserContext);
|
|
52
|
-
const authResult = await i.getInstance(WebsocketUserContext).isAuthorized('admin');
|
|
53
|
-
expect(authResult).toBe(false);
|
|
54
|
-
});
|
|
55
|
-
});
|
|
56
|
-
it('should return false if getting the current user throws', async () => {
|
|
57
|
-
await usingAsync(new Injector(), async (i) => {
|
|
58
|
-
const authFn = vi.fn(() => Promise.reject('Hey! No user here!'));
|
|
59
|
-
const incomingMessage = {};
|
|
60
|
-
i.setExplicitInstance(incomingMessage, IncomingMessage);
|
|
61
|
-
i.setExplicitInstance({ authenticateRequest: authFn }, HttpUserContext);
|
|
62
|
-
const authResult = await i.getInstance(WebsocketUserContext).isAuthorized('admin');
|
|
63
|
-
expect(authResult).toBe(false);
|
|
64
|
-
});
|
|
65
|
-
});
|
|
66
|
-
});
|
|
67
|
-
});
|
|
68
|
-
//# sourceMappingURL=websocket-user-context.spec.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"websocket-user-context.spec.js","sourceRoot":"","sources":["../src/websocket-user-context.spec.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import { Injector } from '@furystack/inject'
|
|
2
|
-
import { IncomingMessage } from 'http'
|
|
3
|
-
import '.'
|
|
4
|
-
import { HttpUserContext } from '@furystack/rest-service'
|
|
5
|
-
import { usingAsync } from '@furystack/utils'
|
|
6
|
-
import { WebsocketUserContext } from './websocket-user-context.js'
|
|
7
|
-
import { describe, it, expect, vi } from 'vitest'
|
|
8
|
-
|
|
9
|
-
describe('WebSocket User Context', () => {
|
|
10
|
-
const mockUser = { username: 'mock@gmail.com', roles: [] }
|
|
11
|
-
const mockAdmin = { username: 'mock@gmail.com', roles: ['admin'] }
|
|
12
|
-
|
|
13
|
-
describe('isAuthenticated', () => {
|
|
14
|
-
it('should authenticate with HttpUserContext and the IncomingMessage', async () => {
|
|
15
|
-
await usingAsync(new Injector(), async (i) => {
|
|
16
|
-
const authFn = vi.fn(async () => mockUser)
|
|
17
|
-
const incomingMessage = {}
|
|
18
|
-
i.setExplicitInstance(incomingMessage, IncomingMessage)
|
|
19
|
-
i.setExplicitInstance({ authenticateRequest: authFn }, HttpUserContext)
|
|
20
|
-
const authResult = await i.getInstance(WebsocketUserContext).isAuthenticated()
|
|
21
|
-
expect(authResult).toBeTruthy()
|
|
22
|
-
expect(authFn).toBeCalledWith(incomingMessage)
|
|
23
|
-
})
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
it('should return false if HttpUserContext throws', async () => {
|
|
27
|
-
await usingAsync(new Injector(), async (i) => {
|
|
28
|
-
const authFn = vi.fn(() => Promise.reject('Hey! No user here!'))
|
|
29
|
-
const incomingMessage = {}
|
|
30
|
-
i.setExplicitInstance(incomingMessage, IncomingMessage)
|
|
31
|
-
i.setExplicitInstance({ authenticateRequest: authFn }, HttpUserContext)
|
|
32
|
-
const authResult = await i.getInstance(WebsocketUserContext).isAuthenticated()
|
|
33
|
-
expect(authResult).toBeFalsy()
|
|
34
|
-
expect(authFn).toBeCalledWith(incomingMessage)
|
|
35
|
-
})
|
|
36
|
-
})
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
describe('isAuthorized', () => {
|
|
40
|
-
it('should return true if the user has the role', async () => {
|
|
41
|
-
await usingAsync(new Injector(), async (i) => {
|
|
42
|
-
const authFn = vi.fn(async () => mockAdmin)
|
|
43
|
-
const incomingMessage = {}
|
|
44
|
-
i.setExplicitInstance(incomingMessage, IncomingMessage)
|
|
45
|
-
i.setExplicitInstance({ authenticateRequest: authFn }, HttpUserContext)
|
|
46
|
-
const authResult = await i.getInstance(WebsocketUserContext).isAuthorized('admin')
|
|
47
|
-
expect(authResult).toBe(true)
|
|
48
|
-
})
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
it('should return false if the user does not have the role', async () => {
|
|
52
|
-
await usingAsync(new Injector(), async (i) => {
|
|
53
|
-
const authFn = vi.fn(async () => mockUser)
|
|
54
|
-
const incomingMessage = {}
|
|
55
|
-
i.setExplicitInstance(incomingMessage, IncomingMessage)
|
|
56
|
-
i.setExplicitInstance({ authenticateRequest: authFn }, HttpUserContext)
|
|
57
|
-
const authResult = await i.getInstance(WebsocketUserContext).isAuthorized('admin')
|
|
58
|
-
expect(authResult).toBe(false)
|
|
59
|
-
})
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
it('should return false if getting the current user throws', async () => {
|
|
63
|
-
await usingAsync(new Injector(), async (i) => {
|
|
64
|
-
const authFn = vi.fn(() => Promise.reject('Hey! No user here!'))
|
|
65
|
-
const incomingMessage = {}
|
|
66
|
-
i.setExplicitInstance(incomingMessage, IncomingMessage)
|
|
67
|
-
i.setExplicitInstance({ authenticateRequest: authFn }, HttpUserContext)
|
|
68
|
-
const authResult = await i.getInstance(WebsocketUserContext).isAuthorized('admin')
|
|
69
|
-
expect(authResult).toBe(false)
|
|
70
|
-
})
|
|
71
|
-
})
|
|
72
|
-
})
|
|
73
|
-
})
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { IncomingMessage } from 'http'
|
|
2
|
-
import type { IdentityContext, User } from '@furystack/core'
|
|
3
|
-
import { Injectable, Injected, Injector } from '@furystack/inject'
|
|
4
|
-
import { HttpUserContext } from '@furystack/rest-service'
|
|
5
|
-
|
|
6
|
-
@Injectable({ lifetime: 'scoped' })
|
|
7
|
-
export class WebsocketUserContext implements IdentityContext {
|
|
8
|
-
public async isAuthenticated(): Promise<boolean> {
|
|
9
|
-
try {
|
|
10
|
-
return (await this.getCurrentUser()) ? true : false
|
|
11
|
-
} catch (error) {
|
|
12
|
-
return false
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
public async isAuthorized(...roles: string[]): Promise<boolean> {
|
|
16
|
-
try {
|
|
17
|
-
const currentUser = await this.getCurrentUser()
|
|
18
|
-
for (const role of roles) {
|
|
19
|
-
if (!currentUser || !currentUser.roles.some((c) => c === role)) {
|
|
20
|
-
return false
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
return true
|
|
24
|
-
} catch (error) {
|
|
25
|
-
return false
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
public async getCurrentUser<TUser extends User>(): Promise<TUser> {
|
|
29
|
-
const user = await this.injector
|
|
30
|
-
.getInstance(HttpUserContext)
|
|
31
|
-
.authenticateRequest(this.injector.getInstance(IncomingMessage))
|
|
32
|
-
return user as TUser
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
@Injected(Injector)
|
|
36
|
-
private readonly injector!: Injector
|
|
37
|
-
}
|