Enable collaboration for public users and fix collaboration for non-devs
This commit is contained in:
parent
9d6fbf067f
commit
3f20a3a439
|
@ -234,6 +234,14 @@ export const createAPIClient = config => {
|
|||
invalidateCache: () => {
|
||||
cache = {}
|
||||
},
|
||||
|
||||
// Generic utility to extract the current app ID. Assumes that any client
|
||||
// that exists in an app context will be attaching our app ID header.
|
||||
getAppID: () => {
|
||||
let headers = {}
|
||||
config?.attachHeaders(headers)
|
||||
return headers?.["x-budibase-app-id"]
|
||||
},
|
||||
}
|
||||
|
||||
// Attach all endpoints
|
||||
|
|
|
@ -3,7 +3,7 @@ import { createWebsocket } from "../../../utils"
|
|||
import { SocketEvent, GridSocketEvent } from "@budibase/shared-core"
|
||||
|
||||
export const createGridWebsocket = context => {
|
||||
const { rows, tableId, users, focusedCellId, table } = context
|
||||
const { rows, tableId, users, focusedCellId, table, API } = context
|
||||
const socket = createWebsocket("/socket/grid")
|
||||
|
||||
const connectToTable = tableId => {
|
||||
|
@ -11,9 +11,10 @@ export const createGridWebsocket = context => {
|
|||
return
|
||||
}
|
||||
// Identify which table we are editing
|
||||
const appId = API.getAppID()
|
||||
socket.emit(
|
||||
GridSocketEvent.SelectTable,
|
||||
{ tableId },
|
||||
{ tableId, appId },
|
||||
({ users: gridUsers }) => {
|
||||
users.set(gridUsers)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import authorized from "../middleware/authorized"
|
||||
import { BaseSocket } from "./websocket"
|
||||
import { permissions } from "@budibase/backend-core"
|
||||
import { context, permissions } from "@budibase/backend-core"
|
||||
import http from "http"
|
||||
import Koa from "koa"
|
||||
import { getTableId } from "../api/controllers/row/utils"
|
||||
|
@ -8,20 +8,49 @@ import { Row, Table } from "@budibase/types"
|
|||
import { Socket } from "socket.io"
|
||||
import { GridSocketEvent } from "@budibase/shared-core"
|
||||
|
||||
const { PermissionType, PermissionLevel } = permissions
|
||||
|
||||
export default class GridSocket extends BaseSocket {
|
||||
constructor(app: Koa, server: http.Server) {
|
||||
super(app, server, "/socket/grid", [authorized(permissions.BUILDER)])
|
||||
super(app, server, "/socket/grid")
|
||||
}
|
||||
|
||||
async onConnect(socket: Socket) {
|
||||
// Initial identification of connected spreadsheet
|
||||
socket.on(GridSocketEvent.SelectTable, async ({ tableId }, callback) => {
|
||||
await this.joinRoom(socket, tableId)
|
||||
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)
|
||||
|
||||
// Reply with all users in current room
|
||||
const sessions = await this.getRoomSessions(tableId)
|
||||
callback({ users: sessions })
|
||||
})
|
||||
// Reply with all users in current room
|
||||
const sessions = await this.getRoomSessions(tableId)
|
||||
callback({ users: sessions })
|
||||
})
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
// Handle users selecting a new cell
|
||||
socket.on(GridSocketEvent.SelectCell, ({ cellId }) => {
|
||||
|
|
|
@ -4,12 +4,18 @@ import Koa from "koa"
|
|||
import Cookies from "cookies"
|
||||
import { userAgent } from "koa-useragent"
|
||||
import { auth, Header, redis } from "@budibase/backend-core"
|
||||
import currentApp from "../middleware/currentapp"
|
||||
import { createAdapter } from "@socket.io/redis-adapter"
|
||||
import { Socket } from "socket.io"
|
||||
import { getSocketPubSubClients } from "../utilities/redis"
|
||||
import { SocketEvent, SocketSessionTTL } from "@budibase/shared-core"
|
||||
import { SocketSession } from "@budibase/types"
|
||||
import { v4 as uuid } from "uuid"
|
||||
|
||||
const anonUser = () => ({
|
||||
_id: uuid(),
|
||||
email: "user@mail.com",
|
||||
firstName: "Anonymous",
|
||||
})
|
||||
|
||||
export class BaseSocket {
|
||||
io: Server
|
||||
|
@ -34,7 +40,6 @@ export class BaseSocket {
|
|||
const middlewares = [
|
||||
userAgent,
|
||||
authenticate,
|
||||
currentApp,
|
||||
...(additionalMiddlewares || []),
|
||||
]
|
||||
|
||||
|
@ -70,7 +75,8 @@ export class BaseSocket {
|
|||
// Middlewares are finished
|
||||
// Extract some data from our enriched koa context to persist
|
||||
// as metadata for the socket
|
||||
const { _id, email, firstName, lastName } = ctx.user
|
||||
const user = ctx.user?._id ? ctx.user : anonUser()
|
||||
const { _id, email, firstName, lastName } = user
|
||||
socket.data = {
|
||||
_id,
|
||||
email,
|
||||
|
@ -78,6 +84,8 @@ export class BaseSocket {
|
|||
lastName,
|
||||
sessionId: socket.id,
|
||||
connectedAt: Date.now(),
|
||||
isAuthenticated: ctx.isAuthenticated,
|
||||
roleId: ctx.roleId,
|
||||
}
|
||||
next()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue