diff --git a/lerna.json b/lerna.json index bacdcb782f..906e9fba50 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "2.22.13", + "version": "2.22.14", "npmClient": "yarn", "packages": [ "packages/*", diff --git a/packages/account-portal b/packages/account-portal index 63ce32bca8..360ad2dc29 160000 --- a/packages/account-portal +++ b/packages/account-portal @@ -1 +1 @@ -Subproject commit 63ce32bca871f0a752323f5f7ebb5ec16bbbacc3 +Subproject commit 360ad2dc29c3f1fd5a1182ae258c45666b7f5eb1 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/builder/src/components/common/HelpMenu.svelte b/packages/builder/src/components/common/HelpMenu.svelte index baff9a5a27..63156676d2 100644 --- a/packages/builder/src/components/common/HelpMenu.svelte +++ b/packages/builder/src/components/common/HelpMenu.svelte @@ -5,7 +5,7 @@ import { licensing } from "stores/portal" import { isPremiumOrAbove } from "helpers/planTitle" - $: premiumOrAboveLicense = isPremiumOrAbove($licensing?.license.plan.type) + $: premiumOrAboveLicense = isPremiumOrAbove($licensing?.license?.plan?.type) let show let hide diff --git a/packages/builder/src/stores/portal/apps.js b/packages/builder/src/stores/portal/apps.js index 84c4348075..6af9fa56ac 100644 --- a/packages/builder/src/stores/portal/apps.js +++ b/packages/builder/src/stores/portal/apps.js @@ -148,7 +148,7 @@ export const enrichedApps = derived([appsStore, auth], ([$store, $auth]) => { deployed: app.status === AppStatus.DEPLOYED, lockedYou: app.lockedBy && app.lockedBy.email === $auth.user?.email, lockedOther: app.lockedBy && app.lockedBy.email !== $auth.user?.email, - favourite: $auth?.user.appFavourites?.includes(app.appId), + favourite: $auth.user?.appFavourites?.includes(app.appId), })) : [] 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({