diff --git a/packages/server/src/api/controllers/auth.ts b/packages/server/src/api/controllers/auth.ts index eabfe10bab..9b1b78ed9e 100644 --- a/packages/server/src/api/controllers/auth.ts +++ b/packages/server/src/api/controllers/auth.ts @@ -26,7 +26,7 @@ export async function fetchSelf(ctx: UserCtx) { } const appId = context.getAppId() - let user: ContextUser = await getFullUser(ctx, userId) + let user: ContextUser = await getFullUser(userId) // this shouldn't be returned by the app self delete user.roles // forward the csrf token from the session diff --git a/packages/server/src/api/controllers/user.ts b/packages/server/src/api/controllers/user.ts index b6c3e7c6bd..bfe206e98a 100644 --- a/packages/server/src/api/controllers/user.ts +++ b/packages/server/src/api/controllers/user.ts @@ -1,10 +1,10 @@ import { generateUserFlagID, InternalTables } from "../../db/utils" import { getFullUser } from "../../utilities/users" import { context } from "@budibase/backend-core" -import { Ctx, UserCtx } from "@budibase/types" +import { Ctx, FetchUserMetadataResponse, UserCtx } from "@budibase/types" import sdk from "../../sdk" -export async function fetchMetadata(ctx: Ctx) { +export async function fetchMetadata(ctx: Ctx) { ctx.body = await sdk.users.fetchMetadata() } @@ -44,7 +44,7 @@ export async function destroyMetadata(ctx: UserCtx) { } export async function findMetadata(ctx: UserCtx) { - ctx.body = await getFullUser(ctx, ctx.params.id) + ctx.body = await getFullUser(ctx.params.id) } export async function setFlag(ctx: UserCtx) { diff --git a/packages/server/src/api/routes/tests/user.spec.js b/packages/server/src/api/routes/tests/user.spec.ts similarity index 89% rename from packages/server/src/api/routes/tests/user.spec.js rename to packages/server/src/api/routes/tests/user.spec.ts index e8ffd8df2b..caae54bc68 100644 --- a/packages/server/src/api/routes/tests/user.spec.js +++ b/packages/server/src/api/routes/tests/user.spec.ts @@ -1,7 +1,6 @@ -const { roles, utils } = require("@budibase/backend-core") -const { checkPermissionsEndpoint } = require("./utilities/TestFunctions") -const setup = require("./utilities") -const { BUILTIN_ROLE_IDS } = roles +import { roles, utils } from "@budibase/backend-core" +import { checkPermissionsEndpoint } from "./utilities/TestFunctions" +import * as setup from "./utilities" jest.setTimeout(30000) @@ -47,8 +46,8 @@ describe("/users", () => { request, method: "GET", url: `/api/users/metadata`, - passRole: BUILTIN_ROLE_IDS.ADMIN, - failRole: BUILTIN_ROLE_IDS.PUBLIC, + passRole: roles.BUILTIN_ROLE_IDS.ADMIN, + failRole: roles.BUILTIN_ROLE_IDS.PUBLIC, }) }) }) @@ -56,7 +55,7 @@ describe("/users", () => { describe("update", () => { it("should be able to update the user", async () => { const user = await config.createUser({ id: `us_update${utils.newid()}` }) - user.roleId = BUILTIN_ROLE_IDS.BASIC + user.roleId = roles.BUILTIN_ROLE_IDS.BASIC delete user._rev const res = await request .put(`/api/users/metadata`) @@ -74,14 +73,18 @@ describe("/users", () => { const res1 = await request .put(`/api/users/metadata`) .set(config.defaultHeaders()) - .send({ ...user, roleId: BUILTIN_ROLE_IDS.BASIC }) + .send({ ...user, roleId: roles.BUILTIN_ROLE_IDS.BASIC }) .expect(200) .expect("Content-Type", /json/) const res = await request .put(`/api/users/metadata`) .set(config.defaultHeaders()) - .send({ ...user, _rev: res1.body.rev, roleId: BUILTIN_ROLE_IDS.POWER }) + .send({ + ...user, + _rev: res1.body.rev, + roleId: roles.BUILTIN_ROLE_IDS.POWER, + }) .expect(200) .expect("Content-Type", /json/) @@ -95,14 +98,14 @@ describe("/users", () => { await request .put(`/api/users/metadata`) .set(config.defaultHeaders()) - .send({ ...user, roleId: BUILTIN_ROLE_IDS.BASIC }) + .send({ ...user, roleId: roles.BUILTIN_ROLE_IDS.BASIC }) .expect(200) .expect("Content-Type", /json/) await request .put(`/api/users/metadata`) .set(config.defaultHeaders()) - .send({ ...user, roleId: BUILTIN_ROLE_IDS.POWER }) + .send({ ...user, roleId: roles.BUILTIN_ROLE_IDS.POWER }) .expect(409) .expect("Content-Type", /json/) }) @@ -129,7 +132,7 @@ describe("/users", () => { .expect(200) .expect("Content-Type", /json/) expect(res.body._id).toEqual(user._id) - expect(res.body.roleId).toEqual(BUILTIN_ROLE_IDS.ADMIN) + expect(res.body.roleId).toEqual(roles.BUILTIN_ROLE_IDS.ADMIN) expect(res.body.tableId).toBeDefined() }) }) diff --git a/packages/server/src/tests/utilities/api/index.ts b/packages/server/src/tests/utilities/api/index.ts index c553e7b8f4..20b96f7a99 100644 --- a/packages/server/src/tests/utilities/api/index.ts +++ b/packages/server/src/tests/utilities/api/index.ts @@ -9,6 +9,7 @@ import { ScreenAPI } from "./screen" import { ApplicationAPI } from "./application" import { BackupAPI } from "./backup" import { AttachmentAPI } from "./attachment" +import { UserAPI } from "./user" export default class API { table: TableAPI @@ -21,6 +22,7 @@ export default class API { application: ApplicationAPI backup: BackupAPI attachment: AttachmentAPI + user: UserAPI constructor(config: TestConfiguration) { this.table = new TableAPI(config) @@ -33,5 +35,6 @@ export default class API { this.application = new ApplicationAPI(config) this.backup = new BackupAPI(config) this.attachment = new AttachmentAPI(config) + this.user = new UserAPI(config) } } diff --git a/packages/server/src/tests/utilities/api/user.ts b/packages/server/src/tests/utilities/api/user.ts new file mode 100644 index 0000000000..2066315778 --- /dev/null +++ b/packages/server/src/tests/utilities/api/user.ts @@ -0,0 +1,48 @@ +import { FetchUserMetadataResponse } from "@budibase/types" +import TestConfiguration from "../TestConfiguration" +import { TestAPI } from "./base" + +export class UserAPI extends TestAPI { + constructor(config: TestConfiguration) { + super(config) + } + + fetch = async ( + { expectStatus } = { expectStatus: 200 } + ): Promise => { + const res = await this.request + .get(`/api/users/metadata`) + .set(this.config.defaultHeaders()) + .expect("Content-Type", /json/) + + if (res.status !== expectStatus) { + throw new Error( + `Expected status ${expectStatus} but got ${ + res.status + } with body ${JSON.stringify(res.body)}` + ) + } + + return res.body + } + + get = async ( + id: string, + { expectStatus } = { expectStatus: 200 } + ): Promise => { + const res = await this.request + .get(`/api/users/metadata/${id}`) + .set(this.config.defaultHeaders()) + .expect("Content-Type", /json/) + + if (res.status !== expectStatus) { + throw new Error( + `Expected status ${expectStatus} but got ${ + res.status + } with body ${JSON.stringify(res.body)}` + ) + } + + return res.body + } +} diff --git a/packages/server/src/utilities/users.ts b/packages/server/src/utilities/users.ts index bbc1370355..73b2f48b15 100644 --- a/packages/server/src/utilities/users.ts +++ b/packages/server/src/utilities/users.ts @@ -1,11 +1,13 @@ import { InternalTables } from "../db/utils" import { getGlobalUser } from "./global" import { context, roles } from "@budibase/backend-core" -import { UserCtx } from "@budibase/types" +import { ContextUserMetadata, UserCtx, UserMetadata } from "@budibase/types" -export async function getFullUser(ctx: UserCtx, userId: string) { +export async function getFullUser( + userId: string +): Promise { const global = await getGlobalUser(userId) - let metadata: any = {} + let metadata: UserMetadata | undefined = undefined // always prefer the user metadata _id and _rev delete global._id @@ -14,11 +16,11 @@ export async function getFullUser(ctx: UserCtx, userId: string) { try { // this will throw an error if the db doesn't exist, or there is no appId const db = context.getAppDB() - metadata = await db.get(userId) + metadata = await db.get(userId) + delete metadata.csrfToken } catch (err) { // it is fine if there is no user metadata yet } - delete metadata.csrfToken return { ...metadata, ...global, diff --git a/packages/types/src/api/web/app/index.ts b/packages/types/src/api/web/app/index.ts index f5b876009b..cb1cea2b08 100644 --- a/packages/types/src/api/web/app/index.ts +++ b/packages/types/src/api/web/app/index.ts @@ -6,3 +6,4 @@ export * from "./rows" export * from "./table" export * from "./permission" export * from "./attachment" +export * from "./user" diff --git a/packages/types/src/api/web/app/user.ts b/packages/types/src/api/web/app/user.ts new file mode 100644 index 0000000000..2e0eeee7f8 --- /dev/null +++ b/packages/types/src/api/web/app/user.ts @@ -0,0 +1,3 @@ +import { ContextUserMetadata } from "src/documents" + +export type FetchUserMetadataResponse = ContextUserMetadata[]