Merge pull request #14741 from Budibase/budi-8708-single-and-multi-select-user-fields-appear-to-no-longer-be
Allow conditional search for users
This commit is contained in:
commit
47985748d2
|
@ -24,6 +24,7 @@ import * as context from "../context"
|
|||
import { getGlobalDB } from "../context"
|
||||
import { isCreator } from "./utils"
|
||||
import { UserDB } from "./db"
|
||||
import { dataFilters } from "@budibase/shared-core"
|
||||
|
||||
type GetOpts = { cleanup?: boolean }
|
||||
|
||||
|
@ -262,10 +263,17 @@ export async function paginatedUsers({
|
|||
userList = await bulkGetGlobalUsersById(query?.oneOf?._id, {
|
||||
cleanup: true,
|
||||
})
|
||||
} else if (query) {
|
||||
// TODO: this should use SQS search, but the logic is built in the 'server' package. Using the in-memory filtering to get this working meanwhile
|
||||
const response = await db.allDocs<User>(
|
||||
getGlobalUserParams(null, { ...opts, limit: undefined })
|
||||
)
|
||||
userList = response.rows.map(row => row.doc!)
|
||||
userList = dataFilters.search(userList, { query, limit: opts.limit }).rows
|
||||
} else {
|
||||
// no search, query allDocs
|
||||
const response = await db.allDocs(getGlobalUserParams(null, opts))
|
||||
userList = response.rows.map((row: any) => row.doc)
|
||||
const response = await db.allDocs<User>(getGlobalUserParams(null, opts))
|
||||
userList = response.rows.map(row => row.doc!)
|
||||
}
|
||||
return pagination(userList, pageSize, {
|
||||
paginate: true,
|
||||
|
|
|
@ -187,7 +187,6 @@ describe.each([
|
|||
if (isInMemory) {
|
||||
return dataFilters.search(_.cloneDeep(rows), {
|
||||
...this.query,
|
||||
tableId: tableOrViewId,
|
||||
})
|
||||
} else {
|
||||
return config.api.row.search(tableOrViewId, this.query)
|
||||
|
|
|
@ -639,19 +639,19 @@ export function fixupFilterArrays(filters: SearchFilters) {
|
|||
return filters
|
||||
}
|
||||
|
||||
export function search<T>(
|
||||
docs: Record<string, T>[],
|
||||
query: RowSearchParams
|
||||
): SearchResponse<Record<string, T>> {
|
||||
export function search<T extends Record<string, any>>(
|
||||
docs: T[],
|
||||
query: Omit<RowSearchParams, "tableId">
|
||||
): SearchResponse<T> {
|
||||
let result = runQuery(docs, query.query)
|
||||
if (query.sort) {
|
||||
result = sort(result, query.sort, query.sortOrder || SortOrder.ASCENDING)
|
||||
}
|
||||
let totalRows = result.length
|
||||
const totalRows = result.length
|
||||
if (query.limit) {
|
||||
result = limit(result, query.limit.toString())
|
||||
}
|
||||
const response: SearchResponse<Record<string, any>> = { rows: result }
|
||||
const response: SearchResponse<T> = { rows: result }
|
||||
if (query.countRows) {
|
||||
response.totalRows = totalRows
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import {
|
|||
SearchFilters,
|
||||
BasicOperator,
|
||||
ArrayOperator,
|
||||
isLogicalSearchOperator,
|
||||
} from "@budibase/types"
|
||||
import * as Constants from "./constants"
|
||||
import { removeKeyNumbering } from "./filters"
|
||||
|
@ -97,10 +98,20 @@ export function isSupportedUserSearch(query: SearchFilters) {
|
|||
{ op: BasicOperator.EQUAL, key: "_id" },
|
||||
{ op: ArrayOperator.ONE_OF, key: "_id" },
|
||||
]
|
||||
for (let [key, operation] of Object.entries(query)) {
|
||||
for (const [key, operation] of Object.entries(query)) {
|
||||
if (typeof operation !== "object") {
|
||||
return false
|
||||
}
|
||||
|
||||
if (isLogicalSearchOperator(key)) {
|
||||
for (const condition of query[key]!.conditions) {
|
||||
if (!isSupportedUserSearch(condition)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
const fields = Object.keys(operation || {})
|
||||
// this filter doesn't contain options - ignore
|
||||
if (fields.length === 0) {
|
||||
|
|
|
@ -741,6 +741,25 @@ describe("/api/global/users", () => {
|
|||
it("should throw an error if public query performed", async () => {
|
||||
await config.api.users.searchUsers({}, { status: 403, noHeaders: true })
|
||||
})
|
||||
|
||||
it("should be able to search using logical conditions", async () => {
|
||||
const user = await config.createUser()
|
||||
const response = await config.api.users.searchUsers({
|
||||
query: {
|
||||
$and: {
|
||||
conditions: [
|
||||
{
|
||||
$and: {
|
||||
conditions: [{ string: { email: user.email } }],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
})
|
||||
expect(response.body.data.length).toBe(1)
|
||||
expect(response.body.data[0].email).toBe(user.email)
|
||||
})
|
||||
})
|
||||
|
||||
describe("DELETE /api/global/users/:userId", () => {
|
||||
|
|
Loading…
Reference in New Issue