Merge branch 'fix/massive-attachment-export' of github.com:Budibase/budibase into fix/massive-attachment-export

This commit is contained in:
Andrew Kingston 2023-12-05 16:54:27 +00:00
commit 3cd44d850a
9 changed files with 40 additions and 32 deletions

View File

@ -19,6 +19,7 @@ import {
GoogleInnerConfig, GoogleInnerConfig,
OIDCInnerConfig, OIDCInnerConfig,
PlatformLogoutOpts, PlatformLogoutOpts,
SessionInfo,
SSOProviderType, SSOProviderType,
} from "@budibase/types" } from "@budibase/types"
import * as events from "../events" import * as events from "../events"
@ -44,7 +45,6 @@ export const buildAuthMiddleware = authenticated
export const buildTenancyMiddleware = tenancy export const buildTenancyMiddleware = tenancy
export const buildCsrfMiddleware = csrf export const buildCsrfMiddleware = csrf
export const passport = _passport export const passport = _passport
export const jwt = require("jsonwebtoken")
// Strategies // Strategies
_passport.use(new LocalStrategy(local.options, local.authenticate)) _passport.use(new LocalStrategy(local.options, local.authenticate))
@ -191,10 +191,10 @@ export async function platformLogout(opts: PlatformLogoutOpts) {
if (!ctx) throw new Error("Koa context must be supplied to logout.") if (!ctx) throw new Error("Koa context must be supplied to logout.")
const currentSession = getCookie(ctx, Cookie.Auth) const currentSession = getCookie<SessionInfo>(ctx, Cookie.Auth)
let sessions = await getSessionsForUser(userId) let sessions = await getSessionsForUser(userId)
if (keepActiveSession) { if (currentSession && keepActiveSession) {
sessions = sessions.filter( sessions = sessions.filter(
session => session.sessionId !== currentSession.sessionId session => session.sessionId !== currentSession.sessionId
) )

View File

@ -13,7 +13,7 @@ import { getGlobalDB, doInTenant } from "../context"
import { decrypt } from "../security/encryption" import { decrypt } from "../security/encryption"
import * as identity from "../context/identity" import * as identity from "../context/identity"
import env from "../environment" import env from "../environment"
import { Ctx, EndpointMatcher } from "@budibase/types" import { Ctx, EndpointMatcher, SessionInfo } from "@budibase/types"
import { InvalidAPIKeyError, ErrorCode } from "../errors" import { InvalidAPIKeyError, ErrorCode } from "../errors"
const ONE_MINUTE = env.SESSION_UPDATE_PERIOD const ONE_MINUTE = env.SESSION_UPDATE_PERIOD
@ -98,7 +98,9 @@ export default function (
// check the actual user is authenticated first, try header or cookie // check the actual user is authenticated first, try header or cookie
let headerToken = ctx.request.headers[Header.TOKEN] let headerToken = ctx.request.headers[Header.TOKEN]
const authCookie = getCookie(ctx, Cookie.Auth) || openJwt(headerToken) const authCookie =
getCookie<SessionInfo>(ctx, Cookie.Auth) ||
openJwt<SessionInfo>(headerToken)
let apiKey = ctx.request.headers[Header.API_KEY] let apiKey = ctx.request.headers[Header.API_KEY]
if (!apiKey && ctx.request.headers[Header.AUTHORIZATION]) { if (!apiKey && ctx.request.headers[Header.AUTHORIZATION]) {

View File

@ -58,7 +58,14 @@ export async function postAuth(
const platformUrl = await configs.getPlatformUrl({ tenantAware: false }) const platformUrl = await configs.getPlatformUrl({ tenantAware: false })
let callbackUrl = `${platformUrl}/api/global/auth/datasource/google/callback` let callbackUrl = `${platformUrl}/api/global/auth/datasource/google/callback`
const authStateCookie = utils.getCookie(ctx, Cookie.DatasourceAuth) const authStateCookie = utils.getCookie<{ appId: string }>(
ctx,
Cookie.DatasourceAuth
)
if (!authStateCookie) {
throw new Error("Unable to fetch datasource auth cookie")
}
return passport.authenticate( return passport.authenticate(
new GoogleStrategy( new GoogleStrategy(

View File

@ -11,8 +11,7 @@ import {
TenantResolutionStrategy, TenantResolutionStrategy,
} from "@budibase/types" } from "@budibase/types"
import type { SetOption } from "cookies" import type { SetOption } from "cookies"
import jwt, { Secret } from "jsonwebtoken"
const jwt = require("jsonwebtoken")
const APP_PREFIX = DocumentType.APP + SEPARATOR const APP_PREFIX = DocumentType.APP + SEPARATOR
const PROD_APP_PREFIX = "/app/" const PROD_APP_PREFIX = "/app/"
@ -60,10 +59,7 @@ export function isServingApp(ctx: Ctx) {
return true return true
} }
// prod app // prod app
if (ctx.path.startsWith(PROD_APP_PREFIX)) { return ctx.path.startsWith(PROD_APP_PREFIX)
return true
}
return false
} }
export function isServingBuilder(ctx: Ctx): boolean { export function isServingBuilder(ctx: Ctx): boolean {
@ -138,16 +134,16 @@ function parseAppIdFromUrl(url?: string) {
* opens the contents of the specified encrypted JWT. * opens the contents of the specified encrypted JWT.
* @return the contents of the token. * @return the contents of the token.
*/ */
export function openJwt(token: string) { export function openJwt<T>(token?: string): T | undefined {
if (!token) { if (!token) {
return token return undefined
} }
try { try {
return jwt.verify(token, env.JWT_SECRET) return jwt.verify(token, env.JWT_SECRET as Secret) as T
} catch (e) { } catch (e) {
if (env.JWT_SECRET_FALLBACK) { if (env.JWT_SECRET_FALLBACK) {
// fallback to enable rotation // fallback to enable rotation
return jwt.verify(token, env.JWT_SECRET_FALLBACK) return jwt.verify(token, env.JWT_SECRET_FALLBACK) as T
} else { } else {
throw e throw e
} }
@ -159,13 +155,9 @@ export function isValidInternalAPIKey(apiKey: string) {
return true return true
} }
// fallback to enable rotation // fallback to enable rotation
if ( return !!(
env.INTERNAL_API_KEY_FALLBACK && env.INTERNAL_API_KEY_FALLBACK && env.INTERNAL_API_KEY_FALLBACK === apiKey
env.INTERNAL_API_KEY_FALLBACK === apiKey )
) {
return true
}
return false
} }
/** /**
@ -173,14 +165,14 @@ export function isValidInternalAPIKey(apiKey: string) {
* @param ctx The request which is to be manipulated. * @param ctx The request which is to be manipulated.
* @param name The name of the cookie to get. * @param name The name of the cookie to get.
*/ */
export function getCookie(ctx: Ctx, name: string) { export function getCookie<T>(ctx: Ctx, name: string) {
const cookie = ctx.cookies.get(name) const cookie = ctx.cookies.get(name)
if (!cookie) { if (!cookie) {
return cookie return undefined
} }
return openJwt(cookie) return openJwt(cookie) as T
} }
/** /**
@ -197,7 +189,7 @@ export function setCookie(
opts = { sign: true } opts = { sign: true }
) { ) {
if (value && opts && opts.sign) { if (value && opts && opts.sign) {
value = jwt.sign(value, env.JWT_SECRET) value = jwt.sign(value, env.JWT_SECRET as Secret)
} }
const config: SetOption = { const config: SetOption = {

View File

@ -46,7 +46,7 @@
if (!$validation.valid) { if (!$validation.valid) {
return keepOpen return keepOpen
} }
exportApp(password) await exportApp(password)
}, },
isValid: $validation.valid, isValid: $validation.valid,
}, },

View File

@ -56,6 +56,7 @@ import {
import API from "./api" import API from "./api"
import { cloneDeep } from "lodash" import { cloneDeep } from "lodash"
import jwt, { Secret } from "jsonwebtoken"
mocks.licenses.init(pro) mocks.licenses.init(pro)
@ -391,7 +392,7 @@ class TestConfiguration {
sessionId: "sessionid", sessionId: "sessionid",
tenantId: this.getTenantId(), tenantId: this.getTenantId(),
} }
const authToken = auth.jwt.sign(authObj, coreEnv.JWT_SECRET) const authToken = jwt.sign(authObj, coreEnv.JWT_SECRET as Secret)
// returning necessary request headers // returning necessary request headers
await cache.user.invalidateUser(userId) await cache.user.invalidateUser(userId)
@ -412,7 +413,7 @@ class TestConfiguration {
sessionId: "sessionid", sessionId: "sessionid",
tenantId, tenantId,
} }
const authToken = auth.jwt.sign(authObj, coreEnv.JWT_SECRET) const authToken = jwt.sign(authObj, coreEnv.JWT_SECRET as Secret)
const headers: any = { const headers: any = {
Accept: "application/json", Accept: "application/json",

View File

@ -4,3 +4,4 @@ export * from "./events"
export * from "./configs" export * from "./configs"
export * from "./scim" export * from "./scim"
export * from "./license" export * from "./license"
export * from "./sessions"

View File

@ -0,0 +1,4 @@
export interface SessionInfo {
sessionId: string
userId: string
}

View File

@ -35,6 +35,7 @@ import {
ConfigType, ConfigType,
} from "@budibase/types" } from "@budibase/types"
import API from "./api" import API from "./api"
import jwt, { Secret } from "jsonwebtoken"
class TestConfiguration { class TestConfiguration {
server: any server: any
@ -209,7 +210,7 @@ class TestConfiguration {
sessionId: "sessionid", sessionId: "sessionid",
tenantId: user.tenantId, tenantId: user.tenantId,
} }
const authCookie = auth.jwt.sign(authToken, coreEnv.JWT_SECRET) const authCookie = jwt.sign(authToken, coreEnv.JWT_SECRET as Secret)
return { return {
Accept: "application/json", Accept: "application/json",
...this.cookieHeader([`${constants.Cookie.Auth}=${authCookie}`]), ...this.cookieHeader([`${constants.Cookie.Auth}=${authCookie}`]),
@ -327,7 +328,7 @@ class TestConfiguration {
// CONFIGS - OIDC // CONFIGS - OIDC
getOIDConfigCookie(configId: string) { getOIDConfigCookie(configId: string) {
const token = auth.jwt.sign(configId, coreEnv.JWT_SECRET) const token = jwt.sign(configId, coreEnv.JWT_SECRET as Secret)
return this.cookieHeader([[`${constants.Cookie.OIDC_CONFIG}=${token}`]]) return this.cookieHeader([[`${constants.Cookie.OIDC_CONFIG}=${token}`]])
} }