Merge remote-tracking branch 'origin/master' into feature/screen-deselect
This commit is contained in:
commit
f4fc8e5e97
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"version": "2.22.13",
|
"version": "2.22.14",
|
||||||
"npmClient": "yarn",
|
"npmClient": "yarn",
|
||||||
"packages": [
|
"packages": [
|
||||||
"packages/*",
|
"packages/*",
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 63ce32bca871f0a752323f5f7ebb5ec16bbbacc3
|
Subproject commit 360ad2dc29c3f1fd5a1182ae258c45666b7f5eb1
|
|
@ -14,16 +14,16 @@ import {
|
||||||
} from "../db"
|
} from "../db"
|
||||||
import {
|
import {
|
||||||
BulkDocsResponse,
|
BulkDocsResponse,
|
||||||
|
ContextUser,
|
||||||
|
CouchFindOptions,
|
||||||
|
DatabaseQueryOpts,
|
||||||
SearchQuery,
|
SearchQuery,
|
||||||
SearchQueryOperators,
|
SearchQueryOperators,
|
||||||
SearchUsersRequest,
|
SearchUsersRequest,
|
||||||
User,
|
User,
|
||||||
ContextUser,
|
|
||||||
DatabaseQueryOpts,
|
|
||||||
CouchFindOptions,
|
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import { getGlobalDB } from "../context"
|
|
||||||
import * as context from "../context"
|
import * as context from "../context"
|
||||||
|
import { getGlobalDB } from "../context"
|
||||||
import { isCreator } from "./utils"
|
import { isCreator } from "./utils"
|
||||||
import { UserDB } from "./db"
|
import { UserDB } from "./db"
|
||||||
|
|
||||||
|
@ -48,6 +48,7 @@ export function isSupportedUserSearch(query: SearchQuery) {
|
||||||
const allowed = [
|
const allowed = [
|
||||||
{ op: SearchQueryOperators.STRING, key: "email" },
|
{ op: SearchQueryOperators.STRING, key: "email" },
|
||||||
{ op: SearchQueryOperators.EQUAL, key: "_id" },
|
{ op: SearchQueryOperators.EQUAL, key: "_id" },
|
||||||
|
{ op: SearchQueryOperators.ONE_OF, key: "_id" },
|
||||||
]
|
]
|
||||||
for (let [key, operation] of Object.entries(query)) {
|
for (let [key, operation] of Object.entries(query)) {
|
||||||
if (typeof operation !== "object") {
|
if (typeof operation !== "object") {
|
||||||
|
@ -285,6 +286,10 @@ export async function paginatedUsers({
|
||||||
} else if (query?.string?.email) {
|
} else if (query?.string?.email) {
|
||||||
userList = await searchGlobalUsersByEmail(query?.string?.email, opts)
|
userList = await searchGlobalUsersByEmail(query?.string?.email, opts)
|
||||||
property = "email"
|
property = "email"
|
||||||
|
} else if (query?.oneOf?._id) {
|
||||||
|
userList = await bulkGetGlobalUsersById(query?.oneOf?._id, {
|
||||||
|
cleanup: true,
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
// no search, query allDocs
|
// no search, query allDocs
|
||||||
const response = await db.allDocs(getGlobalUserParams(null, opts))
|
const response = await db.allDocs(getGlobalUserParams(null, opts))
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
import ModalBindableInput from "components/common/bindings/ModalBindableInput.svelte"
|
import ModalBindableInput from "components/common/bindings/ModalBindableInput.svelte"
|
||||||
import CodeEditor from "components/common/CodeEditor/CodeEditor.svelte"
|
import CodeEditor from "components/common/CodeEditor/CodeEditor.svelte"
|
||||||
import BindingSidePanel from "components/common/bindings/BindingSidePanel.svelte"
|
import BindingSidePanel from "components/common/bindings/BindingSidePanel.svelte"
|
||||||
import { BindingHelpers } from "components/common/bindings/utils"
|
import { BindingHelpers, BindingType } from "components/common/bindings/utils"
|
||||||
import {
|
import {
|
||||||
bindingsToCompletions,
|
bindingsToCompletions,
|
||||||
hbAutocomplete,
|
hbAutocomplete,
|
||||||
|
@ -576,6 +576,7 @@
|
||||||
{
|
{
|
||||||
js: true,
|
js: true,
|
||||||
dontDecode: true,
|
dontDecode: true,
|
||||||
|
type: BindingType.RUNTIME,
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
mode="javascript"
|
mode="javascript"
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
import { licensing } from "stores/portal"
|
import { licensing } from "stores/portal"
|
||||||
import { isPremiumOrAbove } from "helpers/planTitle"
|
import { isPremiumOrAbove } from "helpers/planTitle"
|
||||||
|
|
||||||
$: premiumOrAboveLicense = isPremiumOrAbove($licensing?.license.plan.type)
|
$: premiumOrAboveLicense = isPremiumOrAbove($licensing?.license?.plan?.type)
|
||||||
|
|
||||||
let show
|
let show
|
||||||
let hide
|
let hide
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
import { decodeJSBinding } from "@budibase/string-templates"
|
import { decodeJSBinding } from "@budibase/string-templates"
|
||||||
import { hbInsert, jsInsert } from "components/common/CodeEditor"
|
import { hbInsert, jsInsert } from "components/common/CodeEditor"
|
||||||
|
|
||||||
|
export const BindingType = {
|
||||||
|
READABLE: "readableBinding",
|
||||||
|
RUNTIME: "runtimeBinding",
|
||||||
|
}
|
||||||
|
|
||||||
export class BindingHelpers {
|
export class BindingHelpers {
|
||||||
constructor(getCaretPosition, insertAtPos, { disableWrapping } = {}) {
|
constructor(getCaretPosition, insertAtPos, { disableWrapping } = {}) {
|
||||||
this.getCaretPosition = getCaretPosition
|
this.getCaretPosition = getCaretPosition
|
||||||
|
@ -25,16 +30,20 @@ export class BindingHelpers {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds a data binding to the expression
|
// Adds a data binding to the expression
|
||||||
onSelectBinding(value, binding, { js, dontDecode }) {
|
onSelectBinding(
|
||||||
|
value,
|
||||||
|
binding,
|
||||||
|
{ js, dontDecode, type = BindingType.READABLE }
|
||||||
|
) {
|
||||||
const { start, end } = this.getCaretPosition()
|
const { start, end } = this.getCaretPosition()
|
||||||
if (js) {
|
if (js) {
|
||||||
const jsVal = dontDecode ? value : decodeJSBinding(value)
|
const jsVal = dontDecode ? value : decodeJSBinding(value)
|
||||||
const insertVal = jsInsert(jsVal, start, end, binding.readableBinding, {
|
const insertVal = jsInsert(jsVal, start, end, binding[type], {
|
||||||
disableWrapping: this.disableWrapping,
|
disableWrapping: this.disableWrapping,
|
||||||
})
|
})
|
||||||
this.insertAtPos({ start, end, value: insertVal })
|
this.insertAtPos({ start, end, value: insertVal })
|
||||||
} else {
|
} else {
|
||||||
const insertVal = hbInsert(value, start, end, binding.readableBinding)
|
const insertVal = hbInsert(value, start, end, binding[type])
|
||||||
this.insertAtPos({ start, end, value: insertVal })
|
this.insertAtPos({ start, end, value: insertVal })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -148,7 +148,7 @@ export const enrichedApps = derived([appsStore, auth], ([$store, $auth]) => {
|
||||||
deployed: app.status === AppStatus.DEPLOYED,
|
deployed: app.status === AppStatus.DEPLOYED,
|
||||||
lockedYou: app.lockedBy && app.lockedBy.email === $auth.user?.email,
|
lockedYou: app.lockedBy && app.lockedBy.email === $auth.user?.email,
|
||||||
lockedOther: 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),
|
||||||
}))
|
}))
|
||||||
: []
|
: []
|
||||||
|
|
||||||
|
|
|
@ -229,7 +229,7 @@ export const search = async (ctx: Ctx<SearchUsersRequest>) => {
|
||||||
}
|
}
|
||||||
// Validate we aren't trying to search on any illegal fields
|
// Validate we aren't trying to search on any illegal fields
|
||||||
if (!userSdk.core.isSupportedUserSearch(body.query)) {
|
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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -649,6 +649,24 @@ describe("/api/global/users", () => {
|
||||||
expect(response.body.data[0]._id).toBe(user._id)
|
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 () => {
|
it("should be able to search by _id with numeric prefixing", async () => {
|
||||||
const user = await config.createUser()
|
const user = await config.createUser()
|
||||||
const response = await config.api.users.searchUsers({
|
const response = await config.api.users.searchUsers({
|
||||||
|
|
Loading…
Reference in New Issue