2024-08-26 17:13:52 +02:00
|
|
|
import { Next } from "koa"
|
2024-09-04 10:16:59 +02:00
|
|
|
import { PermissionLevel, PermissionType, UserCtx } from "@budibase/types"
|
2024-08-26 17:13:52 +02:00
|
|
|
import { paramSubResource } from "./resourceId"
|
|
|
|
import { docIds } from "@budibase/backend-core"
|
|
|
|
import * as utils from "../db/utils"
|
|
|
|
import sdk from "../sdk"
|
2024-09-04 10:16:59 +02:00
|
|
|
import { authorizedResource } from "./authorized"
|
2024-09-03 17:53:25 +02:00
|
|
|
|
2024-08-26 17:13:52 +02:00
|
|
|
export function triggerRowActionAuthorised(
|
|
|
|
sourcePath: string,
|
|
|
|
actionPath: string
|
|
|
|
) {
|
2024-09-04 10:16:59 +02:00
|
|
|
return async (ctx: UserCtx, next: Next) => {
|
|
|
|
async function getResourceIds() {
|
|
|
|
// Reusing the existing middleware to extract the value
|
|
|
|
await paramSubResource(sourcePath, actionPath)(ctx, () => {})
|
|
|
|
|
|
|
|
const sourceId: string = ctx.resourceId
|
|
|
|
const rowActionId: string = ctx.subResourceId
|
|
|
|
|
|
|
|
const isTableId = docIds.isTableId(sourceId)
|
|
|
|
const isViewId = utils.isViewID(sourceId)
|
|
|
|
if (!isTableId && !isViewId) {
|
|
|
|
ctx.throw(400, `'${sourceId}' is not a valid source id`)
|
|
|
|
}
|
|
|
|
|
|
|
|
const tableId = isTableId
|
|
|
|
? sourceId
|
|
|
|
: utils.extractViewInfoFromID(sourceId).tableId
|
|
|
|
const viewId = isTableId ? undefined : sourceId
|
|
|
|
return { tableId, viewId, rowActionId }
|
2024-08-26 17:13:52 +02:00
|
|
|
}
|
|
|
|
|
2024-09-04 10:16:59 +02:00
|
|
|
async function guardResourcePermissions(
|
|
|
|
ctx: UserCtx,
|
|
|
|
tableId: string,
|
|
|
|
viewId?: string
|
|
|
|
) {
|
|
|
|
const { params } = ctx
|
|
|
|
try {
|
|
|
|
if (!viewId) {
|
|
|
|
ctx.params = { tableId }
|
|
|
|
await authorizedResource(
|
|
|
|
PermissionType.TABLE,
|
|
|
|
PermissionLevel.READ,
|
|
|
|
"tableId"
|
|
|
|
)(ctx, () => {})
|
|
|
|
} else {
|
|
|
|
ctx.params = { viewId }
|
|
|
|
await authorizedResource(
|
|
|
|
PermissionType.VIEW,
|
|
|
|
PermissionLevel.READ,
|
|
|
|
"__viewId"
|
|
|
|
)(ctx, () => {})
|
|
|
|
}
|
|
|
|
} finally {
|
|
|
|
ctx.params = params
|
|
|
|
}
|
|
|
|
}
|
2024-09-03 17:21:13 +02:00
|
|
|
|
2024-09-04 10:16:59 +02:00
|
|
|
const { tableId, viewId, rowActionId } = await getResourceIds()
|
2024-08-26 18:00:14 +02:00
|
|
|
|
2024-08-26 17:13:52 +02:00
|
|
|
const rowAction = await sdk.rowActions.get(tableId, rowActionId)
|
|
|
|
|
2024-09-03 17:21:13 +02:00
|
|
|
if (!viewId && !rowAction.permissions.table.runAllowed) {
|
2024-08-26 17:13:52 +02:00
|
|
|
ctx.throw(
|
|
|
|
403,
|
2024-09-03 17:21:13 +02:00
|
|
|
`Row action '${rowActionId}' is not enabled for table '${tableId}'`
|
2024-08-26 17:13:52 +02:00
|
|
|
)
|
2024-09-03 17:21:13 +02:00
|
|
|
} else if (viewId && !rowAction.permissions.views[viewId]?.runAllowed) {
|
2024-08-26 17:13:52 +02:00
|
|
|
ctx.throw(
|
|
|
|
403,
|
2024-09-03 17:21:13 +02:00
|
|
|
`Row action '${rowActionId}' is not enabled for view '${viewId}'`
|
2024-08-26 17:13:52 +02:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2024-09-04 10:16:59 +02:00
|
|
|
await guardResourcePermissions(ctx, tableId, viewId)
|
|
|
|
|
2024-08-26 18:00:14 +02:00
|
|
|
// Enrich tableId
|
|
|
|
ctx.params.tableId = tableId
|
2024-08-26 17:13:52 +02:00
|
|
|
return next()
|
|
|
|
}
|
|
|
|
}
|