1
0
Fork 0
mirror of synced 2024-10-05 12:34:50 +13:00

Adding test cases for admin/builder checking middlewares.

This commit is contained in:
mike12345567 2023-07-18 18:10:15 +01:00
parent 39746e0bf0
commit 91847504c8
6 changed files with 172 additions and 6 deletions

View file

@ -1,6 +1,6 @@
import { BBContext } from "@budibase/types" import { UserCtx } from "@budibase/types"
export default async (ctx: BBContext, next: any) => { export default async (ctx: UserCtx, next: any) => {
if ( if (
!ctx.internal && !ctx.internal &&
(!ctx.user || !ctx.user.admin || !ctx.user.admin.global) (!ctx.user || !ctx.user.admin || !ctx.user.admin.global)

View file

@ -0,0 +1,141 @@
import adminOnly from "../adminOnly"
import builderOnly from "../builderOnly"
import builderOrAdmin from "../builderOrAdmin"
import { structures } from "../../../tests"
import { ContextUser } from "@budibase/types"
import { doInAppContext } from "../../context"
const appId = "app_aaa"
const basicUser = structures.users.user()
const adminUser = structures.users.adminUser()
const adminOnlyUser = structures.users.adminOnlyUser()
const builderUser = structures.users.builderUser()
const appBuilderUser = structures.users.appBuilderUser(appId)
function buildUserCtx(user: ContextUser) {
return {
internal: false,
user,
throw: jest.fn(),
} as any
}
function passed(throwFn: jest.Func, nextFn: jest.Func) {
expect(throwFn).not.toBeCalled()
expect(nextFn).toBeCalled()
}
function threw(throwFn: jest.Func) {
// cant check next, the throw function doesn't actually throw - so it still continues
expect(throwFn).toBeCalled()
}
describe("adminOnly middleware", () => {
it("should allow admin user", () => {
const ctx = buildUserCtx(adminUser),
next = jest.fn()
adminOnly(ctx, next)
passed(ctx.throw, next)
})
it("should not allow basic user", () => {
const ctx = buildUserCtx(basicUser),
next = jest.fn()
adminOnly(ctx, next)
threw(ctx.throw)
})
it("should not allow builder user", () => {
const ctx = buildUserCtx(builderUser),
next = jest.fn()
adminOnly(ctx, next)
threw(ctx.throw)
})
})
describe("builderOnly middleware", () => {
it("should allow builder user", () => {
const ctx = buildUserCtx(builderUser),
next = jest.fn()
builderOnly(ctx, next)
passed(ctx.throw, next)
})
it("should allow app builder user", () => {
const ctx = buildUserCtx(appBuilderUser),
next = jest.fn()
doInAppContext(appId, () => {
builderOnly(ctx, next)
})
passed(ctx.throw, next)
})
it("should allow admin and builder user", () => {
const ctx = buildUserCtx(adminUser),
next = jest.fn()
builderOnly(ctx, next)
passed(ctx.throw, next)
})
it("should not allow admin user", () => {
const ctx = buildUserCtx(adminOnlyUser),
next = jest.fn()
builderOnly(ctx, next)
threw(ctx.throw)
})
it("should not allow app builder user to different app", () => {
const ctx = buildUserCtx(appBuilderUser),
next = jest.fn()
doInAppContext("app_bbb", () => {
builderOnly(ctx, next)
})
threw(ctx.throw)
})
it("should not allow basic user", () => {
const ctx = buildUserCtx(basicUser),
next = jest.fn()
builderOnly(ctx, next)
threw(ctx.throw)
})
})
describe("builderOrAdmin middleware", () => {
it("should allow builder user", () => {
const ctx = buildUserCtx(builderUser),
next = jest.fn()
builderOrAdmin(ctx, next)
passed(ctx.throw, next)
})
it("should allow builder and admin user", () => {
const ctx = buildUserCtx(adminUser),
next = jest.fn()
builderOrAdmin(ctx, next)
passed(ctx.throw, next)
})
it("should allow admin user", () => {
const ctx = buildUserCtx(adminOnlyUser),
next = jest.fn()
builderOrAdmin(ctx, next)
passed(ctx.throw, next)
})
it("should allow app builder user", () => {
const ctx = buildUserCtx(appBuilderUser),
next = jest.fn()
doInAppContext(appId, () => {
builderOrAdmin(ctx, next)
})
passed(ctx.throw, next)
})
it("should not allow basic user", () => {
const ctx = buildUserCtx(basicUser),
next = jest.fn()
builderOrAdmin(ctx, next)
threw(ctx.throw)
})
})

View file

@ -258,7 +258,7 @@ export async function getUserCount() {
export function isBuilder(user: User | ContextUser, appId?: string) { export function isBuilder(user: User | ContextUser, appId?: string) {
if (user.builder?.global) { if (user.builder?.global) {
return true return true
} else if (appId && user.builder?.apps?.includes(appId)) { } else if (appId && user.builder?.apps?.includes(getProdAppID(appId))) {
return true return true
} }
return false return false

View file

@ -1,5 +1,6 @@
import { import {
AdminUser, AdminUser,
AdminOnlyUser,
BuilderUser, BuilderUser,
SSOAuthDetails, SSOAuthDetails,
SSOUser, SSOUser,
@ -21,6 +22,15 @@ export const adminUser = (userProps?: any): AdminUser => {
} }
} }
export const adminOnlyUser = (userProps?: any): AdminOnlyUser => {
return {
...user(userProps),
admin: {
global: true,
},
}
}
export const builderUser = (userProps?: any): BuilderUser => { export const builderUser = (userProps?: any): BuilderUser => {
return { return {
...user(userProps), ...user(userProps),
@ -30,6 +40,15 @@ export const builderUser = (userProps?: any): BuilderUser => {
} }
} }
export const appBuilderUser = (appId: string, userProps?: any): BuilderUser => {
return {
...user(userProps),
builder: {
apps: [appId],
},
}
}
export function ssoUser( export function ssoUser(
opts: { user?: any; details?: SSOAuthDetails } = {} opts: { user?: any; details?: SSOAuthDetails } = {}
): SSOUser { ): SSOUser {

View file

@ -11,7 +11,6 @@ import { getCachedSelf } from "../utilities/global"
import env from "../environment" import env from "../environment"
import { isWebhookEndpoint } from "./utils" import { isWebhookEndpoint } from "./utils"
import { UserCtx, ContextUser } from "@budibase/types" import { UserCtx, ContextUser } from "@budibase/types"
import { removePortalUserPermissions } from "@budibase/backend-core/src/users"
export default async (ctx: UserCtx, next: any) => { export default async (ctx: UserCtx, next: any) => {
// try to get the appID from the request // try to get the appID from the request

View file

@ -42,7 +42,7 @@ export interface User extends Document {
forceResetPassword?: boolean forceResetPassword?: boolean
roles: UserRoles roles: UserRoles
builder?: { builder?: {
global: boolean global?: boolean
apps?: string[] apps?: string[]
} }
admin?: { admin?: {
@ -70,7 +70,8 @@ export interface UserRoles {
export interface BuilderUser extends User { export interface BuilderUser extends User {
builder: { builder: {
global: boolean global?: boolean
apps?: string[]
} }
} }
@ -83,6 +84,12 @@ export interface AdminUser extends User {
} }
} }
export interface AdminOnlyUser extends User {
admin: {
global: boolean
}
}
export function isUser(user: object): user is User { export function isUser(user: object): user is User {
return !!(user as User).roles return !!(user as User).roles
} }