From 8a77aca54021e0012040652855fd342e194cb012 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Fri, 29 Jul 2022 13:10:00 +0100 Subject: [PATCH] more efficient fetching of total users per app --- .../overview/_components/AssignmentModal.svelte | 5 ++--- packages/builder/src/stores/portal/users.js | 6 ++++++ packages/frontend-core/src/api/user.js | 11 +++++++++++ packages/worker/src/api/controllers/global/users.ts | 12 +++++++++++- packages/worker/src/api/routes/global/users.js | 1 + packages/worker/src/sdk/users/users.ts | 13 +++++++++++-- 6 files changed, 42 insertions(+), 6 deletions(-) diff --git a/packages/builder/src/pages/builder/portal/overview/_components/AssignmentModal.svelte b/packages/builder/src/pages/builder/portal/overview/_components/AssignmentModal.svelte index aee7a8aa7d..48503e56e6 100644 --- a/packages/builder/src/pages/builder/portal/overview/_components/AssignmentModal.svelte +++ b/packages/builder/src/pages/builder/portal/overview/_components/AssignmentModal.svelte @@ -13,7 +13,6 @@ export let app export let addData export let appUsers = [] - let prevSearch = undefined, search = undefined let pageInfo = createPaginationStore() @@ -32,7 +31,7 @@ prevSearch = search try { pageInfo.loading() - await users.search({ page, search }) + await users.search({ page, email: search }) pageInfo.fetched($users.hasNextPage, $users.nextPage) } catch (error) { notifications.error("Error getting user list") @@ -83,10 +82,10 @@ group.name} getPrimaryOptionValue={group => group.name} getPrimaryOptionIcon={group => group.icon} diff --git a/packages/builder/src/stores/portal/users.js b/packages/builder/src/stores/portal/users.js index 94fdf806e6..490d1bc9f6 100644 --- a/packages/builder/src/stores/portal/users.js +++ b/packages/builder/src/stores/portal/users.js @@ -61,6 +61,7 @@ export function createUsersStore() { break case "admin": body.admin = { global: true } + body.builder = { global: true } break } @@ -77,6 +78,10 @@ export function createUsersStore() { update(users => users.filter(user => user._id !== id)) } + async function getUserCountByApp({ appId }) { + return await API.getUserCountByApp({ appId }) + } + async function bulkDelete(userIds) { await API.deleteUsers(userIds) } @@ -99,6 +104,7 @@ export function createUsersStore() { create, save, bulkDelete, + getUserCountByApp, delete: del, } } diff --git a/packages/frontend-core/src/api/user.js b/packages/frontend-core/src/api/user.js index b2ecafdb35..17223a80e6 100644 --- a/packages/frontend-core/src/api/user.js +++ b/packages/frontend-core/src/api/user.js @@ -172,4 +172,15 @@ export const buildUserEndpoints = API => ({ }, }) }, + + /** + * Accepts an invite to join the platform and creates a user. + * @param inviteCode the invite code sent in the email + * @param password the password for the newly created user + */ + getUserCountByApp: async ({ appId }) => { + return await API.get({ + url: `/api/global/users/count/${appId}`, + }) + }, }) diff --git a/packages/worker/src/api/controllers/global/users.ts b/packages/worker/src/api/controllers/global/users.ts index ff630efae8..17e655edb3 100644 --- a/packages/worker/src/api/controllers/global/users.ts +++ b/packages/worker/src/api/controllers/global/users.ts @@ -3,7 +3,7 @@ import { checkInviteCode } from "../../../utilities/redis" import { sendEmail } from "../../../utilities/email" import { users } from "../../../sdk" import env from "../../../environment" -import { User, CloudAccount, UserGroup } from "@budibase/types" +import { User, CloudAccount } from "@budibase/types" import { events, errors, @@ -114,6 +114,16 @@ export const adminUser = async (ctx: any) => { }) } +export const countByApp = async (ctx: any) => { + const appId = ctx.params.appId + try { + const response = await users.countUsersByApp(appId) + ctx.body = response + } catch (err: any) { + ctx.throw(err.status || 400, err) + } +} + export const destroy = async (ctx: any) => { const id = ctx.params.id diff --git a/packages/worker/src/api/routes/global/users.js b/packages/worker/src/api/routes/global/users.js index a1aa9fca7f..e62e996443 100644 --- a/packages/worker/src/api/routes/global/users.js +++ b/packages/worker/src/api/routes/global/users.js @@ -64,6 +64,7 @@ router .post("/api/global/users/search", builderOrAdmin, controller.search) .delete("/api/global/users/:id", adminOnly, controller.destroy) .post("/api/global/users/bulkDelete", adminOnly, controller.bulkDelete) + .get("/api/global/users/count/:appId", adminOnly, controller.countByApp) .get("/api/global/roles/:appId") .post( "/api/global/users/invite", diff --git a/packages/worker/src/sdk/users/users.ts b/packages/worker/src/sdk/users/users.ts index 48e4f0db02..d6c667dbfb 100644 --- a/packages/worker/src/sdk/users/users.ts +++ b/packages/worker/src/sdk/users/users.ts @@ -20,7 +20,7 @@ import { groups as groupUtils } from "@budibase/pro" const PAGE_LIMIT = 8 -export const allUsers = async (newDb?: any) => { +export const allUsers = async () => { const db = tenancy.getGlobalDB() const response = await db.allDocs( dbUtils.getGlobalUserParams(null, { @@ -30,6 +30,15 @@ export const allUsers = async (newDb?: any) => { return response.rows.map((row: any) => row.doc) } +export const countUsersByApp = async (appId: string) => { + let response: any = await usersCore.searchGlobalUsersByApp(appId, { + include_docs: true, + }) + return { + userCount: response.length, + } +} + export const paginatedUsers = async ({ page, email, @@ -56,7 +65,7 @@ export const paginatedUsers = async ({ userList = await usersCore.searchGlobalUsersByEmail(email, opts) property = "email" } else { - // no search, query allDocs + // no search, query allDcso const response = await db.allDocs(dbUtils.getGlobalUserParams(null, opts)) userList = response.rows.map((row: any) => row.doc) }