Merge remote-tracking branch 'origin/develop' into feature/whitelabelling
This commit is contained in:
commit
f3b58923cf
|
@ -1,6 +1,10 @@
|
|||
name: "deploy-preprod"
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: Budibase release version. For example - 1.0.0
|
||||
required: false
|
||||
workflow_call:
|
||||
|
||||
jobs:
|
||||
|
@ -8,10 +12,16 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: 'Get Previous tag'
|
||||
id: previoustag
|
||||
uses: "WyriHaximus/github-action-get-previous-tag@v1"
|
||||
|
||||
- name: Get the latest budibase release version
|
||||
id: version
|
||||
run: |
|
||||
if [ -z "${{ github.event.inputs.version }}" ]; then
|
||||
release_version=$(cat lerna.json | jq -r '.version')
|
||||
else
|
||||
release_version=${{ github.event.inputs.version }}
|
||||
fi
|
||||
echo "RELEASE_VERSION=$release_version" >> $GITHUB_ENV
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
|
@ -26,7 +36,6 @@ jobs:
|
|||
-o values.preprod.yaml \
|
||||
-L https://api.github.com/repos/budibase/budibase-infra/contents/kubernetes/budibase-preprod/values.yaml
|
||||
wc -l values.preprod.yaml
|
||||
|
||||
- name: Deploy to Preprod Environment
|
||||
uses: budibase/helm@v1.8.0
|
||||
with:
|
||||
|
@ -37,7 +46,7 @@ jobs:
|
|||
helm: helm3
|
||||
values: |
|
||||
globals:
|
||||
appVersion: ${{ steps.previoustag.outputs.tag }}
|
||||
appVersion: v${{ env.RELEASE_VERSION }}
|
||||
ingress:
|
||||
enabled: true
|
||||
nginx: true
|
||||
|
@ -52,5 +61,5 @@ jobs:
|
|||
uses: tsickert/discord-webhook@v4.0.0
|
||||
with:
|
||||
webhook-url: ${{ secrets.PROD_DEPLOY_WEBHOOK_URL }}
|
||||
content: "Preprod Deployment Complete: ${{ steps.previoustag.outputs.tag }} deployed to Budibase Pre-prod."
|
||||
embed-title: ${{ steps.previoustag.outputs.tag }}
|
||||
content: "Preprod Deployment Complete: ${{ env.RELEASE_VERSION }} deployed to Budibase Pre-prod."
|
||||
embed-title: ${{ env.RELEASE_VERSION }}
|
||||
|
|
|
@ -91,9 +91,11 @@ jobs:
|
|||
uses: azure/setup-helm@v1
|
||||
id: helm-install
|
||||
|
||||
- name: 'Get Previous tag'
|
||||
id: previoustag
|
||||
uses: "WyriHaximus/github-action-get-previous-tag@v1"
|
||||
- name: Get the latest budibase release version
|
||||
id: version
|
||||
run: |
|
||||
release_version=$(cat lerna.json | jq -r '.version')
|
||||
echo "RELEASE_VERSION=$release_version" >> $GITHUB_ENV
|
||||
|
||||
# due to helm repo index issue: https://github.com/helm/helm/issues/7363
|
||||
# we need to create new package in a different dir, merge the index and move the package back
|
||||
|
@ -116,8 +118,6 @@ jobs:
|
|||
git add -A
|
||||
git commit -m "Helm Release: ${{ env.RELEASE_VERSION }}"
|
||||
git push
|
||||
env:
|
||||
RELEASE_VERSION: ${{ steps.previoustag.outputs.tag }}
|
||||
|
||||
deploy-to-legacy-preprod-env:
|
||||
needs: [release-images]
|
||||
|
@ -130,13 +130,16 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: 'Get Previous tag'
|
||||
id: previoustag
|
||||
uses: "WyriHaximus/github-action-get-previous-tag@v1"
|
||||
|
||||
- name: Get the latest budibase release version
|
||||
id: version
|
||||
run: |
|
||||
release_version=$(cat lerna.json | jq -r '.version')
|
||||
echo "RELEASE_VERSION=$release_version" >> $GITHUB_ENV
|
||||
|
||||
- uses: passeidireto/trigger-external-workflow-action@main
|
||||
env:
|
||||
PAYLOAD_VERSION: ${{ steps.previoustag.outputs.tag }}
|
||||
PAYLOAD_VERSION: ${{ env.RELEASE_VERSION }}
|
||||
with:
|
||||
repository: budibase/budibase-deploys
|
||||
event: budicloud-preprod-deploy
|
||||
|
|
|
@ -62,16 +62,22 @@ spec:
|
|||
{{ end }}
|
||||
- name: ENABLE_ANALYTICS
|
||||
value: {{ .Values.globals.enableAnalytics | quote }}
|
||||
- name: API_ENCRYPTION_KEY
|
||||
value: {{ .Values.globals.apiEncryptionKey | quote }}
|
||||
- name: INTERNAL_API_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ template "budibase.fullname" . }}
|
||||
key: internalApiKey
|
||||
- name: INTERNAL_API_KEY_FALLBACK
|
||||
value: {{ .Values.globals.internalApiKeyFallback | quote }}
|
||||
- name: JWT_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ template "budibase.fullname" . }}
|
||||
key: jwtSecret
|
||||
- name: JWT_SECRET_FALLBACK
|
||||
value: {{ .Values.globals.jwtSecretFallback | quote }}
|
||||
{{ if .Values.services.objectStore.region }}
|
||||
- name: AWS_REGION
|
||||
value: {{ .Values.services.objectStore.region }}
|
||||
|
@ -125,9 +131,9 @@ spec:
|
|||
- name: SELF_HOSTED
|
||||
value: {{ .Values.globals.selfHosted | quote }}
|
||||
- name: SENTRY_DSN
|
||||
value: {{ .Values.globals.sentryDSN }}
|
||||
value: {{ .Values.globals.sentryDSN | quote }}
|
||||
- name: POSTHOG_TOKEN
|
||||
value: {{ .Values.globals.posthogToken }}
|
||||
value: {{ .Values.globals.posthogToken | quote }}
|
||||
- name: WORKER_URL
|
||||
value: http://worker-service:{{ .Values.services.worker.port }}
|
||||
- name: PLATFORM_URL
|
||||
|
@ -198,8 +204,6 @@ spec:
|
|||
- name: GLOBAL_AGENT_NO_PROXY
|
||||
value: {{ .Values.globals.globalAgentNoProxy | quote }}
|
||||
{{ end }}
|
||||
- name: CDN_URL
|
||||
value: {{ .Values.globals.cdnUrl }}
|
||||
{{ if .Values.services.tlsRejectUnauthorized }}
|
||||
- name: NODE_TLS_REJECT_UNAUTHORIZED
|
||||
value: {{ .Values.services.tlsRejectUnauthorized }}
|
||||
|
|
|
@ -62,16 +62,22 @@ spec:
|
|||
{{ else }}
|
||||
value: http://{{ .Release.Name }}-svc-couchdb:{{ .Values.services.couchdb.port }}
|
||||
{{ end }}
|
||||
- name: API_ENCRYPTION_KEY
|
||||
value: {{ .Values.globals.apiEncryptionKey | quote }}
|
||||
- name: INTERNAL_API_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ template "budibase.fullname" . }}
|
||||
key: internalApiKey
|
||||
- name: INTERNAL_API_KEY_FALLBACK
|
||||
value: {{ .Values.globals.internalApiKeyFallback | quote }}
|
||||
- name: JWT_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ template "budibase.fullname" . }}
|
||||
key: jwtSecret
|
||||
- name: JWT_SECRET_FALLBACK
|
||||
value: {{ .Values.globals.jwtSecretFallback | quote }}
|
||||
{{ if .Values.services.objectStore.region }}
|
||||
- name: AWS_REGION
|
||||
value: {{ .Values.services.objectStore.region }}
|
||||
|
@ -188,8 +194,6 @@ spec:
|
|||
- name: GLOBAL_AGENT_NO_PROXY
|
||||
value: {{ .Values.globals.globalAgentNoProxy | quote }}
|
||||
{{ end }}
|
||||
- name: CDN_URL
|
||||
value: {{ .Values.globals.cdnUrl }}
|
||||
{{ if .Values.services.tlsRejectUnauthorized }}
|
||||
- name: NODE_TLS_REJECT_UNAUTHORIZED
|
||||
value: {{ .Values.services.tlsRejectUnauthorized }}
|
||||
|
|
|
@ -96,9 +96,13 @@ globals:
|
|||
createSecrets: true # creates an internal API key, JWT secrets and redis password for you
|
||||
|
||||
# if createSecrets is set to false, you can hard-code your secrets here
|
||||
apiEncryptionKey: ""
|
||||
internalApiKey: ""
|
||||
jwtSecret: ""
|
||||
cdnUrl: ""
|
||||
# fallback values used during live rotation
|
||||
internalApiKeyFallback: ""
|
||||
jwtSecretFallback: ""
|
||||
|
||||
smtp:
|
||||
enabled: false
|
||||
|
|
|
@ -3,6 +3,7 @@ MAIN_PORT=10000
|
|||
|
||||
# This section contains all secrets pertaining to the system
|
||||
# These should be updated
|
||||
API_ENCRYPTION_KEY=testsecret
|
||||
JWT_SECRET=testsecret
|
||||
MINIO_ACCESS_KEY=budibase
|
||||
MINIO_SECRET_KEY=budibase
|
||||
|
|
|
@ -17,6 +17,7 @@ services:
|
|||
INTERNAL_API_KEY: ${INTERNAL_API_KEY}
|
||||
BUDIBASE_ENVIRONMENT: ${BUDIBASE_ENVIRONMENT}
|
||||
PORT: 4002
|
||||
API_ENCRYPTION_KEY: ${API_ENCRYPTION_KEY}
|
||||
JWT_SECRET: ${JWT_SECRET}
|
||||
LOG_LEVEL: info
|
||||
SENTRY_DSN: https://a34ae347621946bf8acded18e5b7d4b8@o420233.ingest.sentry.io/5338131
|
||||
|
@ -40,6 +41,7 @@ services:
|
|||
SELF_HOSTED: 1
|
||||
PORT: 4003
|
||||
CLUSTER_PORT: ${MAIN_PORT}
|
||||
API_ENCRYPTION_KEY: ${API_ENCRYPTION_KEY}
|
||||
JWT_SECRET: ${JWT_SECRET}
|
||||
MINIO_ACCESS_KEY: ${MINIO_ACCESS_KEY}
|
||||
MINIO_SECRET_KEY: ${MINIO_SECRET_KEY}
|
||||
|
|
|
@ -3,6 +3,7 @@ MAIN_PORT=10000
|
|||
|
||||
# This section contains all secrets pertaining to the system
|
||||
# These should be updated
|
||||
API_ENCRYPTION_KEY=testsecret
|
||||
JWT_SECRET=testsecret
|
||||
MINIO_ACCESS_KEY=budibase
|
||||
MINIO_SECRET_KEY=budibase
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"version": "2.4.12-alpha.5",
|
||||
"version": "2.4.26",
|
||||
"npmClient": "yarn",
|
||||
"packages": [
|
||||
"packages/*"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@budibase/backend-core",
|
||||
"version": "2.4.12-alpha.5",
|
||||
"version": "2.4.26",
|
||||
"description": "Budibase backend core libraries used in server and worker",
|
||||
"main": "dist/src/index.js",
|
||||
"types": "dist/src/index.d.ts",
|
||||
|
@ -24,7 +24,7 @@
|
|||
"dependencies": {
|
||||
"@budibase/nano": "10.1.2",
|
||||
"@budibase/pouchdb-replication-stream": "1.2.10",
|
||||
"@budibase/types": "2.4.12-alpha.5",
|
||||
"@budibase/types": "^2.4.26",
|
||||
"@shopify/jest-koa-mocks": "5.0.1",
|
||||
"@techpass/passport-openidconnect": "0.3.2",
|
||||
"aws-cloudfront-sign": "2.2.0",
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
const _passport = require("koa-passport")
|
||||
const LocalStrategy = require("passport-local").Strategy
|
||||
const JwtStrategy = require("passport-jwt").Strategy
|
||||
import { getGlobalDB } from "../context"
|
||||
import { Cookie } from "../constants"
|
||||
import { getSessionsForUser, invalidateSessions } from "../security/sessions"
|
||||
|
@ -8,7 +7,6 @@ import {
|
|||
authenticated,
|
||||
csrf,
|
||||
google,
|
||||
jwt as jwtPassport,
|
||||
local,
|
||||
oidc,
|
||||
tenancy,
|
||||
|
@ -21,14 +19,11 @@ import {
|
|||
OIDCInnerConfig,
|
||||
PlatformLogoutOpts,
|
||||
SSOProviderType,
|
||||
User,
|
||||
} from "@budibase/types"
|
||||
import { logAlert } from "../logging"
|
||||
import * as events from "../events"
|
||||
import * as configs from "../configs"
|
||||
import { clearCookie, getCookie } from "../utils"
|
||||
import { ssoSaveUserNoOp } from "../middleware/passport/sso/sso"
|
||||
import env from "../environment"
|
||||
|
||||
const refresh = require("passport-oauth2-refresh")
|
||||
export {
|
||||
|
@ -51,25 +46,6 @@ export const jwt = require("jsonwebtoken")
|
|||
|
||||
// Strategies
|
||||
_passport.use(new LocalStrategy(local.options, local.authenticate))
|
||||
if (jwtPassport.options.secretOrKey) {
|
||||
_passport.use(new JwtStrategy(jwtPassport.options, jwtPassport.authenticate))
|
||||
} else if (!env.DISABLE_JWT_WARNING) {
|
||||
logAlert("No JWT Secret supplied, cannot configure JWT strategy")
|
||||
}
|
||||
|
||||
_passport.serializeUser((user: User, done: any) => done(null, user))
|
||||
|
||||
_passport.deserializeUser(async (user: User, done: any) => {
|
||||
const db = getGlobalDB()
|
||||
|
||||
try {
|
||||
const dbUser = await db.get(user._id)
|
||||
return done(null, dbUser)
|
||||
} catch (err) {
|
||||
console.error(`User not found`, err)
|
||||
return done(null, false, { message: "User not found" })
|
||||
}
|
||||
})
|
||||
|
||||
async function refreshOIDCAccessToken(
|
||||
chosenConfig: OIDCInnerConfig,
|
||||
|
|
|
@ -30,6 +30,12 @@ const DefaultBucketName = {
|
|||
|
||||
const selfHosted = !!parseInt(process.env.SELF_HOSTED || "")
|
||||
|
||||
function getAPIEncryptionKey() {
|
||||
return process.env.API_ENCRYPTION_KEY
|
||||
? process.env.API_ENCRYPTION_KEY
|
||||
: process.env.JWT_SECRET // fallback to the JWT_SECRET used historically
|
||||
}
|
||||
|
||||
const environment = {
|
||||
isTest,
|
||||
isJest,
|
||||
|
@ -39,7 +45,9 @@ const environment = {
|
|||
},
|
||||
JS_BCRYPT: process.env.JS_BCRYPT,
|
||||
JWT_SECRET: process.env.JWT_SECRET,
|
||||
JWT_SECRET_FALLBACK: process.env.JWT_SECRET_FALLBACK,
|
||||
ENCRYPTION_KEY: process.env.ENCRYPTION_KEY,
|
||||
API_ENCRYPTION_KEY: getAPIEncryptionKey(),
|
||||
COUCH_DB_URL: process.env.COUCH_DB_URL || "http://localhost:4005",
|
||||
COUCH_DB_USERNAME: process.env.COUCH_DB_USER,
|
||||
COUCH_DB_PASSWORD: process.env.COUCH_DB_PASSWORD,
|
||||
|
@ -55,6 +63,7 @@ const environment = {
|
|||
MINIO_URL: process.env.MINIO_URL,
|
||||
MINIO_ENABLED: process.env.MINIO_ENABLED || 1,
|
||||
INTERNAL_API_KEY: process.env.INTERNAL_API_KEY,
|
||||
INTERNAL_API_KEY_FALLBACK: process.env.INTERNAL_API_KEY_FALLBACK,
|
||||
MULTI_TENANCY: process.env.MULTI_TENANCY,
|
||||
ACCOUNT_PORTAL_URL:
|
||||
process.env.ACCOUNT_PORTAL_URL || "https://account.budibase.app",
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
import { Cookie, Header } from "../constants"
|
||||
import { getCookie, clearCookie, openJwt } from "../utils"
|
||||
import {
|
||||
getCookie,
|
||||
clearCookie,
|
||||
openJwt,
|
||||
isValidInternalAPIKey,
|
||||
} from "../utils"
|
||||
import { getUser } from "../cache/user"
|
||||
import { getSession, updateSessionTTL } from "../security/sessions"
|
||||
import { buildMatcherRegex, matches } from "./matchers"
|
||||
|
@ -35,7 +40,9 @@ function finalise(ctx: any, opts: FinaliseOpts = {}) {
|
|||
}
|
||||
|
||||
async function checkApiKey(apiKey: string, populateUser?: Function) {
|
||||
if (apiKey === env.INTERNAL_API_KEY) {
|
||||
// check both the primary and the fallback internal api keys
|
||||
// this allows for rotation
|
||||
if (isValidInternalAPIKey(apiKey)) {
|
||||
return { valid: true }
|
||||
}
|
||||
const decrypted = decrypt(apiKey)
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
export * as jwt from "./passport/jwt"
|
||||
export * as local from "./passport/local"
|
||||
export * as google from "./passport/sso/google"
|
||||
export * as oidc from "./passport/sso/oidc"
|
||||
|
|
|
@ -1,13 +1,21 @@
|
|||
import env from "../environment"
|
||||
import { Header } from "../constants"
|
||||
import { BBContext } from "@budibase/types"
|
||||
import { isValidInternalAPIKey } from "../utils"
|
||||
|
||||
/**
|
||||
* API Key only endpoint.
|
||||
*/
|
||||
export default async (ctx: BBContext, next: any) => {
|
||||
const apiKey = ctx.request.headers[Header.API_KEY]
|
||||
if (apiKey !== env.INTERNAL_API_KEY) {
|
||||
if (!apiKey) {
|
||||
ctx.throw(403, "Unauthorized")
|
||||
}
|
||||
|
||||
if (Array.isArray(apiKey)) {
|
||||
ctx.throw(403, "Unauthorized")
|
||||
}
|
||||
|
||||
if (!isValidInternalAPIKey(apiKey)) {
|
||||
ctx.throw(403, "Unauthorized")
|
||||
}
|
||||
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
import { Cookie } from "../../constants"
|
||||
import env from "../../environment"
|
||||
import { authError } from "./utils"
|
||||
import { BBContext } from "@budibase/types"
|
||||
|
||||
export const options = {
|
||||
secretOrKey: env.JWT_SECRET,
|
||||
jwtFromRequest: function (ctx: BBContext) {
|
||||
return ctx.cookies.get(Cookie.Auth)
|
||||
},
|
||||
}
|
||||
|
||||
export async function authenticate(jwt: Function, done: Function) {
|
||||
try {
|
||||
return done(null, jwt)
|
||||
} catch (err) {
|
||||
return authError(done, "JWT invalid", err)
|
||||
}
|
||||
}
|
|
@ -8,7 +8,7 @@ const RANDOM_BYTES = 16
|
|||
const STRETCH_LENGTH = 32
|
||||
|
||||
export enum SecretOption {
|
||||
JWT = "jwt",
|
||||
API = "api",
|
||||
ENCRYPTION = "encryption",
|
||||
}
|
||||
|
||||
|
@ -19,10 +19,10 @@ function getSecret(secretOption: SecretOption): string {
|
|||
secret = env.ENCRYPTION_KEY
|
||||
secretName = "ENCRYPTION_KEY"
|
||||
break
|
||||
case SecretOption.JWT:
|
||||
case SecretOption.API:
|
||||
default:
|
||||
secret = env.JWT_SECRET
|
||||
secretName = "JWT_SECRET"
|
||||
secret = env.API_ENCRYPTION_KEY
|
||||
secretName = "API_ENCRYPTION_KEY"
|
||||
break
|
||||
}
|
||||
if (!secret) {
|
||||
|
@ -37,7 +37,7 @@ function stretchString(string: string, salt: Buffer) {
|
|||
|
||||
export function encrypt(
|
||||
input: string,
|
||||
secretOption: SecretOption = SecretOption.JWT
|
||||
secretOption: SecretOption = SecretOption.API
|
||||
) {
|
||||
const salt = crypto.randomBytes(RANDOM_BYTES)
|
||||
const stretched = stretchString(getSecret(secretOption), salt)
|
||||
|
@ -50,7 +50,7 @@ export function encrypt(
|
|||
|
||||
export function decrypt(
|
||||
input: string,
|
||||
secretOption: SecretOption = SecretOption.JWT
|
||||
secretOption: SecretOption = SecretOption.API
|
||||
) {
|
||||
const [salt, encrypted] = input.split(SEPARATOR)
|
||||
const saltBuffer = Buffer.from(salt, "hex")
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { getAllApps, queryGlobalView } from "../db"
|
||||
import { options } from "../middleware/passport/jwt"
|
||||
import {
|
||||
Header,
|
||||
MAX_VALID_DATE,
|
||||
|
@ -133,7 +132,30 @@ export function openJwt(token: string) {
|
|||
if (!token) {
|
||||
return token
|
||||
}
|
||||
return jwt.verify(token, options.secretOrKey)
|
||||
try {
|
||||
return jwt.verify(token, env.JWT_SECRET)
|
||||
} catch (e) {
|
||||
if (env.JWT_SECRET_FALLBACK) {
|
||||
// fallback to enable rotation
|
||||
return jwt.verify(token, env.JWT_SECRET_FALLBACK)
|
||||
} else {
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function isValidInternalAPIKey(apiKey: string) {
|
||||
if (env.INTERNAL_API_KEY && env.INTERNAL_API_KEY === apiKey) {
|
||||
return true
|
||||
}
|
||||
// fallback to enable rotation
|
||||
if (
|
||||
env.INTERNAL_API_KEY_FALLBACK &&
|
||||
env.INTERNAL_API_KEY_FALLBACK === apiKey
|
||||
) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -165,7 +187,7 @@ export function setCookie(
|
|||
opts = { sign: true }
|
||||
) {
|
||||
if (value && opts && opts.sign) {
|
||||
value = jwt.sign(value, options.secretOrKey)
|
||||
value = jwt.sign(value, env.JWT_SECRET)
|
||||
}
|
||||
|
||||
const config: SetOption = {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "@budibase/bbui",
|
||||
"description": "A UI solution used in the different Budibase projects.",
|
||||
"version": "2.4.12-alpha.5",
|
||||
"version": "2.4.26",
|
||||
"license": "MPL-2.0",
|
||||
"svelte": "src/index.js",
|
||||
"module": "dist/bbui.es.js",
|
||||
|
@ -38,8 +38,8 @@
|
|||
],
|
||||
"dependencies": {
|
||||
"@adobe/spectrum-css-workflow-icons": "1.2.1",
|
||||
"@budibase/shared-core": "2.4.12-alpha.5",
|
||||
"@budibase/string-templates": "2.4.12-alpha.5",
|
||||
"@budibase/shared-core": "^2.4.26",
|
||||
"@budibase/string-templates": "^2.4.26",
|
||||
"@spectrum-css/accordion": "3.0.24",
|
||||
"@spectrum-css/actionbutton": "1.0.1",
|
||||
"@spectrum-css/actiongroup": "1.0.1",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@budibase/builder",
|
||||
"version": "2.4.12-alpha.5",
|
||||
"version": "2.4.26",
|
||||
"license": "GPL-3.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
@ -58,11 +58,11 @@
|
|||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@budibase/bbui": "2.4.12-alpha.5",
|
||||
"@budibase/client": "2.4.12-alpha.5",
|
||||
"@budibase/frontend-core": "2.4.12-alpha.5",
|
||||
"@budibase/shared-core": "2.4.12-alpha.5",
|
||||
"@budibase/string-templates": "2.4.12-alpha.5",
|
||||
"@budibase/bbui": "^2.4.26",
|
||||
"@budibase/client": "^2.4.26",
|
||||
"@budibase/frontend-core": "^2.4.26",
|
||||
"@budibase/shared-core": "^2.4.26",
|
||||
"@budibase/string-templates": "^2.4.26",
|
||||
"@fortawesome/fontawesome-svg-core": "^6.2.1",
|
||||
"@fortawesome/free-brands-svg-icons": "^6.2.1",
|
||||
"@fortawesome/free-solid-svg-icons": "^6.2.1",
|
||||
|
|
|
@ -74,6 +74,14 @@
|
|||
}
|
||||
return capitalise(name)
|
||||
}
|
||||
|
||||
function getDisplayError(error, configKey) {
|
||||
return error?.replace(
|
||||
new RegExp(`${configKey}`, "i"),
|
||||
getDisplayName(configKey)
|
||||
)
|
||||
}
|
||||
|
||||
function getFieldGroupKeys(fieldGroup) {
|
||||
return Object.entries(schema[fieldGroup].fields || {})
|
||||
.filter(el => filter(el))
|
||||
|
@ -147,7 +155,7 @@
|
|||
type={schema[configKey].type}
|
||||
on:change
|
||||
bind:value={config[configKey]}
|
||||
error={$validation.errors[configKey]}
|
||||
error={getDisplayError($validation.errors[configKey], configKey)}
|
||||
/>
|
||||
</div>
|
||||
{:else if schema[configKey].type === "fieldGroup"}
|
||||
|
@ -180,7 +188,7 @@
|
|||
type={configKey === "port" ? "string" : schema[configKey].type}
|
||||
on:change
|
||||
bind:value={config[configKey]}
|
||||
error={$validation.errors[configKey]}
|
||||
error={getDisplayError($validation.errors[configKey], configKey)}
|
||||
environmentVariablesEnabled={$licensing.environmentVariablesEnabled}
|
||||
{handleUpgradePanel}
|
||||
/>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@budibase/cli",
|
||||
"version": "2.4.12-alpha.5",
|
||||
"version": "2.4.26",
|
||||
"description": "Budibase CLI, for developers, self hosting and migrations.",
|
||||
"main": "dist/index.js",
|
||||
"bin": {
|
||||
|
@ -29,9 +29,9 @@
|
|||
"outputPath": "build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@budibase/backend-core": "2.4.12-alpha.5",
|
||||
"@budibase/string-templates": "2.4.12-alpha.5",
|
||||
"@budibase/types": "2.4.12-alpha.5",
|
||||
"@budibase/backend-core": "^2.4.26",
|
||||
"@budibase/string-templates": "^2.4.26",
|
||||
"@budibase/types": "^2.4.26",
|
||||
"axios": "0.21.2",
|
||||
"chalk": "4.1.0",
|
||||
"cli-progress": "3.11.2",
|
||||
|
|
|
@ -13,6 +13,7 @@ export const ENV_PATH = path.resolve("./.env")
|
|||
|
||||
function getSecrets(opts = { single: false }) {
|
||||
const secrets = [
|
||||
"API_ENCRYPTION_KEY",
|
||||
"JWT_SECRET",
|
||||
"MINIO_ACCESS_KEY",
|
||||
"MINIO_SECRET_KEY",
|
||||
|
|
|
@ -4,6 +4,8 @@ import {
|
|||
downloadDockerCompose,
|
||||
handleError,
|
||||
getServices,
|
||||
getServiceImage,
|
||||
setServiceImage,
|
||||
} from "./utils"
|
||||
import { confirmation } from "../questions"
|
||||
import compose from "docker-compose"
|
||||
|
@ -23,7 +25,11 @@ export async function update() {
|
|||
!isSingle &&
|
||||
(await confirmation("Do you wish to update you docker-compose.yaml?"))
|
||||
) {
|
||||
// get current MinIO image
|
||||
const image = await getServiceImage("minio")
|
||||
await downloadDockerCompose()
|
||||
// replace MinIO image
|
||||
setServiceImage("minio", image)
|
||||
}
|
||||
await handleError(async () => {
|
||||
const status = await compose.ps()
|
||||
|
|
|
@ -9,10 +9,44 @@ const ERROR_FILE = "docker-error.log"
|
|||
const COMPOSE_URL =
|
||||
"https://raw.githubusercontent.com/Budibase/budibase/master/hosting/docker-compose.yaml"
|
||||
|
||||
export async function downloadDockerCompose() {
|
||||
const fileName = COMPOSE_URL.split("/").slice(-1)[0]
|
||||
function composeFilename() {
|
||||
return COMPOSE_URL.split("/").slice(-1)[0]
|
||||
}
|
||||
|
||||
export function getServiceImage(service: string) {
|
||||
const filename = composeFilename()
|
||||
try {
|
||||
await downloadFile(COMPOSE_URL, `./${fileName}`)
|
||||
const { services } = getServices(filename)
|
||||
const serviceKey = Object.keys(services).find(name =>
|
||||
name.includes(service)
|
||||
)
|
||||
if (serviceKey) {
|
||||
return services[serviceKey].image
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
} catch (err) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
export function setServiceImage(service: string, image: string) {
|
||||
const filename = composeFilename()
|
||||
if (!fs.existsSync(filename)) {
|
||||
throw new Error(
|
||||
`File ${filename} not found, cannot update ${service} image.`
|
||||
)
|
||||
}
|
||||
const current = getServiceImage(service)!
|
||||
let contents = fs.readFileSync(filename, "utf8")
|
||||
contents = contents.replace(`image: ${current}`, `image: ${image}`)
|
||||
fs.writeFileSync(filename, contents)
|
||||
}
|
||||
|
||||
export async function downloadDockerCompose() {
|
||||
const filename = composeFilename()
|
||||
try {
|
||||
await downloadFile(COMPOSE_URL, `./${filename}`)
|
||||
} catch (err) {
|
||||
console.error(error(`Failed to retrieve compose file - ${err}`))
|
||||
}
|
||||
|
@ -49,6 +83,9 @@ export async function handleError(func: Function) {
|
|||
}
|
||||
|
||||
export function getServices(path: string) {
|
||||
if (!fs.existsSync(path)) {
|
||||
throw new Error(`No yaml found at path: ${path}`)
|
||||
}
|
||||
const dockerYaml = fs.readFileSync(path, "utf8")
|
||||
const parsedYaml = yaml.parse(dockerYaml)
|
||||
return { yaml: parsedYaml, services: parsedYaml.services }
|
||||
|
|
|
@ -17,10 +17,7 @@
|
|||
"description": "This component is specific only to layouts",
|
||||
"icon": "Sandbox",
|
||||
"hasChildren": true,
|
||||
"styles": [
|
||||
"padding",
|
||||
"background"
|
||||
],
|
||||
"styles": ["padding", "background"],
|
||||
"settings": [
|
||||
{
|
||||
"type": "text",
|
||||
|
@ -36,23 +33,14 @@
|
|||
"type": "select",
|
||||
"label": "Navigation",
|
||||
"key": "navigation",
|
||||
"options": [
|
||||
"Top",
|
||||
"Left",
|
||||
"None"
|
||||
],
|
||||
"options": ["Top", "Left", "None"],
|
||||
"defaultValue": "Top"
|
||||
},
|
||||
{
|
||||
"type": "select",
|
||||
"label": "Width",
|
||||
"key": "width",
|
||||
"options": [
|
||||
"Small",
|
||||
"Medium",
|
||||
"Large",
|
||||
"Max"
|
||||
],
|
||||
"options": ["Small", "Medium", "Large", "Max"],
|
||||
"defaultValue": "Large"
|
||||
},
|
||||
{
|
||||
|
@ -89,13 +77,7 @@
|
|||
"width": 400,
|
||||
"height": 200
|
||||
},
|
||||
"styles": [
|
||||
"padding",
|
||||
"size",
|
||||
"background",
|
||||
"border",
|
||||
"shadow"
|
||||
],
|
||||
"styles": ["padding", "size", "background", "border", "shadow"],
|
||||
"settings": [
|
||||
{
|
||||
"type": "select",
|
||||
|
@ -255,9 +237,7 @@
|
|||
"description": "Add a section to your application",
|
||||
"icon": "ColumnTwoB",
|
||||
"hasChildren": true,
|
||||
"illegalChildren": [
|
||||
"section"
|
||||
],
|
||||
"illegalChildren": ["section"],
|
||||
"showEmptyState": false,
|
||||
"size": {
|
||||
"width": 400,
|
||||
|
@ -376,9 +356,7 @@
|
|||
"name": "Divider",
|
||||
"description": "A basic divider",
|
||||
"icon": "Separator",
|
||||
"illegalChildren": [
|
||||
"section"
|
||||
],
|
||||
"illegalChildren": ["section"],
|
||||
"size": {
|
||||
"width": 400,
|
||||
"height": 10
|
||||
|
@ -415,9 +393,7 @@
|
|||
"name": "Repeater",
|
||||
"description": "A configurable data list that attaches to your backend tables.",
|
||||
"icon": "JourneyData",
|
||||
"illegalChildren": [
|
||||
"section"
|
||||
],
|
||||
"illegalChildren": ["section"],
|
||||
"hasChildren": true,
|
||||
"size": {
|
||||
"width": 400,
|
||||
|
@ -574,9 +550,7 @@
|
|||
"name": "Stacked List",
|
||||
"icon": "TaskList",
|
||||
"description": "A basic card component that can contain content and actions.",
|
||||
"illegalChildren": [
|
||||
"section"
|
||||
],
|
||||
"illegalChildren": ["section"],
|
||||
"settings": [
|
||||
{
|
||||
"type": "text",
|
||||
|
@ -606,9 +580,7 @@
|
|||
"name": "Vertical Card",
|
||||
"description": "A basic card component that can contain content and actions.",
|
||||
"icon": "ViewColumn",
|
||||
"illegalChildren": [
|
||||
"section"
|
||||
],
|
||||
"illegalChildren": ["section"],
|
||||
"settings": [
|
||||
{
|
||||
"type": "text",
|
||||
|
@ -652,24 +624,14 @@
|
|||
"type": "select",
|
||||
"label": "Image Height",
|
||||
"key": "imageHeight",
|
||||
"options": [
|
||||
"auto",
|
||||
"12rem",
|
||||
"16rem",
|
||||
"20rem",
|
||||
"24rem"
|
||||
],
|
||||
"options": ["auto", "12rem", "16rem", "20rem", "24rem"],
|
||||
"defaultValue": "auto"
|
||||
},
|
||||
{
|
||||
"type": "select",
|
||||
"label": "Card Width",
|
||||
"key": "cardWidth",
|
||||
"options": [
|
||||
"16rem",
|
||||
"20rem",
|
||||
"24rem"
|
||||
],
|
||||
"options": ["16rem", "20rem", "24rem"],
|
||||
"defaultValue": "20rem"
|
||||
}
|
||||
]
|
||||
|
@ -678,9 +640,7 @@
|
|||
"name": "Paragraph",
|
||||
"description": "A component for displaying paragraph text.",
|
||||
"icon": "TextParagraph",
|
||||
"illegalChildren": [
|
||||
"section"
|
||||
],
|
||||
"illegalChildren": ["section"],
|
||||
"editable": true,
|
||||
"size": {
|
||||
"width": 400,
|
||||
|
@ -803,9 +763,7 @@
|
|||
"name": "Headline",
|
||||
"icon": "TextBold",
|
||||
"description": "A component for displaying heading text",
|
||||
"illegalChildren": [
|
||||
"section"
|
||||
],
|
||||
"illegalChildren": ["section"],
|
||||
"editable": true,
|
||||
"size": {
|
||||
"width": 400,
|
||||
|
@ -982,9 +940,7 @@
|
|||
"name": "Image",
|
||||
"description": "A basic component for displaying images",
|
||||
"icon": "Image",
|
||||
"styles": [
|
||||
"size"
|
||||
],
|
||||
"styles": ["size"],
|
||||
"size": {
|
||||
"width": 400,
|
||||
"height": 300
|
||||
|
@ -1002,9 +958,8 @@
|
|||
"name": "Background Image",
|
||||
"description": "A background image",
|
||||
"icon": "Images",
|
||||
"styles": [
|
||||
"size"
|
||||
],
|
||||
"hasChildren": true,
|
||||
"styles": ["size"],
|
||||
"size": {
|
||||
"width": 400,
|
||||
"height": 300
|
||||
|
@ -1162,9 +1117,7 @@
|
|||
"name": "Nav Bar",
|
||||
"description": "A component for handling the navigation within your app.",
|
||||
"icon": "BreadcrumbNavigation",
|
||||
"illegalChildren": [
|
||||
"section"
|
||||
],
|
||||
"illegalChildren": ["section"],
|
||||
"hasChildren": true,
|
||||
"settings": [
|
||||
{
|
||||
|
@ -1365,25 +1318,14 @@
|
|||
"type": "select",
|
||||
"label": "Image Width",
|
||||
"key": "imageWidth",
|
||||
"options": [
|
||||
"auto",
|
||||
"8rem",
|
||||
"12rem",
|
||||
"16rem"
|
||||
],
|
||||
"options": ["auto", "8rem", "12rem", "16rem"],
|
||||
"defaultValue": "8rem"
|
||||
},
|
||||
{
|
||||
"type": "select",
|
||||
"label": "Image Height",
|
||||
"key": "imageHeight",
|
||||
"options": [
|
||||
"auto",
|
||||
"8rem",
|
||||
"12rem",
|
||||
"16rem",
|
||||
"auto"
|
||||
],
|
||||
"options": ["auto", "8rem", "12rem", "16rem", "auto"],
|
||||
"defaultValue": "auto"
|
||||
}
|
||||
]
|
||||
|
@ -1424,9 +1366,7 @@
|
|||
"name": "Embed",
|
||||
"icon": "Code",
|
||||
"description": "Embed content from 3rd party sources",
|
||||
"styles": [
|
||||
"size"
|
||||
],
|
||||
"styles": ["size"],
|
||||
"size": {
|
||||
"width": 400,
|
||||
"height": 100
|
||||
|
@ -1478,11 +1418,7 @@
|
|||
"type": "select",
|
||||
"label": "Format",
|
||||
"key": "yAxisUnits",
|
||||
"options": [
|
||||
"Default",
|
||||
"Thousands",
|
||||
"Millions"
|
||||
],
|
||||
"options": ["Default", "Thousands", "Millions"],
|
||||
"defaultValue": "Default"
|
||||
},
|
||||
{
|
||||
|
@ -1640,11 +1576,7 @@
|
|||
"type": "select",
|
||||
"label": "Format",
|
||||
"key": "yAxisUnits",
|
||||
"options": [
|
||||
"Default",
|
||||
"Thousands",
|
||||
"Millions"
|
||||
],
|
||||
"options": ["Default", "Thousands", "Millions"],
|
||||
"defaultValue": "Default"
|
||||
},
|
||||
{
|
||||
|
@ -1736,11 +1668,7 @@
|
|||
"type": "select",
|
||||
"label": "Curve",
|
||||
"key": "curve",
|
||||
"options": [
|
||||
"Smooth",
|
||||
"Straight",
|
||||
"Stepline"
|
||||
],
|
||||
"options": ["Smooth", "Straight", "Stepline"],
|
||||
"defaultValue": "Smooth"
|
||||
},
|
||||
{
|
||||
|
@ -1801,11 +1729,7 @@
|
|||
"type": "select",
|
||||
"label": "Format",
|
||||
"key": "yAxisUnits",
|
||||
"options": [
|
||||
"Default",
|
||||
"Thousands",
|
||||
"Millions"
|
||||
],
|
||||
"options": ["Default", "Thousands", "Millions"],
|
||||
"defaultValue": "Default"
|
||||
},
|
||||
{
|
||||
|
@ -1897,11 +1821,7 @@
|
|||
"type": "select",
|
||||
"label": "Curve",
|
||||
"key": "curve",
|
||||
"options": [
|
||||
"Smooth",
|
||||
"Straight",
|
||||
"Stepline"
|
||||
],
|
||||
"options": ["Smooth", "Straight", "Stepline"],
|
||||
"defaultValue": "Smooth"
|
||||
},
|
||||
{
|
||||
|
@ -2253,11 +2173,7 @@
|
|||
"type": "select",
|
||||
"label": "Format",
|
||||
"key": "yAxisUnits",
|
||||
"options": [
|
||||
"Default",
|
||||
"Thousands",
|
||||
"Millions"
|
||||
],
|
||||
"options": ["Default", "Thousands", "Millions"],
|
||||
"defaultValue": "Default"
|
||||
},
|
||||
{
|
||||
|
@ -2293,19 +2209,14 @@
|
|||
"name": "Form",
|
||||
"icon": "Form",
|
||||
"hasChildren": true,
|
||||
"illegalChildren": [
|
||||
"section",
|
||||
"form"
|
||||
],
|
||||
"illegalChildren": ["section", "form"],
|
||||
"actions": [
|
||||
"ValidateForm",
|
||||
"ClearForm",
|
||||
"ChangeFormStep",
|
||||
"UpdateFieldValue"
|
||||
],
|
||||
"styles": [
|
||||
"size"
|
||||
],
|
||||
"styles": ["size"],
|
||||
"size": {
|
||||
"width": 400,
|
||||
"height": 400
|
||||
|
@ -2315,10 +2226,7 @@
|
|||
"type": "select",
|
||||
"label": "Type",
|
||||
"key": "actionType",
|
||||
"options": [
|
||||
"Create",
|
||||
"Update"
|
||||
],
|
||||
"options": ["Create", "Update"],
|
||||
"defaultValue": "Create"
|
||||
},
|
||||
{
|
||||
|
@ -2388,14 +2296,8 @@
|
|||
"name": "Form Step",
|
||||
"icon": "AssetsAdded",
|
||||
"hasChildren": true,
|
||||
"illegalChildren": [
|
||||
"section",
|
||||
"form",
|
||||
"form step"
|
||||
],
|
||||
"styles": [
|
||||
"size"
|
||||
],
|
||||
"illegalChildren": ["section", "form", "form step"],
|
||||
"styles": ["size"],
|
||||
"size": {
|
||||
"width": 400,
|
||||
"height": 400
|
||||
|
@ -2413,12 +2315,8 @@
|
|||
"fieldgroup": {
|
||||
"name": "Field Group",
|
||||
"icon": "Group",
|
||||
"illegalChildren": [
|
||||
"section"
|
||||
],
|
||||
"styles": [
|
||||
"size"
|
||||
],
|
||||
"illegalChildren": ["section"],
|
||||
"styles": ["size"],
|
||||
"hasChildren": true,
|
||||
"size": {
|
||||
"width": 400,
|
||||
|
@ -2451,9 +2349,7 @@
|
|||
"skeleton": false,
|
||||
"name": "Text Field",
|
||||
"icon": "Text",
|
||||
"styles": [
|
||||
"size"
|
||||
],
|
||||
"styles": ["size"],
|
||||
"editable": true,
|
||||
"size": {
|
||||
"width": 400,
|
||||
|
@ -2543,9 +2439,7 @@
|
|||
"skeleton": false,
|
||||
"name": "Number Field",
|
||||
"icon": "123",
|
||||
"styles": [
|
||||
"size"
|
||||
],
|
||||
"styles": ["size"],
|
||||
"editable": true,
|
||||
"size": {
|
||||
"width": 400,
|
||||
|
@ -2601,9 +2495,7 @@
|
|||
"skeleton": false,
|
||||
"name": "Password Field",
|
||||
"icon": "LockClosed",
|
||||
"styles": [
|
||||
"size"
|
||||
],
|
||||
"styles": ["size"],
|
||||
"editable": true,
|
||||
"size": {
|
||||
"width": 400,
|
||||
|
@ -2659,9 +2551,7 @@
|
|||
"skeleton": false,
|
||||
"name": "Options Picker",
|
||||
"icon": "Menu",
|
||||
"styles": [
|
||||
"size"
|
||||
],
|
||||
"styles": ["size"],
|
||||
"editable": true,
|
||||
"size": {
|
||||
"width": 400,
|
||||
|
@ -2828,9 +2718,7 @@
|
|||
"skeleton": false,
|
||||
"name": "Multi-select Picker",
|
||||
"icon": "ViewList",
|
||||
"styles": [
|
||||
"size"
|
||||
],
|
||||
"styles": ["size"],
|
||||
"editable": true,
|
||||
"size": {
|
||||
"width": 400,
|
||||
|
@ -3070,9 +2958,7 @@
|
|||
"skeleton": false,
|
||||
"name": "Long Form Field",
|
||||
"icon": "TextAlignLeft",
|
||||
"styles": [
|
||||
"size"
|
||||
],
|
||||
"styles": ["size"],
|
||||
"editable": true,
|
||||
"size": {
|
||||
"width": 400,
|
||||
|
@ -3150,9 +3036,7 @@
|
|||
"skeleton": false,
|
||||
"name": "Date Picker",
|
||||
"icon": "Date",
|
||||
"styles": [
|
||||
"size"
|
||||
],
|
||||
"styles": ["size"],
|
||||
"editable": true,
|
||||
"size": {
|
||||
"width": 400,
|
||||
|
@ -3232,9 +3116,7 @@
|
|||
"skeleton": false,
|
||||
"name": "Barcode/QR Scanner",
|
||||
"icon": "Camera",
|
||||
"styles": [
|
||||
"size"
|
||||
],
|
||||
"styles": ["size"],
|
||||
"size": {
|
||||
"width": 400,
|
||||
"height": 50
|
||||
|
@ -3283,9 +3165,7 @@
|
|||
"embeddedmap": {
|
||||
"name": "Embedded Map",
|
||||
"icon": "Location",
|
||||
"styles": [
|
||||
"size"
|
||||
],
|
||||
"styles": ["size"],
|
||||
"draggable": false,
|
||||
"size": {
|
||||
"width": 400,
|
||||
|
@ -3398,9 +3278,7 @@
|
|||
"skeleton": false,
|
||||
"name": "Attachment",
|
||||
"icon": "Attach",
|
||||
"styles": [
|
||||
"size"
|
||||
],
|
||||
"styles": ["size"],
|
||||
"editable": true,
|
||||
"size": {
|
||||
"width": 400,
|
||||
|
@ -3463,9 +3341,7 @@
|
|||
"skeleton": false,
|
||||
"name": "Relationship Picker",
|
||||
"icon": "TaskList",
|
||||
"styles": [
|
||||
"size"
|
||||
],
|
||||
"styles": ["size"],
|
||||
"editable": true,
|
||||
"size": {
|
||||
"width": 400,
|
||||
|
@ -3527,9 +3403,7 @@
|
|||
"skeleton": false,
|
||||
"name": "JSON Field",
|
||||
"icon": "Brackets",
|
||||
"styles": [
|
||||
"size"
|
||||
],
|
||||
"styles": ["size"],
|
||||
"editable": true,
|
||||
"size": {
|
||||
"width": 400,
|
||||
|
@ -3579,9 +3453,7 @@
|
|||
"s3upload": {
|
||||
"name": "S3 File Upload",
|
||||
"icon": "UploadToCloud",
|
||||
"styles": [
|
||||
"size"
|
||||
],
|
||||
"styles": ["size"],
|
||||
"editable": true,
|
||||
"size": {
|
||||
"width": 400,
|
||||
|
@ -3642,13 +3514,9 @@
|
|||
"dataprovider": {
|
||||
"name": "Data Provider",
|
||||
"icon": "Data",
|
||||
"illegalChildren": [
|
||||
"section"
|
||||
],
|
||||
"illegalChildren": ["section"],
|
||||
"hasChildren": true,
|
||||
"actions": [
|
||||
"RefreshDatasource"
|
||||
],
|
||||
"actions": ["RefreshDatasource"],
|
||||
"size": {
|
||||
"width": 400,
|
||||
"height": 100
|
||||
|
@ -3674,10 +3542,7 @@
|
|||
"type": "select",
|
||||
"label": "Sort Order",
|
||||
"key": "sortOrder",
|
||||
"options": [
|
||||
"Ascending",
|
||||
"Descending"
|
||||
],
|
||||
"options": ["Ascending", "Descending"],
|
||||
"defaultValue": "Ascending"
|
||||
},
|
||||
{
|
||||
|
@ -3729,9 +3594,7 @@
|
|||
"skeleton": false,
|
||||
"name": "Table",
|
||||
"icon": "Table",
|
||||
"illegalChildren": [
|
||||
"section"
|
||||
],
|
||||
"illegalChildren": ["section"],
|
||||
"hasChildren": true,
|
||||
"showEmptyState": false,
|
||||
"size": {
|
||||
|
@ -3815,9 +3678,7 @@
|
|||
"daterangepicker": {
|
||||
"name": "Date Range",
|
||||
"icon": "Calendar",
|
||||
"styles": [
|
||||
"size"
|
||||
],
|
||||
"styles": ["size"],
|
||||
"hasChildren": false,
|
||||
"size": {
|
||||
"width": 200,
|
||||
|
@ -3856,9 +3717,7 @@
|
|||
"spectrumcard": {
|
||||
"name": "Card",
|
||||
"icon": "PersonalizationField",
|
||||
"styles": [
|
||||
"size"
|
||||
],
|
||||
"styles": ["size"],
|
||||
"size": {
|
||||
"width": 300,
|
||||
"height": 120
|
||||
|
@ -4031,10 +3890,7 @@
|
|||
"type": "select",
|
||||
"label": "Sort Order",
|
||||
"key": "sortOrder",
|
||||
"options": [
|
||||
"Ascending",
|
||||
"Descending"
|
||||
],
|
||||
"options": ["Ascending", "Descending"],
|
||||
"defaultValue": "Ascending"
|
||||
},
|
||||
{
|
||||
|
@ -4213,11 +4069,7 @@
|
|||
"type": "select",
|
||||
"label": "Format",
|
||||
"key": "yAxisUnits",
|
||||
"options": [
|
||||
"Default",
|
||||
"Thousands",
|
||||
"Millions"
|
||||
],
|
||||
"options": ["Default", "Thousands", "Millions"],
|
||||
"defaultValue": "Default"
|
||||
},
|
||||
{
|
||||
|
@ -4271,11 +4123,7 @@
|
|||
"type": "select",
|
||||
"label": "Format",
|
||||
"key": "yAxisUnits",
|
||||
"options": [
|
||||
"Default",
|
||||
"Thousands",
|
||||
"Millions"
|
||||
],
|
||||
"options": ["Default", "Thousands", "Millions"],
|
||||
"defaultValue": "Default"
|
||||
},
|
||||
{
|
||||
|
@ -4292,11 +4140,7 @@
|
|||
"type": "select",
|
||||
"label": "Curve",
|
||||
"key": "curve",
|
||||
"options": [
|
||||
"Smooth",
|
||||
"Straight",
|
||||
"Stepline"
|
||||
],
|
||||
"options": ["Smooth", "Straight", "Stepline"],
|
||||
"defaultValue": "Smooth"
|
||||
}
|
||||
]
|
||||
|
@ -4328,11 +4172,7 @@
|
|||
"type": "select",
|
||||
"label": "Format",
|
||||
"key": "yAxisUnits",
|
||||
"options": [
|
||||
"Default",
|
||||
"Thousands",
|
||||
"Millions"
|
||||
],
|
||||
"options": ["Default", "Thousands", "Millions"],
|
||||
"defaultValue": "Default"
|
||||
},
|
||||
{
|
||||
|
@ -4349,11 +4189,7 @@
|
|||
"type": "select",
|
||||
"label": "Curve",
|
||||
"key": "curve",
|
||||
"options": [
|
||||
"Smooth",
|
||||
"Straight",
|
||||
"Stepline"
|
||||
],
|
||||
"options": ["Smooth", "Straight", "Stepline"],
|
||||
"defaultValue": "Smooth"
|
||||
},
|
||||
{
|
||||
|
@ -4418,11 +4254,7 @@
|
|||
"type": "select",
|
||||
"label": "Format",
|
||||
"key": "yAxisUnits",
|
||||
"options": [
|
||||
"Default",
|
||||
"Thousands",
|
||||
"Millions"
|
||||
],
|
||||
"options": ["Default", "Thousands", "Millions"],
|
||||
"defaultValue": "Default"
|
||||
},
|
||||
{
|
||||
|
@ -4443,9 +4275,7 @@
|
|||
"block": true,
|
||||
"name": "Table block",
|
||||
"icon": "Table",
|
||||
"styles": [
|
||||
"size"
|
||||
],
|
||||
"styles": ["size"],
|
||||
"size": {
|
||||
"width": 600,
|
||||
"height": 400
|
||||
|
@ -4483,10 +4313,7 @@
|
|||
"type": "select",
|
||||
"label": "Sort Order",
|
||||
"key": "sortOrder",
|
||||
"options": [
|
||||
"Ascending",
|
||||
"Descending"
|
||||
],
|
||||
"options": ["Ascending", "Descending"],
|
||||
"defaultValue": "Ascending"
|
||||
},
|
||||
{
|
||||
|
@ -4638,9 +4465,7 @@
|
|||
"block": true,
|
||||
"name": "Cards block",
|
||||
"icon": "PersonalizationField",
|
||||
"styles": [
|
||||
"size"
|
||||
],
|
||||
"styles": ["size"],
|
||||
"size": {
|
||||
"width": 600,
|
||||
"height": 400
|
||||
|
@ -4679,10 +4504,7 @@
|
|||
"type": "select",
|
||||
"label": "Sort Order",
|
||||
"key": "sortOrder",
|
||||
"options": [
|
||||
"Ascending",
|
||||
"Descending"
|
||||
],
|
||||
"options": ["Ascending", "Descending"],
|
||||
"defaultValue": "Descending"
|
||||
},
|
||||
{
|
||||
|
@ -4816,9 +4638,7 @@
|
|||
"block": true,
|
||||
"name": "Repeater block",
|
||||
"icon": "ViewList",
|
||||
"illegalChildren": [
|
||||
"section"
|
||||
],
|
||||
"illegalChildren": ["section"],
|
||||
"hasChildren": true,
|
||||
"size": {
|
||||
"width": 400,
|
||||
|
@ -4846,10 +4666,7 @@
|
|||
"type": "select",
|
||||
"label": "Sort Order",
|
||||
"key": "sortOrder",
|
||||
"options": [
|
||||
"Ascending",
|
||||
"Descending"
|
||||
],
|
||||
"options": ["Ascending", "Descending"],
|
||||
"defaultValue": "Descending"
|
||||
},
|
||||
{
|
||||
|
@ -5044,9 +4861,7 @@
|
|||
"markdownviewer": {
|
||||
"name": "Markdown Viewer",
|
||||
"icon": "Preview",
|
||||
"styles": [
|
||||
"size"
|
||||
],
|
||||
"styles": ["size"],
|
||||
"size": {
|
||||
"width": 400,
|
||||
"height": 100
|
||||
|
@ -5063,9 +4878,7 @@
|
|||
"formblock": {
|
||||
"name": "Form Block",
|
||||
"icon": "Form",
|
||||
"styles": [
|
||||
"size"
|
||||
],
|
||||
"styles": ["size"],
|
||||
"block": true,
|
||||
"info": "Form blocks are only compatible with internal or SQL tables",
|
||||
"size": {
|
||||
|
@ -5077,11 +4890,7 @@
|
|||
"type": "select",
|
||||
"label": "Type",
|
||||
"key": "actionType",
|
||||
"options": [
|
||||
"Create",
|
||||
"Update",
|
||||
"View"
|
||||
],
|
||||
"options": ["Create", "Update", "View"],
|
||||
"defaultValue": "Create"
|
||||
},
|
||||
{
|
||||
|
@ -5215,10 +5024,7 @@
|
|||
"name": "Side Panel",
|
||||
"icon": "RailRight",
|
||||
"hasChildren": true,
|
||||
"illegalChildren": [
|
||||
"section",
|
||||
"sidepanel"
|
||||
],
|
||||
"illegalChildren": ["section", "sidepanel"],
|
||||
"showEmptyState": false,
|
||||
"draggable": false,
|
||||
"info": "Side panels are hidden by default. They will only be revealed when triggered by the 'Open Side Panel' action."
|
||||
|
@ -5307,4 +5113,4 @@
|
|||
"suffix": "repeater"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@budibase/client",
|
||||
"version": "2.4.12-alpha.5",
|
||||
"version": "2.4.26",
|
||||
"license": "MPL-2.0",
|
||||
"module": "dist/budibase-client.js",
|
||||
"main": "dist/budibase-client.js",
|
||||
|
@ -19,11 +19,11 @@
|
|||
"dev:builder": "rollup -cw"
|
||||
},
|
||||
"dependencies": {
|
||||
"@budibase/bbui": "2.4.12-alpha.5",
|
||||
"@budibase/frontend-core": "2.4.12-alpha.5",
|
||||
"@budibase/shared-core": "2.4.12-alpha.5",
|
||||
"@budibase/string-templates": "2.4.12-alpha.5",
|
||||
"@budibase/types": "2.4.12-alpha.5",
|
||||
"@budibase/bbui": "^2.4.26",
|
||||
"@budibase/frontend-core": "^2.4.26",
|
||||
"@budibase/shared-core": "^2.4.26",
|
||||
"@budibase/string-templates": "^2.4.26",
|
||||
"@budibase/types": "^2.4.26",
|
||||
"@spectrum-css/button": "^3.0.3",
|
||||
"@spectrum-css/card": "^3.0.3",
|
||||
"@spectrum-css/divider": "^1.0.3",
|
||||
|
|
|
@ -21,7 +21,9 @@
|
|||
|
||||
{#if url}
|
||||
<div class="outer" use:styleable={$component.styles}>
|
||||
<div class="inner" {style} />
|
||||
<div class="inner" {style}>
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
{:else if $builderStore.inBuilder}
|
||||
<div
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
{
|
||||
"name": "@budibase/frontend-core",
|
||||
"version": "2.4.12-alpha.5",
|
||||
"version": "2.4.26",
|
||||
"description": "Budibase frontend core libraries used in builder and client",
|
||||
"author": "Budibase",
|
||||
"license": "MPL-2.0",
|
||||
"svelte": "src/index.js",
|
||||
"dependencies": {
|
||||
"@budibase/bbui": "2.4.12-alpha.5",
|
||||
"@budibase/shared-core": "2.4.12-alpha.5",
|
||||
"@budibase/bbui": "^2.4.26",
|
||||
"@budibase/shared-core": "^2.4.26",
|
||||
"lodash": "^4.17.21",
|
||||
"svelte": "^3.46.2"
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@budibase/sdk",
|
||||
"version": "2.4.12-alpha.5",
|
||||
"version": "2.4.26",
|
||||
"description": "Budibase Public API SDK",
|
||||
"author": "Budibase",
|
||||
"license": "MPL-2.0",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "@budibase/server",
|
||||
"email": "hi@budibase.com",
|
||||
"version": "2.4.12-alpha.5",
|
||||
"version": "2.4.26",
|
||||
"description": "Budibase Web Server",
|
||||
"main": "src/index.ts",
|
||||
"repository": {
|
||||
|
@ -43,12 +43,12 @@
|
|||
"license": "GPL-3.0",
|
||||
"dependencies": {
|
||||
"@apidevtools/swagger-parser": "10.0.3",
|
||||
"@budibase/backend-core": "2.4.12-alpha.5",
|
||||
"@budibase/client": "2.4.12-alpha.5",
|
||||
"@budibase/pro": "2.4.12-alpha.5",
|
||||
"@budibase/shared-core": "2.4.12-alpha.5",
|
||||
"@budibase/string-templates": "2.4.12-alpha.5",
|
||||
"@budibase/types": "2.4.12-alpha.5",
|
||||
"@budibase/backend-core": "^2.4.26",
|
||||
"@budibase/client": "^2.4.26",
|
||||
"@budibase/pro": "2.4.26",
|
||||
"@budibase/shared-core": "^2.4.26",
|
||||
"@budibase/string-templates": "^2.4.26",
|
||||
"@budibase/types": "^2.4.26",
|
||||
"@bull-board/api": "3.7.0",
|
||||
"@bull-board/koa": "3.9.4",
|
||||
"@elastic/elasticsearch": "7.10.0",
|
||||
|
|
|
@ -29,13 +29,6 @@ router
|
|||
br: false,
|
||||
})
|
||||
)
|
||||
.use(async (ctx, next) => {
|
||||
ctx.config = {
|
||||
jwtSecret: env.JWT_SECRET,
|
||||
useAppRootPath: true,
|
||||
}
|
||||
await next()
|
||||
})
|
||||
// re-direct before any middlewares occur
|
||||
.redirect("/", "/builder")
|
||||
.use(
|
||||
|
|
|
@ -39,17 +39,14 @@ let inThread = false
|
|||
const environment = {
|
||||
// important - prefer app port to generic port
|
||||
PORT: process.env.APP_PORT || process.env.PORT,
|
||||
JWT_SECRET: process.env.JWT_SECRET,
|
||||
COUCH_DB_URL: process.env.COUCH_DB_URL,
|
||||
MINIO_URL: process.env.MINIO_URL,
|
||||
WORKER_URL: process.env.WORKER_URL,
|
||||
AWS_REGION: process.env.AWS_REGION,
|
||||
MINIO_ACCESS_KEY: process.env.MINIO_ACCESS_KEY,
|
||||
MINIO_SECRET_KEY: process.env.MINIO_SECRET_KEY,
|
||||
CDN_URL: process.env.CDN_URL || "https://cdn.budi.live",
|
||||
REDIS_URL: process.env.REDIS_URL,
|
||||
REDIS_PASSWORD: process.env.REDIS_PASSWORD,
|
||||
INTERNAL_API_KEY: process.env.INTERNAL_API_KEY,
|
||||
HTTP_MIGRATIONS: process.env.HTTP_MIGRATIONS,
|
||||
API_REQ_LIMIT_PER_SEC: process.env.API_REQ_LIMIT_PER_SEC,
|
||||
GOOGLE_CLIENT_ID: process.env.GOOGLE_CLIENT_ID,
|
||||
|
|
|
@ -67,6 +67,7 @@ const SCHEMA: Integration = {
|
|||
database: {
|
||||
type: DatasourceFieldType.STRING,
|
||||
required: true,
|
||||
display: "Service Name",
|
||||
},
|
||||
user: {
|
||||
type: DatasourceFieldType.STRING,
|
||||
|
|
|
@ -107,6 +107,7 @@ const SCHEMA: Integration = {
|
|||
readCsv: {
|
||||
displayName: "Read CSV",
|
||||
type: QueryType.FIELDS,
|
||||
readable: true,
|
||||
fields: {
|
||||
bucket: {
|
||||
type: DatasourceFieldType.STRING,
|
||||
|
|
|
@ -205,7 +205,6 @@ class TestConfiguration {
|
|||
request.appId = appId
|
||||
// fake cookies, we don't need them
|
||||
request.cookies = { set: () => {}, get: () => {} }
|
||||
request.config = { jwtSecret: env.JWT_SECRET }
|
||||
request.user = { appId, tenantId: this.getTenantId() }
|
||||
request.query = {}
|
||||
request.request = {
|
||||
|
@ -332,8 +331,8 @@ class TestConfiguration {
|
|||
roleId: roleId,
|
||||
appId,
|
||||
}
|
||||
const authToken = auth.jwt.sign(authObj, env.JWT_SECRET)
|
||||
const appToken = auth.jwt.sign(app, env.JWT_SECRET)
|
||||
const authToken = auth.jwt.sign(authObj, coreEnv.JWT_SECRET)
|
||||
const appToken = auth.jwt.sign(app, coreEnv.JWT_SECRET)
|
||||
|
||||
// returning necessary request headers
|
||||
await cache.user.invalidateUser(userId)
|
||||
|
@ -361,8 +360,8 @@ class TestConfiguration {
|
|||
roleId: roles.BUILTIN_ROLE_IDS.ADMIN,
|
||||
appId: this.appId,
|
||||
}
|
||||
const authToken = auth.jwt.sign(authObj, env.JWT_SECRET)
|
||||
const appToken = auth.jwt.sign(app, env.JWT_SECRET)
|
||||
const authToken = auth.jwt.sign(authObj, coreEnv.JWT_SECRET)
|
||||
const appToken = auth.jwt.sign(app, coreEnv.JWT_SECRET)
|
||||
const headers: any = {
|
||||
Accept: "application/json",
|
||||
Cookie: [
|
||||
|
|
|
@ -6,6 +6,7 @@ import {
|
|||
constants,
|
||||
tenancy,
|
||||
logging,
|
||||
env as coreEnv,
|
||||
} from "@budibase/backend-core"
|
||||
import { updateAppRole } from "./global"
|
||||
import { BBContext, User } from "@budibase/types"
|
||||
|
@ -15,7 +16,7 @@ export function request(ctx?: BBContext, request?: any) {
|
|||
request.headers = {}
|
||||
}
|
||||
if (!ctx) {
|
||||
request.headers[constants.Header.API_KEY] = env.INTERNAL_API_KEY
|
||||
request.headers[constants.Header.API_KEY] = coreEnv.INTERNAL_API_KEY
|
||||
if (tenancy.isTenantIdSet()) {
|
||||
request.headers[constants.Header.TENANT_ID] = tenancy.getTenantId()
|
||||
}
|
||||
|
|
|
@ -1278,14 +1278,14 @@
|
|||
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
||||
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
||||
|
||||
"@budibase/backend-core@2.4.12-alpha.5":
|
||||
version "2.4.12-alpha.5"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-2.4.12-alpha.5.tgz#6fc37b439e05f0806909954c5c9f01f37e99f4d8"
|
||||
integrity sha512-TVXjKXT/67ZWK3L6Rs1eJ1+8li4o3+zxOisVuSzgAHTepm6tbF9GLNWIVlzMoLGh5k9M9GHjCkhRKmxozMrBYw==
|
||||
"@budibase/backend-core@2.4.26":
|
||||
version "2.4.26"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-2.4.26.tgz#ae9679f20e86ce1706d6d549aed78a342365a4b4"
|
||||
integrity sha512-9QYJbAT9WPiOckBIR6a/CoqqbUiP9vlmc/Iy5TR5Yj2wy1JnWsf09ReTuL3CsHmh+8bCJlUHZZC4m6PUMg7+ow==
|
||||
dependencies:
|
||||
"@budibase/nano" "10.1.2"
|
||||
"@budibase/pouchdb-replication-stream" "1.2.10"
|
||||
"@budibase/types" "2.4.12-alpha.5"
|
||||
"@budibase/types" "^2.4.26"
|
||||
"@shopify/jest-koa-mocks" "5.0.1"
|
||||
"@techpass/passport-openidconnect" "0.3.2"
|
||||
aws-cloudfront-sign "2.2.0"
|
||||
|
@ -1417,14 +1417,14 @@
|
|||
pouchdb-promise "^6.0.4"
|
||||
through2 "^2.0.0"
|
||||
|
||||
"@budibase/pro@2.4.12-alpha.5":
|
||||
version "2.4.12-alpha.5"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-2.4.12-alpha.5.tgz#ebdaf6fe987a35c9dee00a36bbcf5acb738015de"
|
||||
integrity sha512-j749G4I9NHnEE+0AlFckFjBa3Hkx8M93Raw5s+C7YxaPpChws2HfN/7fCSgY33aeCCGqB0SpwCKAm48BSwbwwQ==
|
||||
"@budibase/pro@2.4.26":
|
||||
version "2.4.26"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-2.4.26.tgz#37ca2b94f5dfc28ee4ff0ffa088e29112de5b66f"
|
||||
integrity sha512-PXpsj5DFnUaSlp3AHZRZa/N4CD02HPpvVFv35/FUGkeGwGJ5AihhmzxlD54U9Q9X3Ln8miejYTFoWvEnV5Ei8w==
|
||||
dependencies:
|
||||
"@budibase/backend-core" "2.4.12-alpha.5"
|
||||
"@budibase/backend-core" "2.4.26"
|
||||
"@budibase/string-templates" "2.3.20"
|
||||
"@budibase/types" "2.4.12-alpha.5"
|
||||
"@budibase/types" "2.4.26"
|
||||
"@koa/router" "8.0.8"
|
||||
bull "4.10.1"
|
||||
joi "17.6.0"
|
||||
|
@ -1463,10 +1463,10 @@
|
|||
lodash "^4.17.20"
|
||||
vm2 "^3.9.4"
|
||||
|
||||
"@budibase/types@2.4.12-alpha.5":
|
||||
version "2.4.12-alpha.5"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-2.4.12-alpha.5.tgz#3727ddef178aebb354e43de0efe03a329b37b91f"
|
||||
integrity sha512-ddtKzLjNcqdQjwYv1lNRo1t5XHdxiHRsFl+xMFsMwpB/8IY8LDw7zvkoC58sFYPUvOP4c1cBA0Wne9YNxM5IiA==
|
||||
"@budibase/types@2.4.26", "@budibase/types@^2.4.26":
|
||||
version "2.4.26"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-2.4.26.tgz#c4efd9286e736feee56d623c21a9f6fd7c922b94"
|
||||
integrity sha512-q2QfDXJAopmHNq6Y25udmVJoEtnoskZEtaMy5d7/hX4jePJX3QnBd9sjgnAoOeSC3NOuXDjmvcRGtqXz6ao/Ag==
|
||||
|
||||
"@bull-board/api@3.7.0":
|
||||
version "3.7.0"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@budibase/shared-core",
|
||||
"version": "2.4.12-alpha.5",
|
||||
"version": "2.4.26",
|
||||
"description": "Shared data utils",
|
||||
"main": "dist/cjs/src/index.js",
|
||||
"types": "dist/mjs/src/index.d.ts",
|
||||
|
@ -20,7 +20,7 @@
|
|||
"dev:builder": "yarn prebuild && concurrently \"tsc -p tsconfig.build.json --watch\" \"tsc -p tsconfig-cjs.build.json --watch\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@budibase/types": "2.4.12-alpha.5"
|
||||
"@budibase/types": "^2.4.26"
|
||||
},
|
||||
"devDependencies": {
|
||||
"concurrently": "^7.6.0",
|
||||
|
|
|
@ -62,7 +62,7 @@ export const getValidOperatorsForType = (
|
|||
|
||||
// Only allow equal/not equal for _id in SQL tables
|
||||
if (field === "_id" && externalTable) {
|
||||
ops = [Op.Equals, Op.NotEquals]
|
||||
ops = [Op.Equals, Op.NotEquals, Op.In]
|
||||
}
|
||||
|
||||
return ops
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@budibase/string-templates",
|
||||
"version": "2.4.12-alpha.5",
|
||||
"version": "2.4.26",
|
||||
"description": "Handlebars wrapper for Budibase templating.",
|
||||
"main": "src/index.cjs",
|
||||
"module": "dist/bundle.mjs",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@budibase/types",
|
||||
"version": "2.4.12-alpha.5",
|
||||
"version": "2.4.26",
|
||||
"description": "Budibase types",
|
||||
"main": "dist/cjs/index.js",
|
||||
"types": "dist/mjs/index.d.ts",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "@budibase/worker",
|
||||
"email": "hi@budibase.com",
|
||||
"version": "2.4.12-alpha.5",
|
||||
"version": "2.4.26",
|
||||
"description": "Budibase background service",
|
||||
"main": "src/index.ts",
|
||||
"repository": {
|
||||
|
@ -36,10 +36,10 @@
|
|||
"author": "Budibase",
|
||||
"license": "GPL-3.0",
|
||||
"dependencies": {
|
||||
"@budibase/backend-core": "2.4.12-alpha.5",
|
||||
"@budibase/pro": "2.4.12-alpha.5",
|
||||
"@budibase/string-templates": "2.4.12-alpha.5",
|
||||
"@budibase/types": "2.4.12-alpha.5",
|
||||
"@budibase/backend-core": "^2.4.26",
|
||||
"@budibase/pro": "2.4.26",
|
||||
"@budibase/string-templates": "^2.4.26",
|
||||
"@budibase/types": "^2.4.26",
|
||||
"@koa/router": "8.0.8",
|
||||
"@sentry/node": "6.17.7",
|
||||
"@techpass/passport-openidconnect": "0.3.2",
|
||||
|
|
|
@ -295,7 +295,7 @@ export async function publicSettings(
|
|||
|
||||
// google
|
||||
const googleConfig = await configs.getGoogleConfig()
|
||||
const preActivated = googleConfig?.activated == null
|
||||
const preActivated = googleConfig && googleConfig.activated == null
|
||||
const google = preActivated || !!googleConfig?.activated
|
||||
const _googleCallbackUrl = await googleCallbackUrl(googleConfig)
|
||||
|
||||
|
|
|
@ -288,7 +288,7 @@ describe("configs", () => {
|
|||
company: "Budibase",
|
||||
logoUrl: "",
|
||||
analyticsEnabled: false,
|
||||
google: true,
|
||||
google: false,
|
||||
googleCallbackUrl: `http://localhost:10000/api/global/auth/${config.tenantId}/google/callback`,
|
||||
isSSOEnforced: false,
|
||||
oidc: false,
|
||||
|
|
|
@ -30,10 +30,8 @@ const environment = {
|
|||
// auth
|
||||
MINIO_ACCESS_KEY: process.env.MINIO_ACCESS_KEY,
|
||||
MINIO_SECRET_KEY: process.env.MINIO_SECRET_KEY,
|
||||
JWT_SECRET: process.env.JWT_SECRET,
|
||||
SALT_ROUNDS: process.env.SALT_ROUNDS,
|
||||
REDIS_PASSWORD: process.env.REDIS_PASSWORD,
|
||||
INTERNAL_API_KEY: process.env.INTERNAL_API_KEY,
|
||||
COOKIE_DOMAIN: process.env.COOKIE_DOMAIN,
|
||||
// urls
|
||||
MINIO_URL: process.env.MINIO_URL,
|
||||
|
@ -42,7 +40,6 @@ const environment = {
|
|||
ACCOUNT_PORTAL_URL: process.env.ACCOUNT_PORTAL_URL,
|
||||
PLATFORM_URL: process.env.PLATFORM_URL,
|
||||
APPS_URL: process.env.APPS_URL,
|
||||
CDN_URL: process.env.CDN_URL || "https://tenants.cdn.budi.live",
|
||||
// ports
|
||||
// prefer worker port to generic port
|
||||
PORT: process.env.WORKER_PORT || process.env.PORT,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import env from "../environment"
|
||||
import { constants } from "@budibase/backend-core"
|
||||
import { constants, utils } from "@budibase/backend-core"
|
||||
import { BBContext } from "@budibase/types"
|
||||
|
||||
/**
|
||||
|
@ -9,7 +9,15 @@ import { BBContext } from "@budibase/types"
|
|||
export default async (ctx: BBContext, next: any) => {
|
||||
if (!env.SELF_HOSTED && !env.DISABLE_ACCOUNT_PORTAL) {
|
||||
const apiKey = ctx.request.headers[constants.Header.API_KEY]
|
||||
if (apiKey !== env.INTERNAL_API_KEY) {
|
||||
if (!apiKey) {
|
||||
ctx.throw(403, "Unauthorized")
|
||||
}
|
||||
|
||||
if (Array.isArray(apiKey)) {
|
||||
ctx.throw(403, "Unauthorized")
|
||||
}
|
||||
|
||||
if (!utils.isValidInternalAPIKey(apiKey)) {
|
||||
ctx.throw(403, "Unauthorized")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,10 +5,10 @@ import {
|
|||
sessions,
|
||||
events,
|
||||
HTTPError,
|
||||
env as coreEnv,
|
||||
} from "@budibase/backend-core"
|
||||
import { PlatformLogoutOpts, User } from "@budibase/types"
|
||||
import jwt from "jsonwebtoken"
|
||||
import env from "../../environment"
|
||||
import * as userSdk from "../users"
|
||||
import * as emails from "../../utilities/email"
|
||||
import * as redis from "../../utilities/redis"
|
||||
|
@ -26,7 +26,7 @@ export async function loginUser(user: User) {
|
|||
sessionId,
|
||||
tenantId,
|
||||
},
|
||||
env.JWT_SECRET!
|
||||
coreEnv.JWT_SECRET!
|
||||
)
|
||||
return token
|
||||
}
|
||||
|
|
|
@ -74,7 +74,6 @@ class TestConfiguration {
|
|||
const request: any = {}
|
||||
// fake cookies, we don't need them
|
||||
request.cookies = { set: () => {}, get: () => {} }
|
||||
request.config = { jwtSecret: env.JWT_SECRET }
|
||||
request.user = { tenantId: this.getTenantId() }
|
||||
request.query = {}
|
||||
request.request = {
|
||||
|
@ -180,7 +179,7 @@ class TestConfiguration {
|
|||
sessionId: "sessionid",
|
||||
tenantId: user.tenantId,
|
||||
}
|
||||
const authCookie = auth.jwt.sign(authToken, env.JWT_SECRET)
|
||||
const authCookie = auth.jwt.sign(authToken, coreEnv.JWT_SECRET)
|
||||
return {
|
||||
Accept: "application/json",
|
||||
...this.cookieHeader([`${constants.Cookie.Auth}=${authCookie}`]),
|
||||
|
@ -197,7 +196,7 @@ class TestConfiguration {
|
|||
}
|
||||
|
||||
internalAPIHeaders() {
|
||||
return { [constants.Header.API_KEY]: env.INTERNAL_API_KEY }
|
||||
return { [constants.Header.API_KEY]: coreEnv.INTERNAL_API_KEY }
|
||||
}
|
||||
|
||||
adminOnlyResponse = () => {
|
||||
|
@ -277,7 +276,7 @@ class TestConfiguration {
|
|||
// CONFIGS - OIDC
|
||||
|
||||
getOIDConfigCookie(configId: string) {
|
||||
const token = auth.jwt.sign(configId, env.JWT_SECRET)
|
||||
const token = auth.jwt.sign(configId, coreEnv.JWT_SECRET)
|
||||
return this.cookieHeader([[`${constants.Cookie.OIDC_CONFIG}=${token}`]])
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
import fetch from "node-fetch"
|
||||
import { constants, tenancy, logging } from "@budibase/backend-core"
|
||||
import {
|
||||
constants,
|
||||
tenancy,
|
||||
logging,
|
||||
env as coreEnv,
|
||||
} from "@budibase/backend-core"
|
||||
import { checkSlashesInUrl } from "../utilities"
|
||||
import env from "../environment"
|
||||
import { SyncUserRequest, User } from "@budibase/types"
|
||||
|
@ -9,7 +14,7 @@ async function makeAppRequest(url: string, method: string, body: any) {
|
|||
return
|
||||
}
|
||||
const request: any = { headers: {} }
|
||||
request.headers[constants.Header.API_KEY] = env.INTERNAL_API_KEY
|
||||
request.headers[constants.Header.API_KEY] = coreEnv.INTERNAL_API_KEY
|
||||
if (tenancy.isTenantIdSet()) {
|
||||
request.headers[constants.Header.TENANT_ID] = tenancy.getTenantId()
|
||||
}
|
||||
|
|
|
@ -475,14 +475,14 @@
|
|||
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
||||
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
||||
|
||||
"@budibase/backend-core@2.4.12-alpha.5":
|
||||
version "2.4.12-alpha.5"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-2.4.12-alpha.5.tgz#6fc37b439e05f0806909954c5c9f01f37e99f4d8"
|
||||
integrity sha512-TVXjKXT/67ZWK3L6Rs1eJ1+8li4o3+zxOisVuSzgAHTepm6tbF9GLNWIVlzMoLGh5k9M9GHjCkhRKmxozMrBYw==
|
||||
"@budibase/backend-core@2.4.26":
|
||||
version "2.4.26"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-2.4.26.tgz#ae9679f20e86ce1706d6d549aed78a342365a4b4"
|
||||
integrity sha512-9QYJbAT9WPiOckBIR6a/CoqqbUiP9vlmc/Iy5TR5Yj2wy1JnWsf09ReTuL3CsHmh+8bCJlUHZZC4m6PUMg7+ow==
|
||||
dependencies:
|
||||
"@budibase/nano" "10.1.2"
|
||||
"@budibase/pouchdb-replication-stream" "1.2.10"
|
||||
"@budibase/types" "2.4.12-alpha.5"
|
||||
"@budibase/types" "^2.4.26"
|
||||
"@shopify/jest-koa-mocks" "5.0.1"
|
||||
"@techpass/passport-openidconnect" "0.3.2"
|
||||
aws-cloudfront-sign "2.2.0"
|
||||
|
@ -564,14 +564,14 @@
|
|||
pouchdb-promise "^6.0.4"
|
||||
through2 "^2.0.0"
|
||||
|
||||
"@budibase/pro@2.4.12-alpha.5":
|
||||
version "2.4.12-alpha.5"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-2.4.12-alpha.5.tgz#ebdaf6fe987a35c9dee00a36bbcf5acb738015de"
|
||||
integrity sha512-j749G4I9NHnEE+0AlFckFjBa3Hkx8M93Raw5s+C7YxaPpChws2HfN/7fCSgY33aeCCGqB0SpwCKAm48BSwbwwQ==
|
||||
"@budibase/pro@2.4.26":
|
||||
version "2.4.26"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-2.4.26.tgz#37ca2b94f5dfc28ee4ff0ffa088e29112de5b66f"
|
||||
integrity sha512-PXpsj5DFnUaSlp3AHZRZa/N4CD02HPpvVFv35/FUGkeGwGJ5AihhmzxlD54U9Q9X3Ln8miejYTFoWvEnV5Ei8w==
|
||||
dependencies:
|
||||
"@budibase/backend-core" "2.4.12-alpha.5"
|
||||
"@budibase/backend-core" "2.4.26"
|
||||
"@budibase/string-templates" "2.3.20"
|
||||
"@budibase/types" "2.4.12-alpha.5"
|
||||
"@budibase/types" "2.4.26"
|
||||
"@koa/router" "8.0.8"
|
||||
bull "4.10.1"
|
||||
joi "17.6.0"
|
||||
|
@ -592,10 +592,10 @@
|
|||
lodash "^4.17.20"
|
||||
vm2 "^3.9.4"
|
||||
|
||||
"@budibase/types@2.4.12-alpha.5":
|
||||
version "2.4.12-alpha.5"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-2.4.12-alpha.5.tgz#3727ddef178aebb354e43de0efe03a329b37b91f"
|
||||
integrity sha512-ddtKzLjNcqdQjwYv1lNRo1t5XHdxiHRsFl+xMFsMwpB/8IY8LDw7zvkoC58sFYPUvOP4c1cBA0Wne9YNxM5IiA==
|
||||
"@budibase/types@2.4.26", "@budibase/types@^2.4.26":
|
||||
version "2.4.26"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-2.4.26.tgz#c4efd9286e736feee56d623c21a9f6fd7c922b94"
|
||||
integrity sha512-q2QfDXJAopmHNq6Y25udmVJoEtnoskZEtaMy5d7/hX4jePJX3QnBd9sjgnAoOeSC3NOuXDjmvcRGtqXz6ao/Ag==
|
||||
|
||||
"@cspotcode/source-map-support@^0.8.0":
|
||||
version "0.8.1"
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
BB_ADMIN_USER_EMAIL=qa@budibase.com
|
||||
BB_ADMIN_USER_PASSWORD=budibase
|
||||
ENCRYPTED_TEST_PUBLIC_API_KEY=a65722f06bee5caeadc5d7ca2f543a43-d610e627344210c643bb726f
|
||||
COUCH_DB_URL=http://budibase:budibase@localhost:4567
|
||||
COUCH_DB_USER=budibase
|
||||
COUCH_DB_PASSWORD=budibase
|
||||
|
|
|
@ -1,11 +1,3 @@
|
|||
const env = require("../src/environment")
|
||||
|
||||
env._set("BUDIBASE_SERVER_URL", "http://localhost:4100")
|
||||
env._set(
|
||||
"BUDIBASE_PUBLIC_API_KEY",
|
||||
"a65722f06bee5caeadc5d7ca2f543a43-d610e627344210c643bb726f"
|
||||
)
|
||||
|
||||
// mock all dates to 2020-01-01T00:00:00.000Z
|
||||
// use tk.reset() to use real dates in individual tests
|
||||
const MOCK_DATE = new Date("2020-01-01T00:00:00.000Z")
|
||||
|
|
|
@ -49,14 +49,16 @@ class InternalAPIClient {
|
|||
// @ts-ignore
|
||||
const response = await fetch(`https://${process.env.TENANT_ID}.${this.host}${url}`, requestOptions)
|
||||
|
||||
if (response.status == 404 || response.status == 500) {
|
||||
if (
|
||||
response.status == 404 ||
|
||||
response.status == 500 ||
|
||||
response.status == 403
|
||||
) {
|
||||
console.error("Error in apiCall")
|
||||
console.error("Response:")
|
||||
console.error(response)
|
||||
console.error("Response body:")
|
||||
console.error(response.body)
|
||||
console.error("Request body:")
|
||||
console.error(requestOptions.body)
|
||||
console.error("Response:", response)
|
||||
const json = await response.json()
|
||||
console.error("Response body:", json)
|
||||
console.error("Request body:", requestOptions.body)
|
||||
}
|
||||
return response
|
||||
}
|
||||
|
|
|
@ -44,12 +44,10 @@ class AccountsAPIClient {
|
|||
const response = await fetch(`${this.host}${url}`, requestOptions)
|
||||
if (response.status == 404 || response.status == 500) {
|
||||
console.error("Error in apiCall")
|
||||
console.error("Response:")
|
||||
console.error(response)
|
||||
console.error("Response body:")
|
||||
console.error(response.body)
|
||||
console.error("Request body:")
|
||||
console.error(requestOptions.body)
|
||||
console.error("Response:", response)
|
||||
const json = await response.json()
|
||||
console.error("Response body:", json)
|
||||
console.error("Request body:", requestOptions.body)
|
||||
}
|
||||
return response
|
||||
}
|
||||
|
|
|
@ -5,7 +5,8 @@ import { Hosting } from "@budibase/types"
|
|||
|
||||
export const generateAccount = (): Partial<NewAccount> => {
|
||||
const randomGuid = generator.guid()
|
||||
let tenant: string = "a" + randomGuid
|
||||
//Needs to start with a letter
|
||||
let tenant: string = "tenant" + randomGuid
|
||||
tenant = tenant.replace(/-/g, "")
|
||||
|
||||
return {
|
||||
|
|
|
@ -11,20 +11,32 @@ interface ApiOptions {
|
|||
|
||||
class PublicAPIClient {
|
||||
host: string
|
||||
apiKey: string
|
||||
apiKey?: string
|
||||
tenantName?: string
|
||||
appId?: string
|
||||
cookie?: string
|
||||
|
||||
constructor(appId?: string) {
|
||||
if (!env.BUDIBASE_PUBLIC_API_KEY || !env.BUDIBASE_SERVER_URL) {
|
||||
if (!env.BUDIBASE_HOST) {
|
||||
throw new Error(
|
||||
"Must set BUDIBASE_PUBLIC_API_KEY and BUDIBASE_SERVER_URL env vars"
|
||||
)
|
||||
}
|
||||
this.host = `${env.BUDIBASE_SERVER_URL}/api/public/v1`
|
||||
this.apiKey = env.BUDIBASE_PUBLIC_API_KEY
|
||||
this.host = `${env.BUDIBASE_HOST}/api/public/v1`
|
||||
|
||||
this.appId = appId
|
||||
}
|
||||
|
||||
setTenantName(tenantName: string) {
|
||||
this.tenantName = tenantName
|
||||
}
|
||||
|
||||
setApiKey(apiKey: string) {
|
||||
this.apiKey = apiKey
|
||||
process.env.BUDIBASE_PUBLIC_API_KEY = apiKey
|
||||
this.host = `${env.BUDIBASE_HOST}/api/public/v1`
|
||||
}
|
||||
|
||||
apiCall =
|
||||
(method: APIMethod) =>
|
||||
async (url = "", options: ApiOptions = {}) => {
|
||||
|
@ -32,18 +44,27 @@ class PublicAPIClient {
|
|||
method,
|
||||
body: JSON.stringify(options.body),
|
||||
headers: {
|
||||
"x-budibase-api-key": this.apiKey,
|
||||
"x-budibase-api-key": this.apiKey || null,
|
||||
"x-budibase-app-id": this.appId,
|
||||
"Content-Type": "application/json",
|
||||
Accept: "application/json",
|
||||
...options.headers,
|
||||
cookie: this.cookie,
|
||||
redirect: "follow",
|
||||
follow: 20,
|
||||
},
|
||||
}
|
||||
|
||||
// prettier-ignore
|
||||
// @ts-ignore
|
||||
const response = await fetch(`${this.host}${url}`, requestOptions)
|
||||
if (response.status !== 200) {
|
||||
console.error(response)
|
||||
const response = await fetch(`https://${process.env.TENANT_ID}.${this.host}${url}`, requestOptions)
|
||||
|
||||
if (response.status == 500 || response.status == 403) {
|
||||
console.error("Error in apiCall")
|
||||
console.error("Response:", response)
|
||||
const json = await response.json()
|
||||
console.error("Response body:", json)
|
||||
console.error("Request body:", requestOptions.body)
|
||||
}
|
||||
return response
|
||||
}
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
import { Response } from "node-fetch"
|
||||
import { Account } from "@budibase/types"
|
||||
import AccountsAPIClient from "./accountsAPIClient"
|
||||
import { NewAccount } from "../fixtures/types/newAccount"
|
||||
|
||||
export default class AccountsApi {
|
||||
api: AccountsAPIClient
|
||||
|
||||
constructor(AccountsAPIClient: AccountsAPIClient) {
|
||||
this.api = AccountsAPIClient
|
||||
}
|
||||
|
||||
async validateEmail(email: string): Promise<Response> {
|
||||
const response = await this.api.post(`/accounts/validate/email`, {
|
||||
body: { email },
|
||||
})
|
||||
expect(response).toHaveStatusCode(200)
|
||||
return response
|
||||
}
|
||||
|
||||
async validateTenantId(tenantId: string): Promise<Response> {
|
||||
const response = await this.api.post(`/accounts/validate/tenantId`, {
|
||||
body: { tenantId },
|
||||
})
|
||||
expect(response).toHaveStatusCode(200)
|
||||
return response
|
||||
}
|
||||
|
||||
async create(body: Partial<NewAccount>): Promise<[Response, Account]> {
|
||||
const headers = {
|
||||
"no-verify": "1",
|
||||
}
|
||||
const response = await this.api.post(`/accounts`, { body, headers })
|
||||
const json = await response.json()
|
||||
expect(response).toHaveStatusCode(201)
|
||||
return [response, json]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
import env from "../../../environment"
|
||||
import fetch, { HeadersInit } from "node-fetch"
|
||||
|
||||
type APIMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE"
|
||||
|
||||
interface ApiOptions {
|
||||
method?: APIMethod
|
||||
body?: object
|
||||
headers?: HeadersInit | undefined
|
||||
}
|
||||
|
||||
class AccountsAPIClient {
|
||||
host: string
|
||||
appId?: string
|
||||
cookie?: string
|
||||
|
||||
constructor(appId?: string) {
|
||||
if (!env.BUDIBASE_ACCOUNTS_URL) {
|
||||
throw new Error("Must set BUDIBASE_SERVER_URL env var")
|
||||
}
|
||||
this.host = `${env.BUDIBASE_ACCOUNTS_URL}/api`
|
||||
this.appId = appId
|
||||
}
|
||||
|
||||
apiCall =
|
||||
(method: APIMethod) =>
|
||||
async (url = "", options: ApiOptions = {}) => {
|
||||
const requestOptions = {
|
||||
method,
|
||||
body: JSON.stringify(options.body),
|
||||
headers: {
|
||||
"x-budibase-app-id": this.appId,
|
||||
"Content-Type": "application/json",
|
||||
Accept: "application/json",
|
||||
cookie: this.cookie,
|
||||
redirect: "follow",
|
||||
follow: 20,
|
||||
...options.headers,
|
||||
},
|
||||
credentials: "include",
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
const response = await fetch(`${this.host}${url}`, requestOptions)
|
||||
if (
|
||||
response.status == 404 ||
|
||||
response.status == 500 ||
|
||||
response.status == 400
|
||||
) {
|
||||
console.error("Error in apiCall")
|
||||
console.error("Response:", response)
|
||||
const json = await response.json()
|
||||
console.error("Response body:", json)
|
||||
console.error("Request body:", requestOptions.body)
|
||||
}
|
||||
return response
|
||||
}
|
||||
|
||||
post = this.apiCall("POST")
|
||||
get = this.apiCall("GET")
|
||||
patch = this.apiCall("PATCH")
|
||||
del = this.apiCall("DELETE")
|
||||
put = this.apiCall("PUT")
|
||||
}
|
||||
|
||||
export default AccountsAPIClient
|
|
@ -63,4 +63,15 @@ export default class AppApi {
|
|||
const response = await this.api.post(`/applications/${id}/unpublish`)
|
||||
return [response]
|
||||
}
|
||||
|
||||
async createFirstApp() {
|
||||
const body = {
|
||||
name: "My first app",
|
||||
url: "my-first-app",
|
||||
useTemplate: false,
|
||||
sampleData: true,
|
||||
}
|
||||
const response = await this.api.post("/applications", { body })
|
||||
expect(response).toHaveStatusCode(200)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
import { Response } from "node-fetch"
|
||||
import AccountsAPIClient from "./accountsAPIClient"
|
||||
import { ApiKeyResponse } from "../fixtures/types/apiKeyResponse"
|
||||
|
||||
export default class AuthApi {
|
||||
api: AccountsAPIClient
|
||||
|
||||
constructor(apiClient: AccountsAPIClient) {
|
||||
this.api = apiClient
|
||||
}
|
||||
|
||||
async loginAsAdmin(): Promise<[Response, any]> {
|
||||
const response = await this.api.post(`/auth/login`, {
|
||||
body: {
|
||||
username: process.env.BB_ADMIN_USER_EMAIL,
|
||||
password: process.env.BB_ADMIN_USER_PASSWORD,
|
||||
},
|
||||
})
|
||||
const cookie = response.headers.get("set-cookie")
|
||||
this.api.cookie = cookie as any
|
||||
return [response, cookie]
|
||||
}
|
||||
|
||||
async login(email: String, password: String): Promise<[Response, any]> {
|
||||
const response = await this.api.post(`/global/auth/default/login`, {
|
||||
body: {
|
||||
username: email,
|
||||
password: password,
|
||||
},
|
||||
})
|
||||
expect(response).toHaveStatusCode(200)
|
||||
const cookie = response.headers.get("set-cookie")
|
||||
this.api.cookie = cookie as any
|
||||
return [response, cookie]
|
||||
}
|
||||
|
||||
async logout(): Promise<any> {
|
||||
return this.api.post(`/global/auth/logout`)
|
||||
}
|
||||
|
||||
async getApiKey(): Promise<ApiKeyResponse> {
|
||||
const response = await this.api.get(`/global/self/api_key`)
|
||||
const json = await response.json()
|
||||
expect(response).toHaveStatusCode(200)
|
||||
expect(json).toHaveProperty("apiKey")
|
||||
return json
|
||||
}
|
||||
}
|
|
@ -3,19 +3,82 @@ import ApplicationApi from "./applications"
|
|||
import TableApi from "./tables"
|
||||
import UserApi from "./users"
|
||||
import RowApi from "./rows"
|
||||
import AuthApi from "./auth"
|
||||
import AccountsApiClient from "./accountsAPIClient"
|
||||
import AccountsApi from "./accounts"
|
||||
import { generateAccount } from "../fixtures/accounts"
|
||||
import internalApplicationsApi from "../../internal-api/TestConfiguration/applications"
|
||||
|
||||
import InternalAPIClient from "../../internal-api/TestConfiguration/InternalAPIClient"
|
||||
|
||||
export default class TestConfiguration<T> {
|
||||
applications: ApplicationApi
|
||||
auth: AuthApi
|
||||
users: UserApi
|
||||
tables: TableApi
|
||||
rows: RowApi
|
||||
context: T
|
||||
accounts: AccountsApi
|
||||
apiClient: PublicAPIClient
|
||||
accountsApiClient: AccountsApiClient
|
||||
internalApiClient: InternalAPIClient
|
||||
internalApplicationsApi: internalApplicationsApi
|
||||
|
||||
constructor(apiClient: PublicAPIClient) {
|
||||
constructor(
|
||||
apiClient: PublicAPIClient,
|
||||
accountsApiClient: AccountsApiClient,
|
||||
internalApiClient: InternalAPIClient
|
||||
) {
|
||||
this.apiClient = apiClient
|
||||
this.accountsApiClient = accountsApiClient
|
||||
this.internalApiClient = internalApiClient
|
||||
|
||||
this.auth = new AuthApi(this.internalApiClient)
|
||||
this.accounts = new AccountsApi(this.accountsApiClient)
|
||||
this.applications = new ApplicationApi(apiClient)
|
||||
this.users = new UserApi(apiClient)
|
||||
this.tables = new TableApi(apiClient)
|
||||
this.rows = new RowApi(apiClient)
|
||||
this.internalApplicationsApi = new internalApplicationsApi(
|
||||
internalApiClient
|
||||
)
|
||||
|
||||
this.context = <T>{}
|
||||
}
|
||||
|
||||
async setupAccountAndTenant() {
|
||||
// This step is required to create a new account and tenant for the tests, its part of
|
||||
// the support for running tests in multiple environments.
|
||||
const account = generateAccount()
|
||||
await this.accounts.validateEmail(<string>account.email)
|
||||
await this.accounts.validateTenantId(<string>account.tenantId)
|
||||
process.env.TENANT_ID = <string>account.tenantId
|
||||
await this.accounts.create(account)
|
||||
await this.updateApiClients(<string>account.tenantName)
|
||||
await this.auth.login(<string>account.email, <string>account.password)
|
||||
const body = {
|
||||
name: "My first app",
|
||||
url: "my-first-app",
|
||||
useTemplate: false,
|
||||
sampleData: true,
|
||||
}
|
||||
await this.internalApplicationsApi.create(body)
|
||||
}
|
||||
|
||||
// After the account and tenant have been created, we need to get and set the API key for the test
|
||||
async setApiKey() {
|
||||
const apiKeyResponse = await this.auth.getApiKey()
|
||||
this.apiClient.setApiKey(apiKeyResponse.apiKey)
|
||||
}
|
||||
async updateApiClients(tenantName: string) {
|
||||
this.apiClient.setTenantName(tenantName)
|
||||
this.applications = new ApplicationApi(this.apiClient)
|
||||
this.rows = new RowApi(this.apiClient)
|
||||
this.internalApiClient.setTenantName(tenantName)
|
||||
this.internalApplicationsApi = new internalApplicationsApi(
|
||||
this.internalApiClient
|
||||
)
|
||||
this.auth = new AuthApi(this.internalApiClient)
|
||||
this.context = <T>{}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
import { NewAccount } from "./types/newAccount"
|
||||
|
||||
import generator from "../../generator"
|
||||
import { Hosting } from "@budibase/types"
|
||||
|
||||
export const generateAccount = (): Partial<NewAccount> => {
|
||||
const randomGuid = generator.guid()
|
||||
//Needs to start with a letter
|
||||
let tenant: string = "tenant" + randomGuid
|
||||
tenant = tenant.replace(/-/g, "")
|
||||
|
||||
return {
|
||||
email: `qa+${randomGuid}@budibase.com`,
|
||||
hosting: Hosting.CLOUD,
|
||||
name: `qa+${randomGuid}@budibase.com`,
|
||||
password: `${randomGuid}`,
|
||||
profession: "software_engineer",
|
||||
size: "10+",
|
||||
tenantId: `${tenant}`,
|
||||
tenantName: `${tenant}`,
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
export interface ApiKeyResponse {
|
||||
apiKey: string
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
userId: string
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
import { Account } from "@budibase/types"
|
||||
|
||||
export interface NewAccount extends Account {
|
||||
password: string
|
||||
}
|
|
@ -1,15 +1,25 @@
|
|||
import TestConfiguration from "../../../config/public-api/TestConfiguration"
|
||||
import PublicAPIClient from "../../../config/public-api/TestConfiguration/PublicAPIClient"
|
||||
import AccountsAPIClient from "../../../config/public-api/TestConfiguration/accountsAPIClient"
|
||||
import generateApp from "../../../config/public-api/fixtures/applications"
|
||||
import { Application } from "@budibase/server/api/controllers/public/mapping/types"
|
||||
import { db as dbCore } from "@budibase/backend-core"
|
||||
import InternalAPIClient from "../../../config/internal-api/TestConfiguration/InternalAPIClient"
|
||||
|
||||
describe("Public API - /applications endpoints", () => {
|
||||
const api = new PublicAPIClient()
|
||||
const config = new TestConfiguration<Application>(api)
|
||||
const accountsAPI = new AccountsAPIClient()
|
||||
const internalAPI = new InternalAPIClient()
|
||||
const config = new TestConfiguration<Application>(
|
||||
api,
|
||||
accountsAPI,
|
||||
internalAPI
|
||||
)
|
||||
|
||||
beforeAll(async () => {
|
||||
await config.beforeAll()
|
||||
await config.setupAccountAndTenant()
|
||||
await config.setApiKey()
|
||||
|
||||
const [response, app] = await config.applications.seed()
|
||||
config.context = app
|
||||
})
|
||||
|
|
|
@ -2,14 +2,19 @@ import { Row } from "@budibase/server/api/controllers/public/mapping/types"
|
|||
import { generateRow } from "../../../config/public-api/fixtures/tables"
|
||||
import TestConfiguration from "../../../config/public-api/TestConfiguration"
|
||||
import PublicAPIClient from "../../../config/public-api/TestConfiguration/PublicAPIClient"
|
||||
import AccountsAPIClient from "../../../config/public-api/TestConfiguration/accountsAPIClient"
|
||||
import InternalAPIClient from "../../../config/internal-api/TestConfiguration/InternalAPIClient"
|
||||
|
||||
describe("Public API - /rows endpoints", () => {
|
||||
let api = new PublicAPIClient()
|
||||
|
||||
const config = new TestConfiguration<Row>(api)
|
||||
const api = new PublicAPIClient()
|
||||
const accountsAPI = new AccountsAPIClient()
|
||||
const internalAPI = new InternalAPIClient()
|
||||
const config = new TestConfiguration<Row>(api, accountsAPI, internalAPI)
|
||||
|
||||
beforeAll(async () => {
|
||||
await config.beforeAll()
|
||||
await config.setupAccountAndTenant()
|
||||
await config.setApiKey()
|
||||
|
||||
const [aResp, app] = await config.applications.seed()
|
||||
|
||||
config.tables.api.appId = app._id
|
||||
|
|
|
@ -2,13 +2,19 @@ import { Table } from "@budibase/server/api/controllers/public/mapping/types"
|
|||
import { generateTable } from "../../../config/public-api/fixtures/tables"
|
||||
import TestConfiguration from "../../../config/public-api/TestConfiguration"
|
||||
import PublicAPIClient from "../../../config/public-api/TestConfiguration/PublicAPIClient"
|
||||
import AccountsAPIClient from "../../../config/public-api/TestConfiguration/accountsAPIClient"
|
||||
import InternalAPIClient from "../../../config/internal-api/TestConfiguration/InternalAPIClient"
|
||||
|
||||
describe("Public API - /tables endpoints", () => {
|
||||
let api = new PublicAPIClient()
|
||||
const config = new TestConfiguration<Table>(api)
|
||||
const api = new PublicAPIClient()
|
||||
const accountsAPI = new AccountsAPIClient()
|
||||
const internalAPI = new InternalAPIClient()
|
||||
const config = new TestConfiguration<Table>(api, accountsAPI, internalAPI)
|
||||
|
||||
beforeAll(async () => {
|
||||
await config.beforeAll()
|
||||
await config.setupAccountAndTenant()
|
||||
await config.setApiKey()
|
||||
|
||||
const [appResp, app] = await config.applications.seed()
|
||||
config.tables.api.appId = app._id
|
||||
|
||||
|
|
|
@ -2,13 +2,18 @@ import TestConfiguration from "../../../config/public-api/TestConfiguration"
|
|||
import PublicAPIClient from "../../../config/public-api/TestConfiguration/PublicAPIClient"
|
||||
import generateUser from "../../../config/public-api/fixtures/users"
|
||||
import { User } from "@budibase/server/api/controllers/public/mapping/types"
|
||||
import AccountsAPIClient from "../../../config/public-api/TestConfiguration/accountsAPIClient"
|
||||
import InternalAPIClient from "../../../config/internal-api/TestConfiguration/InternalAPIClient"
|
||||
|
||||
describe("Public API - /users endpoints", () => {
|
||||
const api = new PublicAPIClient()
|
||||
const config = new TestConfiguration<User>(api)
|
||||
const accountsAPI = new AccountsAPIClient()
|
||||
const internalAPI = new InternalAPIClient()
|
||||
const config = new TestConfiguration<User>(api, accountsAPI, internalAPI)
|
||||
|
||||
beforeAll(async () => {
|
||||
await config.beforeAll()
|
||||
await config.setupAccountAndTenant()
|
||||
await config.setApiKey()
|
||||
const [_, user] = await config.users.seed()
|
||||
config.context = user
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue