From 6494962c1ad47e52c5046dc3fd24a752ca579952 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Tue, 3 Dec 2024 18:06:09 +0000 Subject: [PATCH 01/15] Screens and some slightly changes to Table API typing. --- packages/backend-core/src/security/roles.ts | 5 ++++- packages/server/src/api/controllers/screen.ts | 13 +++++++++---- packages/server/src/api/controllers/script.ts | 4 ---- .../server/src/api/controllers/table/index.ts | 15 +++++++++------ packages/server/src/api/routes/script.ts | 10 ---------- packages/server/src/sdk/app/tables/getters.ts | 6 ++++-- .../server/src/tests/utilities/api/table.ts | 19 +++++++++++-------- packages/types/src/api/web/app/screen.ts | 11 ++++++++++- packages/types/src/api/web/app/table.ts | 18 ++++++++---------- 9 files changed, 55 insertions(+), 46 deletions(-) delete mode 100644 packages/server/src/api/routes/script.ts diff --git a/packages/backend-core/src/security/roles.ts b/packages/backend-core/src/security/roles.ts index 4076be93a0..2c424a4900 100644 --- a/packages/backend-core/src/security/roles.ts +++ b/packages/backend-core/src/security/roles.ts @@ -592,7 +592,10 @@ export class AccessController { ) } - async checkScreensAccess(screens: Screen[], userRoleId: string) { + async checkScreensAccess( + screens: Screen[], + userRoleId: string + ): Promise { let accessibleScreens = [] // don't want to handle this with Promise.all as this would mean all custom roles would be // retrieved at same time, it is likely a custom role will be re-used and therefore want diff --git a/packages/server/src/api/controllers/screen.ts b/packages/server/src/api/controllers/screen.ts index ee8e0ff892..cccc0c4d77 100644 --- a/packages/server/src/api/controllers/screen.ts +++ b/packages/server/src/api/controllers/screen.ts @@ -10,13 +10,16 @@ import { updateAppPackage } from "./application" import { Plugin, ScreenProps, - BBContext, Screen, UserCtx, + FetchScreenResponse, + SaveScreenRequest, + SaveScreenResponse, + DeleteScreenResponse, } from "@budibase/types" import { builderSocket } from "../../websockets" -export async function fetch(ctx: BBContext) { +export async function fetch(ctx: UserCtx) { const db = context.getAppDB() const screens = ( @@ -37,7 +40,9 @@ export async function fetch(ctx: BBContext) { ) } -export async function save(ctx: UserCtx) { +export async function save( + ctx: UserCtx +) { const db = context.getAppDB() let screen = ctx.request.body @@ -107,7 +112,7 @@ export async function save(ctx: UserCtx) { builderSocket?.emitScreenUpdate(ctx, savedScreen) } -export async function destroy(ctx: BBContext) { +export async function destroy(ctx: UserCtx) { const db = context.getAppDB() const id = ctx.params.screenId const screen = await db.get(id) diff --git a/packages/server/src/api/controllers/script.ts b/packages/server/src/api/controllers/script.ts index 0565b30f74..ac6ac24fcc 100644 --- a/packages/server/src/api/controllers/script.ts +++ b/packages/server/src/api/controllers/script.ts @@ -14,7 +14,3 @@ export async function execute(ctx: Ctx) { throw err } } - -export async function save(ctx: Ctx) { - ctx.throw(501, "Not currently implemented") -} diff --git a/packages/server/src/api/controllers/table/index.ts b/packages/server/src/api/controllers/table/index.ts index 77c1f3923a..4b020290e9 100644 --- a/packages/server/src/api/controllers/table/index.ts +++ b/packages/server/src/api/controllers/table/index.ts @@ -19,17 +19,18 @@ import { EventType, FetchTablesResponse, FieldType, - MigrateRequest, - MigrateResponse, + MigrateTableRequest, + MigrateTableResponse, SaveTableRequest, SaveTableResponse, Table, - TableResponse, + FindTableResponse, TableSourceType, UserCtx, ValidateNewTableImportRequest, ValidateTableImportRequest, ValidateTableImportResponse, + DeleteTableResponse, } from "@budibase/types" import sdk from "../../../sdk" import { jsonFromCsvString } from "../../../utilities/csv" @@ -94,7 +95,7 @@ export async function fetch(ctx: UserCtx) { ctx.body = result } -export async function find(ctx: UserCtx) { +export async function find(ctx: UserCtx) { const tableId = ctx.params.tableId const table = await sdk.tables.getTable(tableId) @@ -137,7 +138,7 @@ export async function save(ctx: UserCtx) { builderSocket?.emitTableUpdate(ctx, cloneDeep(savedTable)) } -export async function destroy(ctx: UserCtx) { +export async function destroy(ctx: UserCtx) { const appId = ctx.appId const tableId = ctx.params.tableId await sdk.rowActions.deleteAll(tableId) @@ -223,7 +224,9 @@ export async function validateExistingTableImport( } } -export async function migrate(ctx: UserCtx) { +export async function migrate( + ctx: UserCtx +) { const { oldColumn, newColumn } = ctx.request.body let tableId = ctx.params.tableId as string const table = await sdk.tables.getTable(tableId) diff --git a/packages/server/src/api/routes/script.ts b/packages/server/src/api/routes/script.ts deleted file mode 100644 index 3780142ab5..0000000000 --- a/packages/server/src/api/routes/script.ts +++ /dev/null @@ -1,10 +0,0 @@ -import Router from "@koa/router" -import * as controller from "../controllers/script" -import authorized from "../../middleware/authorized" -import { permissions } from "@budibase/backend-core" - -const router: Router = new Router() - -router.post("/api/script", authorized(permissions.BUILDER), controller.save) - -export default router diff --git a/packages/server/src/sdk/app/tables/getters.ts b/packages/server/src/sdk/app/tables/getters.ts index 79091ea660..f32150c63d 100644 --- a/packages/server/src/sdk/app/tables/getters.ts +++ b/packages/server/src/sdk/app/tables/getters.ts @@ -9,7 +9,7 @@ import { Database, INTERNAL_TABLE_SOURCE_ID, Table, - TableResponse, + FindTableResponse, TableSourceType, TableViewsResponse, } from "@budibase/types" @@ -173,7 +173,9 @@ export async function getTables(tableIds: string[]): Promise { return await processTables(tables) } -export async function enrichViewSchemas(table: Table): Promise { +export async function enrichViewSchemas( + table: Table +): Promise { const views = [] for (const view of Object.values(table.views ?? [])) { if (sdk.views.isV2(view)) { diff --git a/packages/server/src/tests/utilities/api/table.ts b/packages/server/src/tests/utilities/api/table.ts index baaf890b52..86c9002c03 100644 --- a/packages/server/src/tests/utilities/api/table.ts +++ b/packages/server/src/tests/utilities/api/table.ts @@ -3,8 +3,8 @@ import { BulkImportResponse, CsvToJsonRequest, CsvToJsonResponse, - MigrateRequest, - MigrateResponse, + MigrateTableRequest, + MigrateTableResponse, SaveTableRequest, SaveTableResponse, Table, @@ -38,13 +38,16 @@ export class TableAPI extends TestAPI { migrate = async ( tableId: string, - data: MigrateRequest, + data: MigrateTableRequest, expectations?: Expectations - ): Promise => { - return await this._post(`/api/tables/${tableId}/migrate`, { - body: data, - expectations, - }) + ): Promise => { + return await this._post( + `/api/tables/${tableId}/migrate`, + { + body: data, + expectations, + } + ) } import = async ( diff --git a/packages/types/src/api/web/app/screen.ts b/packages/types/src/api/web/app/screen.ts index fc9eb63975..372d1ba2ea 100644 --- a/packages/types/src/api/web/app/screen.ts +++ b/packages/types/src/api/web/app/screen.ts @@ -1,4 +1,4 @@ -import { ScreenRoutingJson } from "../../../documents" +import { ScreenRoutingJson, Screen } from "../../../documents" export interface FetchScreenRoutingResponse { routes: ScreenRoutingJson @@ -6,3 +6,12 @@ export interface FetchScreenRoutingResponse { export interface FetchClientScreenRoutingResponse extends FetchScreenRoutingResponse {} + +export type FetchScreenResponse = Screen[] + +export interface SaveScreenRequest extends Screen {} +export interface SaveScreenResponse extends Screen {} + +export interface DeleteScreenResponse { + message: string +} diff --git a/packages/types/src/api/web/app/table.ts b/packages/types/src/api/web/app/table.ts index bb9329f6c1..f5d0d71560 100644 --- a/packages/types/src/api/web/app/table.ts +++ b/packages/types/src/api/web/app/table.ts @@ -3,33 +3,30 @@ import { ViewV2Enriched } from "../../../sdk" export type TableViewsResponse = { [key: string]: View | ViewV2Enriched } -export interface TableResponse extends Table { +export interface FindTableResponse extends Table { views?: TableViewsResponse } -export type FetchTablesResponse = TableResponse[] +export type FetchTablesResponse = FindTableResponse[] export interface SaveTableRequest extends TableRequest { rows?: Row[] } - export type SaveTableResponse = Table export interface BulkImportRequest { rows: Row[] identifierFields?: Array } - export interface BulkImportResponse { message: string } -export interface MigrateRequest { +export interface MigrateTableRequest { oldColumn: string newColumn: string } - -export interface MigrateResponse { +export interface MigrateTableResponse { message: string } @@ -37,12 +34,10 @@ export interface ValidateNewTableImportRequest { rows: Row[] schema: TableSchema } - export interface ValidateTableImportRequest { tableId?: string rows: Row[] } - export interface ValidateTableImportResponse { schemaValidation: { [field: string]: boolean @@ -55,5 +50,8 @@ export interface ValidateTableImportResponse { export interface CsvToJsonRequest { csvString: string } - export type CsvToJsonResponse = any[] + +export interface DeleteTableResponse { + message: string +} From fdb328aaa1ddf28a76261a3a0c1cf87856d7f45b Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Wed, 4 Dec 2024 14:27:09 +0000 Subject: [PATCH 02/15] Moving some types around - make sure app types are all correctly filed away. --- .../server/src/api/controllers/templates.ts | 12 +++- .../src/api/web/{ => app}/application.ts | 4 +- packages/types/src/api/web/app/automation.ts | 56 ++++++++++++++++++ .../types/src/api/web/{ => app}/deployment.ts | 2 +- packages/types/src/api/web/app/index.ts | 4 ++ .../types/src/api/web/{ => app}/layout.ts | 2 +- packages/types/src/api/web/{ => app}/role.ts | 4 +- packages/types/src/api/web/automation.ts | 58 ------------------- packages/types/src/api/web/index.ts | 6 +- packages/types/src/api/web/template.ts | 5 ++ 10 files changed, 81 insertions(+), 72 deletions(-) rename packages/types/src/api/web/{ => app}/application.ts (93%) rename packages/types/src/api/web/{ => app}/deployment.ts (78%) rename packages/types/src/api/web/{ => app}/layout.ts (79%) rename packages/types/src/api/web/{ => app}/role.ts (79%) delete mode 100644 packages/types/src/api/web/automation.ts create mode 100644 packages/types/src/api/web/template.ts diff --git a/packages/server/src/api/controllers/templates.ts b/packages/server/src/api/controllers/templates.ts index 6774fa2766..8008b63fd3 100644 --- a/packages/server/src/api/controllers/templates.ts +++ b/packages/server/src/api/controllers/templates.ts @@ -1,13 +1,17 @@ import nodeFetch from "node-fetch" import { downloadTemplate as dlTemplate } from "../../utilities/fileSystem" import env from "../../environment" -import { BBContext } from "@budibase/types" +import { + DownloadTemplateResponse, + FetchTemplateResponse, + UserCtx, +} from "@budibase/types" // development flag, can be used to test against templates exported locally const DEFAULT_TEMPLATES_BUCKET = "prod-budi-templates.s3-eu-west-1.amazonaws.com" -export async function fetch(ctx: BBContext) { +export async function fetch(ctx: UserCtx) { let type = env.TEMPLATE_REPOSITORY let response, error = false @@ -32,7 +36,9 @@ export async function fetch(ctx: BBContext) { // can't currently test this, have to ignore from coverage /* istanbul ignore next */ -export async function downloadTemplate(ctx: BBContext) { +export async function downloadTemplate( + ctx: UserCtx +) { const { type, name } = ctx.params await dlTemplate(type, name) diff --git a/packages/types/src/api/web/application.ts b/packages/types/src/api/web/app/application.ts similarity index 93% rename from packages/types/src/api/web/application.ts rename to packages/types/src/api/web/app/application.ts index ed999ee574..bc00ade217 100644 --- a/packages/types/src/api/web/application.ts +++ b/packages/types/src/api/web/app/application.ts @@ -1,5 +1,5 @@ -import type { PlanType } from "../../sdk" -import type { Layout, App, Screen } from "../../documents" +import type { PlanType } from "../../../sdk" +import type { Layout, App, Screen } from "../../../documents" import { ReadStream } from "fs" export interface SyncAppResponse { diff --git a/packages/types/src/api/web/app/automation.ts b/packages/types/src/api/web/app/automation.ts index c10f19c88d..40f69fc467 100644 --- a/packages/types/src/api/web/app/automation.ts +++ b/packages/types/src/api/web/app/automation.ts @@ -1,9 +1,14 @@ import { + Automation, AutomationActionStepId, + AutomationLogPage, + AutomationStatus, AutomationStepDefinition, AutomationTriggerDefinition, AutomationTriggerStepId, + Row, } from "../../../documents" +import { DocumentDestroyResponse } from "@budibase/nano" export type GetAutomationTriggerDefinitionsResponse = Record< keyof typeof AutomationTriggerStepId, @@ -19,3 +24,54 @@ export interface GetAutomationStepDefinitionsResponse { trigger: GetAutomationTriggerDefinitionsResponse action: GetAutomationActionDefinitionsResponse } + +export interface DeleteAutomationResponse extends DocumentDestroyResponse {} + +export interface FetchAutomationResponse { + automations: Automation[] +} + +export interface FindAutomationResponse extends Automation {} + +export interface UpdateAutomationRequest extends Automation {} +export interface UpdateAutomationResponse { + message: string + automation: Automation +} + +export interface CreateAutomationRequest extends Automation {} +export interface CreateAutomationResponse { + message: string + automation: Automation +} + +export interface SearchAutomationLogsRequest { + startDate?: string + status?: AutomationStatus + automationId?: string + page?: string +} +export interface SearchAutomationLogsResponse extends AutomationLogPage {} + +export interface ClearAutomationLogRequest { + automationId: string + appId: string +} +export interface ClearAutomationLogResponse { + message: string +} + +export interface TriggerAutomationRequest { + fields: Record + // time in seconds + timeout: number +} +export type TriggerAutomationResponse = Record | undefined + +export interface TestAutomationRequest { + id?: string + revision?: string + fields: Record + row?: Row +} +export interface TestAutomationResponse {} diff --git a/packages/types/src/api/web/deployment.ts b/packages/types/src/api/web/app/deployment.ts similarity index 78% rename from packages/types/src/api/web/deployment.ts rename to packages/types/src/api/web/app/deployment.ts index f5ed9242b1..eed3f6eb77 100644 --- a/packages/types/src/api/web/deployment.ts +++ b/packages/types/src/api/web/app/deployment.ts @@ -1,4 +1,4 @@ -import { DeploymentDoc, DeploymentStatus } from "../../documents" +import { DeploymentDoc, DeploymentStatus } from "../../../documents" export interface PublishAppResponse extends DeploymentDoc {} diff --git a/packages/types/src/api/web/app/index.ts b/packages/types/src/api/web/app/index.ts index d130d19a42..90dfd7833e 100644 --- a/packages/types/src/api/web/app/index.ts +++ b/packages/types/src/api/web/app/index.ts @@ -13,3 +13,7 @@ export * from "./integration" export * from "./metadata" export * from "./query" export * from "./screen" +export * from "./application" +export * from "./layout" +export * from "./deployment" +export * from "./role" diff --git a/packages/types/src/api/web/layout.ts b/packages/types/src/api/web/app/layout.ts similarity index 79% rename from packages/types/src/api/web/layout.ts rename to packages/types/src/api/web/app/layout.ts index 45f7fb9d0a..3067a1f49f 100644 --- a/packages/types/src/api/web/layout.ts +++ b/packages/types/src/api/web/app/layout.ts @@ -1,4 +1,4 @@ -import { Layout } from "../../documents" +import { Layout } from "../../../documents" export interface SaveLayoutRequest extends Layout {} diff --git a/packages/types/src/api/web/role.ts b/packages/types/src/api/web/app/role.ts similarity index 79% rename from packages/types/src/api/web/role.ts rename to packages/types/src/api/web/app/role.ts index eeedaea163..f23b2fd232 100644 --- a/packages/types/src/api/web/role.ts +++ b/packages/types/src/api/web/app/role.ts @@ -1,5 +1,5 @@ -import { Role, RoleUIMetadata } from "../../documents" -import { PermissionLevel, BuiltinPermissionID } from "../../sdk" +import { Role, RoleUIMetadata } from "../../../documents" +import { PermissionLevel, BuiltinPermissionID } from "../../../sdk" export interface SaveRoleRequest { _id?: string diff --git a/packages/types/src/api/web/automation.ts b/packages/types/src/api/web/automation.ts deleted file mode 100644 index 0f0699939e..0000000000 --- a/packages/types/src/api/web/automation.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { DocumentDestroyResponse } from "@budibase/nano" -import { - Automation, - AutomationLogPage, - AutomationStatus, - Row, -} from "../../documents" - -export interface DeleteAutomationResponse extends DocumentDestroyResponse {} - -export interface FetchAutomationResponse { - automations: Automation[] -} - -export interface FindAutomationResponse extends Automation {} - -export interface UpdateAutomationRequest extends Automation {} -export interface UpdateAutomationResponse { - message: string - automation: Automation -} - -export interface CreateAutomationRequest extends Automation {} -export interface CreateAutomationResponse { - message: string - automation: Automation -} - -export interface SearchAutomationLogsRequest { - startDate?: string - status?: AutomationStatus - automationId?: string - page?: string -} -export interface SearchAutomationLogsResponse extends AutomationLogPage {} - -export interface ClearAutomationLogRequest { - automationId: string - appId: string -} -export interface ClearAutomationLogResponse { - message: string -} - -export interface TriggerAutomationRequest { - fields: Record - // time in seconds - timeout: number -} -export type TriggerAutomationResponse = Record | undefined - -export interface TestAutomationRequest { - id?: string - revision?: string - fields: Record - row?: Row -} -export interface TestAutomationResponse {} diff --git a/packages/types/src/api/web/index.ts b/packages/types/src/api/web/index.ts index dd2ee3beae..9fcfb77f4f 100644 --- a/packages/types/src/api/web/index.ts +++ b/packages/types/src/api/web/index.ts @@ -1,4 +1,3 @@ -export * from "./application" export * from "./analytics" export * from "./auth" export * from "./user" @@ -11,10 +10,7 @@ export * from "./global" export * from "./pagination" export * from "./searchFilter" export * from "./cookies" -export * from "./automation" -export * from "./layout" -export * from "./role" export * from "./plugins" export * from "./apikeys" -export * from "./deployment" export * from "./dev" +export * from "./template" diff --git a/packages/types/src/api/web/template.ts b/packages/types/src/api/web/template.ts new file mode 100644 index 0000000000..bd5fdf1cb0 --- /dev/null +++ b/packages/types/src/api/web/template.ts @@ -0,0 +1,5 @@ +export interface FetchTemplateResponse {} + +export interface DownloadTemplateResponse { + message: string +} From 29d912e24eac78f5c20a7f98f81ac6aee930339c Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Wed, 4 Dec 2024 14:32:27 +0000 Subject: [PATCH 03/15] Template API typing. --- packages/types/src/api/web/template.ts | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/packages/types/src/api/web/template.ts b/packages/types/src/api/web/template.ts index bd5fdf1cb0..34b846b7ef 100644 --- a/packages/types/src/api/web/template.ts +++ b/packages/types/src/api/web/template.ts @@ -1,4 +1,20 @@ -export interface FetchTemplateResponse {} +export enum TemplateType { + APP = "app", +} + +export interface Template { + background: string + icon: string + category: string + description: string + name: string + url: string + type: TemplateType + key: string + image: string +} + +export type FetchTemplateResponse = Template[] export interface DownloadTemplateResponse { message: string From a7a2a56044717eaeb054ca767639269ad4c20c05 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Wed, 4 Dec 2024 15:00:05 +0000 Subject: [PATCH 04/15] User metadata API typing. --- packages/server/src/api/controllers/user.ts | 23 ++++++++++++++------- packages/types/src/api/web/app/user.ts | 20 ++++++++++++++++-- 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/packages/server/src/api/controllers/user.ts b/packages/server/src/api/controllers/user.ts index 108e29fd3d..d8ce37edb4 100644 --- a/packages/server/src/api/controllers/user.ts +++ b/packages/server/src/api/controllers/user.ts @@ -7,19 +7,24 @@ import { FetchUserMetadataResponse, FindUserMetadataResponse, Flags, - SetFlagRequest, + SetUserFlagRequest, + UpdateSelfMetadataRequest, + UpdateSelfMetadataResponse, + UpdateUserMetadataResponse, + UpdateUserMetadataRequest, UserCtx, - UserMetadata, + DeleteUserMetadataResponse, + SetUserFlagResponse, + GetUserFlagsResponse, } from "@budibase/types" import sdk from "../../sdk" -import { DocumentInsertResponse } from "@budibase/nano" export async function fetchMetadata(ctx: Ctx) { ctx.body = await sdk.users.fetchMetadata() } export async function updateSelfMetadata( - ctx: UserCtx + ctx: UserCtx ) { // overwrite the ID with current users ctx.request.body._id = ctx.user?._id @@ -31,7 +36,7 @@ export async function updateSelfMetadata( } export async function updateMetadata( - ctx: UserCtx + ctx: UserCtx ) { const db = context.getAppDB() const user = ctx.request.body @@ -44,7 +49,9 @@ export async function updateMetadata( ctx.body = await db.put(metadata) } -export async function destroyMetadata(ctx: UserCtx) { +export async function destroyMetadata( + ctx: UserCtx +) { const db = context.getAppDB() try { const dbUser = await sdk.users.get(ctx.params.id) @@ -64,7 +71,7 @@ export async function findMetadata( } export async function setFlag( - ctx: UserCtx + ctx: UserCtx ) { const userId = ctx.user?._id const { flag, value } = ctx.request.body @@ -84,7 +91,7 @@ export async function setFlag( ctx.body = { message: "Flag set successfully" } } -export async function getFlags(ctx: UserCtx) { +export async function getFlags(ctx: UserCtx) { const userId = ctx.user?._id const docId = generateUserFlagID(userId!) const db = context.getAppDB() diff --git a/packages/types/src/api/web/app/user.ts b/packages/types/src/api/web/app/user.ts index f5f2049724..ebdc43ea27 100644 --- a/packages/types/src/api/web/app/user.ts +++ b/packages/types/src/api/web/app/user.ts @@ -1,11 +1,27 @@ -import { ContextUserMetadata } from "../../../" +import { ContextUserMetadata, Flags, UserMetadata } from "../../../" +import { DocumentInsertResponse } from "@budibase/nano" export type FetchUserMetadataResponse = ContextUserMetadata[] export type FindUserMetadataResponse = ContextUserMetadata -export interface SetFlagRequest { +export interface SetUserFlagRequest { flag: string value: any } +export interface SetUserFlagResponse { + message: string +} + +export interface GetUserFlagsResponse extends Flags {} export type AppSelfResponse = ContextUserMetadata | {} + +export interface UpdateSelfMetadataRequest extends UserMetadata {} +export interface UpdateSelfMetadataResponse extends DocumentInsertResponse {} + +export interface UpdateUserMetadataRequest extends UserMetadata {} +export interface UpdateUserMetadataResponse extends DocumentInsertResponse {} + +export interface DeleteUserMetadataResponse { + message: string +} From aa2d6779cde3622ca3089e0b8787fad907ba139f Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Wed, 4 Dec 2024 15:02:16 +0000 Subject: [PATCH 05/15] Small view API typing update. --- packages/server/src/api/controllers/view/viewsV2.ts | 10 ++++++---- packages/types/src/api/web/app/view.ts | 2 ++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/server/src/api/controllers/view/viewsV2.ts b/packages/server/src/api/controllers/view/viewsV2.ts index 986764a697..c99b79d8fa 100644 --- a/packages/server/src/api/controllers/view/viewsV2.ts +++ b/packages/server/src/api/controllers/view/viewsV2.ts @@ -4,7 +4,6 @@ import { Ctx, RequiredKeys, UpdateViewRequest, - ViewResponse, ViewResponseEnriched, ViewV2, BasicViewFieldMetadata, @@ -15,6 +14,9 @@ import { ViewFetchResponseEnriched, CountDistinctCalculationFieldMetadata, CountCalculationFieldMetadata, + CreateViewResponse, + UpdateViewResponse, + DeleteViewResponse, } from "@budibase/types" import { builderSocket, gridSocket } from "../../../websockets" import { helpers } from "@budibase/shared-core" @@ -132,7 +134,7 @@ export async function fetch(ctx: Ctx) { } } -export async function create(ctx: Ctx) { +export async function create(ctx: Ctx) { const view = ctx.request.body const { tableId } = view @@ -159,7 +161,7 @@ export async function create(ctx: Ctx) { gridSocket?.emitViewUpdate(ctx, result) } -export async function update(ctx: Ctx) { +export async function update(ctx: Ctx) { const view = ctx.request.body if (view.version !== 2) { @@ -196,7 +198,7 @@ export async function update(ctx: Ctx) { gridSocket?.emitViewUpdate(ctx, result) } -export async function remove(ctx: Ctx) { +export async function remove(ctx: Ctx) { const { viewId } = ctx.params const view = await sdk.views.remove(viewId) diff --git a/packages/types/src/api/web/app/view.ts b/packages/types/src/api/web/app/view.ts index 2560f7507f..8ce7d5ca9e 100644 --- a/packages/types/src/api/web/app/view.ts +++ b/packages/types/src/api/web/app/view.ts @@ -14,5 +14,7 @@ export interface ViewFetchResponseEnriched { } export interface CreateViewRequest extends Omit {} +export interface CreateViewResponse extends ViewResponse {} export interface UpdateViewRequest extends ViewV2 {} +export interface UpdateViewResponse extends ViewResponse {} From bd27d1755f96b4443490594f5645f4c59f0fc63c Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Wed, 4 Dec 2024 16:14:54 +0000 Subject: [PATCH 06/15] Webhook API typing. --- .../server/src/api/controllers/webhook.ts | 122 ++++++++++-------- packages/types/src/api/web/app/index.ts | 1 + packages/types/src/api/web/app/webhook.ts | 21 +++ 3 files changed, 91 insertions(+), 53 deletions(-) create mode 100644 packages/types/src/api/web/app/webhook.ts diff --git a/packages/server/src/api/controllers/webhook.ts b/packages/server/src/api/controllers/webhook.ts index 7c648ea827..543ab80e59 100644 --- a/packages/server/src/api/controllers/webhook.ts +++ b/packages/server/src/api/controllers/webhook.ts @@ -4,9 +4,17 @@ import { db as dbCore, context } from "@budibase/backend-core" import { Webhook, WebhookActionType, - BBContext, + Ctx, Automation, AutomationActionStepId, + FetchWebhooksResponse, + SaveWebhookResponse, + SaveWebhookRequest, + DeleteWebhookResponse, + BuildWebhookSchemaRequest, + BuildWebhookSchemaResponse, + TriggerWebhookRequest, + TriggerWebhookResponse, } from "@budibase/types" import sdk from "../../sdk" import * as pro from "@budibase/pro" @@ -16,17 +24,17 @@ const validate = require("jsonschema").validate const AUTOMATION_DESCRIPTION = "Generated from Webhook Schema" -export async function fetch(ctx: BBContext) { +export async function fetch(ctx: Ctx) { const db = context.getAppDB() - const response = await db.allDocs( + const response = await db.allDocs( getWebhookParams(null, { include_docs: true, }) ) - ctx.body = response.rows.map((row: any) => row.doc) + ctx.body = response.rows.filter(row => row.doc).map(row => row.doc!) } -export async function save(ctx: BBContext) { +export async function save(ctx: Ctx) { const webhook = await sdk.automations.webhook.save(ctx.request.body) ctx.body = { message: "Webhook created successfully", @@ -34,21 +42,23 @@ export async function save(ctx: BBContext) { } } -export async function destroy(ctx: BBContext) { +export async function destroy(ctx: Ctx) { ctx.body = await sdk.automations.webhook.destroy( ctx.params.id, ctx.params.rev ) } -export async function buildSchema(ctx: BBContext) { +export async function buildSchema( + ctx: Ctx +) { await context.doInAppContext(ctx.params.instance, async () => { const db = context.getAppDB() - const webhook = (await db.get(ctx.params.id)) as Webhook + const webhook = await db.get(ctx.params.id) webhook.bodySchema = toJsonSchema(ctx.request.body) // update the automation outputs if (webhook.action.type === WebhookActionType.AUTOMATION) { - let automation = (await db.get(webhook.action.target)) as Automation + let automation = await db.get(webhook.action.target) const autoOutputs = automation.definition.trigger.schema.outputs let properties = webhook.bodySchema.properties // reset webhook outputs @@ -67,60 +77,66 @@ export async function buildSchema(ctx: BBContext) { }) } -export async function trigger(ctx: BBContext) { +export async function trigger( + ctx: Ctx +) { const prodAppId = dbCore.getProdAppID(ctx.params.instance) + const appNotDeployed = () => { + ctx.body = { + message: "Application not deployed yet.", + } + } await context.doInAppContext(prodAppId, async () => { - try { - const db = context.getAppDB() - const webhook = (await db.get(ctx.params.id)) as Webhook - // validate against the schema - if (webhook.bodySchema) { - validate(ctx.request.body, webhook.bodySchema) - } - const target = await db.get(webhook.action.target) - if (webhook.action.type === WebhookActionType.AUTOMATION) { - // trigger with both the pure request and then expand it - // incase the user has produced a schema to bind to - let hasCollectStep = sdk.automations.utils.checkForCollectStep(target) + const db = context.getAppDB() + const webhook = await db.tryGet(ctx.params.id) + if (!webhook) { + return appNotDeployed() + } + // validate against the schema + if (webhook.bodySchema) { + validate(ctx.request.body, webhook.bodySchema) + } + const target = await db.tryGet(webhook.action.target) + if (!target) { + return appNotDeployed() + } + if (webhook.action.type === WebhookActionType.AUTOMATION) { + // trigger with both the pure request and then expand it + // incase the user has produced a schema to bind to + let hasCollectStep = sdk.automations.utils.checkForCollectStep(target) - if (hasCollectStep && (await pro.features.isSyncAutomationsEnabled())) { - const response = await triggers.externalTrigger( - target, - { - body: ctx.request.body, + if (hasCollectStep && (await pro.features.isSyncAutomationsEnabled())) { + const response = await triggers.externalTrigger( + target, + { + fields: { ...ctx.request.body, - appId: prodAppId, + body: ctx.request.body, }, - { getResponses: true } + appId: prodAppId, + }, + { getResponses: true } + ) + + if (triggers.isAutomationResults(response)) { + let collectedValue = response.steps.find( + (step: any) => step.stepId === AutomationActionStepId.COLLECT ) - if (triggers.isAutomationResults(response)) { - let collectedValue = response.steps.find( - (step: any) => step.stepId === AutomationActionStepId.COLLECT - ) - - ctx.status = 200 - ctx.body = collectedValue?.outputs - } else { - ctx.throw(400, "Automation did not have a collect block.") - } + ctx.body = collectedValue?.outputs } else { - await triggers.externalTrigger(target, { - body: ctx.request.body, - ...ctx.request.body, - appId: prodAppId, - }) - ctx.status = 200 - ctx.body = { - message: "Webhook trigger fired successfully", - } + ctx.throw(400, "Automation did not have a collect block.") } - } - } catch (err: any) { - if (err.status === 404) { - ctx.status = 200 + } else { + await triggers.externalTrigger(target, { + fields: { + ...ctx.request.body, + body: ctx.request.body, + }, + appId: prodAppId, + }) ctx.body = { - message: "Application not deployed yet.", + message: "Webhook trigger fired successfully", } } } diff --git a/packages/types/src/api/web/app/index.ts b/packages/types/src/api/web/app/index.ts index 90dfd7833e..49d888d629 100644 --- a/packages/types/src/api/web/app/index.ts +++ b/packages/types/src/api/web/app/index.ts @@ -17,3 +17,4 @@ export * from "./application" export * from "./layout" export * from "./deployment" export * from "./role" +export * from "./webhook" diff --git a/packages/types/src/api/web/app/webhook.ts b/packages/types/src/api/web/app/webhook.ts new file mode 100644 index 0000000000..a75b6a1515 --- /dev/null +++ b/packages/types/src/api/web/app/webhook.ts @@ -0,0 +1,21 @@ +import { Webhook } from "../../../documents" +import { DocumentDestroyResponse, DocumentInsertResponse } from "@budibase/nano" + +export type FetchWebhooksResponse = Webhook[] + +export interface SaveWebhookRequest extends Webhook {} +export interface SaveWebhookResponse { + message: string + webhook: Webhook +} + +export interface DeleteWebhookResponse extends DocumentDestroyResponse {} + +export interface BuildWebhookSchemaRequest extends Record {} +export interface BuildWebhookSchemaResponse extends DocumentInsertResponse {} + +export interface TriggerWebhookRequest {} +export type TriggerWebhookResponse = + | Record + | { message: string } + | undefined From ecf4ea58266945da3ab5da3ec1a03f0cb5ed0a81 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Wed, 4 Dec 2024 16:45:56 +0000 Subject: [PATCH 07/15] Static API typing. --- .../src/api/controllers/static/index.ts | 28 ++++++++++++++----- packages/types/src/api/web/app/index.ts | 1 + packages/types/src/api/web/app/static.ts | 25 +++++++++++++++++ 3 files changed, 47 insertions(+), 7 deletions(-) create mode 100644 packages/types/src/api/web/app/static.ts diff --git a/packages/server/src/api/controllers/static/index.ts b/packages/server/src/api/controllers/static/index.ts index 1bf04e94f0..0dd5e77c50 100644 --- a/packages/server/src/api/controllers/static/index.ts +++ b/packages/server/src/api/controllers/static/index.ts @@ -27,7 +27,13 @@ import { Ctx, DocumentType, Feature, + GetSignedUploadUrlRequest, + GetSignedUploadUrlResponse, ProcessAttachmentResponse, + ServeAppResponse, + ServeBuilderPreviewResponse, + ServeClientLibraryResponse, + ToggleBetaFeatureResponse, UserCtx, } from "@budibase/types" import { @@ -38,7 +44,9 @@ import { import send from "koa-send" import { getThemeVariables } from "../../../constants/themes" -export const toggleBetaUiFeature = async function (ctx: Ctx) { +export const toggleBetaUiFeature = async function ( + ctx: Ctx +) { const cookieName = `beta:${ctx.params.feature}` if (ctx.cookies.get(cookieName)) { @@ -66,13 +74,13 @@ export const toggleBetaUiFeature = async function (ctx: Ctx) { } } -export const serveBuilder = async function (ctx: Ctx) { +export const serveBuilder = async function (ctx: Ctx) { const builderPath = join(TOP_LEVEL_PATH, "builder") await send(ctx, ctx.file, { root: builderPath }) } export const uploadFile = async function ( - ctx: Ctx<{}, ProcessAttachmentResponse> + ctx: Ctx ) { const file = ctx.request?.files?.file if (!file) { @@ -144,7 +152,7 @@ const requiresMigration = async (ctx: Ctx) => { return latestMigrationApplied !== latestMigration } -export const serveApp = async function (ctx: UserCtx) { +export const serveApp = async function (ctx: UserCtx) { if (ctx.url.includes("apple-touch-icon.png")) { ctx.redirect("/builder/bblogo.png") return @@ -249,7 +257,9 @@ export const serveApp = async function (ctx: UserCtx) { } } -export const serveBuilderPreview = async function (ctx: Ctx) { +export const serveBuilderPreview = async function ( + ctx: Ctx +) { const db = context.getAppDB({ skip_setup: true }) const appInfo = await db.get(DocumentType.APP_METADATA) @@ -268,7 +278,9 @@ export const serveBuilderPreview = async function (ctx: Ctx) { } } -export const serveClientLibrary = async function (ctx: Ctx) { +export const serveClientLibrary = async function ( + ctx: Ctx +) { const version = ctx.request.query.version if (Array.isArray(version)) { @@ -297,7 +309,9 @@ export const serveClientLibrary = async function (ctx: Ctx) { } } -export const getSignedUploadURL = async function (ctx: Ctx) { +export const getSignedUploadURL = async function ( + ctx: Ctx +) { // Ensure datasource is valid let datasource try { diff --git a/packages/types/src/api/web/app/index.ts b/packages/types/src/api/web/app/index.ts index 49d888d629..e2f8532dfe 100644 --- a/packages/types/src/api/web/app/index.ts +++ b/packages/types/src/api/web/app/index.ts @@ -18,3 +18,4 @@ export * from "./layout" export * from "./deployment" export * from "./role" export * from "./webhook" +export * from "./static" diff --git a/packages/types/src/api/web/app/static.ts b/packages/types/src/api/web/app/static.ts new file mode 100644 index 0000000000..bcd901d1e1 --- /dev/null +++ b/packages/types/src/api/web/app/static.ts @@ -0,0 +1,25 @@ +import { App } from "../../../documents" +import stream from "node:stream" + +export interface ToggleBetaFeatureResponse { + message: string +} + +export type ServeAppResponse = string + +interface BuilderPreview extends App { + builderPreview: boolean +} + +export type ServeBuilderPreviewResponse = BuilderPreview | string + +export type ServeClientLibraryResponse = stream.Readable + +export interface GetSignedUploadUrlRequest { + bucket: string + key: string +} +export interface GetSignedUploadUrlResponse { + signedUrl?: string + publicUrl?: string +} From cb49beb317309daf7ce97002ad70eb1203a396a1 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Wed, 4 Dec 2024 16:51:56 +0000 Subject: [PATCH 08/15] Replacing BBContext where its still used in backend-core and middlewares. --- packages/backend-core/src/middleware/auditLog.ts | 4 ++-- packages/backend-core/src/middleware/csrf.ts | 4 ++-- packages/backend-core/src/middleware/internalApi.ts | 4 ++-- packages/backend-core/src/middleware/matchers.ts | 4 ++-- packages/backend-core/src/middleware/passport/local.ts | 4 ++-- packages/backend-core/src/middleware/tenancy.ts | 4 ++-- packages/backend-core/src/tenancy/tenancy.ts | 4 ++-- packages/backend-core/src/utils/tests/utils.spec.ts | 8 ++++---- .../backend-core/tests/core/utilities/structures/koa.ts | 6 +++--- packages/server/src/middleware/appInfo.ts | 4 ++-- packages/server/src/middleware/joi-validator.ts | 4 ++-- packages/server/src/middleware/resourceId.ts | 4 ++-- packages/server/src/middleware/selfhost.ts | 4 ++-- packages/types/src/sdk/auth.ts | 4 ++-- 14 files changed, 31 insertions(+), 31 deletions(-) diff --git a/packages/backend-core/src/middleware/auditLog.ts b/packages/backend-core/src/middleware/auditLog.ts index 9b76bb10b7..2febbf879c 100644 --- a/packages/backend-core/src/middleware/auditLog.ts +++ b/packages/backend-core/src/middleware/auditLog.ts @@ -1,6 +1,6 @@ -import { BBContext } from "@budibase/types" +import { Ctx } from "@budibase/types" -export default async (ctx: BBContext | any, next: any) => { +export default async (ctx: Ctx, next: any) => { // Placeholder for audit log middleware return next() } diff --git a/packages/backend-core/src/middleware/csrf.ts b/packages/backend-core/src/middleware/csrf.ts index cced4d5f7d..e20841cca0 100644 --- a/packages/backend-core/src/middleware/csrf.ts +++ b/packages/backend-core/src/middleware/csrf.ts @@ -1,6 +1,6 @@ import { Header } from "../constants" import { buildMatcherRegex, matches } from "./matchers" -import { BBContext, EndpointMatcher } from "@budibase/types" +import { Ctx, EndpointMatcher } from "@budibase/types" /** * GET, HEAD and OPTIONS methods are considered safe operations @@ -36,7 +36,7 @@ export default function ( opts: { noCsrfPatterns: EndpointMatcher[] } = { noCsrfPatterns: [] } ) { const noCsrfOptions = buildMatcherRegex(opts.noCsrfPatterns) - return async (ctx: BBContext | any, next: any) => { + return async (ctx: Ctx, next: any) => { // don't apply for excluded paths const found = matches(ctx, noCsrfOptions) if (found) { diff --git a/packages/backend-core/src/middleware/internalApi.ts b/packages/backend-core/src/middleware/internalApi.ts index dc73cd6b66..b240738aee 100644 --- a/packages/backend-core/src/middleware/internalApi.ts +++ b/packages/backend-core/src/middleware/internalApi.ts @@ -1,11 +1,11 @@ import { Header } from "../constants" -import { BBContext } from "@budibase/types" +import { Ctx } from "@budibase/types" import { isValidInternalAPIKey } from "../utils" /** * API Key only endpoint. */ -export default async (ctx: BBContext, next: any) => { +export default async (ctx: Ctx, next: any) => { const apiKey = ctx.request.headers[Header.API_KEY] if (!apiKey) { ctx.throw(403, "Unauthorized") diff --git a/packages/backend-core/src/middleware/matchers.ts b/packages/backend-core/src/middleware/matchers.ts index 757d93a60d..8ed0b4d608 100644 --- a/packages/backend-core/src/middleware/matchers.ts +++ b/packages/backend-core/src/middleware/matchers.ts @@ -1,4 +1,4 @@ -import { BBContext, EndpointMatcher, RegexMatcher } from "@budibase/types" +import { Ctx, EndpointMatcher, RegexMatcher } from "@budibase/types" const PARAM_REGEX = /\/:(.*?)(\/.*)?$/g @@ -27,7 +27,7 @@ export const buildMatcherRegex = ( }) } -export const matches = (ctx: BBContext, options: RegexMatcher[]) => { +export const matches = (ctx: Ctx, options: RegexMatcher[]) => { return options.find(({ regex, method }) => { const urlMatch = regex.test(ctx.request.url) const methodMatch = diff --git a/packages/backend-core/src/middleware/passport/local.ts b/packages/backend-core/src/middleware/passport/local.ts index f1d72cab7a..40e6d294c1 100644 --- a/packages/backend-core/src/middleware/passport/local.ts +++ b/packages/backend-core/src/middleware/passport/local.ts @@ -2,7 +2,7 @@ import { UserStatus } from "../../constants" import { compare } from "../../utils" import * as users from "../../users" import { authError } from "./utils" -import { BBContext } from "@budibase/types" +import { Ctx } from "@budibase/types" const INVALID_ERR = "Invalid credentials" const EXPIRED = "This account has expired. Please reset your password" @@ -20,7 +20,7 @@ export const options = { * @returns The authenticated user, or errors if they occur */ export async function authenticate( - ctx: BBContext, + ctx: Ctx, email: string, password: string, done: Function diff --git a/packages/backend-core/src/middleware/tenancy.ts b/packages/backend-core/src/middleware/tenancy.ts index 22b7cc213d..e0c1be2a03 100644 --- a/packages/backend-core/src/middleware/tenancy.ts +++ b/packages/backend-core/src/middleware/tenancy.ts @@ -3,7 +3,7 @@ import { getTenantIDFromCtx } from "../tenancy" import { buildMatcherRegex, matches } from "./matchers" import { Header } from "../constants" import { - BBContext, + Ctx, EndpointMatcher, GetTenantIdOptions, TenantResolutionStrategy, @@ -17,7 +17,7 @@ export default function ( const allowQsOptions = buildMatcherRegex(allowQueryStringPatterns) const noTenancyOptions = buildMatcherRegex(noTenancyPatterns) - return async function (ctx: BBContext | any, next: any) { + return async function (ctx: Ctx, next: any) { const allowNoTenant = opts.noTenancyRequired || !!matches(ctx, noTenancyOptions) const tenantOpts: GetTenantIdOptions = { diff --git a/packages/backend-core/src/tenancy/tenancy.ts b/packages/backend-core/src/tenancy/tenancy.ts index 8835960ca5..6096b45800 100644 --- a/packages/backend-core/src/tenancy/tenancy.ts +++ b/packages/backend-core/src/tenancy/tenancy.ts @@ -6,7 +6,7 @@ import { getPlatformURL, } from "../context" import { - BBContext, + Ctx, TenantResolutionStrategy, GetTenantIdOptions, } from "@budibase/types" @@ -37,7 +37,7 @@ export const isUserInAppTenant = (appId: string, user?: any) => { const ALL_STRATEGIES = Object.values(TenantResolutionStrategy) export const getTenantIDFromCtx = ( - ctx: BBContext, + ctx: Ctx, opts: GetTenantIdOptions ): string | undefined => { // exit early if not multi-tenant diff --git a/packages/backend-core/src/utils/tests/utils.spec.ts b/packages/backend-core/src/utils/tests/utils.spec.ts index 4dc3855c35..b5c6283ce2 100644 --- a/packages/backend-core/src/utils/tests/utils.spec.ts +++ b/packages/backend-core/src/utils/tests/utils.spec.ts @@ -5,7 +5,7 @@ import * as db from "../../db" import { Header } from "../../constants" import { newid } from "../../utils" import env from "../../environment" -import { BBContext } from "@budibase/types" +import { Ctx } from "@budibase/types" describe("utils", () => { const config = new DBTestConfiguration() @@ -109,7 +109,7 @@ describe("utils", () => { }) describe("isServingBuilder", () => { - let ctx: BBContext + let ctx: Ctx const expectResult = (result: boolean) => expect(utils.isServingBuilder(ctx)).toBe(result) @@ -133,7 +133,7 @@ describe("utils", () => { }) describe("isServingBuilderPreview", () => { - let ctx: BBContext + let ctx: Ctx const expectResult = (result: boolean) => expect(utils.isServingBuilderPreview(ctx)).toBe(result) @@ -157,7 +157,7 @@ describe("utils", () => { }) describe("isPublicAPIRequest", () => { - let ctx: BBContext + let ctx: Ctx const expectResult = (result: boolean) => expect(utils.isPublicApiRequest(ctx)).toBe(result) diff --git a/packages/backend-core/tests/core/utilities/structures/koa.ts b/packages/backend-core/tests/core/utilities/structures/koa.ts index f9883dc1b9..c804d3b5f2 100644 --- a/packages/backend-core/tests/core/utilities/structures/koa.ts +++ b/packages/backend-core/tests/core/utilities/structures/koa.ts @@ -1,8 +1,8 @@ import { createMockContext, createMockCookies } from "@shopify/jest-koa-mocks" -import { BBContext } from "@budibase/types" +import { Ctx } from "@budibase/types" -export const newContext = (): BBContext => { - const ctx = createMockContext() as any +export const newContext = (): Ctx => { + const ctx = createMockContext() as Ctx return { ...ctx, path: "/", diff --git a/packages/server/src/middleware/appInfo.ts b/packages/server/src/middleware/appInfo.ts index 75e40ed473..b62047ec5b 100644 --- a/packages/server/src/middleware/appInfo.ts +++ b/packages/server/src/middleware/appInfo.ts @@ -1,5 +1,5 @@ import { isDevAppID, isProdAppID } from "../db/utils" -import { BBContext } from "@budibase/types" +import { Ctx } from "@budibase/types" export enum AppType { DEV = "dev", @@ -7,7 +7,7 @@ export enum AppType { } export function middleware({ appType }: { appType?: AppType } = {}) { - return (ctx: BBContext, next: any) => { + return (ctx: Ctx, next: any) => { const appId = ctx.appId if (appType === AppType.DEV && appId && !isDevAppID(appId)) { ctx.throw(400, "Only apps in development support this endpoint") diff --git a/packages/server/src/middleware/joi-validator.ts b/packages/server/src/middleware/joi-validator.ts index 5d783acc80..df09c3efa7 100644 --- a/packages/server/src/middleware/joi-validator.ts +++ b/packages/server/src/middleware/joi-validator.ts @@ -1,9 +1,9 @@ import Joi from "joi" -import { BBContext } from "@budibase/types" +import { Ctx } from "@budibase/types" function validate(schema: Joi.Schema, property: string) { // Return a Koa middleware function - return (ctx: BBContext, next: any) => { + return (ctx: Ctx, next: any) => { if (!schema) { return next() } diff --git a/packages/server/src/middleware/resourceId.ts b/packages/server/src/middleware/resourceId.ts index 1ad0b2a0c1..b57a8c2d85 100644 --- a/packages/server/src/middleware/resourceId.ts +++ b/packages/server/src/middleware/resourceId.ts @@ -1,4 +1,4 @@ -import { BBContext } from "@budibase/types" +import { Ctx } from "@budibase/types" export class ResourceIdGetter { parameter: string @@ -26,7 +26,7 @@ export class ResourceIdGetter { const parameter = this.parameter, main = this.main, sub = this.sub - return (ctx: BBContext, next: any) => { + return (ctx: Ctx, next: any) => { // @ts-ignore const request = ctx.request[parameter] || ctx[parameter] if (request == null) { diff --git a/packages/server/src/middleware/selfhost.ts b/packages/server/src/middleware/selfhost.ts index fd2ca6517b..3571931835 100644 --- a/packages/server/src/middleware/selfhost.ts +++ b/packages/server/src/middleware/selfhost.ts @@ -1,9 +1,9 @@ import env from "../environment" -import { BBContext } from "@budibase/types" +import { Ctx } from "@budibase/types" // if added as a middleware will stop requests unless builder is in self host mode // or cloud is in self host -export default async (ctx: BBContext, next: any) => { +export default async (ctx: Ctx, next: any) => { if (env.SELF_HOSTED) { await next() return diff --git a/packages/types/src/sdk/auth.ts b/packages/types/src/sdk/auth.ts index 5bc75e8377..94180143f9 100644 --- a/packages/types/src/sdk/auth.ts +++ b/packages/types/src/sdk/auth.ts @@ -1,4 +1,4 @@ -import { BBContext } from "./koa" +import { Ctx } from "./koa" import { Hosting } from "./hosting" export interface AuthToken { @@ -32,7 +32,7 @@ export interface ScannedSession { } export interface PlatformLogoutOpts { - ctx: BBContext + ctx: Ctx userId: string keepActiveSession?: boolean } From 48f72dad86223bcfd19b6a192e81e0e317161f0a Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Wed, 4 Dec 2024 18:36:06 +0000 Subject: [PATCH 09/15] Renaming and fixing lint. --- packages/server/src/api/controllers/view/viewsV2.ts | 1 - packages/types/src/api/web/template.ts | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/server/src/api/controllers/view/viewsV2.ts b/packages/server/src/api/controllers/view/viewsV2.ts index c99b79d8fa..b1433985c1 100644 --- a/packages/server/src/api/controllers/view/viewsV2.ts +++ b/packages/server/src/api/controllers/view/viewsV2.ts @@ -16,7 +16,6 @@ import { CountCalculationFieldMetadata, CreateViewResponse, UpdateViewResponse, - DeleteViewResponse, } from "@budibase/types" import { builderSocket, gridSocket } from "../../../websockets" import { helpers } from "@budibase/shared-core" diff --git a/packages/types/src/api/web/template.ts b/packages/types/src/api/web/template.ts index 34b846b7ef..c21fcc18ca 100644 --- a/packages/types/src/api/web/template.ts +++ b/packages/types/src/api/web/template.ts @@ -2,7 +2,7 @@ export enum TemplateType { APP = "app", } -export interface Template { +export interface TemplateMetadata { background: string icon: string category: string @@ -14,7 +14,7 @@ export interface Template { image: string } -export type FetchTemplateResponse = Template[] +export type FetchTemplateResponse = TemplateMetadata[] export interface DownloadTemplateResponse { message: string From 48379021ef636433061a2de585339bfb5616b43d Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Thu, 5 Dec 2024 11:36:56 +0000 Subject: [PATCH 10/15] PR comments and fixes. --- packages/backend-core/src/middleware/auditLog.ts | 8 ++++++-- packages/backend-core/src/middleware/tenancy.ts | 5 +++-- packages/server/src/api/index.ts | 3 --- packages/server/src/middleware/appMigrations.ts | 7 +++++-- packages/server/src/middleware/cleanup.ts | 7 +++++-- packages/server/src/middleware/currentapp.ts | 7 +++++-- packages/types/src/sdk/koa.ts | 2 +- 7 files changed, 25 insertions(+), 14 deletions(-) diff --git a/packages/backend-core/src/middleware/auditLog.ts b/packages/backend-core/src/middleware/auditLog.ts index 2febbf879c..f4cbb8b45f 100644 --- a/packages/backend-core/src/middleware/auditLog.ts +++ b/packages/backend-core/src/middleware/auditLog.ts @@ -1,6 +1,10 @@ import { Ctx } from "@budibase/types" +import { Middleware, Next } from "koa" -export default async (ctx: Ctx, next: any) => { +// this middleware exists purely to be overridden by middlewares supplied by the @budibase/pro library +const middleware = (async (ctx: Ctx, next: Next) => { // Placeholder for audit log middleware return next() -} +}) as Middleware + +export default middleware diff --git a/packages/backend-core/src/middleware/tenancy.ts b/packages/backend-core/src/middleware/tenancy.ts index e0c1be2a03..a614ab5438 100644 --- a/packages/backend-core/src/middleware/tenancy.ts +++ b/packages/backend-core/src/middleware/tenancy.ts @@ -8,6 +8,7 @@ import { GetTenantIdOptions, TenantResolutionStrategy, } from "@budibase/types" +import { Next, Middleware } from "koa" export default function ( allowQueryStringPatterns: EndpointMatcher[], @@ -17,7 +18,7 @@ export default function ( const allowQsOptions = buildMatcherRegex(allowQueryStringPatterns) const noTenancyOptions = buildMatcherRegex(noTenancyPatterns) - return async function (ctx: Ctx, next: any) { + return async function (ctx: Ctx, next: Next) { const allowNoTenant = opts.noTenancyRequired || !!matches(ctx, noTenancyOptions) const tenantOpts: GetTenantIdOptions = { @@ -32,5 +33,5 @@ export default function ( const tenantId = getTenantIDFromCtx(ctx, tenantOpts) ctx.set(Header.TENANT_ID, tenantId as string) return doInTenant(tenantId, next) - } + } as Middleware } diff --git a/packages/server/src/api/index.ts b/packages/server/src/api/index.ts index 92cee95ea6..230e5079b4 100644 --- a/packages/server/src/api/index.ts +++ b/packages/server/src/api/index.ts @@ -58,12 +58,9 @@ if (apiEnabled()) { }) ) .use(pro.licensing()) - // @ts-ignore .use(currentApp) .use(auth.auditLog) - // @ts-ignore .use(migrations) - // @ts-ignore .use(cleanup) // authenticated routes diff --git a/packages/server/src/middleware/appMigrations.ts b/packages/server/src/middleware/appMigrations.ts index 6ad356427b..c8fcfa217e 100644 --- a/packages/server/src/middleware/appMigrations.ts +++ b/packages/server/src/middleware/appMigrations.ts @@ -1,8 +1,9 @@ import { UserCtx } from "@budibase/types" import { checkMissingMigrations } from "../appMigrations" import env from "../environment" +import { Middleware, Next } from "koa" -export default async (ctx: UserCtx, next: any) => { +const middleware = (async (ctx: UserCtx, next: Next) => { const { appId } = ctx // migrations can be disabled via environment variable if you @@ -16,4 +17,6 @@ export default async (ctx: UserCtx, next: any) => { } return checkMissingMigrations(ctx, next, appId) -} +}) as Middleware + +export default middleware diff --git a/packages/server/src/middleware/cleanup.ts b/packages/server/src/middleware/cleanup.ts index fa04743cee..7279c4cddc 100644 --- a/packages/server/src/middleware/cleanup.ts +++ b/packages/server/src/middleware/cleanup.ts @@ -1,8 +1,9 @@ import { Ctx } from "@budibase/types" import { context } from "@budibase/backend-core" import { tracer } from "dd-trace" +import { Middleware, Next } from "koa" -export default async (ctx: Ctx, next: any) => { +const middleware = (async (ctx: Ctx, next: Next) => { const resp = await next() const current = context.getCurrentContext() @@ -30,4 +31,6 @@ export default async (ctx: Ctx, next: any) => { } return resp -} +}) as Middleware + +export default middleware diff --git a/packages/server/src/middleware/currentapp.ts b/packages/server/src/middleware/currentapp.ts index 6b44e56a66..796098a4d2 100644 --- a/packages/server/src/middleware/currentapp.ts +++ b/packages/server/src/middleware/currentapp.ts @@ -13,8 +13,9 @@ import env from "../environment" import { isWebhookEndpoint, isBrowser, isApiKey } from "./utils" import { UserCtx, ContextUser } from "@budibase/types" import tracer from "dd-trace" +import { Middleware, Next } from "koa" -export default async (ctx: UserCtx, next: any) => { +const middleware = (async (ctx: UserCtx, next: Next) => { // try to get the appID from the request let requestAppId = await utils.getAppIdFromCtx(ctx) if (!requestAppId) { @@ -116,4 +117,6 @@ export default async (ctx: UserCtx, next: any) => { return next() }) -} +}) as Middleware + +export default middleware diff --git a/packages/types/src/sdk/koa.ts b/packages/types/src/sdk/koa.ts index 826b7b371c..deb457d009 100644 --- a/packages/types/src/sdk/koa.ts +++ b/packages/types/src/sdk/koa.ts @@ -47,7 +47,7 @@ export interface BBRequest extends Request { export interface Ctx extends Context { request: BBRequest body: ResponseBody - userAgent: UserAgentContext["userAgent"] + userAgent?: UserAgentContext["userAgent"] state: { nonce?: string } } From ce08276250a0230d3de59f77d4d1c00815a18695 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Thu, 5 Dec 2024 11:49:22 +0000 Subject: [PATCH 11/15] Fixing type. --- packages/types/src/sdk/koa.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/types/src/sdk/koa.ts b/packages/types/src/sdk/koa.ts index deb457d009..826b7b371c 100644 --- a/packages/types/src/sdk/koa.ts +++ b/packages/types/src/sdk/koa.ts @@ -47,7 +47,7 @@ export interface BBRequest extends Request { export interface Ctx extends Context { request: BBRequest body: ResponseBody - userAgent?: UserAgentContext["userAgent"] + userAgent: UserAgentContext["userAgent"] state: { nonce?: string } } From 2a31aca37a82b82ce0fdab4b58f5d588030e8ddd Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Thu, 5 Dec 2024 13:37:20 +0000 Subject: [PATCH 12/15] Type fixes. --- packages/server/src/middleware/appMigrations.ts | 2 +- packages/server/src/middleware/cleanup.ts | 2 +- packages/server/src/middleware/currentapp.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/server/src/middleware/appMigrations.ts b/packages/server/src/middleware/appMigrations.ts index c8fcfa217e..2ebd522add 100644 --- a/packages/server/src/middleware/appMigrations.ts +++ b/packages/server/src/middleware/appMigrations.ts @@ -1,7 +1,7 @@ import { UserCtx } from "@budibase/types" import { checkMissingMigrations } from "../appMigrations" import env from "../environment" -import { Middleware, Next } from "koa" +import type { Middleware, Next } from "koa" const middleware = (async (ctx: UserCtx, next: Next) => { const { appId } = ctx diff --git a/packages/server/src/middleware/cleanup.ts b/packages/server/src/middleware/cleanup.ts index 7279c4cddc..443eacc52d 100644 --- a/packages/server/src/middleware/cleanup.ts +++ b/packages/server/src/middleware/cleanup.ts @@ -1,7 +1,7 @@ import { Ctx } from "@budibase/types" import { context } from "@budibase/backend-core" import { tracer } from "dd-trace" -import { Middleware, Next } from "koa" +import type { Middleware, Next } from "koa" const middleware = (async (ctx: Ctx, next: Next) => { const resp = await next() diff --git a/packages/server/src/middleware/currentapp.ts b/packages/server/src/middleware/currentapp.ts index 796098a4d2..866730297a 100644 --- a/packages/server/src/middleware/currentapp.ts +++ b/packages/server/src/middleware/currentapp.ts @@ -13,7 +13,7 @@ import env from "../environment" import { isWebhookEndpoint, isBrowser, isApiKey } from "./utils" import { UserCtx, ContextUser } from "@budibase/types" import tracer from "dd-trace" -import { Middleware, Next } from "koa" +import type { Middleware, Next } from "koa" const middleware = (async (ctx: UserCtx, next: Next) => { // try to get the appID from the request From 10c1c18f16ab9b05e0b315fed79fefd560377df0 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Thu, 5 Dec 2024 13:44:08 +0000 Subject: [PATCH 13/15] More typing fixes. --- packages/backend-core/package.json | 1 + .../backend-core/src/middleware/auditLog.ts | 2 +- .../src/middleware/authenticated.ts | 21 +++++++++++++------ .../backend-core/src/middleware/tenancy.ts | 2 +- 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/packages/backend-core/package.json b/packages/backend-core/package.json index a4381b4200..3248fd8ceb 100644 --- a/packages/backend-core/package.json +++ b/packages/backend-core/package.json @@ -83,6 +83,7 @@ "@types/semver": "7.3.7", "@types/tar-fs": "2.0.1", "@types/uuid": "8.3.4", + "@types/koa": "2.13.4", "chance": "1.1.8", "ioredis-mock": "8.9.0", "jest": "29.7.0", diff --git a/packages/backend-core/src/middleware/auditLog.ts b/packages/backend-core/src/middleware/auditLog.ts index f4cbb8b45f..d529e8f908 100644 --- a/packages/backend-core/src/middleware/auditLog.ts +++ b/packages/backend-core/src/middleware/auditLog.ts @@ -1,5 +1,5 @@ import { Ctx } from "@budibase/types" -import { Middleware, Next } from "koa" +import type { Middleware, Next } from "koa" // this middleware exists purely to be overridden by middlewares supplied by the @budibase/pro library const middleware = (async (ctx: Ctx, next: Next) => { diff --git a/packages/backend-core/src/middleware/authenticated.ts b/packages/backend-core/src/middleware/authenticated.ts index b713f509e0..6713cc7687 100644 --- a/packages/backend-core/src/middleware/authenticated.ts +++ b/packages/backend-core/src/middleware/authenticated.ts @@ -22,6 +22,7 @@ import { } from "@budibase/types" import { ErrorCode, InvalidAPIKeyError } from "../errors" import tracer from "dd-trace" +import type { Middleware, Next } from "koa" const ONE_MINUTE = env.SESSION_UPDATE_PERIOD ? parseInt(env.SESSION_UPDATE_PERIOD) @@ -94,6 +95,14 @@ async function checkApiKey( }) } +function getHeader(ctx: Ctx, header: Header): string | undefined { + const contents = ctx.request.headers[header] + if (Array.isArray(contents)) { + throw new Error("Unexpected header format") + } + return contents +} + /** * This middleware is tenancy aware, so that it does not depend on other middlewares being used. * The tenancy modules should not be used here and it should be assumed that the tenancy context @@ -106,9 +115,9 @@ export default function ( } ) { const noAuthOptions = noAuthPatterns ? buildMatcherRegex(noAuthPatterns) : [] - return async (ctx: Ctx | any, next: any) => { + return (async (ctx: Ctx, next: Next) => { let publicEndpoint = false - const version = ctx.request.headers[Header.API_VER] + const version = getHeader(ctx, Header.API_VER) // the path is not authenticated const found = matches(ctx, noAuthOptions) if (found) { @@ -116,18 +125,18 @@ export default function ( } try { // check the actual user is authenticated first, try header or cookie - let headerToken = ctx.request.headers[Header.TOKEN] + let headerToken = getHeader(ctx, Header.TOKEN) const authCookie = getCookie(ctx, Cookie.Auth) || openJwt(headerToken) - let apiKey = ctx.request.headers[Header.API_KEY] + let apiKey = getHeader(ctx, Header.API_KEY) if (!apiKey && ctx.request.headers[Header.AUTHORIZATION]) { apiKey = ctx.request.headers[Header.AUTHORIZATION].split(" ")[1] } - const tenantId = ctx.request.headers[Header.TENANT_ID] + const tenantId = getHeader(ctx, Header.TENANT_ID) let authenticated: boolean = false, user: User | { tenantId: string } | undefined = undefined, internal: boolean = false, @@ -243,5 +252,5 @@ export default function ( ctx.throw(err.status || 403, err) } } - } + }) as Middleware } diff --git a/packages/backend-core/src/middleware/tenancy.ts b/packages/backend-core/src/middleware/tenancy.ts index a614ab5438..de756c0af2 100644 --- a/packages/backend-core/src/middleware/tenancy.ts +++ b/packages/backend-core/src/middleware/tenancy.ts @@ -8,7 +8,7 @@ import { GetTenantIdOptions, TenantResolutionStrategy, } from "@budibase/types" -import { Next, Middleware } from "koa" +import type { Next, Middleware } from "koa" export default function ( allowQueryStringPatterns: EndpointMatcher[], From 862fcee0b4a53dfc958d275c61982944c8c10a86 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Thu, 5 Dec 2024 13:58:17 +0000 Subject: [PATCH 14/15] More middleware typing (pls) --- packages/backend-core/src/middleware/csrf.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/backend-core/src/middleware/csrf.ts b/packages/backend-core/src/middleware/csrf.ts index e20841cca0..2419cca9c5 100644 --- a/packages/backend-core/src/middleware/csrf.ts +++ b/packages/backend-core/src/middleware/csrf.ts @@ -1,6 +1,7 @@ import { Header } from "../constants" import { buildMatcherRegex, matches } from "./matchers" import { Ctx, EndpointMatcher } from "@budibase/types" +import { Middleware, Next } from "koa" /** * GET, HEAD and OPTIONS methods are considered safe operations @@ -36,7 +37,7 @@ export default function ( opts: { noCsrfPatterns: EndpointMatcher[] } = { noCsrfPatterns: [] } ) { const noCsrfOptions = buildMatcherRegex(opts.noCsrfPatterns) - return async (ctx: Ctx, next: any) => { + return (async (ctx: Ctx, next: Next) => { // don't apply for excluded paths const found = matches(ctx, noCsrfOptions) if (found) { @@ -77,5 +78,5 @@ export default function ( } return next() - } + }) as Middleware } From 6371296246e428eca8f859953e56313da695e86f Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Thu, 5 Dec 2024 14:06:58 +0000 Subject: [PATCH 15/15] Adding type keyword. --- packages/backend-core/src/middleware/csrf.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend-core/src/middleware/csrf.ts b/packages/backend-core/src/middleware/csrf.ts index 2419cca9c5..907c53a87d 100644 --- a/packages/backend-core/src/middleware/csrf.ts +++ b/packages/backend-core/src/middleware/csrf.ts @@ -1,7 +1,7 @@ import { Header } from "../constants" import { buildMatcherRegex, matches } from "./matchers" import { Ctx, EndpointMatcher } from "@budibase/types" -import { Middleware, Next } from "koa" +import type { Middleware, Next } from "koa" /** * GET, HEAD and OPTIONS methods are considered safe operations