2023-03-05 19:57:05 +01:00
|
|
|
import authorized from "../middleware/authorized"
|
2023-05-31 11:21:50 +02:00
|
|
|
import { BaseSocket } from "./websocket"
|
2023-06-21 09:33:58 +02:00
|
|
|
import { context, permissions } from "@budibase/backend-core"
|
2023-03-05 19:57:05 +01:00
|
|
|
import http from "http"
|
|
|
|
import Koa from "koa"
|
2023-05-12 17:13:32 +02:00
|
|
|
import { getTableId } from "../api/controllers/row/utils"
|
2023-05-22 16:59:44 +02:00
|
|
|
import { Row, Table } from "@budibase/types"
|
2023-05-31 11:21:50 +02:00
|
|
|
import { Socket } from "socket.io"
|
2023-05-31 18:03:14 +02:00
|
|
|
import { GridSocketEvent } from "@budibase/shared-core"
|
2023-03-05 19:57:05 +01:00
|
|
|
|
2023-06-21 09:33:58 +02:00
|
|
|
const { PermissionType, PermissionLevel } = permissions
|
|
|
|
|
2023-05-31 11:21:50 +02:00
|
|
|
export default class GridSocket extends BaseSocket {
|
2023-03-05 19:57:05 +01:00
|
|
|
constructor(app: Koa, server: http.Server) {
|
2023-06-21 09:33:58 +02:00
|
|
|
super(app, server, "/socket/grid")
|
2023-05-31 11:21:50 +02:00
|
|
|
}
|
2023-03-05 19:57:05 +01:00
|
|
|
|
2023-05-31 11:21:50 +02:00
|
|
|
async onConnect(socket: Socket) {
|
|
|
|
// Initial identification of connected spreadsheet
|
2023-06-21 09:33:58 +02:00
|
|
|
socket.on(
|
|
|
|
GridSocketEvent.SelectTable,
|
|
|
|
async ({ tableId, appId }, callback) => {
|
|
|
|
// Check if the user has permission to read this resource
|
|
|
|
const middleware = authorized(
|
|
|
|
PermissionType.TABLE,
|
|
|
|
PermissionLevel.READ
|
|
|
|
)
|
|
|
|
const ctx = {
|
|
|
|
appId,
|
|
|
|
resourceId: tableId,
|
|
|
|
roleId: socket.data.roleId,
|
|
|
|
user: { _id: socket.data._id },
|
|
|
|
isAuthenticated: socket.data.isAuthenticated,
|
|
|
|
request: {
|
|
|
|
url: "/fake",
|
|
|
|
},
|
|
|
|
get: () => null,
|
|
|
|
throw: () => {
|
|
|
|
// If they don't have access, immediately disconnect them
|
|
|
|
socket.disconnect(true)
|
|
|
|
},
|
|
|
|
}
|
|
|
|
await context.doInAppContext(appId, async () => {
|
|
|
|
await middleware(ctx, async () => {
|
|
|
|
await this.joinRoom(socket, tableId)
|
2023-03-06 08:43:45 +01:00
|
|
|
|
2023-06-21 09:33:58 +02:00
|
|
|
// Reply with all users in current room
|
|
|
|
const sessions = await this.getRoomSessions(tableId)
|
|
|
|
callback({ users: sessions })
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
)
|
2023-03-05 19:57:05 +01:00
|
|
|
|
2023-05-31 11:21:50 +02:00
|
|
|
// Handle users selecting a new cell
|
2023-06-05 14:54:17 +02:00
|
|
|
socket.on(GridSocketEvent.SelectCell, ({ cellId }) => {
|
2023-05-31 11:21:50 +02:00
|
|
|
this.updateUser(socket, { focusedCellId: cellId })
|
2023-03-05 19:57:05 +01:00
|
|
|
})
|
|
|
|
}
|
2023-05-12 17:13:32 +02:00
|
|
|
|
|
|
|
emitRowUpdate(ctx: any, row: Row) {
|
|
|
|
const tableId = getTableId(ctx)
|
2023-06-01 18:14:32 +02:00
|
|
|
this.emitToRoom(ctx, tableId, GridSocketEvent.RowChange, {
|
|
|
|
id: row._id,
|
|
|
|
row,
|
|
|
|
})
|
2023-05-12 17:13:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
emitRowDeletion(ctx: any, id: string) {
|
|
|
|
const tableId = getTableId(ctx)
|
2023-06-01 18:14:32 +02:00
|
|
|
this.emitToRoom(ctx, tableId, GridSocketEvent.RowChange, { id, row: null })
|
2023-05-22 16:59:44 +02:00
|
|
|
}
|
|
|
|
|
2023-06-01 18:14:32 +02:00
|
|
|
emitTableUpdate(ctx: any, table: Table) {
|
|
|
|
this.emitToRoom(ctx, table._id!, GridSocketEvent.TableChange, {
|
|
|
|
id: table._id,
|
|
|
|
table,
|
|
|
|
})
|
2023-05-22 16:59:44 +02:00
|
|
|
}
|
|
|
|
|
2023-06-01 18:14:32 +02:00
|
|
|
emitTableDeletion(ctx: any, id: string) {
|
|
|
|
this.emitToRoom(ctx, id, GridSocketEvent.TableChange, { id, table: null })
|
2023-05-12 17:13:32 +02:00
|
|
|
}
|
2023-03-05 19:57:05 +01:00
|
|
|
}
|