more efficient fetching of total users per app

This commit is contained in:
Peter Clement 2022-07-29 13:10:00 +01:00
parent 6c555c121c
commit 8a77aca540
6 changed files with 42 additions and 6 deletions

View File

@ -13,7 +13,6 @@
export let app export let app
export let addData export let addData
export let appUsers = [] export let appUsers = []
let prevSearch = undefined, let prevSearch = undefined,
search = undefined search = undefined
let pageInfo = createPaginationStore() let pageInfo = createPaginationStore()
@ -32,7 +31,7 @@
prevSearch = search prevSearch = search
try { try {
pageInfo.loading() pageInfo.loading()
await users.search({ page, search }) await users.search({ page, email: search })
pageInfo.fetched($users.hasNextPage, $users.nextPage) pageInfo.fetched($users.hasNextPage, $users.nextPage)
} catch (error) { } catch (error) {
notifications.error("Error getting user list") notifications.error("Error getting user list")
@ -83,10 +82,10 @@
<PickerDropdown <PickerDropdown
autocomplete autocomplete
primaryOptions={optionSections} primaryOptions={optionSections}
placeholder={"Search Users"}
secondaryOptions={$roles} secondaryOptions={$roles}
bind:primaryValue={input.id} bind:primaryValue={input.id}
bind:secondaryValue={input.role} bind:secondaryValue={input.role}
bind:searchTerm={search}
getPrimaryOptionLabel={group => group.name} getPrimaryOptionLabel={group => group.name}
getPrimaryOptionValue={group => group.name} getPrimaryOptionValue={group => group.name}
getPrimaryOptionIcon={group => group.icon} getPrimaryOptionIcon={group => group.icon}

View File

@ -61,6 +61,7 @@ export function createUsersStore() {
break break
case "admin": case "admin":
body.admin = { global: true } body.admin = { global: true }
body.builder = { global: true }
break break
} }
@ -77,6 +78,10 @@ export function createUsersStore() {
update(users => users.filter(user => user._id !== id)) update(users => users.filter(user => user._id !== id))
} }
async function getUserCountByApp({ appId }) {
return await API.getUserCountByApp({ appId })
}
async function bulkDelete(userIds) { async function bulkDelete(userIds) {
await API.deleteUsers(userIds) await API.deleteUsers(userIds)
} }
@ -99,6 +104,7 @@ export function createUsersStore() {
create, create,
save, save,
bulkDelete, bulkDelete,
getUserCountByApp,
delete: del, delete: del,
} }
} }

View File

@ -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}`,
})
},
}) })

View File

@ -3,7 +3,7 @@ import { checkInviteCode } from "../../../utilities/redis"
import { sendEmail } from "../../../utilities/email" import { sendEmail } from "../../../utilities/email"
import { users } from "../../../sdk" import { users } from "../../../sdk"
import env from "../../../environment" import env from "../../../environment"
import { User, CloudAccount, UserGroup } from "@budibase/types" import { User, CloudAccount } from "@budibase/types"
import { import {
events, events,
errors, 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) => { export const destroy = async (ctx: any) => {
const id = ctx.params.id const id = ctx.params.id

View File

@ -64,6 +64,7 @@ router
.post("/api/global/users/search", builderOrAdmin, controller.search) .post("/api/global/users/search", builderOrAdmin, controller.search)
.delete("/api/global/users/:id", adminOnly, controller.destroy) .delete("/api/global/users/:id", adminOnly, controller.destroy)
.post("/api/global/users/bulkDelete", adminOnly, controller.bulkDelete) .post("/api/global/users/bulkDelete", adminOnly, controller.bulkDelete)
.get("/api/global/users/count/:appId", adminOnly, controller.countByApp)
.get("/api/global/roles/:appId") .get("/api/global/roles/:appId")
.post( .post(
"/api/global/users/invite", "/api/global/users/invite",

View File

@ -20,7 +20,7 @@ import { groups as groupUtils } from "@budibase/pro"
const PAGE_LIMIT = 8 const PAGE_LIMIT = 8
export const allUsers = async (newDb?: any) => { export const allUsers = async () => {
const db = tenancy.getGlobalDB() const db = tenancy.getGlobalDB()
const response = await db.allDocs( const response = await db.allDocs(
dbUtils.getGlobalUserParams(null, { dbUtils.getGlobalUserParams(null, {
@ -30,6 +30,15 @@ export const allUsers = async (newDb?: any) => {
return response.rows.map((row: any) => row.doc) 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 ({ export const paginatedUsers = async ({
page, page,
email, email,
@ -56,7 +65,7 @@ export const paginatedUsers = async ({
userList = await usersCore.searchGlobalUsersByEmail(email, opts) userList = await usersCore.searchGlobalUsersByEmail(email, opts)
property = "email" property = "email"
} else { } else {
// no search, query allDocs // no search, query allDcso
const response = await db.allDocs(dbUtils.getGlobalUserParams(null, opts)) const response = await db.allDocs(dbUtils.getGlobalUserParams(null, opts))
userList = response.rows.map((row: any) => row.doc) userList = response.rows.map((row: any) => row.doc)
} }