diff --git a/packages/server/src/api/controllers/permission.ts b/packages/server/src/api/controllers/permission.ts index cdfa6d8b1c..14a450a4de 100644 --- a/packages/server/src/api/controllers/permission.ts +++ b/packages/server/src/api/controllers/permission.ts @@ -45,18 +45,6 @@ async function updatePermissionOnRole( }: { roleId: string; resourceId: string; level: PermissionLevel }, updateType: PermissionUpdateType ) { - const allowedAction = await sdk.permissions.resourceActionAllowed({ - resourceId, - level, - }) - - if (!allowedAction.allowed) { - throw new HTTPError( - `You are not allowed to '${allowedAction.level}' the resource type '${allowedAction.resourceType}'`, - 403 - ) - } - const db = context.getAppDB() const remove = updateType === PermissionUpdateType.REMOVE const isABuiltin = roles.isBuiltin(roleId) @@ -182,9 +170,6 @@ export async function getResourcePerms( }, {} as Record ), - requiresPlanToModify: ( - await sdk.permissions.allowsExplicitPermissions(resourceId) - ).minPlan, } } diff --git a/packages/server/src/api/routes/tests/permissions.spec.ts b/packages/server/src/api/routes/tests/permissions.spec.ts index 838e1aca0b..0fba930144 100644 --- a/packages/server/src/api/routes/tests/permissions.spec.ts +++ b/packages/server/src/api/routes/tests/permissions.spec.ts @@ -1,8 +1,4 @@ const mockedSdk = sdk.permissions as jest.Mocked -jest.mock("../../../sdk/app/permissions", () => ({ - ...jest.requireActual("../../../sdk/app/permissions"), - resourceActionAllowed: jest.fn(), -})) import sdk from "../../../sdk" @@ -40,8 +36,6 @@ describe("/permission", () => { beforeEach(async () => { mocks.licenses.useCloudFree() - mockedSdk.resourceActionAllowed.mockResolvedValue({ allowed: true }) - table = (await config.createTable()) as typeof table row = await config.createRow() view = await config.api.viewV2.create({ @@ -112,29 +106,6 @@ describe("/permission", () => { expect(allRes.body[table._id]["read"]).toEqual(STD_ROLE_ID) expect(allRes.body[table._id]["write"]).toEqual(HIGHER_ROLE_ID) }) - - it("throw forbidden if the action is not allowed for the resource", async () => { - mockedSdk.resourceActionAllowed.mockResolvedValue({ - allowed: false, - resourceType: DocumentType.DATASOURCE, - level: PermissionLevel.READ, - }) - - await config.api.permission.add( - { - roleId: STD_ROLE_ID, - resourceId: table._id, - level: PermissionLevel.EXECUTE, - }, - { - status: 403, - body: { - message: - "You are not allowed to 'read' the resource type 'datasource'", - }, - } - ) - }) }) describe("remove", () => { @@ -148,29 +119,6 @@ describe("/permission", () => { const permsRes = await config.api.permission.get(table._id) expect(permsRes.permissions[STD_ROLE_ID]).toBeUndefined() }) - - it("throw forbidden if the action is not allowed for the resource", async () => { - mockedSdk.resourceActionAllowed.mockResolvedValue({ - allowed: false, - resourceType: DocumentType.DATASOURCE, - level: PermissionLevel.READ, - }) - - await config.api.permission.revoke( - { - roleId: STD_ROLE_ID, - resourceId: table._id, - level: PermissionLevel.EXECUTE, - }, - { - status: 403, - body: { - message: - "You are not allowed to 'read' the resource type 'datasource'", - }, - } - ) - }) }) describe("check public user allowed", () => { diff --git a/packages/server/src/sdk/app/permissions/index.ts b/packages/server/src/sdk/app/permissions/index.ts deleted file mode 100644 index 18a376aaf0..0000000000 --- a/packages/server/src/sdk/app/permissions/index.ts +++ /dev/null @@ -1,151 +0,0 @@ -import { db, roles } from "@budibase/backend-core" -import { features } from "@budibase/pro" -import { - DocumentType, - PermissionLevel, - PermissionSource, - PlanType, - VirtualDocumentType, -} from "@budibase/types" -import { extractViewInfoFromID, isViewID } from "../../../db/utils" -import { - CURRENTLY_SUPPORTED_LEVELS, - getBasePermissions, -} from "../../../utilities/security" -import sdk from "../../../sdk" -import { isV2 } from "../views" - -type ResourceActionAllowedResult = - | { allowed: true } - | { - allowed: false - level: PermissionLevel - resourceType: DocumentType | VirtualDocumentType - } - -export async function resourceActionAllowed({ - resourceId, - level, -}: { - resourceId: string - level: PermissionLevel -}): Promise { - if (!isViewID(resourceId)) { - return { allowed: true } - } - - if (await features.isViewPermissionEnabled()) { - return { allowed: true } - } - - return { - allowed: false, - level, - resourceType: VirtualDocumentType.VIEW, - } -} - -type ResourcePermissions = Record< - string, - { role: string; type: PermissionSource } -> - -export async function getInheritablePermissions( - resourceId: string -): Promise { - if (isViewID(resourceId)) { - return await getResourcePerms(extractViewInfoFromID(resourceId).tableId) - } -} - -export async function allowsExplicitPermissions(resourceId: string) { - if (isViewID(resourceId)) { - const allowed = await features.isViewPermissionEnabled() - const minPlan = !allowed ? PlanType.PREMIUM_PLUS : undefined - - return { - allowed, - minPlan, - } - } - - return { allowed: true } -} - -export async function getResourcePerms( - resourceId: string -): Promise { - const rolesList = await roles.getAllRoles() - - let permissions: ResourcePermissions = {} - - const permsToInherit = await getInheritablePermissions(resourceId) - - const allowsExplicitPerm = (await allowsExplicitPermissions(resourceId)) - .allowed - - for (let level of CURRENTLY_SUPPORTED_LEVELS) { - // update the various roleIds in the resource permissions - for (let role of rolesList) { - const rolePerms = allowsExplicitPerm - ? roles.checkForRoleResourceArray(role.permissions || {}, resourceId) - : {} - if (rolePerms[resourceId]?.indexOf(level) > -1) { - permissions[level] = { - role: roles.getExternalRoleID(role._id!, role.version), - type: PermissionSource.EXPLICIT, - } - } else if ( - !permissions[level] && - permsToInherit && - permsToInherit[level] - ) { - permissions[level] = { - role: permsToInherit[level].role, - type: PermissionSource.INHERITED, - } - } - } - } - - const basePermissions = Object.entries( - getBasePermissions(resourceId) - ).reduce((p, [level, role]) => { - p[level] = { role, type: PermissionSource.BASE } - return p - }, {}) - const result = Object.assign(basePermissions, permissions) - return result -} - -export async function getDependantResources( - resourceId: string -): Promise | undefined> { - if (db.isTableId(resourceId)) { - const dependants: Record> = {} - - const table = await sdk.tables.getTable(resourceId) - const views = Object.values(table.views || {}) - - for (const view of views) { - if (!isV2(view)) { - continue - } - - const permissions = await getResourcePerms(view.id) - for (const [, roleInfo] of Object.entries(permissions)) { - if (roleInfo.type === PermissionSource.INHERITED) { - dependants[VirtualDocumentType.VIEW] ??= new Set() - dependants[VirtualDocumentType.VIEW].add(view.id) - } - } - } - - return Object.entries(dependants).reduce((p, [type, resources]) => { - p[type] = resources.size - return p - }, {} as Record) - } - - return -} diff --git a/packages/server/src/sdk/app/permissions/tests/permissions.spec.ts b/packages/server/src/sdk/app/permissions/tests/permissions.spec.ts deleted file mode 100644 index 4c233e68fa..0000000000 --- a/packages/server/src/sdk/app/permissions/tests/permissions.spec.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { PermissionLevel } from "@budibase/types" -import { mocks, structures } from "@budibase/backend-core/tests" -import { resourceActionAllowed } from ".." -import { generateViewID } from "../../../../db/utils" -import { initProMocks } from "../../../../tests/utilities/mocks/pro" - -initProMocks() - -describe("permissions sdk", () => { - beforeEach(() => { - mocks.licenses.useCloudFree() - }) - - describe("resourceActionAllowed", () => { - it("non view resources actions are always allowed", async () => { - const resourceId = structures.users.user()._id! - - const result = await resourceActionAllowed({ - resourceId, - level: PermissionLevel.READ, - }) - - expect(result).toEqual({ allowed: true }) - }) - - it("view resources actions allowed if the feature flag is enabled", async () => { - mocks.licenses.useViewPermissions() - const resourceId = generateViewID(structures.generator.guid()) - - const result = await resourceActionAllowed({ - resourceId, - level: PermissionLevel.READ, - }) - - expect(result).toEqual({ allowed: true }) - }) - - it("view resources actions allowed if the feature flag is disabled", async () => { - const resourceId = generateViewID(structures.generator.guid()) - - const result = await resourceActionAllowed({ - resourceId, - level: PermissionLevel.READ, - }) - - expect(result).toEqual({ - allowed: false, - level: "read", - resourceType: "view", - }) - }) - }) -}) diff --git a/packages/types/src/api/web/app/permission.ts b/packages/types/src/api/web/app/permission.ts index 88ff4e9d2f..719be4f78e 100644 --- a/packages/types/src/api/web/app/permission.ts +++ b/packages/types/src/api/web/app/permission.ts @@ -8,7 +8,6 @@ export interface ResourcePermissionInfo { export interface GetResourcePermsResponse { permissions: Record - requiresPlanToModify?: PlanType } export interface GetDependantResourcesResponse {