budibase/packages/server/src/utilities/workerRequests.ts

203 lines
5.5 KiB
TypeScript
Raw Normal View History

2024-03-20 12:46:39 +01:00
import { Response, default as fetch, type RequestInit } from "node-fetch"
import env from "../environment"
import { checkSlashesInUrl } from "./index"
import {
db as dbCore,
constants,
tenancy,
logging,
env as coreEnv,
} from "@budibase/backend-core"
REST file handling and SMTP automation block attachments (#13403) * handle files in rest connector * fetch presigned url and return * further updates to handle files in rest connector * remove unused important and fix extension bug * wrong expiry param * tests * add const for temp bucket * handle ttl on bucket * more bucket ttl work * split out fileresponse and xmlresponse into utils * lint * remove log * fix tests * some pr comments * update function naming and lint * adding back needed response for frontend * use fsp * handle different content-disposition and potential path traversal * add test container for s3 / minio * add test case for filename* and ascii filenames * move tests into separate describe * remove log * up timeout * switch to minio image instead of localstack * use minio image instead of s3 for testing * stream file upload instead * use streamUpload and update signatures * update bucketcreate return * throw real error * tidy up * pro * pro ref fix? * pro fix * pro fix? * move minio test provider to backend-core * update email builder to allow attachments * testing for sending files via smtp * use backend-core minio test container in server * handle different types of url * fix minio test provider * test with container host * lint * try different hostname? * Revert "try different hostname?" This reverts commit cfefdb8ded2b49462604053cf140e7292771c651. * fix issue with fetching of signed url with test minio * update autoamtion attachments to take filename and url * fix tests * pro ref * fix parsing of url object * pr comments and linting * pro ref * fix pro again * fix pro * account-portal * fix null issue * fix ref * ref * When sending a file attachment in email fetch it directly from our object store * add more checks to ensure we're working with a signed url * update test to account for direct object store read * formatting * fix time issues within test * update bucket and path extraction to regex * use const in regex * pro * Updating TTL handling in upload functions (#13539) * Updating TTL handling in upload functions * describe ttl type * account for ttl creation in existing buckets and update types * fix tests * pro * pro
2024-04-22 17:30:57 +02:00
import { Ctx, User, EmailInvite, EmailAttachment } from "@budibase/types"
interface Request {
ctx?: Ctx
method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH"
headers?: { [key: string]: string }
body?: { [key: string]: any }
}
export function createRequest(request: Request): RequestInit {
const headers: Record<string, string> = {}
const requestInit: RequestInit = {
method: request.method,
}
2024-02-15 15:48:47 +01:00
const ctx = request.ctx
if (!ctx && coreEnv.INTERNAL_API_KEY) {
headers[constants.Header.API_KEY] = coreEnv.INTERNAL_API_KEY
} else if (ctx && ctx.headers) {
// copy all Budibase utilised headers over - copying everything can have
// side effects like requests being rejected due to odd content types etc
for (let header of Object.values(constants.Header)) {
2024-02-15 15:48:47 +01:00
const value = ctx.headers[header]
if (value === undefined) {
continue
}
2024-02-15 17:28:59 +01:00
headers[header] = Array.isArray(value) ? value[0] : value
}
// be specific about auth headers
const cookie = ctx.headers[constants.Header.COOKIE],
apiKey = ctx.headers[constants.Header.API_KEY]
if (cookie) {
2024-02-15 17:12:47 +01:00
headers[constants.Header.COOKIE] = cookie
} else if (apiKey) {
2024-02-15 17:28:59 +01:00
headers[constants.Header.API_KEY] = Array.isArray(apiKey)
? apiKey[0]
: apiKey
}
}
// apply tenancy if its available
if (tenancy.isTenantIdSet()) {
headers[constants.Header.TENANT_ID] = tenancy.getTenantId()
}
if (request.body && Object.keys(request.body).length > 0) {
headers["Content-Type"] = "application/json"
requestInit.body = JSON.stringify(request.body)
}
logging.correlation.setHeader(headers)
2024-02-15 17:44:19 +01:00
requestInit.headers = headers
return requestInit
}
async function checkResponse(
response: Response,
errorMsg: string,
{ ctx }: { ctx?: Ctx } = {}
) {
if (response.status >= 300) {
let responseErrorMessage
if (response.headers.get("content-type")?.includes("json")) {
const error = await response.json()
responseErrorMessage = error.message ?? JSON.stringify(error)
} else {
responseErrorMessage = await response.text()
2022-02-25 20:00:12 +01:00
}
const msg = `Unable to ${errorMsg} - ${responseErrorMessage}`
2022-02-25 20:00:12 +01:00
if (ctx) {
ctx.throw(response.status || 500, msg)
2022-02-25 20:00:12 +01:00
} else {
throw msg
}
}
return response.json()
}
// have to pass in the tenant ID as this could be coming from an automation
export async function sendSmtpEmail({
to,
from,
subject,
contents,
cc,
bcc,
automation,
invite,
REST file handling and SMTP automation block attachments (#13403) * handle files in rest connector * fetch presigned url and return * further updates to handle files in rest connector * remove unused important and fix extension bug * wrong expiry param * tests * add const for temp bucket * handle ttl on bucket * more bucket ttl work * split out fileresponse and xmlresponse into utils * lint * remove log * fix tests * some pr comments * update function naming and lint * adding back needed response for frontend * use fsp * handle different content-disposition and potential path traversal * add test container for s3 / minio * add test case for filename* and ascii filenames * move tests into separate describe * remove log * up timeout * switch to minio image instead of localstack * use minio image instead of s3 for testing * stream file upload instead * use streamUpload and update signatures * update bucketcreate return * throw real error * tidy up * pro * pro ref fix? * pro fix * pro fix? * move minio test provider to backend-core * update email builder to allow attachments * testing for sending files via smtp * use backend-core minio test container in server * handle different types of url * fix minio test provider * test with container host * lint * try different hostname? * Revert "try different hostname?" This reverts commit cfefdb8ded2b49462604053cf140e7292771c651. * fix issue with fetching of signed url with test minio * update autoamtion attachments to take filename and url * fix tests * pro ref * fix parsing of url object * pr comments and linting * pro ref * fix pro again * fix pro * account-portal * fix null issue * fix ref * ref * When sending a file attachment in email fetch it directly from our object store * add more checks to ensure we're working with a signed url * update test to account for direct object store read * formatting * fix time issues within test * update bucket and path extraction to regex * use const in regex * pro * Updating TTL handling in upload functions (#13539) * Updating TTL handling in upload functions * describe ttl type * account for ttl creation in existing buckets and update types * fix tests * pro * pro
2024-04-22 17:30:57 +02:00
attachments,
}: {
to: string
from: string
subject: string
contents: string
cc: string
bcc: string
automation: boolean
REST file handling and SMTP automation block attachments (#13403) * handle files in rest connector * fetch presigned url and return * further updates to handle files in rest connector * remove unused important and fix extension bug * wrong expiry param * tests * add const for temp bucket * handle ttl on bucket * more bucket ttl work * split out fileresponse and xmlresponse into utils * lint * remove log * fix tests * some pr comments * update function naming and lint * adding back needed response for frontend * use fsp * handle different content-disposition and potential path traversal * add test container for s3 / minio * add test case for filename* and ascii filenames * move tests into separate describe * remove log * up timeout * switch to minio image instead of localstack * use minio image instead of s3 for testing * stream file upload instead * use streamUpload and update signatures * update bucketcreate return * throw real error * tidy up * pro * pro ref fix? * pro fix * pro fix? * move minio test provider to backend-core * update email builder to allow attachments * testing for sending files via smtp * use backend-core minio test container in server * handle different types of url * fix minio test provider * test with container host * lint * try different hostname? * Revert "try different hostname?" This reverts commit cfefdb8ded2b49462604053cf140e7292771c651. * fix issue with fetching of signed url with test minio * update autoamtion attachments to take filename and url * fix tests * pro ref * fix parsing of url object * pr comments and linting * pro ref * fix pro again * fix pro * account-portal * fix null issue * fix ref * ref * When sending a file attachment in email fetch it directly from our object store * add more checks to ensure we're working with a signed url * update test to account for direct object store read * formatting * fix time issues within test * update bucket and path extraction to regex * use const in regex * pro * Updating TTL handling in upload functions (#13539) * Updating TTL handling in upload functions * describe ttl type * account for ttl creation in existing buckets and update types * fix tests * pro * pro
2024-04-22 17:30:57 +02:00
attachments?: EmailAttachment[]
invite?: EmailInvite
}) {
// tenant ID will be set in header
const response = await fetch(
checkSlashesInUrl(env.WORKER_URL + `/api/global/email/send`),
createRequest({
method: "POST",
body: {
email: to,
from,
contents,
subject,
2022-09-21 16:58:04 +02:00
cc,
bcc,
purpose: "custom",
2021-09-27 17:28:39 +02:00
automation,
invite,
REST file handling and SMTP automation block attachments (#13403) * handle files in rest connector * fetch presigned url and return * further updates to handle files in rest connector * remove unused important and fix extension bug * wrong expiry param * tests * add const for temp bucket * handle ttl on bucket * more bucket ttl work * split out fileresponse and xmlresponse into utils * lint * remove log * fix tests * some pr comments * update function naming and lint * adding back needed response for frontend * use fsp * handle different content-disposition and potential path traversal * add test container for s3 / minio * add test case for filename* and ascii filenames * move tests into separate describe * remove log * up timeout * switch to minio image instead of localstack * use minio image instead of s3 for testing * stream file upload instead * use streamUpload and update signatures * update bucketcreate return * throw real error * tidy up * pro * pro ref fix? * pro fix * pro fix? * move minio test provider to backend-core * update email builder to allow attachments * testing for sending files via smtp * use backend-core minio test container in server * handle different types of url * fix minio test provider * test with container host * lint * try different hostname? * Revert "try different hostname?" This reverts commit cfefdb8ded2b49462604053cf140e7292771c651. * fix issue with fetching of signed url with test minio * update autoamtion attachments to take filename and url * fix tests * pro ref * fix parsing of url object * pr comments and linting * pro ref * fix pro again * fix pro * account-portal * fix null issue * fix ref * ref * When sending a file attachment in email fetch it directly from our object store * add more checks to ensure we're working with a signed url * update test to account for direct object store read * formatting * fix time issues within test * update bucket and path extraction to regex * use const in regex * pro * Updating TTL handling in upload functions (#13539) * Updating TTL handling in upload functions * describe ttl type * account for ttl creation in existing buckets and update types * fix tests * pro * pro
2024-04-22 17:30:57 +02:00
attachments,
},
})
)
2022-02-25 20:00:12 +01:00
return checkResponse(response, "send email")
}
export async function removeAppFromUserRoles(ctx: Ctx, appId: string) {
const prodAppId = dbCore.getProdAppID(appId)
const response = await fetch(
checkSlashesInUrl(env.WORKER_URL + `/api/global/roles/${prodAppId}`),
createRequest({
2024-02-15 15:48:47 +01:00
ctx,
method: "DELETE",
})
)
2022-02-25 20:00:12 +01:00
return checkResponse(response, "remove app role")
}
export async function allGlobalUsers(ctx: Ctx) {
2022-02-25 20:00:12 +01:00
const response = await fetch(
checkSlashesInUrl(env.WORKER_URL + "/api/global/users"),
// we don't want to use API key when getting self
createRequest({ ctx, method: "GET" })
2022-02-25 20:00:12 +01:00
)
return checkResponse(response, "get users", { ctx })
}
export async function saveGlobalUser(ctx: Ctx) {
2022-02-25 20:00:12 +01:00
const response = await fetch(
checkSlashesInUrl(env.WORKER_URL + "/api/global/users"),
// we don't want to use API key when getting self
createRequest({ ctx, method: "POST", body: ctx.request.body })
2022-02-25 20:00:12 +01:00
)
return checkResponse(response, "save user", { ctx })
}
export async function deleteGlobalUser(ctx: Ctx) {
2022-02-25 20:00:12 +01:00
const response = await fetch(
checkSlashesInUrl(
env.WORKER_URL + `/api/global/users/${ctx.params.userId}`
),
2022-02-25 20:00:12 +01:00
// we don't want to use API key when getting self
createRequest({ ctx, method: "DELETE" })
2022-02-25 20:00:12 +01:00
)
return checkResponse(response, "delete user", { ctx })
2022-02-25 20:00:12 +01:00
}
export async function readGlobalUser(ctx: Ctx): Promise<User> {
2022-02-25 20:00:12 +01:00
const response = await fetch(
checkSlashesInUrl(
env.WORKER_URL + `/api/global/users/${ctx.params.userId}`
),
2022-02-25 20:00:12 +01:00
// we don't want to use API key when getting self
createRequest({ ctx, method: "GET" })
2022-02-25 20:00:12 +01:00
)
return checkResponse(response, "get user", { ctx })
}
export async function getChecklist(): Promise<{
adminUser: { checked: boolean }
}> {
const response = await fetch(
checkSlashesInUrl(env.WORKER_URL + "/api/global/configs/checklist"),
createRequest({ method: "GET" })
)
return checkResponse(response, "get checklist")
}
export async function generateApiKey(userId: string) {
const response = await fetch(
checkSlashesInUrl(env.WORKER_URL + "/api/global/self/api_key"),
createRequest({ method: "POST", body: { userId } })
)
return checkResponse(response, "generate API key")
}