budibase/packages/server/src/sdk/app/permissions/index.ts

137 lines
3.2 KiB
TypeScript
Raw Normal View History

2023-09-01 11:33:59 +02:00
import { context, env, roles } from "@budibase/backend-core"
2023-08-31 10:36:17 +02:00
import { features } from "@budibase/pro"
2023-08-21 16:56:40 +02:00
import {
DocumentType,
PermissionLevel,
2023-09-01 11:33:59 +02:00
PlanType,
2023-08-31 13:01:17 +02:00
Role,
2023-08-21 16:56:40 +02:00
VirtualDocumentType,
} from "@budibase/types"
2023-08-31 13:01:17 +02:00
import {
extractViewInfoFromID,
getRoleParams,
isViewID,
} from "../../../db/utils"
2023-08-31 10:36:17 +02:00
import {
CURRENTLY_SUPPORTED_LEVELS,
getBasePermissions,
} from "../../../utilities/security"
2023-08-21 16:56:40 +02:00
type ResourceActionAllowedResult =
| { allowed: true }
| {
allowed: false
level: PermissionLevel
resourceType: DocumentType | VirtualDocumentType
}
export async function resourceActionAllowed({
resourceId,
level,
}: {
resourceId: string
level: PermissionLevel
}): Promise<ResourceActionAllowedResult> {
if (!isViewID(resourceId)) {
return { allowed: true }
}
2023-08-22 10:27:06 +02:00
if (await features.isViewPermissionEnabled()) {
return { allowed: true }
}
2023-08-21 16:56:40 +02:00
return {
allowed: false,
level,
resourceType: VirtualDocumentType.VIEW,
}
}
2023-08-31 10:36:17 +02:00
2023-09-01 09:50:55 +02:00
enum PermissionSource {
EXPLICIT = "EXPLICIT",
INHERITED = "INHERITED",
BASE = "BASE",
2023-09-01 09:40:29 +02:00
}
2023-08-31 13:01:17 +02:00
type ResourcePermissions = Record<
string,
2023-09-01 09:50:55 +02:00
{ role: string; type: PermissionSource }
2023-08-31 13:01:17 +02:00
>
2023-09-01 09:50:55 +02:00
export async function getInheritablePermissions(
resourceId: string
): Promise<ResourcePermissions | undefined> {
2023-09-01 11:33:59 +02:00
if (isViewID(resourceId)) {
2023-09-01 09:50:55 +02:00
return await getResourcePerms(extractViewInfoFromID(resourceId).tableId)
}
}
2023-09-01 11:33:59 +02:00
export async function allowsExplicitPermissions(resourceId: string) {
if (isViewID(resourceId)) {
const allowed = await features.isViewPermissionEnabled()
const minPlan = !allowed
? env.SELF_HOSTED
? PlanType.BUSINESS
: PlanType.PREMIUM
: undefined
return {
allowed,
minPlan,
}
}
return { allowed: true }
}
2023-08-31 13:01:17 +02:00
export async function getResourcePerms(
resourceId: string
): Promise<ResourcePermissions> {
2023-08-31 10:36:17 +02:00
const db = context.getAppDB()
const body = await db.allDocs(
getRoleParams(null, {
include_docs: true,
})
)
2023-08-31 13:01:17 +02:00
const rolesList = body.rows.map<Role>(row => row.doc)
2023-09-01 09:40:29 +02:00
let permissions: ResourcePermissions = {}
2023-08-31 13:01:17 +02:00
2023-09-01 09:50:55 +02:00
const permsToInherit = await getInheritablePermissions(resourceId)
2023-08-31 13:01:17 +02:00
2023-09-01 11:33:59 +02:00
const allowsExplicitPerm = (await allowsExplicitPermissions(resourceId))
.allowed
2023-08-31 10:36:17 +02:00
for (let level of CURRENTLY_SUPPORTED_LEVELS) {
// update the various roleIds in the resource permissions
for (let role of rolesList) {
2023-09-01 11:33:59 +02:00
const rolePerms = allowsExplicitPerm
? roles.checkForRoleResourceArray(role.permissions, resourceId)
: {}
2023-08-31 13:01:17 +02:00
if (rolePerms[resourceId]?.indexOf(level) > -1) {
permissions[level] = {
role: roles.getExternalRoleID(role._id!, role.version),
2023-09-01 09:50:55 +02:00
type: PermissionSource.EXPLICIT,
2023-08-31 13:01:17 +02:00
}
2023-09-01 10:52:06 +02:00
} else if (
!permissions[level] &&
permsToInherit &&
permsToInherit[level]
) {
2023-08-31 13:01:17 +02:00
permissions[level] = {
2023-09-01 09:40:29 +02:00
role: permsToInherit[level].role,
2023-09-01 09:50:55 +02:00
type: PermissionSource.INHERITED,
2023-08-31 13:01:17 +02:00
}
2023-08-31 10:36:17 +02:00
}
}
}
2023-08-31 13:01:17 +02:00
const basePermissions = Object.entries(
getBasePermissions(resourceId)
).reduce<ResourcePermissions>((p, [level, role]) => {
2023-09-01 09:50:55 +02:00
p[level] = { role, type: PermissionSource.BASE }
2023-08-31 13:01:17 +02:00
return p
}, {})
const result = Object.assign(basePermissions, permissions)
return result
2023-08-31 10:36:17 +02:00
}