Two fixes here - a quick fix for the builder side panel, making sure it fills up with users correctly (not all, but enough to make it look more pleasant) as well as dropping user search endpoint permissions to allow basic users to access it for user columns.
This commit is contained in:
parent
0010e07b47
commit
04a2bbc61a
|
@ -164,14 +164,14 @@ export class UserDB {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static async getUsersByAppAccess(appId?: string) {
|
static async getUsersByAppAccess(opts: { appId?: string; limit?: number }) {
|
||||||
const opts: any = {
|
const params: any = {
|
||||||
include_docs: true,
|
include_docs: true,
|
||||||
limit: 50,
|
limit: opts.limit || 50,
|
||||||
}
|
}
|
||||||
let response: User[] = await usersCore.searchGlobalUsersByAppAccess(
|
let response: User[] = await usersCore.searchGlobalUsersByAppAccess(
|
||||||
appId,
|
opts.appId,
|
||||||
opts
|
params
|
||||||
)
|
)
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ import {
|
||||||
SearchUsersRequest,
|
SearchUsersRequest,
|
||||||
User,
|
User,
|
||||||
ContextUser,
|
ContextUser,
|
||||||
|
DatabaseQueryOpts,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import { getGlobalDB } from "../context"
|
import { getGlobalDB } from "../context"
|
||||||
import * as context from "../context"
|
import * as context from "../context"
|
||||||
|
@ -241,12 +242,14 @@ export const paginatedUsers = async ({
|
||||||
bookmark,
|
bookmark,
|
||||||
query,
|
query,
|
||||||
appId,
|
appId,
|
||||||
|
limit,
|
||||||
}: SearchUsersRequest = {}) => {
|
}: SearchUsersRequest = {}) => {
|
||||||
const db = getGlobalDB()
|
const db = getGlobalDB()
|
||||||
|
const pageLimit = limit ? limit + 1 : PAGE_LIMIT + 1
|
||||||
// get one extra document, to have the next page
|
// get one extra document, to have the next page
|
||||||
const opts: any = {
|
const opts: DatabaseQueryOpts = {
|
||||||
include_docs: true,
|
include_docs: true,
|
||||||
limit: PAGE_LIMIT + 1,
|
limit: pageLimit,
|
||||||
}
|
}
|
||||||
// add a startkey if the page was specified (anchor)
|
// add a startkey if the page was specified (anchor)
|
||||||
if (bookmark) {
|
if (bookmark) {
|
||||||
|
@ -269,7 +272,7 @@ export const paginatedUsers = async ({
|
||||||
const response = await db.allDocs(getGlobalUserParams(null, opts))
|
const response = await db.allDocs(getGlobalUserParams(null, opts))
|
||||||
userList = response.rows.map((row: any) => row.doc)
|
userList = response.rows.map((row: any) => row.doc)
|
||||||
}
|
}
|
||||||
return pagination(userList, PAGE_LIMIT, {
|
return pagination(userList, pageLimit, {
|
||||||
paginate: true,
|
paginate: true,
|
||||||
property,
|
property,
|
||||||
getKey,
|
getKey,
|
||||||
|
|
|
@ -114,8 +114,9 @@
|
||||||
query: {
|
query: {
|
||||||
appId: query || !filterByAppAccess ? null : prodAppId,
|
appId: query || !filterByAppAccess ? null : prodAppId,
|
||||||
email: query,
|
email: query,
|
||||||
paginated: query || !filterByAppAccess ? null : false,
|
|
||||||
},
|
},
|
||||||
|
limit: 50,
|
||||||
|
paginate: query || !filterByAppAccess ? null : false,
|
||||||
})
|
})
|
||||||
await usersFetch.refresh()
|
await usersFetch.refresh()
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,7 @@ export interface SearchUsersRequest {
|
||||||
bookmark?: string
|
bookmark?: string
|
||||||
query?: SearchQuery
|
query?: SearchQuery
|
||||||
appId?: string
|
appId?: string
|
||||||
|
limit?: number
|
||||||
paginate?: boolean
|
paginate?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -189,7 +189,10 @@ export const destroy = async (ctx: any) => {
|
||||||
|
|
||||||
export const getAppUsers = async (ctx: Ctx<SearchUsersRequest>) => {
|
export const getAppUsers = async (ctx: Ctx<SearchUsersRequest>) => {
|
||||||
const body = ctx.request.body
|
const body = ctx.request.body
|
||||||
const users = await userSdk.db.getUsersByAppAccess(body?.appId)
|
const users = await userSdk.db.getUsersByAppAccess({
|
||||||
|
appId: body.appId,
|
||||||
|
limit: body.limit,
|
||||||
|
})
|
||||||
|
|
||||||
ctx.body = { data: users }
|
ctx.body = { data: users }
|
||||||
}
|
}
|
||||||
|
@ -203,8 +206,10 @@ export const search = async (ctx: Ctx<SearchUsersRequest>) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (body.paginate === false) {
|
if (body.paginate === false) {
|
||||||
|
console.log("not paginated")
|
||||||
await getAppUsers(ctx)
|
await getAppUsers(ctx)
|
||||||
} else {
|
} else {
|
||||||
|
console.log("paginated")
|
||||||
const paginated = await userSdk.core.paginatedUsers(body)
|
const paginated = await userSdk.core.paginatedUsers(body)
|
||||||
// user hashed password shouldn't ever be returned
|
// user hashed password shouldn't ever be returned
|
||||||
for (let user of paginated.data) {
|
for (let user of paginated.data) {
|
||||||
|
|
|
@ -569,9 +569,13 @@ describe("/api/global/users", () => {
|
||||||
{
|
{
|
||||||
query: { equal: { firstName: user.firstName } },
|
query: { equal: { firstName: user.firstName } },
|
||||||
},
|
},
|
||||||
501
|
{ status: 501 }
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("should throw an error if public query performed", async () => {
|
||||||
|
await config.api.users.searchUsers({}, { status: 403, noHeaders: true })
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("DELETE /api/global/users/:userId", () => {
|
describe("DELETE /api/global/users/:userId", () => {
|
||||||
|
|
|
@ -72,7 +72,8 @@ router
|
||||||
)
|
)
|
||||||
|
|
||||||
.get("/api/global/users", auth.builderOrAdmin, controller.fetch)
|
.get("/api/global/users", auth.builderOrAdmin, controller.fetch)
|
||||||
.post("/api/global/users/search", auth.builderOrAdmin, controller.search)
|
// search can be used by any user now, to retrieve users for user column
|
||||||
|
.post("/api/global/users/search", controller.search)
|
||||||
.delete("/api/global/users/:id", auth.adminOnly, controller.destroy)
|
.delete("/api/global/users/:id", auth.adminOnly, controller.destroy)
|
||||||
.get(
|
.get(
|
||||||
"/api/global/users/count/:appId",
|
"/api/global/users/count/:appId",
|
||||||
|
|
|
@ -134,13 +134,19 @@ export class UserAPI extends TestAPI {
|
||||||
.expect(status ? status : 200)
|
.expect(status ? status : 200)
|
||||||
}
|
}
|
||||||
|
|
||||||
searchUsers = ({ query }: { query?: SearchQuery }, status = 200) => {
|
searchUsers = (
|
||||||
return this.request
|
{ query }: { query?: SearchQuery },
|
||||||
|
opts?: { status?: number; noHeaders?: boolean }
|
||||||
|
) => {
|
||||||
|
const req = this.request
|
||||||
.post("/api/global/users/search")
|
.post("/api/global/users/search")
|
||||||
.set(this.config.defaultHeaders())
|
|
||||||
.send({ query })
|
.send({ query })
|
||||||
.expect("Content-Type", /json/)
|
.expect("Content-Type", /json/)
|
||||||
.expect(status ? status : 200)
|
.expect(opts?.status ? opts.status : 200)
|
||||||
|
if (!opts?.noHeaders) {
|
||||||
|
req.set(this.config.defaultHeaders())
|
||||||
|
}
|
||||||
|
return req
|
||||||
}
|
}
|
||||||
|
|
||||||
getUser = (userId: string, opts?: TestAPIOpts) => {
|
getUser = (userId: string, opts?: TestAPIOpts) => {
|
||||||
|
|
Loading…
Reference in New Issue