diff --git a/.github/workflows/budibase_ci.yml b/.github/workflows/budibase_ci.yml index 90b747f07e..2151e1e342 100644 --- a/.github/workflows/budibase_ci.yml +++ b/.github/workflows/budibase_ci.yml @@ -200,6 +200,20 @@ jobs: - run: yarn --frozen-lockfile + - name: Set up PostgreSQL 16 + if: matrix.datasource == 'postgres' + run: | + sudo systemctl stop postgresql + sudo apt-get remove --purge -y postgresql* libpq-dev + sudo rm -rf /etc/postgresql /var/lib/postgresql + sudo apt-get autoremove -y + sudo apt-get autoclean + + sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list' + wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add - + sudo apt-get update + sudo apt-get install -y postgresql-16 + - name: Test server env: DATASOURCE: ${{ matrix.datasource }} 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 2febbf879c..d529e8f908 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 type { 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/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/csrf.ts b/packages/backend-core/src/middleware/csrf.ts index e20841cca0..907c53a87d 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 type { 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 } diff --git a/packages/backend-core/src/middleware/tenancy.ts b/packages/backend-core/src/middleware/tenancy.ts index e0c1be2a03..de756c0af2 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 type { 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/builder/src/pages/builder/app/[application]/automation/_layout.svelte b/packages/builder/src/pages/builder/app/[application]/automation/_layout.svelte index acc1b8e2d9..c5c28d1e1e 100644 --- a/packages/builder/src/pages/builder/app/[application]/automation/_layout.svelte +++ b/packages/builder/src/pages/builder/app/[application]/automation/_layout.svelte @@ -1,5 +1,5 @@