Spaces:
Runtime error
Runtime error
Changed room ID to correct length, 31 token, and 6 digits
Browse files
server/package-lock.json
CHANGED
|
@@ -10,6 +10,7 @@
|
|
| 10 |
"license": "ISC",
|
| 11 |
"dependencies": {
|
| 12 |
"@types/ws": "^8.5.9",
|
|
|
|
| 13 |
"express": "^4.18.2",
|
| 14 |
"pino": "^8.16.2",
|
| 15 |
"ws": "^8.14.2",
|
|
@@ -341,6 +342,11 @@
|
|
| 341 |
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
| 342 |
"dev": true
|
| 343 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 344 |
"node_modules/base64-js": {
|
| 345 |
"version": "1.5.1",
|
| 346 |
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
|
|
|
| 10 |
"license": "ISC",
|
| 11 |
"dependencies": {
|
| 12 |
"@types/ws": "^8.5.9",
|
| 13 |
+
"base-x": "^4.0.0",
|
| 14 |
"express": "^4.18.2",
|
| 15 |
"pino": "^8.16.2",
|
| 16 |
"ws": "^8.14.2",
|
|
|
|
| 342 |
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
| 343 |
"dev": true
|
| 344 |
},
|
| 345 |
+
"node_modules/base-x": {
|
| 346 |
+
"version": "4.0.0",
|
| 347 |
+
"resolved": "https://registry.npmjs.org/base-x/-/base-x-4.0.0.tgz",
|
| 348 |
+
"integrity": "sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw=="
|
| 349 |
+
},
|
| 350 |
"node_modules/base64-js": {
|
| 351 |
"version": "1.5.1",
|
| 352 |
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
server/package.json
CHANGED
|
@@ -26,6 +26,7 @@
|
|
| 26 |
},
|
| 27 |
"dependencies": {
|
| 28 |
"@types/ws": "^8.5.9",
|
|
|
|
| 29 |
"express": "^4.18.2",
|
| 30 |
"pino": "^8.16.2",
|
| 31 |
"ws": "^8.14.2",
|
|
|
|
| 26 |
},
|
| 27 |
"dependencies": {
|
| 28 |
"@types/ws": "^8.5.9",
|
| 29 |
+
"base-x": "^4.0.0",
|
| 30 |
"express": "^4.18.2",
|
| 31 |
"pino": "^8.16.2",
|
| 32 |
"ws": "^8.14.2",
|
server/src/helpers.ts
CHANGED
|
@@ -1,7 +1,15 @@
|
|
| 1 |
import * as crypto from "crypto";
|
|
|
|
| 2 |
|
| 3 |
export function generateSessionToken(length: number): string {
|
| 4 |
-
if (length < 1) throw new Error("invalid length. length must be greater than 0")
|
| 5 |
-
|
| 6 |
-
|
|
|
|
|
|
|
| 7 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
import * as crypto from "crypto";
|
| 2 |
+
import basex from "base-x";
|
| 3 |
|
| 4 |
export function generateSessionToken(length: number): string {
|
| 5 |
+
if (length < 1) throw new Error("invalid length. length must be greater than 0");
|
| 6 |
+
const base31Tokens = "ABCDEFGHJKMNPQRSTUVWXYZ23456789";
|
| 7 |
+
const base31 = basex(base31Tokens);
|
| 8 |
+
|
| 9 |
+
const byteLength = Math.ceil((length * Math.log(256)) / Math.log(base31Tokens.length)) + 2;
|
| 10 |
|
| 11 |
+
const buffer = crypto.randomBytes(Math.ceil(byteLength));
|
| 12 |
+
const token = base31.encode(buffer);
|
| 13 |
+
|
| 14 |
+
return token.substring(0, length);
|
| 15 |
+
}
|
server/src/socket/hapticLinkServer.ts
CHANGED
|
@@ -12,13 +12,14 @@ export interface Route<T> {
|
|
| 12 |
}
|
| 13 |
|
| 14 |
export class User {
|
|
|
|
| 15 |
id: string;
|
| 16 |
username?: string;
|
| 17 |
socket: WebSocketInterface;
|
| 18 |
currentRoom?: Room;
|
| 19 |
|
| 20 |
constructor(socket: WebSocketInterface) {
|
| 21 |
-
this.id = generateSessionToken(
|
| 22 |
this.socket = socket;
|
| 23 |
}
|
| 24 |
}
|
|
|
|
| 12 |
}
|
| 13 |
|
| 14 |
export class User {
|
| 15 |
+
static userIdLength: number = 32
|
| 16 |
id: string;
|
| 17 |
username?: string;
|
| 18 |
socket: WebSocketInterface;
|
| 19 |
currentRoom?: Room;
|
| 20 |
|
| 21 |
constructor(socket: WebSocketInterface) {
|
| 22 |
+
this.id = generateSessionToken(32);
|
| 23 |
this.socket = socket;
|
| 24 |
}
|
| 25 |
}
|
server/src/socket/room.ts
CHANGED
|
@@ -9,10 +9,11 @@ export interface UserData {
|
|
| 9 |
}
|
| 10 |
|
| 11 |
export class Room {
|
|
|
|
| 12 |
id: string;
|
| 13 |
users: User[];
|
| 14 |
constructor(roomId?: string) {
|
| 15 |
-
this.id = roomId || generateSessionToken(
|
| 16 |
this.users = [];
|
| 17 |
}
|
| 18 |
|
|
|
|
| 9 |
}
|
| 10 |
|
| 11 |
export class Room {
|
| 12 |
+
static roomIdLength: number = 6;
|
| 13 |
id: string;
|
| 14 |
users: User[];
|
| 15 |
constructor(roomId?: string) {
|
| 16 |
+
this.id = roomId || generateSessionToken(Room.roomIdLength);
|
| 17 |
this.users = [];
|
| 18 |
}
|
| 19 |
|
server/src/socket/routes/join_room.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
| 1 |
import { z } from "zod";
|
| 2 |
-
import { Context
|
| 3 |
-
import { generateSessionToken } from "../../helpers";
|
| 4 |
import { Room } from "../room";
|
| 5 |
|
| 6 |
export interface JoinRoomPayload {
|
|
@@ -18,17 +17,21 @@ export function JoinRoomHandler(ctx: Context<JoinRoomPayload>) {
|
|
| 18 |
ctx.user.username = ctx.payload.username;
|
| 19 |
}
|
| 20 |
|
|
|
|
|
|
|
| 21 |
let room: Room;
|
| 22 |
|
| 23 |
if (ctx.payload.roomId && !ctx.server.rooms[ctx.payload.roomId]) {
|
| 24 |
// User sent roomId, but room doesn't exist
|
| 25 |
room = new Room(ctx.payload.roomId);
|
|
|
|
| 26 |
ctx.server.rooms[room.id] = room;
|
| 27 |
|
| 28 |
} else if (!ctx.payload.roomId) {
|
| 29 |
// Didn't include RoomID, creating new one
|
| 30 |
-
ctx.payload.roomId = generateSessionToken(12);
|
| 31 |
room = new Room(ctx.payload.roomId);
|
|
|
|
|
|
|
| 32 |
ctx.server.rooms[room.id] = room;
|
| 33 |
|
| 34 |
} else {
|
|
|
|
| 1 |
import { z } from "zod";
|
| 2 |
+
import { Context } from "../hapticLinkServer";
|
|
|
|
| 3 |
import { Room } from "../room";
|
| 4 |
|
| 5 |
export interface JoinRoomPayload {
|
|
|
|
| 17 |
ctx.user.username = ctx.payload.username;
|
| 18 |
}
|
| 19 |
|
| 20 |
+
if (ctx.payload.roomId) ctx.payload.roomId = ctx.payload.roomId.toUpperCase();
|
| 21 |
+
|
| 22 |
let room: Room;
|
| 23 |
|
| 24 |
if (ctx.payload.roomId && !ctx.server.rooms[ctx.payload.roomId]) {
|
| 25 |
// User sent roomId, but room doesn't exist
|
| 26 |
room = new Room(ctx.payload.roomId);
|
| 27 |
+
room.id = room.id.toUpperCase();
|
| 28 |
ctx.server.rooms[room.id] = room;
|
| 29 |
|
| 30 |
} else if (!ctx.payload.roomId) {
|
| 31 |
// Didn't include RoomID, creating new one
|
|
|
|
| 32 |
room = new Room(ctx.payload.roomId);
|
| 33 |
+
room.id = room.id.toUpperCase();
|
| 34 |
+
ctx.payload.roomId = room.id;
|
| 35 |
ctx.server.rooms[room.id] = room;
|
| 36 |
|
| 37 |
} else {
|
server/test/helpers.spec.ts
CHANGED
|
@@ -8,12 +8,12 @@ describe('Helpers', () => {
|
|
| 8 |
|
| 9 |
// Since the token is hexadecimal, its string length should be twice the byte length
|
| 10 |
expect(token).to.be.a('string');
|
| 11 |
-
expect(token.length).to.equal(length
|
| 12 |
});
|
| 13 |
|
| 14 |
it('should generate a unique token each time', () => {
|
| 15 |
const tokens = new Set<string>();
|
| 16 |
-
const tokenCount =
|
| 17 |
const length = 16;
|
| 18 |
|
| 19 |
for (let i = 0; i < tokenCount; i++) {
|
|
|
|
| 8 |
|
| 9 |
// Since the token is hexadecimal, its string length should be twice the byte length
|
| 10 |
expect(token).to.be.a('string');
|
| 11 |
+
expect(token.length).to.equal(length);
|
| 12 |
});
|
| 13 |
|
| 14 |
it('should generate a unique token each time', () => {
|
| 15 |
const tokens = new Set<string>();
|
| 16 |
+
const tokenCount = 1000; // Generate a number of tokens to test uniqueness
|
| 17 |
const length = 16;
|
| 18 |
|
| 19 |
for (let i = 0; i < tokenCount; i++) {
|
server/test/socket/routes/join_room.spec.ts
CHANGED
|
@@ -58,4 +58,16 @@ describe("Join Room", () => {
|
|
| 58 |
JoinRoomHandler(ctx);
|
| 59 |
expect(server.rooms[ctx.payload.roomId!].users.length).to.equal(2, "user joined twice");
|
| 60 |
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 61 |
});
|
|
|
|
| 58 |
JoinRoomHandler(ctx);
|
| 59 |
expect(server.rooms[ctx.payload.roomId!].users.length).to.equal(2, "user joined twice");
|
| 60 |
});
|
| 61 |
+
|
| 62 |
+
it("should have case insensitive IDs", () => {
|
| 63 |
+
testJoinRoom(1); // Initial user joins and creates room
|
| 64 |
+
|
| 65 |
+
// Set up second user to join the same room
|
| 66 |
+
ctx.payload.username = "test2";
|
| 67 |
+
ctx.user = user2;
|
| 68 |
+
ctx.ws = ws2;
|
| 69 |
+
ctx.payload.roomId = ctx.payload.roomId?.toLowerCase();
|
| 70 |
+
|
| 71 |
+
testJoinRoom(2); // Second user joins the existing room
|
| 72 |
+
})
|
| 73 |
});
|