From 8c326b501befe8716355b81ec4b6dad4881e6cc5 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Tue, 2 Apr 2024 17:12:31 +0100 Subject: [PATCH] Adding support for oneOf ID search of users, today the relationship picker attempts to use this for the users table, but it was not supported. --- packages/backend-core/src/users/users.ts | 13 +++++++++---- .../worker/src/api/controllers/global/users.ts | 2 +- .../src/api/routes/global/tests/users.spec.ts | 18 ++++++++++++++++++ 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/packages/backend-core/src/users/users.ts b/packages/backend-core/src/users/users.ts index 638da4a5b1..48920a3771 100644 --- a/packages/backend-core/src/users/users.ts +++ b/packages/backend-core/src/users/users.ts @@ -14,16 +14,16 @@ import { } from "../db" import { BulkDocsResponse, + ContextUser, + CouchFindOptions, + DatabaseQueryOpts, SearchQuery, SearchQueryOperators, SearchUsersRequest, User, - ContextUser, - DatabaseQueryOpts, - CouchFindOptions, } from "@budibase/types" -import { getGlobalDB } from "../context" import * as context from "../context" +import { getGlobalDB } from "../context" import { isCreator } from "./utils" import { UserDB } from "./db" @@ -48,6 +48,7 @@ export function isSupportedUserSearch(query: SearchQuery) { const allowed = [ { op: SearchQueryOperators.STRING, key: "email" }, { op: SearchQueryOperators.EQUAL, key: "_id" }, + { op: SearchQueryOperators.ONE_OF, key: "_id" }, ] for (let [key, operation] of Object.entries(query)) { if (typeof operation !== "object") { @@ -285,6 +286,10 @@ export async function paginatedUsers({ } else if (query?.string?.email) { userList = await searchGlobalUsersByEmail(query?.string?.email, opts) property = "email" + } else if (query?.oneOf?._id) { + userList = await bulkGetGlobalUsersById(query?.oneOf?._id, { + cleanup: true, + }) } else { // no search, query allDocs const response = await db.allDocs(getGlobalUserParams(null, opts)) diff --git a/packages/worker/src/api/controllers/global/users.ts b/packages/worker/src/api/controllers/global/users.ts index 93f35b4c37..0c1342fa08 100644 --- a/packages/worker/src/api/controllers/global/users.ts +++ b/packages/worker/src/api/controllers/global/users.ts @@ -229,7 +229,7 @@ export const search = async (ctx: Ctx) => { } // Validate we aren't trying to search on any illegal fields if (!userSdk.core.isSupportedUserSearch(body.query)) { - ctx.throw(400, "Can only search by string.email or equal._id") + ctx.throw(400, "Can only search by string.email, equal._id or oneOf._id") } } diff --git a/packages/worker/src/api/routes/global/tests/users.spec.ts b/packages/worker/src/api/routes/global/tests/users.spec.ts index 2198757be1..fe6089a621 100644 --- a/packages/worker/src/api/routes/global/tests/users.spec.ts +++ b/packages/worker/src/api/routes/global/tests/users.spec.ts @@ -649,6 +649,24 @@ describe("/api/global/users", () => { expect(response.body.data[0]._id).toBe(user._id) }) + it("should be able to search by oneOf _id", async () => { + const [user, user2, user3] = await Promise.all([ + config.createUser(), + config.createUser(), + config.createUser(), + ]) + const response = await config.api.users.searchUsers({ + query: { oneOf: { _id: [user._id, user2._id] } }, + }) + expect(response.body.data.length).toBe(2) + const foundUserIds = response.body.data.map((user: User) => user._id) + expect(foundUserIds).toContain(user._id) + expect(foundUserIds).toContain(user2._id) + expect( + response.body.data.find((user: User) => user._id === user3._id) + ).toBeUndefined() + }) + it("should be able to search by _id with numeric prefixing", async () => { const user = await config.createUser() const response = await config.api.users.searchUsers({