@jskit-ai/realtime 0.1.56 → 0.1.57

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.
@@ -1,7 +1,7 @@
1
1
  export default Object.freeze({
2
2
  packageVersion: 1,
3
3
  packageId: "@jskit-ai/realtime",
4
- version: "0.1.56",
4
+ version: "0.1.57",
5
5
  kind: "runtime",
6
6
  description: "Thin, generic realtime runtime wrappers for socket.io server and client.",
7
7
  options: {
@@ -94,7 +94,7 @@ export default Object.freeze({
94
94
  mutations: {
95
95
  dependencies: {
96
96
  runtime: {
97
- "@jskit-ai/kernel": "0.1.57",
97
+ "@jskit-ai/kernel": "0.1.58",
98
98
  "@socket.io/redis-adapter": "^8.3.0",
99
99
  "redis": "^5.8.2",
100
100
  "socket.io": "^4.8.3",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jskit-ai/realtime",
3
- "version": "0.1.56",
3
+ "version": "0.1.57",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "test": "node --test"
@@ -16,7 +16,7 @@
16
16
  },
17
17
  "dependencies": {
18
18
  "@socket.io/redis-adapter": "^8.3.0",
19
- "@jskit-ai/kernel": "0.1.57",
19
+ "@jskit-ai/kernel": "0.1.58",
20
20
  "redis": "^5.8.2",
21
21
  "socket.io": "^4.8.3",
22
22
  "socket.io-client": "^4.8.3"
@@ -450,9 +450,40 @@ async function resolveSocketActorId(authService, socket) {
450
450
  return null;
451
451
  }
452
452
 
453
- const cookies = parseCookieHeader(socket?.request?.headers?.cookie);
454
- const authResult = await authService.authenticateRequest({
453
+ const handshakeHeaders =
454
+ socket?.handshake?.headers && typeof socket.handshake.headers === "object"
455
+ ? socket.handshake.headers
456
+ : {};
457
+ const requestHeaders =
458
+ socket?.request?.headers && typeof socket.request.headers === "object"
459
+ ? socket.request.headers
460
+ : {};
461
+ const cookieHeader = normalizeText(
462
+ handshakeHeaders.cookie ||
463
+ requestHeaders.cookie
464
+ );
465
+ const cookies = parseCookieHeader(cookieHeader);
466
+ const host = normalizeText(handshakeHeaders.host || requestHeaders.host);
467
+ const remoteAddress = normalizeText(
468
+ socket?.request?.socket?.remoteAddress ||
469
+ socket?.conn?.remoteAddress ||
470
+ socket?.handshake?.address
471
+ );
472
+ const authRequest = {
455
473
  cookies
474
+ };
475
+ if (host) {
476
+ authRequest.headers = {
477
+ host
478
+ };
479
+ }
480
+ if (remoteAddress) {
481
+ authRequest.socket = {
482
+ remoteAddress
483
+ };
484
+ }
485
+ const authResult = await authService.authenticateRequest({
486
+ ...authRequest
456
487
  });
457
488
  if (!authResult || authResult.authenticated !== true) {
458
489
  return null;
@@ -144,6 +144,96 @@ test("RealtimeServiceProvider boot does not eagerly resolve optional auth/worksp
144
144
  await provider.shutdown(app);
145
145
  });
146
146
 
147
+ test("RealtimeServiceProvider boot authenticates sockets from handshake cookies and joins actor workspace rooms", async () => {
148
+ const app = createSingletonApp();
149
+ app.instance("jskit.fastify", {
150
+ server: createServer()
151
+ });
152
+
153
+ const authenticateCalls = [];
154
+ app.singleton("authService", () => ({
155
+ async authenticateRequest(input = {}) {
156
+ authenticateCalls.push(input);
157
+ return {
158
+ authenticated: true,
159
+ profile: {
160
+ id: 9
161
+ }
162
+ };
163
+ }
164
+ }));
165
+ app.singleton("internal.repository.workspace-memberships", () => ({
166
+ async listActiveWorkspaceIdsByUserId(userId) {
167
+ assert.equal(userId, "9");
168
+ return [11, 12];
169
+ }
170
+ }));
171
+
172
+ let connectionHandler = null;
173
+ const io = {
174
+ on(eventName, handler) {
175
+ if (eventName === "connection") {
176
+ connectionHandler = handler;
177
+ }
178
+ }
179
+ };
180
+
181
+ const provider = new RealtimeServiceProvider();
182
+ provider.register(app);
183
+ app.instance("runtime.realtime.io", io);
184
+
185
+ await provider.boot(app);
186
+
187
+ const joinedRooms = [];
188
+ const socket = {
189
+ handshake: {
190
+ headers: {
191
+ cookie: "session=abc123; theme=dark",
192
+ host: "127.0.0.1:3100"
193
+ },
194
+ address: "127.0.0.1"
195
+ },
196
+ request: {
197
+ headers: {},
198
+ socket: {
199
+ remoteAddress: "127.0.0.1"
200
+ }
201
+ },
202
+ data: {},
203
+ join(room) {
204
+ joinedRooms.push(room);
205
+ }
206
+ };
207
+
208
+ await connectionHandler(socket);
209
+ await provider.shutdown(app);
210
+
211
+ assert.deepEqual(authenticateCalls, [
212
+ {
213
+ cookies: {
214
+ session: "abc123",
215
+ theme: "dark"
216
+ },
217
+ headers: {
218
+ host: "127.0.0.1:3100"
219
+ },
220
+ socket: {
221
+ remoteAddress: "127.0.0.1"
222
+ }
223
+ }
224
+ ]);
225
+ assert.equal(socket.data.actorId, "9");
226
+ assert.deepEqual(joinedRooms, [
227
+ "clients",
228
+ "users",
229
+ "user:9",
230
+ "workspace:11",
231
+ "workspace:11:user:9",
232
+ "workspace:12",
233
+ "workspace:12:user:9"
234
+ ]);
235
+ });
236
+
147
237
  test("RealtimeClientProvider registers runtime realtime client api", () => {
148
238
  const app = createSingletonApp();
149
239
  const provider = new RealtimeClientProvider();