Updating middlewares to Typescript, as well as some fixes based on running tests.

This commit is contained in:
mike12345567 2022-11-16 17:24:13 +00:00
parent 535fab7997
commit 4328ed1b67
15 changed files with 76 additions and 67 deletions

View File

@ -109,10 +109,7 @@ export async function doInAppContext(appId: string, task: any): Promise<any> {
if (tenantId) { if (tenantId) {
updates.tenantId = tenantId updates.tenantId = tenantId
} }
return newContext( return newContext(updates, task)
updates,
task
)
} }
export async function doInIdentityContext( export async function doInIdentityContext(

View File

@ -45,9 +45,7 @@ const getSettingsDoc = async () => {
const db = tenancy.getGlobalDB() const db = tenancy.getGlobalDB()
let settings let settings
try { try {
settings = await db.get( settings = await db.get(dbUtils.generateConfigID({ type: Config.SETTINGS }))
dbUtils.generateConfigID({ type: Config.SETTINGS })
)
} catch (e: any) { } catch (e: any) {
if (e.status !== 404) { if (e.status !== 404) {
throw e throw e

View File

@ -31,7 +31,7 @@ async function makeRequest(method, endpoint, body, appId = config.getAppId()) {
if (body) { if (body) {
req.send(body) req.send(body)
} }
const res = await req.expect("Content-Type", /json/).expect(200) const res = await req
expect(res.body).toBeDefined() expect(res.body).toBeDefined()
return res return res
} }

View File

@ -1,19 +1,20 @@
const { isDevAppID, isProdAppID } = require("../db/utils") import { isDevAppID, isProdAppID } from "../db/utils"
import { BBContext } from "@budibase/types"
exports.AppType = { export enum AppType {
DEV: "dev", DEV = "dev",
PROD: "prod", PROD = "prod",
} }
exports.middleware = export function middleware({ appType }: { appType?: AppType } = {}) {
({ appType } = {}) => return (ctx: BBContext, next: any) => {
(ctx, next) => {
const appId = ctx.appId const appId = ctx.appId
if (appType === exports.AppType.DEV && appId && !isDevAppID(appId)) { if (appType === AppType.DEV && appId && !isDevAppID(appId)) {
ctx.throw(400, "Only apps in development support this endpoint") ctx.throw(400, "Only apps in development support this endpoint")
} }
if (appType === exports.AppType.PROD && appId && !isProdAppID(appId)) { if (appType === AppType.PROD && appId && !isProdAppID(appId)) {
ctx.throw(400, "Only apps in production support this endpoint") ctx.throw(400, "Only apps in production support this endpoint")
} }
return next() return next()
} }
}

View File

@ -1,14 +1,17 @@
const { APP_DEV_PREFIX } = require("../db/utils") import {
const { APP_DEV_PREFIX,
DocumentType,
getGlobalIDFromUserMetadataID,
} from "../db/utils"
import {
doesUserHaveLock, doesUserHaveLock,
updateLock, updateLock,
checkDebounce, checkDebounce,
setDebounce, setDebounce,
} = require("../utilities/redis") } from "../utilities/redis"
const { doWithDB } = require("@budibase/backend-core/db") import { db as dbCore, cache, permissions } from "@budibase/backend-core"
const { DocumentType, getGlobalIDFromUserMetadataID } = require("../db/utils") import { BBContext } from "@budibase/types"
const { PermissionTypes } = require("@budibase/backend-core/permissions") import { PouchLike } from "@budibase/backend-core/src/db"
const { app: appCache } = require("@budibase/backend-core/cache")
const DEBOUNCE_TIME_SEC = 30 const DEBOUNCE_TIME_SEC = 30
@ -21,11 +24,11 @@ const DEBOUNCE_TIME_SEC = 30
* through the authorized middleware * * through the authorized middleware *
****************************************************/ ****************************************************/
async function checkDevAppLocks(ctx) { async function checkDevAppLocks(ctx: BBContext) {
const appId = ctx.appId const appId = ctx.appId
// if any public usage, don't proceed // if any public usage, don't proceed
if (!ctx.user._id && !ctx.user.userId) { if (!ctx.user?._id && !ctx.user?.userId) {
return return
} }
@ -41,34 +44,34 @@ async function checkDevAppLocks(ctx) {
await updateLock(appId, ctx.user) await updateLock(appId, ctx.user)
} }
async function updateAppUpdatedAt(ctx) { async function updateAppUpdatedAt(ctx: BBContext) {
const appId = ctx.appId const appId = ctx.appId
// if debouncing skip this update // if debouncing skip this update
// get methods also aren't updating // get methods also aren't updating
if (ctx.method === "GET" || (await checkDebounce(appId))) { if (ctx.method === "GET" || (await checkDebounce(appId))) {
return return
} }
await doWithDB(appId, async db => { await dbCore.doWithDB(appId, async (db: PouchLike) => {
const metadata = await db.get(DocumentType.APP_METADATA) const metadata = await db.get(DocumentType.APP_METADATA)
metadata.updatedAt = new Date().toISOString() metadata.updatedAt = new Date().toISOString()
metadata.updatedBy = getGlobalIDFromUserMetadataID(ctx.user.userId) metadata.updatedBy = getGlobalIDFromUserMetadataID(ctx.user?.userId!)
const response = await db.put(metadata) const response = await db.put(metadata)
metadata._rev = response.rev metadata._rev = response.rev
await appCache.invalidateAppMetadata(appId, metadata) await cache.app.invalidateAppMetadata(appId, metadata)
// set a new debounce record with a short TTL // set a new debounce record with a short TTL
await setDebounce(appId, DEBOUNCE_TIME_SEC) await setDebounce(appId, DEBOUNCE_TIME_SEC)
}) })
} }
module.exports = async (ctx, permType) => { export = async function builder(ctx: BBContext, permType: string) {
const appId = ctx.appId const appId = ctx.appId
// this only functions within an app context // this only functions within an app context
if (!appId) { if (!appId) {
return return
} }
const isBuilderApi = permType === PermissionTypes.BUILDER const isBuilderApi = permType === permissions.PermissionTypes.BUILDER
const referer = ctx.headers["referer"] const referer = ctx.headers["referer"]
const overviewPath = "/builder/portal/overview/" const overviewPath = "/builder/portal/overview/"

View File

@ -1,20 +1,21 @@
const Joi = require("joi") import Joi from "joi"
import { BBContext } from "@budibase/types"
function validate(schema, property) { function validate(schema: Joi.Schema, property: string) {
// Return a Koa middleware function // Return a Koa middleware function
return (ctx, next) => { return (ctx: BBContext, next: any) => {
if (!schema) { if (!schema) {
return next() return next()
} }
let params = null let params = null
if (ctx[property] != null) { if (ctx[property] != null) {
params = ctx[property] params = ctx[property]
} else if (ctx.request[property] != null) { } else if (ctx.request.get(property) != null) {
params = ctx.request[property] params = ctx.request.get(property)
} }
// not all schemas have the append property e.g. array schemas // not all schemas have the append property e.g. array schemas
if (schema.append) { if ("append" in schema && schema.append) {
schema = schema.append({ schema = schema.append({
createdAt: Joi.any().optional(), createdAt: Joi.any().optional(),
updatedAt: Joi.any().optional(), updatedAt: Joi.any().optional(),
@ -30,10 +31,10 @@ function validate(schema, property) {
} }
} }
module.exports.body = schema => { export function body(schema: Joi.Schema) {
return validate(schema, "body") return validate(schema, "body")
} }
module.exports.params = schema => { export function params(schema: Joi.Schema) {
return validate(schema, "params") return validate(schema, "params")
} }

View File

@ -1,19 +1,19 @@
const { Header } = require("@budibase/backend-core/constants") import { constants, utils } from "@budibase/backend-core"
const { getAppIdFromCtx } = require("@budibase/backend-core/utils") import { BBContext } from "@budibase/types"
module.exports = function ({ requiresAppId } = {}) { export = function ({ requiresAppId }: { requiresAppId?: boolean } = {}) {
return async (ctx, next) => { return async (ctx: BBContext, next: any) => {
const appId = await getAppIdFromCtx(ctx) const appId = await utils.getAppIdFromCtx(ctx)
if (requiresAppId && !appId) { if (requiresAppId && !appId) {
ctx.throw( ctx.throw(
400, 400,
`Invalid app ID provided, please check the ${Header.APP_ID} header.` `Invalid app ID provided, please check the ${constants.Header.APP_ID} header.`
) )
} }
if (!ctx.headers[Header.API_KEY]) { if (!ctx.headers[constants.Header.API_KEY]) {
ctx.throw( ctx.throw(
400, 400,
`Invalid API key provided, please check the ${Header.API_KEY} header.` `Invalid API key provided, please check the ${constants.Header.API_KEY} header.`
) )
} }
return next() return next()

View File

@ -1,17 +1,23 @@
class ResourceIdGetter { import { BBContext } from "@budibase/types"
constructor(ctxProperty) {
export class ResourceIdGetter {
parameter: string
main: string | null
sub: string | null
constructor(ctxProperty: string) {
this.parameter = ctxProperty this.parameter = ctxProperty
this.main = null this.main = null
this.sub = null this.sub = null
return this return this
} }
mainResource(field) { mainResource(field: string) {
this.main = field this.main = field
return this return this
} }
subResource(field) { subResource(field: string) {
this.sub = field this.sub = field
return this return this
} }
@ -20,7 +26,8 @@ class ResourceIdGetter {
const parameter = this.parameter, const parameter = this.parameter,
main = this.main, main = this.main,
sub = this.sub sub = this.sub
return (ctx, next) => { return (ctx: BBContext, next: any) => {
// @ts-ignore
const request = ctx.request[parameter] || ctx[parameter] const request = ctx.request[parameter] || ctx[parameter]
if (request == null) { if (request == null) {
return next() return next()
@ -36,24 +43,22 @@ class ResourceIdGetter {
} }
} }
module.exports.ResourceIdGetter = ResourceIdGetter export function paramResource(main: string) {
module.exports.paramResource = main => {
return new ResourceIdGetter("params").mainResource(main).build() return new ResourceIdGetter("params").mainResource(main).build()
} }
module.exports.paramSubResource = (main, sub) => { export function paramSubResource(main: string, sub: string) {
return new ResourceIdGetter("params") return new ResourceIdGetter("params")
.mainResource(main) .mainResource(main)
.subResource(sub) .subResource(sub)
.build() .build()
} }
module.exports.bodyResource = main => { export function bodyResource(main: string) {
return new ResourceIdGetter("body").mainResource(main).build() return new ResourceIdGetter("body").mainResource(main).build()
} }
module.exports.bodySubResource = (main, sub) => { export function bodySubResource(main: string, sub: string) {
return new ResourceIdGetter("body") return new ResourceIdGetter("body")
.mainResource(main) .mainResource(main)
.subResource(sub) .subResource(sub)

View File

@ -1,7 +1,9 @@
const env = require("../environment") import env from "../environment"
import { BBContext } from "@budibase/types"
// if added as a middleware will stop requests unless builder is in self host mode // if added as a middleware will stop requests unless builder is in self host mode
// or cloud is in self host // or cloud is in self host
module.exports = async (ctx, next) => { module.exports = async (ctx: BBContext, next: any) => {
if (env.SELF_HOSTED) { if (env.SELF_HOSTED) {
await next() await next()
return return

View File

@ -1,7 +1,9 @@
import { BBContext } from "@budibase/types"
const WEBHOOK_ENDPOINTS = new RegExp( const WEBHOOK_ENDPOINTS = new RegExp(
["webhooks/trigger", "webhooks/schema"].join("|") ["webhooks/trigger", "webhooks/schema"].join("|")
) )
exports.isWebhookEndpoint = ctx => { export function isWebhookEndpoint(ctx: BBContext) {
return WEBHOOK_ENDPOINTS.test(ctx.request.url) return WEBHOOK_ENDPOINTS.test(ctx.request.url)
} }

View File

@ -16,7 +16,7 @@ const {
const controllers = require("./controllers") const controllers = require("./controllers")
const supertest = require("supertest") const supertest = require("supertest")
const { cleanup } = require("../../utilities/fileSystem") const { cleanup } = require("../../utilities/fileSystem")
const { Cookie, Headers } = require("@budibase/backend-core/constants") const { Cookie, Header } = require("@budibase/backend-core/constants")
const { jwt } = require("@budibase/backend-core/auth") const { jwt } = require("@budibase/backend-core/auth")
const { doInTenant, doWithGlobalDB } = require("@budibase/backend-core/tenancy") const { doInTenant, doWithGlobalDB } = require("@budibase/backend-core/tenancy")
const { createASession } = require("@budibase/backend-core/sessions") const { createASession } = require("@budibase/backend-core/sessions")

View File

@ -3,7 +3,7 @@ const env = require("../environment")
const { checkSlashesInUrl } = require("./index") const { checkSlashesInUrl } = require("./index")
const { getProdAppID } = require("@budibase/backend-core/db") const { getProdAppID } = require("@budibase/backend-core/db")
const { updateAppRole } = require("./global") const { updateAppRole } = require("./global")
const { Headers } = require("@budibase/backend-core/constants") const { Header } = require("@budibase/backend-core/constants")
const { getTenantId, isTenantIdSet } = require("@budibase/backend-core/tenancy") const { getTenantId, isTenantIdSet } = require("@budibase/backend-core/tenancy")
function request(ctx, request) { function request(ctx, request) {

View File

@ -2,7 +2,7 @@ const core = require("@budibase/backend-core")
const { Config, EmailTemplatePurpose } = require("../../../constants") const { Config, EmailTemplatePurpose } = require("../../../constants")
const { sendEmail, isEmailConfigured } = require("../../../utilities/email") const { sendEmail, isEmailConfigured } = require("../../../utilities/email")
const { setCookie, getCookie, clearCookie, hash, platformLogout } = core.utils const { setCookie, getCookie, clearCookie, hash, platformLogout } = core.utils
const { Cookie, Headers } = core.constants const { Cookie, Header } = core.constants
const { passport, ssoCallbackUrl, google, oidc } = core.auth const { passport, ssoCallbackUrl, google, oidc } = core.auth
const { checkResetPasswordCode } = require("../../../utilities/redis") const { checkResetPasswordCode } = require("../../../utilities/redis")
const { getGlobalDB } = require("@budibase/backend-core/tenancy") const { getGlobalDB } = require("@budibase/backend-core/tenancy")

View File

@ -1,5 +1,5 @@
const env = require("../environment") const env = require("../environment")
const { Headers } = require("@budibase/backend-core/constants") const { Header } = require("@budibase/backend-core/constants")
/** /**
* This is a restricted endpoint in the cloud. * This is a restricted endpoint in the cloud.

View File

@ -1,5 +1,5 @@
const fetch = require("node-fetch") const fetch = require("node-fetch")
const { Headers } = require("@budibase/backend-core/constants") const { Header } = require("@budibase/backend-core/constants")
const { getTenantId, isTenantIdSet } = require("@budibase/backend-core/tenancy") const { getTenantId, isTenantIdSet } = require("@budibase/backend-core/tenancy")
const { checkSlashesInUrl } = require("../utilities") const { checkSlashesInUrl } = require("../utilities")
const env = require("../environment") const env = require("../environment")