Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Minor Fix on the Collaboration Service #86

Merged
merged 3 commits into from
Nov 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,6 @@ YJS_DB_LOCAL_URI=mongodb://collaboration-db:27017/yjs-documents
HISTORY_DB_CLOUD_URI=<FILL-THIS-IN>
HISTORY_DB_LOCAL_URI=mongodb://history-db:27017/history

# Will use cloud MongoDB Atlas database
ENV=PROD

# Broker
BROKER_URL=amqp://broker:5672

Expand Down
1 change: 1 addition & 0 deletions services/collaboration/src/controllers/roomController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ export const updateUserStatusInRoomController = async (req: Request, res: Respon

// Check if all users in the room have forfeited
const allUsersForfeited = updatedRoom.users.every(user => user.isForfeit === true);
console.log('All users forfeited check:', allUsersForfeited, updatedRoom.users);
if (allUsersForfeited) {
// Close the room if both users have forfeited
const result = await closeRoomById(roomId);
Expand Down
11 changes: 9 additions & 2 deletions services/collaboration/src/services/mongodbService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,10 @@ export const createYjsDocument = async (roomId: string) => {
*/
export const deleteYjsDocument = async (roomId: string) => {
try {
console.log(`Attempting to delete Yjs document collection for room: ${roomId}`);
const db = await connectToYJSDB();
await db.collection(roomId).drop();
console.log(`Yjs document collection for room ${roomId} deleted`);
const result = await db.collection(roomId).drop();
console.log(`Yjs document collection for room ${roomId} deleted successfully: ${result}`);
} catch (error) {
console.error(`Failed to delete Yjs document for room ${roomId}:`, error);
throw error;
Expand Down Expand Up @@ -196,6 +197,12 @@ export const closeRoomById = async (roomId: string) => {
}
};

/**
* Update the user isForfeit status in a room
* @param roomId
* @param userId
* @param isForfeit
*/
export const updateRoomUserStatus = async (roomId: string, userId: string, isForfeit: boolean) => {
try {
const db = await connectToRoomDB();
Expand Down
30 changes: 19 additions & 11 deletions services/collaboration/src/services/webSocketService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,20 @@ const { setPersistence, setupWSConnection } = require('../utils/utility.js');

const URL_REGEX = /^.*\/([0-9a-f]{24})\?accessToken=([a-zA-Z0-9\-._~%]{1,})$/;

const authorize = async (ws: WebSocket, request: IncomingMessage): Promise<boolean> => {
/**
* Verifies the user's access to a specific room by validating the JWT token,
* checking the room's status, and ensuring the user has not forfeited.
* Returns `roomId` if the access is authorized, or `null` otherwise.
* @param ws
* @param request
* @returns
*/
const authorize = async (ws: WebSocket, request: IncomingMessage): Promise<string | null> => {
const url = request.url ?? '';
const match = url?.match(URL_REGEX);
if (!match) {
handleAuthFailed(ws, 'Authorization failed: Invalid format');
return false;
return null;
}
const roomId = match[1];
const accessToken = match[2];
Expand All @@ -34,27 +42,27 @@ const authorize = async (ws: WebSocket, request: IncomingMessage): Promise<boole
});
if (!user) {
handleAuthFailed(ws, 'Authorization failed: Invalid token');
return false;
return null;
}

const room = await findRoomById(roomId, user.id);
if (!room) {
handleAuthFailed(ws, 'Authorization failed');
return false;
return null;
}

if (!room.room_status) {
handleRoomClosed(ws);
return false;
return null;
}

const userInRoom = room.users.find((u: { id: string }) => u.id === user.id);
if (userInRoom?.isForfeit) {
handleAuthFailed(ws, 'Authorization failed: User has forfeited');
return false;
return null;
}
console.log('WebSocket connection established for room:', roomId);
return true;
return roomId;
};

/**
Expand All @@ -65,13 +73,13 @@ export const startWebSocketServer = (server: Server) => {
const wss = new WebSocketServer({ server });

wss.on('connection', async (conn: WebSocket, req: IncomingMessage) => {
const isAuthorized = await authorize(conn, req);
if (!isAuthorized) {
const roomId = await authorize(conn, req);
if (!roomId) {
return;
}

try {
setupWSConnection(conn, req);
setupWSConnection(conn, req, { docName: roomId });
} catch (error) {
console.error('Failed to set up WebSocket connection:', error);
handleAuthFailed(conn, 'Authorization failed');
Expand All @@ -85,7 +93,7 @@ export const startWebSocketServer = (server: Server) => {
console.log(`Loaded persisted document for ${docName}`);

const newUpdates = Y.encodeStateAsUpdate(ydoc);
mdb.storeUpdate(docName, newUpdates);
await mdb.storeUpdate(docName, newUpdates);

Y.applyUpdate(ydoc, Y.encodeStateAsUpdate(persistedYdoc));

Expand Down