## Description Added ESLint rule to force blank lines between statements. Fixes #`Issue Number` _or_ Fixes `Issue URL` > [!WARNING] > _If no issue exists, please create an issue first, and check with the maintainers if the issue is valid._ ## Automation /ok-to-test tags="@tag.All" ### 🔍 Cypress test results <!-- This is an auto-generated comment: Cypress test results --> > [!CAUTION] > 🔴 🔴 🔴 Some tests have failed. > Workflow run: <https://github.com/appsmithorg/appsmith/actions/runs/10924926728> > Commit: 34f57714a1575ee04e94e03cbcaf95e57a96c86c > <a href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=10924926728&attempt=1&selectiontype=test&testsstatus=failed&specsstatus=fail" target="_blank">Cypress dashboard</a>. > Tags: @tag.All > Spec: > The following are new failures, please fix them before merging the PR: <ol> > <li>cypress/e2e/Regression/ClientSide/Anvil/AnvilModal_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilButtonWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilCheckboxGroupWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilCurrencyInputWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilIconButtonWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilInlineButtonWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilInputWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilParagraphWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilPhoneInputWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilStatsWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilSwitchGroupWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilSwitchWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilTableWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilToolbarButtonWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilZoneSectionWidgetSnapshot_spec.ts</ol> > <a href="https://internal.appsmith.com/app/cypress-dashboard/identified-flaky-tests-65890b3c81d7400d08fa9ee3?branch=master" target="_blank">List of identified flaky tests</a>. > <hr>Wed, 18 Sep 2024 16:33:36 UTC <!-- end of auto-generated comment: Cypress test results --> ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [ ] No --------- Co-authored-by: Valera Melnikov <valera@appsmith.com>
137 lines
3.7 KiB
TypeScript
137 lines
3.7 KiB
TypeScript
import type { Server, Socket } from "socket.io";
|
|
import { tryAuth } from "@middlewares/socket-auth";
|
|
import {
|
|
START_EDIT_EVENT_NAME,
|
|
LEAVE_EDIT_EVENT_NAME,
|
|
MOUSE_POINTER_EVENT_NAME,
|
|
PAGE_EDIT_NAMESPACE,
|
|
PAGE_ROOM_PREFIX,
|
|
EDITORS_EVENT_NAME,
|
|
} from "@constants/socket";
|
|
import type { Policy, MousePointerEvent } from "@utils/models";
|
|
import { AppUser, CurrentEditorsEvent } from "@utils/models";
|
|
|
|
function subscribeToEditEvents(socket: Socket, appRoomPrefix: string) {
|
|
socket.on(START_EDIT_EVENT_NAME, (resourceId) => {
|
|
if (socket.data.email) {
|
|
// user is authenticated, join the room now
|
|
joinEditRoom(socket, resourceId, appRoomPrefix);
|
|
} else {
|
|
// user not authenticated yet, save the resource id and room prefix to join later after auth
|
|
socket.data.pendingRoomId = resourceId;
|
|
socket.data.pendingRoomPrefix = appRoomPrefix;
|
|
}
|
|
});
|
|
|
|
socket.on(LEAVE_EDIT_EVENT_NAME, (resourceId) => {
|
|
const roomName = appRoomPrefix + resourceId;
|
|
|
|
socket.leave(roomName); // remove this socket from room
|
|
});
|
|
}
|
|
|
|
async function onAppSocketConnected(socket: Socket) {
|
|
const isAuthenticated = await tryAuthAndJoinPendingRoom(socket);
|
|
|
|
if (isAuthenticated) {
|
|
socket.join("email:" + socket.data.email);
|
|
}
|
|
}
|
|
|
|
async function onPageSocketConnected(socket: Socket, socketIo: Server) {
|
|
const isAuthenticated = await tryAuthAndJoinPendingRoom(socket);
|
|
|
|
if (isAuthenticated) {
|
|
socket.on(MOUSE_POINTER_EVENT_NAME, (event: MousePointerEvent) => {
|
|
event.user = new AppUser(socket.data.name, socket.data.email);
|
|
event.socketId = socket.id;
|
|
socketIo
|
|
.of(PAGE_EDIT_NAMESPACE)
|
|
.to(PAGE_ROOM_PREFIX + event.pageId)
|
|
.emit(MOUSE_POINTER_EVENT_NAME, event);
|
|
});
|
|
}
|
|
}
|
|
|
|
async function tryAuthAndJoinPendingRoom(socket: Socket) {
|
|
const isAuthenticated = await tryAuth(socket);
|
|
|
|
if (socket.data.pendingRoomId) {
|
|
// an appId or pageId is pending for this socket, join now
|
|
joinEditRoom(
|
|
socket,
|
|
socket.data.pendingRoomId,
|
|
socket.data.pendingRoomPrefix,
|
|
);
|
|
}
|
|
|
|
return isAuthenticated;
|
|
}
|
|
|
|
function joinEditRoom(socket: Socket, roomId: string, roomPrefix: string) {
|
|
// remove this socket from any other rooms with roomPrefix
|
|
if (socket.rooms) {
|
|
socket.rooms.forEach((roomName) => {
|
|
if (roomName.startsWith(roomPrefix)) {
|
|
socket.leave(roomName);
|
|
}
|
|
});
|
|
}
|
|
|
|
// add this socket to room with application id
|
|
const roomName = roomPrefix + roomId;
|
|
|
|
socket.join(roomName);
|
|
}
|
|
|
|
function findPolicyEmails(policies: Policy[], permission: string): string[] {
|
|
const emails: string[] = [];
|
|
|
|
for (const policy of policies) {
|
|
if (policy.permission === permission) {
|
|
for (const email of policy.users) {
|
|
emails.push(email);
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
return emails;
|
|
}
|
|
|
|
function sendCurrentUsers(socketIo, roomName: string, roomPrefix: string) {
|
|
if (roomName.startsWith(roomPrefix)) {
|
|
socketIo
|
|
.in(roomName)
|
|
.fetchSockets()
|
|
.then((sockets) => {
|
|
const onlineUsernames = new Set<string>();
|
|
const onlineUsers = new Array<AppUser>();
|
|
|
|
if (sockets) {
|
|
sockets.forEach((s) => {
|
|
if (!onlineUsernames.has(s.data.email)) {
|
|
onlineUsers.push(new AppUser(s.data.name, s.data.email));
|
|
}
|
|
|
|
onlineUsernames.add(s.data.email);
|
|
});
|
|
}
|
|
|
|
const resourceId = roomName.replace(roomPrefix, ""); // get resourceId from room name by removing the prefix
|
|
const response = new CurrentEditorsEvent(resourceId, onlineUsers);
|
|
|
|
socketIo.to(roomName).emit(EDITORS_EVENT_NAME, response);
|
|
});
|
|
}
|
|
}
|
|
|
|
export {
|
|
subscribeToEditEvents,
|
|
onAppSocketConnected,
|
|
onPageSocketConnected,
|
|
sendCurrentUsers,
|
|
findPolicyEmails,
|
|
};
|