project changes in socket
This commit is contained in:
@@ -99,6 +99,7 @@ export const GetAllProjects = async (data: GetProjectsInterface) => {
|
||||
if (!existingUser) return { status: "User not found" };
|
||||
const projectDatas = await projectModel(organization)
|
||||
.find({
|
||||
createdBy:userId,
|
||||
isArchive: false,
|
||||
})
|
||||
.select("_id projectName createdBy thumbnail createdAt projectUuid");
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import { Socket, Server } from "socket.io";
|
||||
import { createProject, DeleteProject, updateProject } from "../../../shared/services/project/project-Services.ts";
|
||||
import { EVENTS } from "../../socket/events.ts";
|
||||
import { emitEventResponse } from "../../utils/emitEventResponse.ts";
|
||||
import { emitEventResponse, emitToSenderAndAdmins, } from "../../utils/emitEventResponse.ts";
|
||||
|
||||
export const projectHandleEvent = async ( event: string,socket: Socket,data: any,) => {
|
||||
export const projectHandleEvent = async ( event: string,socket: Socket,io:Server,data: any, connectedUsersByOrg: { [org: string]: { socketId: string; userId: string; role: string }[] }, callback?: Function
|
||||
) => {
|
||||
console.log('event: ', event);
|
||||
console.log('data:controller ', data);
|
||||
if (event !== EVENTS.addProject || !data?.organization) return;
|
||||
const requiredFields = ["projectUuid", "projectName", "userId", "thumbnail", "organization"];
|
||||
const requiredFields = ["projectUuid", "userId", "thumbnail", "organization"];
|
||||
const missingFields = requiredFields.filter(field => !data?.[field]);
|
||||
|
||||
if (missingFields.length > 0) {
|
||||
@@ -17,7 +20,7 @@ export const projectHandleEvent = async ( event: string,socket: Socket,data: any
|
||||
organization: data?.organization ?? "unknown",
|
||||
};
|
||||
|
||||
emitEventResponse(socket, data?.organization, EVENTS.projectResponse, response);
|
||||
emitToSenderAndAdmins(io, socket, data.organization, EVENTS.projectResponse, response, connectedUsersByOrg)
|
||||
return;
|
||||
}
|
||||
const result = await createProject(data);
|
||||
@@ -46,17 +49,35 @@ export const projectHandleEvent = async ( event: string,socket: Socket,data: any
|
||||
...(status === "Success" ? { data: projectDatas, projectId: result.project._id } : {}),
|
||||
};
|
||||
|
||||
emitEventResponse(socket, data.organization, EVENTS.projectResponse, response);
|
||||
emitToSenderAndAdmins(io, socket, data.organization, EVENTS.projectResponse, response, connectedUsersByOrg)
|
||||
|
||||
}
|
||||
export const projectDeleteHandleEvent = async (
|
||||
event: string,
|
||||
socket: Socket,
|
||||
io:Server,
|
||||
data: any,
|
||||
connectedUsersByOrg: { [org: string]: { socketId: string; userId: string; role: string }[] },
|
||||
) => {
|
||||
console.log('event: ', event);
|
||||
if (event !== EVENTS.deleteProject || !data?.organization) return;
|
||||
const requiredFields = ["projectId", "userId", "organization"];
|
||||
const missingFields = requiredFields.filter(field => !data?.[field]);
|
||||
|
||||
if (missingFields.length > 0) {
|
||||
const response = {
|
||||
success: false,
|
||||
message: `Missing required field(s): ${missingFields.join(", ")}`,
|
||||
status: "MissingFields",
|
||||
socketId: socket.id,
|
||||
organization: data?.organization ?? "unknown",
|
||||
};
|
||||
|
||||
emitToSenderAndAdmins(io, socket, data.organization, EVENTS.deleteProjectResponse, response, connectedUsersByOrg)
|
||||
return;
|
||||
}
|
||||
const result = await DeleteProject(data);
|
||||
console.log('result: ', result);
|
||||
const status = typeof result?.status === "string" ? result.status : "unknown";
|
||||
|
||||
const messages: Record<string, { message: string }> = {
|
||||
@@ -86,16 +107,32 @@ export const projectDeleteHandleEvent = async (
|
||||
};
|
||||
|
||||
|
||||
emitEventResponse(socket, data.organization, EVENTS.deleteProjectResponse, response);
|
||||
}
|
||||
emitToSenderAndAdmins(io, socket, data.organization, EVENTS.deleteProjectResponse, response, connectedUsersByOrg)}
|
||||
|
||||
export const projecUpdateHandleEvent = async (
|
||||
event: string,
|
||||
socket: Socket,
|
||||
io:Server,
|
||||
data: any,
|
||||
connectedUsersByOrg: { [org: string]: { socketId: string; userId: string; role: string }[] },
|
||||
) => {
|
||||
console.log('data: ', data);
|
||||
console.log('data:update ', data);
|
||||
if (event !== EVENTS.ProjectUpdate || !data?.organization) return;
|
||||
const requiredFields = ["projectId", "userId", "organization"];
|
||||
const missingFields = requiredFields.filter(field => !data?.[field]);
|
||||
|
||||
if (missingFields.length > 0) {
|
||||
const response = {
|
||||
success: false,
|
||||
message: `Missing required field(s): ${missingFields.join(", ")}`,
|
||||
status: "MissingFields",
|
||||
socketId: socket.id,
|
||||
organization: data?.organization ?? "unknown",
|
||||
};
|
||||
|
||||
emitToSenderAndAdmins(io, socket, data.organization, EVENTS.projectUpdateResponse, response, connectedUsersByOrg)
|
||||
return;
|
||||
}
|
||||
const result = await updateProject(data);
|
||||
const status = typeof result?.status === "string" ? result.status : "unknown";
|
||||
|
||||
@@ -107,8 +144,8 @@ export const projecUpdateHandleEvent = async (
|
||||
|
||||
const msg = messages[status] || { message: "Internal server error" };
|
||||
const projectDeleteDatas =
|
||||
status === "Success" && result?.data
|
||||
|
||||
status === "Success" && result?.data
|
||||
|
||||
|
||||
const response = {
|
||||
success: status === "Success",
|
||||
@@ -120,7 +157,7 @@ export const projecUpdateHandleEvent = async (
|
||||
};
|
||||
|
||||
|
||||
emitEventResponse(socket, data.organization, EVENTS.projectUpdateResponse, response);
|
||||
emitToSenderAndAdmins(io, socket, data.organization, EVENTS.projectUpdateResponse, response, connectedUsersByOrg)
|
||||
console.log('response: ', response);
|
||||
|
||||
}
|
||||
@@ -16,7 +16,6 @@ app.get('/', (req: Request, res: Response) => {
|
||||
res.send('Hello, I am Major-Dwinzo RealTime!');
|
||||
});
|
||||
initSocketServer(server);
|
||||
// SocketServer(server)
|
||||
server.listen(PORT, () => {
|
||||
console.log(`socket-Server is running on http://localhost:${PORT}`);
|
||||
});
|
||||
|
||||
@@ -14,6 +14,7 @@ import { addTemplate, addTemplateZone, TemplateZoneDelete } from '../services/vi
|
||||
import { deleteAssetModel, replaceEventDatas, setAssetModel } from '../services/assets/asset-Controller.ts';
|
||||
import { add3Dwidget, delete3Dwidget, update3D } from '../services/visualization/3dWidget-Service.ts';
|
||||
import { projectDeleteHandleEvent, projectHandleEvent, projecUpdateHandleEvent } from '../controllers/project/projectController.ts';
|
||||
import { getUserRole } from '../utils/getUsers.ts';
|
||||
|
||||
|
||||
|
||||
@@ -1065,6 +1066,13 @@ const emitEventResponse = (socket: Socket, organization: string, event: string,
|
||||
console.warn(`Organization missing in response for event: ${event}`);
|
||||
}
|
||||
};
|
||||
interface UserSocketInfo {
|
||||
socketId: string;
|
||||
userId: string;
|
||||
role: string; // e.g., "admin" or "user"
|
||||
}
|
||||
|
||||
const connectedUsersByOrg: { [organization: string]: UserSocketInfo[] } = {};
|
||||
|
||||
export const initSocketServer = (httpServer: any) => {
|
||||
const io = new Server(httpServer, {
|
||||
@@ -1075,44 +1083,12 @@ export const initSocketServer = (httpServer: any) => {
|
||||
});
|
||||
|
||||
|
||||
// Listen for new connections
|
||||
// io.on(EVENTS.connection, (socket: Socket) => {
|
||||
// // console.log(`New client connected: ${socket.id}`);
|
||||
// // console.log(socket.handshake.auth);
|
||||
// userStatus(EVENTS.connection, socket, socket.handshake.auth, io);
|
||||
// // console.log('socket.handshake.auth: ', socket.handshake.auth);
|
||||
|
||||
// // Handle all incoming events with the handleEvent function
|
||||
// socket.onAny((event: string, data: any,) => {
|
||||
// cameraHandleEvent(event, socket, data, io);
|
||||
// EnvironmentHandleEvent(event, socket, data, io);
|
||||
// floorItemsHandleEvent(event, socket, data, io);
|
||||
// wallItemsHandleEvent(event, socket, data, io);
|
||||
// lineHandleEvent(event, socket, data, io);
|
||||
// zoneHandleEvent(event, socket, data, io);
|
||||
|
||||
|
||||
// });
|
||||
// socket.on(EVENTS.disconnect, (reason: string) => {
|
||||
// // console.log(`Client disconnected: ${socket.id}, Reason: ${reason}`);
|
||||
// // console.log(socket.handshake.auth);
|
||||
// userStatus(EVENTS.disconnect, socket, socket.handshake.auth, io);
|
||||
// // Perform cleanup or other necessary actions
|
||||
// });
|
||||
// });
|
||||
// 🔹 Create different namespaces
|
||||
const namespaces = {
|
||||
// camera: io.of("/camera"),
|
||||
// environment: io.of("/environment"),
|
||||
// floorItems: io.of("/floorItems"),
|
||||
// wallItems: io.of("/wallItems"),
|
||||
// line: io.of("/line"),
|
||||
// zone: io.of("/zone"),
|
||||
|
||||
Builder: io.of('/Builder'),
|
||||
visualization: io.of('/Visualization'),
|
||||
project: io.of('/project'),
|
||||
|
||||
// widget:io.of('/widget')
|
||||
};
|
||||
|
||||
// const onlineUsers = new Map<string, Set<string>>();
|
||||
@@ -1121,14 +1097,13 @@ export const initSocketServer = (httpServer: any) => {
|
||||
|
||||
const handleNamespace = (namespaceName: string, namespace: any, ...eventHandlers: Function[]) => {
|
||||
|
||||
namespace.on("connection", (socket: Socket) => {
|
||||
// console.log(`✅ Client connected to ${namespaceName}: ${socket.id}`);
|
||||
// Extract organization from query parameters
|
||||
namespace.on("connection", async (socket: Socket) => {
|
||||
|
||||
|
||||
// const organization = socket.handshake.query.organization as string;
|
||||
// const email = socket.handshake.query.email as string;
|
||||
const { organization, email } = socket.handshake.auth
|
||||
// console.log(`🔍 Received organization: ${organization}`);
|
||||
const { organization, email, userId } = socket.handshake.auth
|
||||
console.log(' socket.handshake.auth: ', socket.handshake.auth);
|
||||
|
||||
if (organization) {
|
||||
socket.join(organization);
|
||||
@@ -1140,24 +1115,49 @@ export const initSocketServer = (httpServer: any) => {
|
||||
onlineUsers[organization] = new Set();
|
||||
}
|
||||
onlineUsers[organization].add(socket.id);
|
||||
// console.log('onlineUsers: ', onlineUsers);
|
||||
|
||||
// console.log(`✅ User ${email} joined ${organization}. Active users:`, onlineUsers[organization]);
|
||||
}
|
||||
|
||||
userStatus(EVENTS.connection, socket, socket.handshake.auth, socket);
|
||||
const role = await getUserRole(userId, organization);
|
||||
console.log('role: ', role);
|
||||
if (role === "Admin") {
|
||||
socket.join(`${organization}_admins`);
|
||||
}
|
||||
// Save user info somewhere
|
||||
if (organization && userId && role) {
|
||||
if (!connectedUsersByOrg[organization]) {
|
||||
connectedUsersByOrg[organization] = [];
|
||||
}
|
||||
|
||||
connectedUsersByOrg[organization].push({
|
||||
socketId: socket.id,
|
||||
userId,
|
||||
role,
|
||||
});
|
||||
|
||||
// console.log(`🔗 User connected: ${userId} with role ${role} in ${organization}`);
|
||||
// console.log("🧩 connectedUsersByOrg: ", connectedUsersByOrg);
|
||||
} else {
|
||||
console.warn(`❌ Cannot store user. Missing data:`,);
|
||||
}
|
||||
|
||||
|
||||
|
||||
userStatus(EVENTS.connection, socket, socket.handshake.auth, socket);
|
||||
socket.onAny((event: string, data: any, callback: any) => {
|
||||
eventHandlers.forEach(handler => handler(event, socket, data, namespace, io, callback));
|
||||
eventHandlers.forEach(handler => handler(event, socket, io, data, connectedUsersByOrg, callback));
|
||||
});
|
||||
|
||||
|
||||
// Handle disconnection
|
||||
socket.on("disconnect", () => {
|
||||
onlineUsers[organization]?.delete(socket.id);
|
||||
if (onlineUsers[organization]?.size === 0) delete onlineUsers[organization];
|
||||
userStatus(EVENTS.disconnect, socket, socket.handshake.auth, socket);
|
||||
// console.log(`❌ User ${email} disconnected. Remaining:`, onlineUsers[organization]);
|
||||
// console.log(`❌ Client disconnected from ${namespaceName}: ${socket.id}, Reason: ${reason}`);
|
||||
connectedUsersByOrg[organization] = connectedUsersByOrg[organization].filter(
|
||||
(u) => u.socketId !== socket.id
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
// Handle reconnection (Auto rejoin)
|
||||
@@ -1172,15 +1172,6 @@ export const initSocketServer = (httpServer: any) => {
|
||||
};
|
||||
|
||||
|
||||
// 🔹 Apply namespace handlers
|
||||
// handleNamespace("camera", namespaces.camera, cameraHandleEvent);
|
||||
// handleNamespace("environment", namespaces.environment, EnvironmentHandleEvent);
|
||||
// handleNamespace("floorItems", namespaces.floorItems, floorItemsHandleEvent);
|
||||
// handleNamespace("wallItems", namespaces.wallItems, wallItemsHandleEvent);
|
||||
// handleNamespace("line", namespaces.line, lineHandleEvent);
|
||||
// handleNamespace("zone", namespaces.zone, zoneHandleEvent);
|
||||
// handleNamespace("visualization", namespaces.panel, panelHandleEvent);
|
||||
// handleNamespace("widget", namespaces.visualization, widgetHandleEvent);
|
||||
handleNamespace("Builder", namespaces.Builder, userStatus, modelAssetHandleEvent, cameraHandleEvent, EnvironmentHandleEvent, wallItemsHandleEvent, lineHandleEvent, zoneHandleEvent);
|
||||
handleNamespace("Visualization", namespaces.visualization, panelHandleEvent, widgetHandleEvent, floatHandleEvent, templateHandleEvent, Widget3DHandleEvent);
|
||||
handleNamespace("project", namespaces.project, projectHandleEvent, projectDeleteHandleEvent, projecUpdateHandleEvent)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Socket } from "socket.io";
|
||||
import { Socket,Server } from "socket.io";
|
||||
|
||||
interface EmitOptions {
|
||||
success: boolean;
|
||||
@@ -19,12 +19,13 @@ export const emitEventResponse = (
|
||||
event: string,
|
||||
result: EmitOptions
|
||||
) => {
|
||||
console.log('event: ', event);
|
||||
if (!organization) {
|
||||
console.log(`Organization missing in response for event: ${event}`);
|
||||
return;
|
||||
}
|
||||
|
||||
socket.emit(event, {
|
||||
socket.to(organization).emit(event, {
|
||||
// success: result.success,
|
||||
message: result.message,
|
||||
data: result.data ,
|
||||
@@ -33,3 +34,55 @@ export const emitEventResponse = (
|
||||
organization,
|
||||
});
|
||||
};
|
||||
|
||||
// interface EmitOptions {
|
||||
// success: boolean;
|
||||
// message: string;
|
||||
// data?: any;
|
||||
// error?: any;
|
||||
// organization: string;
|
||||
// socketId: string;
|
||||
// status?: string;
|
||||
// }
|
||||
|
||||
export const emitToSenderAndAdmins = (
|
||||
io: Server,
|
||||
socket: Socket,
|
||||
organization: string,
|
||||
event: string,
|
||||
result: EmitOptions,
|
||||
connectedUsersByOrg: { [org: string]: { socketId: string; userId: string; role: string }[] }
|
||||
) => {
|
||||
console.log('result.data,: ', result.data,);
|
||||
// Emit to sender directly
|
||||
socket.emit(event, {
|
||||
message: result.message,
|
||||
data: result.data,
|
||||
error: result.error,
|
||||
socketId: result.socketId,
|
||||
organization,
|
||||
});
|
||||
socket.to(`${organization}_admins`).emit(event, {
|
||||
message: result.message,
|
||||
data: result.data,
|
||||
error: result.error,
|
||||
socketId: result.socketId,
|
||||
organization,
|
||||
});
|
||||
// Emit to all admin sockets in organization except sender
|
||||
// const admins = connectedUsersByOrg[organization]?.filter(
|
||||
// user => user.role === 'Admin' && user.socketId !== socket.id
|
||||
// ) || [];
|
||||
// console.log('admins: ', admins);
|
||||
|
||||
|
||||
// admins.forEach(adminUser => {
|
||||
// io.to(adminUser.socketId).emit(event, {
|
||||
// message: result.message,
|
||||
// data: result.data,
|
||||
// error: result.error,
|
||||
// socketId: result.socketId,
|
||||
// organization,
|
||||
// });
|
||||
// });
|
||||
};
|
||||
|
||||
11
src/socket-server/utils/getUsers.ts
Normal file
11
src/socket-server/utils/getUsers.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import userModel from "../../shared/model/user-Model.ts";
|
||||
|
||||
// Example function to get user role from DB
|
||||
|
||||
|
||||
export async function getUserRole(userId: string, organization: string): Promise<string> {
|
||||
console.log('userId: ', userId);
|
||||
const user = await userModel(organization).findOne({ _id: userId });
|
||||
console.log('user: ', user);
|
||||
return user?.role || "User"; // default to 'user' if no role found
|
||||
}
|
||||
Reference in New Issue
Block a user