-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Prevent syncing row changes between users for views filtered by current user #15163
Changes from all commits
1250aa6
62e47cc
dc10bbf
3be6800
df8e7bf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
import authorized from "../middleware/authorized" | ||
import currentApp from "../middleware/currentapp" | ||
import { BaseSocket } from "./websocket" | ||
import { auth, permissions } from "@budibase/backend-core" | ||
import { auth, permissions, context } from "@budibase/backend-core" | ||
import http from "http" | ||
import Koa from "koa" | ||
import { getSourceId } from "../api/controllers/row/utils" | ||
|
@@ -10,6 +10,12 @@ import { Socket } from "socket.io" | |
import { GridSocketEvent } from "@budibase/shared-core" | ||
import { userAgent } from "koa-useragent" | ||
import { createContext, runMiddlewares } from "./middleware" | ||
import sdk from "../sdk" | ||
import { | ||
findHBSBlocks, | ||
isJSBinding, | ||
decodeJSBinding, | ||
} from "@budibase/string-templates" | ||
|
||
const { PermissionType, PermissionLevel } = permissions | ||
|
||
|
@@ -18,15 +24,46 @@ export default class GridSocket extends BaseSocket { | |
super(app, server, "/socket/grid") | ||
} | ||
|
||
// Checks if a view's query contains any current user bindings | ||
containsCurrentUserBinding(view: ViewV2): boolean { | ||
return findHBSBlocks(JSON.stringify(view.query)) | ||
.map(binding => { | ||
const sanitizedBinding = binding.replace(/\\"/g, '"') | ||
if (isJSBinding(sanitizedBinding)) { | ||
return decodeJSBinding(sanitizedBinding) | ||
} else { | ||
return sanitizedBinding | ||
} | ||
}) | ||
.some(binding => binding?.includes("[user]")) | ||
} | ||
|
||
async onConnect(socket: Socket) { | ||
// Initial identification of connected spreadsheet | ||
socket.on(GridSocketEvent.SelectDatasource, async (payload, callback) => { | ||
const ds = payload.datasource | ||
const appId = payload.appId | ||
const resourceId = ds?.type === "table" ? ds?.tableId : ds?.id | ||
let valid = true | ||
|
||
// Ignore if no table or app specified | ||
// Validate datasource | ||
if (!resourceId || !appId) { | ||
// Ignore if no table or app specified | ||
valid = false | ||
} else if (ds.type === "viewV2") { | ||
// If this is a view filtered by current user, don't sync changes | ||
try { | ||
await context.doInAppContext(appId, async () => { | ||
const view = await sdk.views.get(ds.id) | ||
if (this.containsCurrentUserBinding(view)) { | ||
valid = false | ||
} | ||
}) | ||
} catch (err) { | ||
valid = false | ||
} | ||
} | ||
if (!valid) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. More of a product discussion, but are we exposing this somehow to the user? Otherwise they might think it's actually broken There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We aren't, no. But I think that's ok, as you wouldn't expect to be able to see rows created by other users if using a view that's filtered to show only your own rows. |
||
socket.disconnect(true) | ||
return | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will this always be the only true case? Could we not get other issues such as formulas or similar?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For this fix we only care about data segregated per user. There's a wider problem of data not matching filters in general, but by identifying user bindings we can fix cases where users are seeing row they should not be able to access. Only the current user bindings create this security risk. This PR is deliberately only targetting user bindings and is not meant to be a wider fix.