Files
bodyshop/server/web-sockets/redisSocketEvents.js
2024-09-26 10:56:48 -04:00

123 lines
4.4 KiB
JavaScript

const path = require("path");
require("dotenv").config({
path: path.resolve(process.cwd(), `.env.${process.env.NODE_ENV || "development"}`)
});
const logger = require("../utils/logger");
const { admin } = require("../firebase/firebase-handler");
// Logging helper functions
function createLogEvent(socket, level, message) {
console.log(`[IOREDIS LOG EVENT] - ${socket.user.email} - ${socket.id} - ${message}`);
logger.log("ioredis-log-event", level, socket.user.email, null, { wsmessage: message });
}
const registerUpdateEvents = (socket) => {
socket.on("update-token", async (newToken) => {
try {
socket.user = await admin.auth().verifyIdToken(newToken);
createLogEvent(socket, "INFO", "Token updated successfully");
socket.emit("token-updated", { success: true });
} catch (error) {
createLogEvent(socket, "ERROR", `Token update failed: ${error.message}`);
socket.emit("token-updated", { success: false, error: error.message });
// Optionally disconnect the socket if token verification fails
socket.disconnect();
}
});
};
const redisSocketEvents = (io, { addUserToRoom, getUsersInRoom, removeUserFromRoom }, { getBodyshopRoom }) => {
// Room management and broadcasting events
function registerRoomAndBroadcastEvents(socket) {
socket.on("join-bodyshop-room", async (bodyshopUUID) => {
const room = getBodyshopRoom(bodyshopUUID);
socket.join(room);
await addUserToRoom(room, { uid: socket.user.uid, email: socket.user.email });
createLogEvent(socket, "DEBUG", `Client joined bodyshop room: ${bodyshopUUID}`);
// Notify all users in the room about the updated user list
const usersInRoom = await getUsersInRoom(bodyshopUUID);
io.to(room).emit("room-users-updated", usersInRoom);
});
socket.on("leave-bodyshop-room", async (bodyshopUUID) => {
const room = getBodyshopRoom(bodyshopUUID);
socket.leave(room);
createLogEvent(socket, "DEBUG", `Client left bodyshop room: ${room}`);
});
socket.on("get-room-users", async (bodyshopUUID, callback) => {
const usersInRoom = await getUsersInRoom(getBodyshopRoom(bodyshopUUID));
callback(usersInRoom);
});
socket.on("broadcast-to-bodyshop", async (bodyshopUUID, message) => {
const room = getBodyshopRoom(bodyshopUUID);
io.to(room).emit("bodyshop-message", message);
createLogEvent(socket, "INFO", `Broadcast message to bodyshop ${room}`);
});
socket.on("disconnect", async () => {
createLogEvent(socket, "DEBUG", `User disconnected.`);
// Get all rooms the socket is part of
const rooms = Array.from(socket.rooms).filter((room) => room !== socket.id);
for (const bodyshopRoom of rooms) {
await removeUserFromRoom(bodyshopRoom, { uid: socket.user.uid, email: socket.user.email });
// Notify all users in the room about the updated user list
const usersInRoom = await getUsersInRoom(bodyshopRoom);
io.to(bodyshopRoom).emit("room-users-updated", usersInRoom);
}
});
}
// Register all socket events for a given socket connection
function registerSocketEvents(socket) {
createLogEvent(socket, "DEBUG", `Connected and Authenticated.`);
// Register room and broadcasting events
registerRoomAndBroadcastEvents(socket);
registerUpdateEvents(socket);
// Handle socket disconnection
socket.on("disconnect", async () => {
createLogEvent(socket, "DEBUG", `User disconnected.`);
});
}
const authMiddleware = (socket, next) => {
try {
if (socket.handshake.auth.token) {
admin
.auth()
.verifyIdToken(socket.handshake.auth.token)
.then((user) => {
socket.user = user;
next();
})
.catch((error) => {
next(new Error("Authentication error", JSON.stringify(error)));
});
} else {
next(new Error("Authentication error - no authorization token."));
}
} catch (error) {
console.log("Uncaught connection error:::", error);
logger.log("websocket-connection-error", "error", null, null, {
token: socket.handshake.auth.token,
...error
});
next(new Error(`Authentication error ${error}`));
}
};
// Socket.IO Middleware and Connection
io.use(authMiddleware);
io.on("connection", registerSocketEvents);
};
module.exports = {
redisSocketEvents
};