65 lines
2.0 KiB
TypeScript
65 lines
2.0 KiB
TypeScript
import type { Server } from "socket.io";
|
||
import type {
|
||
ServerToClientEvents,
|
||
ClientToServerEvents,
|
||
InterServerEvents,
|
||
SocketData,
|
||
} from "@storybid/shared";
|
||
|
||
import { registerLiveAuctionHandlers } from "./live-auction.js";
|
||
import { registerSilentAuctionHandlers } from "./silent-auction.js";
|
||
import { verifyToken } from "../lib/jwt.js";
|
||
|
||
type IO = Server<ClientToServerEvents, ServerToClientEvents, InterServerEvents, SocketData>;
|
||
|
||
export function registerSocketHandlers(io: IO): void {
|
||
// Auth middleware – validate JWT on handshake
|
||
io.use((socket, next) => {
|
||
const token =
|
||
(socket.handshake.auth["token"] as string | undefined) ??
|
||
(socket.handshake.headers["authorization"] as string | undefined)?.replace("Bearer ", "");
|
||
|
||
if (!token) {
|
||
// Allow unauthenticated connections for display board / public catalog
|
||
return next();
|
||
}
|
||
|
||
try {
|
||
const payload = verifyToken(token);
|
||
socket.data.bidderId = payload.role === "bidder" ? payload.sub : undefined;
|
||
socket.data.staffId = payload.role !== "bidder" ? payload.sub : undefined;
|
||
socket.data.role = payload.role;
|
||
socket.data.deviceId = payload.deviceId;
|
||
} catch {
|
||
return next(new Error("Invalid token"));
|
||
}
|
||
|
||
next();
|
||
});
|
||
|
||
io.on("connection", (socket) => {
|
||
console.log(`[socket] connected ${socket.id} role=${socket.data.role ?? "guest"}`);
|
||
|
||
// Auto-join personal room for outbid / checkout notifications
|
||
if (socket.data.bidderId) {
|
||
void socket.join(`bidder:${socket.data.bidderId}`);
|
||
}
|
||
|
||
// Room join/leave for event-scoped broadcasts
|
||
socket.on("join_event", (eventId) => {
|
||
void socket.join(`event:${eventId}`);
|
||
});
|
||
|
||
socket.on("leave_event", (eventId) => {
|
||
void socket.leave(`event:${eventId}`);
|
||
});
|
||
|
||
registerLiveAuctionHandlers(io, socket);
|
||
registerSilentAuctionHandlers(io, socket);
|
||
|
||
socket.on("disconnect", (reason) => {
|
||
console.log(`[socket] disconnected ${socket.id} reason=${reason}`);
|
||
});
|
||
});
|
||
}
|