Merge branch 'master' into fix/multi-step-form-block
This commit is contained in:
commit
57bdf4b04d
|
@ -1,6 +1,6 @@
|
||||||
import { AnyDocument, Database } from "@budibase/types"
|
import { AnyDocument, Database } from "@budibase/types"
|
||||||
|
|
||||||
import { JobQueue, createQueue } from "../queue"
|
import { JobQueue, Queue, createQueue } from "../queue"
|
||||||
import * as dbUtils from "../db"
|
import * as dbUtils from "../db"
|
||||||
|
|
||||||
interface ProcessDocMessage {
|
interface ProcessDocMessage {
|
||||||
|
@ -12,18 +12,26 @@ interface ProcessDocMessage {
|
||||||
const PERSIST_MAX_ATTEMPTS = 100
|
const PERSIST_MAX_ATTEMPTS = 100
|
||||||
let processor: DocWritethroughProcessor | undefined
|
let processor: DocWritethroughProcessor | undefined
|
||||||
|
|
||||||
export const docWritethroughProcessorQueue = createQueue<ProcessDocMessage>(
|
export class DocWritethroughProcessor {
|
||||||
JobQueue.DOC_WRITETHROUGH_QUEUE,
|
private static _queue: Queue
|
||||||
{
|
|
||||||
jobOptions: {
|
public static get queue() {
|
||||||
attempts: PERSIST_MAX_ATTEMPTS,
|
if (!DocWritethroughProcessor._queue) {
|
||||||
},
|
DocWritethroughProcessor._queue = createQueue<ProcessDocMessage>(
|
||||||
}
|
JobQueue.DOC_WRITETHROUGH_QUEUE,
|
||||||
)
|
{
|
||||||
|
jobOptions: {
|
||||||
|
attempts: PERSIST_MAX_ATTEMPTS,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return DocWritethroughProcessor._queue
|
||||||
|
}
|
||||||
|
|
||||||
class DocWritethroughProcessor {
|
|
||||||
init() {
|
init() {
|
||||||
docWritethroughProcessorQueue.process(async message => {
|
DocWritethroughProcessor.queue.process(async message => {
|
||||||
try {
|
try {
|
||||||
await this.persistToDb(message.data)
|
await this.persistToDb(message.data)
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
|
@ -76,7 +84,7 @@ export class DocWritethrough {
|
||||||
}
|
}
|
||||||
|
|
||||||
async patch(data: Record<string, any>) {
|
async patch(data: Record<string, any>) {
|
||||||
await docWritethroughProcessorQueue.add({
|
await DocWritethroughProcessor.queue.add({
|
||||||
dbName: this.db.name,
|
dbName: this.db.name,
|
||||||
docId: this.docId,
|
docId: this.docId,
|
||||||
data,
|
data,
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { getDB } from "../../db"
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DocWritethrough,
|
DocWritethrough,
|
||||||
docWritethroughProcessorQueue,
|
DocWritethroughProcessor,
|
||||||
init,
|
init,
|
||||||
} from "../docWritethrough"
|
} from "../docWritethrough"
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ import InMemoryQueue from "../../queue/inMemoryQueue"
|
||||||
const initialTime = Date.now()
|
const initialTime = Date.now()
|
||||||
|
|
||||||
async function waitForQueueCompletion() {
|
async function waitForQueueCompletion() {
|
||||||
const queue: InMemoryQueue = docWritethroughProcessorQueue as never
|
const queue: InMemoryQueue = DocWritethroughProcessor.queue as never
|
||||||
await queue.waitForCompletion()
|
await queue.waitForCompletion()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,7 +235,7 @@ describe("docWritethrough", () => {
|
||||||
return acc
|
return acc
|
||||||
}, {})
|
}, {})
|
||||||
}
|
}
|
||||||
const queueMessageSpy = jest.spyOn(docWritethroughProcessorQueue, "add")
|
const queueMessageSpy = jest.spyOn(DocWritethroughProcessor.queue, "add")
|
||||||
|
|
||||||
await config.doInTenant(async () => {
|
await config.doInTenant(async () => {
|
||||||
let patches = await parallelPatch(5)
|
let patches = await parallelPatch(5)
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
"types": ["node", "jest"],
|
"types": ["node", "jest"],
|
||||||
"outDir": "dist",
|
"outDir": "dist",
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
|
"baseUrl": ".",
|
||||||
"paths": {
|
"paths": {
|
||||||
"@budibase/types": ["../types/src"],
|
"@budibase/types": ["../types/src"],
|
||||||
"@budibase/backend-core": ["../backend-core/src"],
|
"@budibase/backend-core": ["../backend-core/src"],
|
||||||
|
|
|
@ -14,22 +14,35 @@ import {
|
||||||
SessionCookie,
|
SessionCookie,
|
||||||
JsonFieldSubType,
|
JsonFieldSubType,
|
||||||
QueryResponse,
|
QueryResponse,
|
||||||
QueryPreview,
|
|
||||||
QuerySchema,
|
QuerySchema,
|
||||||
FieldType,
|
FieldType,
|
||||||
ExecuteQueryRequest,
|
ExecuteQueryRequest,
|
||||||
ExecuteQueryResponse,
|
ExecuteQueryResponse,
|
||||||
Row,
|
|
||||||
QueryParameter,
|
QueryParameter,
|
||||||
PreviewQueryRequest,
|
PreviewQueryRequest,
|
||||||
PreviewQueryResponse,
|
PreviewQueryResponse,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import { ValidQueryNameRegex, utils as JsonUtils } from "@budibase/shared-core"
|
import { ValidQueryNameRegex, utils as JsonUtils } from "@budibase/shared-core"
|
||||||
|
import { findHBSBlocks } from "@budibase/string-templates"
|
||||||
|
|
||||||
const Runner = new Thread(ThreadType.QUERY, {
|
const Runner = new Thread(ThreadType.QUERY, {
|
||||||
timeoutMs: env.QUERY_THREAD_TIMEOUT,
|
timeoutMs: env.QUERY_THREAD_TIMEOUT,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
function validateQueryInputs(parameters: Record<string, string>) {
|
||||||
|
for (let entry of Object.entries(parameters)) {
|
||||||
|
const [key, value] = entry
|
||||||
|
if (typeof value !== "string") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (findHBSBlocks(value).length !== 0) {
|
||||||
|
throw new Error(
|
||||||
|
`Parameter '${key}' input contains a handlebars binding - this is not allowed.`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function fetch(ctx: UserCtx) {
|
export async function fetch(ctx: UserCtx) {
|
||||||
ctx.body = await sdk.queries.fetch()
|
ctx.body = await sdk.queries.fetch()
|
||||||
}
|
}
|
||||||
|
@ -123,10 +136,10 @@ function getAuthConfig(ctx: UserCtx) {
|
||||||
|
|
||||||
function enrichParameters(
|
function enrichParameters(
|
||||||
queryParameters: QueryParameter[],
|
queryParameters: QueryParameter[],
|
||||||
requestParameters: { [key: string]: string } = {}
|
requestParameters: Record<string, string> = {}
|
||||||
): {
|
): Record<string, string> {
|
||||||
[key: string]: string
|
// first check parameters are all valid
|
||||||
} {
|
validateQueryInputs(requestParameters)
|
||||||
// make sure parameters are fully enriched with defaults
|
// make sure parameters are fully enriched with defaults
|
||||||
for (let parameter of queryParameters) {
|
for (let parameter of queryParameters) {
|
||||||
if (!requestParameters[parameter.name]) {
|
if (!requestParameters[parameter.name]) {
|
||||||
|
|
|
@ -408,6 +408,21 @@ describe("/queries", () => {
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("shouldn't allow handlebars to be passed as parameters", async () => {
|
||||||
|
const res = await request
|
||||||
|
.post(`/api/queries/${query._id}`)
|
||||||
|
.send({
|
||||||
|
parameters: {
|
||||||
|
a: "{{ 'test' }}",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.set(config.defaultHeaders())
|
||||||
|
.expect(400)
|
||||||
|
expect(res.body.message).toEqual(
|
||||||
|
"Parameter 'a' input contains a handlebars binding - this is not allowed."
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("variables", () => {
|
describe("variables", () => {
|
||||||
|
|
|
@ -11,7 +11,7 @@ export interface PreviewQueryResponse {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ExecuteQueryRequest {
|
export interface ExecuteQueryRequest {
|
||||||
parameters?: { [key: string]: string }
|
parameters?: Record<string, string>
|
||||||
pagination?: any
|
pagination?: any
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue