Merge branch 'develop' of github.com:Budibase/budibase into feature/query-transformers
This commit is contained in:
commit
e21016960e
Binary file not shown.
|
@ -1,9 +1,35 @@
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
entries:
|
entries:
|
||||||
budibase:
|
budibase:
|
||||||
|
- apiVersion: v2
|
||||||
|
appVersion: 0.9.163
|
||||||
|
created: "2021-10-12T21:58:00.515555+01:00"
|
||||||
|
dependencies:
|
||||||
|
- condition: services.couchdb.enabled
|
||||||
|
name: couchdb
|
||||||
|
repository: https://apache.github.io/couchdb-helm
|
||||||
|
version: 3.3.4
|
||||||
|
- condition: ingress.nginx
|
||||||
|
name: ingress-nginx
|
||||||
|
repository: https://github.com/kubernetes/ingress-nginx
|
||||||
|
version: 3.35.0
|
||||||
|
description: Budibase is an open source low-code platform, helping thousands of teams build apps for their workplace in minutes.
|
||||||
|
digest: f369536c0eac1f6959d51e8ce6d74a87a7a9df29ae84fb9cbed0a273ab77429b
|
||||||
|
keywords:
|
||||||
|
- low-code
|
||||||
|
- database
|
||||||
|
- cluster
|
||||||
|
name: budibase
|
||||||
|
sources:
|
||||||
|
- https://github.com/Budibase/budibase
|
||||||
|
- https://budibase.com
|
||||||
|
type: application
|
||||||
|
urls:
|
||||||
|
- https://budibase.github.io/budibase/budibase-0.2.0.tgz
|
||||||
|
version: 0.2.0
|
||||||
- apiVersion: v2
|
- apiVersion: v2
|
||||||
appVersion: 0.9.56
|
appVersion: 0.9.56
|
||||||
created: "2021-08-18T18:41:52.640176+01:00"
|
created: "2021-10-12T21:58:00.512062+01:00"
|
||||||
dependencies:
|
dependencies:
|
||||||
- condition: services.couchdb.enabled
|
- condition: services.couchdb.enabled
|
||||||
name: couchdb
|
name: couchdb
|
||||||
|
@ -28,7 +54,7 @@ entries:
|
||||||
version: 0.1.1
|
version: 0.1.1
|
||||||
- apiVersion: v2
|
- apiVersion: v2
|
||||||
appVersion: 0.9.56
|
appVersion: 0.9.56
|
||||||
created: "2021-08-18T18:41:52.635603+01:00"
|
created: "2021-10-12T21:58:00.507257+01:00"
|
||||||
dependencies:
|
dependencies:
|
||||||
- condition: services.couchdb.enabled
|
- condition: services.couchdb.enabled
|
||||||
name: couchdb
|
name: couchdb
|
||||||
|
@ -51,4 +77,4 @@ entries:
|
||||||
urls:
|
urls:
|
||||||
- https://budibase.github.io/budibase/budibase-0.1.0.tgz
|
- https://budibase.github.io/budibase/budibase-0.1.0.tgz
|
||||||
version: 0.1.0
|
version: 0.1.0
|
||||||
generated: "2021-08-18T18:41:52.629415+01:00"
|
generated: "2021-10-12T21:58:00.503447+01:00"
|
||||||
|
|
|
@ -22,13 +22,13 @@ type: application
|
||||||
# This is the chart version. This version number should be incremented each time you make changes
|
# This is the chart version. This version number should be incremented each time you make changes
|
||||||
# to the chart and its templates, including the app version.
|
# to the chart and its templates, including the app version.
|
||||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||||
version: 0.1.1
|
version: 0.2.0
|
||||||
|
|
||||||
# This is the version number of the application being deployed. This version number should be
|
# This is the version number of the application being deployed. This version number should be
|
||||||
# incremented each time you make changes to the application. Versions are not expected to
|
# incremented each time you make changes to the application. Versions are not expected to
|
||||||
# follow Semantic Versioning. They should reflect the version the application is using.
|
# follow Semantic Versioning. They should reflect the version the application is using.
|
||||||
# It is recommended to use it with quotes.
|
# It is recommended to use it with quotes.
|
||||||
appVersion: "0.9.56"
|
appVersion: "0.9.163"
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
- name: couchdb
|
- name: couchdb
|
||||||
|
@ -37,5 +37,5 @@ dependencies:
|
||||||
condition: services.couchdb.enabled
|
condition: services.couchdb.enabled
|
||||||
- name: ingress-nginx
|
- name: ingress-nginx
|
||||||
version: 3.35.0
|
version: 3.35.0
|
||||||
repository: https://kubernetes.github.io/ingress-nginx
|
repository: https://github.com/kubernetes/ingress-nginx
|
||||||
condition: services.ingress.nginx
|
condition: ingress.nginx
|
||||||
|
|
|
@ -7,6 +7,8 @@ metadata:
|
||||||
kubernetes.io/ingress.class: alb
|
kubernetes.io/ingress.class: alb
|
||||||
alb.ingress.kubernetes.io/scheme: internet-facing
|
alb.ingress.kubernetes.io/scheme: internet-facing
|
||||||
alb.ingress.kubernetes.io/target-type: ip
|
alb.ingress.kubernetes.io/target-type: ip
|
||||||
|
alb.ingress.kubernetes.io/success-codes: 200,301
|
||||||
|
alb.ingress.kubernetes.io/healthcheck-path: /
|
||||||
{{- if .Values.ingress.certificateArn }}
|
{{- if .Values.ingress.certificateArn }}
|
||||||
alb.ingress.kubernetes.io/actions.ssl-redirect: '{"Type": "redirect", "RedirectConfig": { "Protocol": "HTTPS", "Port": "443", "StatusCode": "HTTP_301"}}'
|
alb.ingress.kubernetes.io/actions.ssl-redirect: '{"Type": "redirect", "RedirectConfig": { "Protocol": "HTTPS", "Port": "443", "StatusCode": "HTTP_301"}}'
|
||||||
alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]'
|
alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]'
|
||||||
|
|
|
@ -14,7 +14,7 @@ spec:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
io.kompose.service: app-service
|
io.kompose.service: app-service
|
||||||
strategy:
|
strategy:
|
||||||
type: Recreate
|
type: RollingUpdate
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
|
@ -73,13 +73,11 @@ spec:
|
||||||
name: {{ template "budibase.fullname" . }}
|
name: {{ template "budibase.fullname" . }}
|
||||||
key: objectStoreSecret
|
key: objectStoreSecret
|
||||||
- name: MINIO_URL
|
- name: MINIO_URL
|
||||||
{{ if .Values.services.objectStore.url }}
|
|
||||||
value: {{ .Values.services.objectStore.url }}
|
value: {{ .Values.services.objectStore.url }}
|
||||||
{{ else }}
|
|
||||||
value: http://minio-service:{{ .Values.services.objectStore.port }}
|
|
||||||
{{ end }}
|
|
||||||
- name: PORT
|
- name: PORT
|
||||||
value: {{ .Values.services.apps.port | quote }}
|
value: {{ .Values.services.apps.port | quote }}
|
||||||
|
- name: MULTI_TENANCY
|
||||||
|
value: "1"
|
||||||
- name: REDIS_PASSWORD
|
- name: REDIS_PASSWORD
|
||||||
value: {{ .Values.services.redis.password }}
|
value: {{ .Values.services.redis.password }}
|
||||||
- name: REDIS_URL
|
- name: REDIS_URL
|
||||||
|
@ -92,14 +90,20 @@ spec:
|
||||||
value: {{ .Values.globals.selfHosted | quote }}
|
value: {{ .Values.globals.selfHosted | quote }}
|
||||||
- name: SENTRY_DSN
|
- name: SENTRY_DSN
|
||||||
value: {{ .Values.globals.sentryDSN }}
|
value: {{ .Values.globals.sentryDSN }}
|
||||||
|
- name: POSTHOG_TOKEN
|
||||||
|
value: {{ .Values.globals.posthogToken }}
|
||||||
- name: WORKER_URL
|
- name: WORKER_URL
|
||||||
value: worker-service:{{ .Values.services.worker.port }}
|
value: http://worker-service:{{ .Values.services.worker.port }}
|
||||||
- name: COOKIE_DOMAIN
|
- name: PLATFORM_URL
|
||||||
value: {{ .Values.globals.cookieDomain | quote }}
|
value: {{ .Values.globals.platformUrl | quote }}
|
||||||
|
- name: USE_QUOTAS
|
||||||
|
value: "1"
|
||||||
- name: ACCOUNT_PORTAL_URL
|
- name: ACCOUNT_PORTAL_URL
|
||||||
value: {{ .Values.globals.accountPortalUrl | quote }}
|
value: {{ .Values.globals.accountPortalUrl | quote }}
|
||||||
- name: ACCOUNT_PORTAL_API_KEY
|
- name: ACCOUNT_PORTAL_API_KEY
|
||||||
value: {{ .Values.globals.accountPortalApiKey | quote }}
|
value: {{ .Values.globals.accountPortalApiKey | quote }}
|
||||||
|
- name: COOKIE_DOMAIN
|
||||||
|
value: {{ .Values.globals.cookieDomain | quote }}
|
||||||
image: budibase/apps
|
image: budibase/apps
|
||||||
imagePullPolicy: Always
|
imagePullPolicy: Always
|
||||||
name: bbapps
|
name: bbapps
|
||||||
|
|
|
@ -14,7 +14,7 @@ spec:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
app.kubernetes.io/name: budibase-proxy
|
app.kubernetes.io/name: budibase-proxy
|
||||||
strategy:
|
strategy:
|
||||||
type: Recreate
|
type: RollingUpdate
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
|
@ -26,7 +26,7 @@ spec:
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- image: budibase/proxy
|
- image: budibase/proxy
|
||||||
imagePullPolicy: ""
|
imagePullPolicy: Always
|
||||||
name: proxy-service
|
name: proxy-service
|
||||||
ports:
|
ports:
|
||||||
- containerPort: {{ .Values.services.proxy.port }}
|
- containerPort: {{ .Values.services.proxy.port }}
|
||||||
|
|
|
@ -15,7 +15,7 @@ spec:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
io.kompose.service: worker-service
|
io.kompose.service: worker-service
|
||||||
strategy:
|
strategy:
|
||||||
type: Recreate
|
type: RollingUpdate
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
|
@ -70,13 +70,11 @@ spec:
|
||||||
name: {{ template "budibase.fullname" . }}
|
name: {{ template "budibase.fullname" . }}
|
||||||
key: objectStoreSecret
|
key: objectStoreSecret
|
||||||
- name: MINIO_URL
|
- name: MINIO_URL
|
||||||
{{ if .Values.services.objectStore.url }}
|
|
||||||
value: {{ .Values.services.objectStore.url }}
|
value: {{ .Values.services.objectStore.url }}
|
||||||
{{ else }}
|
|
||||||
value: http://minio-service:{{ .Values.services.objectStore.port }}
|
|
||||||
{{ end }}
|
|
||||||
- name: PORT
|
- name: PORT
|
||||||
value: {{ .Values.services.worker.port | quote }}
|
value: {{ .Values.services.worker.port | quote }}
|
||||||
|
- name: MULTI_TENANCY
|
||||||
|
value: "1"
|
||||||
- name: REDIS_PASSWORD
|
- name: REDIS_PASSWORD
|
||||||
value: {{ .Values.services.redis.password | quote }}
|
value: {{ .Values.services.redis.password | quote }}
|
||||||
- name: REDIS_URL
|
- name: REDIS_URL
|
||||||
|
@ -91,8 +89,22 @@ spec:
|
||||||
value: {{ .Values.globals.accountPortalUrl | quote }}
|
value: {{ .Values.globals.accountPortalUrl | quote }}
|
||||||
- name: ACCOUNT_PORTAL_API_KEY
|
- name: ACCOUNT_PORTAL_API_KEY
|
||||||
value: {{ .Values.globals.accountPortalApiKey | quote }}
|
value: {{ .Values.globals.accountPortalApiKey | quote }}
|
||||||
|
- name: PLATFORM_URL
|
||||||
|
value: {{ .Values.globals.platformUrl | quote }}
|
||||||
- name: COOKIE_DOMAIN
|
- name: COOKIE_DOMAIN
|
||||||
value: {{ .Values.globals.cookieDomain | quote }}
|
value: {{ .Values.globals.cookieDomain | quote }}
|
||||||
|
- name: SMTP_FALLBACK_ENABLED
|
||||||
|
value: {{ .Values.globals.smtp.enabled | quote }}
|
||||||
|
- name: SMTP_USER
|
||||||
|
value: {{ .Values.globals.smtp.user | quote }}
|
||||||
|
- name: SMTP_PASSWORD
|
||||||
|
value: {{ .Values.globals.smtp.password | quote }}
|
||||||
|
- name: SMTP_HOST
|
||||||
|
value: {{ .Values.globals.smtp.host | quote }}
|
||||||
|
- name: SMTP_PORT
|
||||||
|
value: {{ .Values.globals.smtp.port | quote }}
|
||||||
|
- name: SMTP_FROM_ADDRESS
|
||||||
|
value: {{ .Values.globals.smtp.from | quote }}
|
||||||
image: budibase/worker
|
image: budibase/worker
|
||||||
imagePullPolicy: Always
|
imagePullPolicy: Always
|
||||||
name: bbworker
|
name: bbworker
|
||||||
|
|
|
@ -40,11 +40,12 @@ service:
|
||||||
port: 10000
|
port: 10000
|
||||||
|
|
||||||
ingress:
|
ingress:
|
||||||
enabled: true
|
enabled: false
|
||||||
nginx: true
|
aws: false
|
||||||
certificateArn: ""
|
nginx: true
|
||||||
|
certificateArn: ""
|
||||||
className: ""
|
className: ""
|
||||||
annotations:
|
annotations:
|
||||||
kubernetes.io/ingress.class: nginx
|
kubernetes.io/ingress.class: nginx
|
||||||
hosts:
|
hosts:
|
||||||
- host: # change if using custom domain
|
- host: # change if using custom domain
|
||||||
|
@ -55,7 +56,7 @@ ingress:
|
||||||
service:
|
service:
|
||||||
name: proxy-service
|
name: proxy-service
|
||||||
port:
|
port:
|
||||||
number: 10000
|
number: 10000
|
||||||
|
|
||||||
resources: {}
|
resources: {}
|
||||||
# We usually recommend not to specify default resources and to leave this as a conscious
|
# We usually recommend not to specify default resources and to leave this as a conscious
|
||||||
|
@ -84,20 +85,24 @@ affinity: {}
|
||||||
|
|
||||||
globals:
|
globals:
|
||||||
budibaseEnv: PRODUCTION
|
budibaseEnv: PRODUCTION
|
||||||
enableAnalytics: false
|
enableAnalytics: true
|
||||||
posthogToken: ""
|
|
||||||
sentryDSN: ""
|
sentryDSN: ""
|
||||||
|
posthogToken: ""
|
||||||
logLevel: info
|
logLevel: info
|
||||||
selfHosted: 1
|
selfHosted: ""
|
||||||
accountPortalUrL: ""
|
accountPortalUrl: ""
|
||||||
accountPortalApiKey: ""
|
accountPortalApiKey: ""
|
||||||
cookieDomain: ""
|
cookieDomain: ""
|
||||||
|
platformUrl: ""
|
||||||
|
|
||||||
createSecrets: true # creates an internal API key, JWT secrets and redis password for you
|
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
|
# if createSecrets is set to false, you can hard-code your secrets here
|
||||||
internalApiKey: ""
|
internalApiKey: ""
|
||||||
jwtSecret: ""
|
jwtSecret: ""
|
||||||
|
|
||||||
|
smtp:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
services:
|
services:
|
||||||
dns: cluster.local
|
dns: cluster.local
|
||||||
|
@ -118,12 +123,12 @@ services:
|
||||||
couchdb:
|
couchdb:
|
||||||
enabled: true
|
enabled: true
|
||||||
replicaCount: 3
|
replicaCount: 3
|
||||||
url: "" # only change if pointing to existing couch server
|
# url: "" # only change if pointing to existing couch server
|
||||||
user: "" # only change if pointing to existing couch server
|
# user: "" # only change if pointing to existing couch server
|
||||||
password: "" # only change if pointing to existing couch server
|
# password: "" # only change if pointing to existing couch server
|
||||||
port: 5984
|
port: 5984
|
||||||
storage: 100Mi
|
storage: 100Mi
|
||||||
|
|
||||||
redis:
|
redis:
|
||||||
enabled: true # disable if using external redis
|
enabled: true # disable if using external redis
|
||||||
port: 6379
|
port: 6379
|
||||||
|
@ -131,7 +136,7 @@ services:
|
||||||
url: "" # only change if pointing to existing redis cluster and enabled: false
|
url: "" # only change if pointing to existing redis cluster and enabled: false
|
||||||
password: "budibase" # recommended to override if using built-in redis
|
password: "budibase" # recommended to override if using built-in redis
|
||||||
storage: 100Mi
|
storage: 100Mi
|
||||||
|
|
||||||
objectStore:
|
objectStore:
|
||||||
minio: true
|
minio: true
|
||||||
browser: true
|
browser: true
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"version": "0.9.163",
|
"version": "0.9.166",
|
||||||
"npmClient": "yarn",
|
"npmClient": "yarn",
|
||||||
"packages": [
|
"packages": [
|
||||||
"packages/*"
|
"packages/*"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/auth",
|
"name": "@budibase/auth",
|
||||||
"version": "0.9.163",
|
"version": "0.9.166",
|
||||||
"description": "Authentication middlewares for budibase builder and apps",
|
"description": "Authentication middlewares for budibase builder and apps",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"author": "Budibase",
|
"author": "Budibase",
|
||||||
|
|
|
@ -42,8 +42,9 @@ module.exports = (
|
||||||
internal = false
|
internal = false
|
||||||
if (authCookie) {
|
if (authCookie) {
|
||||||
let error = null
|
let error = null
|
||||||
const sessionId = authCookie.sessionId,
|
const sessionId = authCookie.sessionId
|
||||||
userId = authCookie.userId
|
const userId = authCookie.userId
|
||||||
|
|
||||||
const session = await getSession(userId, sessionId)
|
const session = await getSession(userId, sessionId)
|
||||||
if (!session) {
|
if (!session) {
|
||||||
error = "No session found"
|
error = "No session found"
|
||||||
|
|
|
@ -24,17 +24,24 @@ exports.createASession = async (userId, session) => {
|
||||||
await client.store(makeSessionID(userId, sessionId), session, EXPIRY_SECONDS)
|
await client.store(makeSessionID(userId, sessionId), session, EXPIRY_SECONDS)
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.invalidateSessions = async (userId, sessionId = null) => {
|
exports.invalidateSessions = async (userId, sessionIds = null) => {
|
||||||
let sessions = []
|
let sessions = []
|
||||||
if (sessionId) {
|
|
||||||
sessions.push({ key: makeSessionID(userId, sessionId) })
|
// If no sessionIds, get all the sessions for the user
|
||||||
} else {
|
if (!sessionIds) {
|
||||||
sessions = await getSessionsForUser(userId)
|
sessions = await getSessionsForUser(userId)
|
||||||
sessions.forEach(
|
sessions.forEach(
|
||||||
session =>
|
session =>
|
||||||
(session.key = makeSessionID(session.userId, session.sessionId))
|
(session.key = makeSessionID(session.userId, session.sessionId))
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
// use the passed array of sessionIds
|
||||||
|
sessions = Array.isArray(sessionIds) ? sessionIds : [sessionIds]
|
||||||
|
sessions = sessions.map(sessionId => ({
|
||||||
|
key: makeSessionID(userId, sessionId),
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
const client = await redis.getSessionClient()
|
const client = await redis.getSessionClient()
|
||||||
const promises = []
|
const promises = []
|
||||||
for (let session of sessions) {
|
for (let session of sessions) {
|
||||||
|
|
|
@ -7,7 +7,7 @@ const {
|
||||||
const jwt = require("jsonwebtoken")
|
const jwt = require("jsonwebtoken")
|
||||||
const { options } = require("./middleware/passport/jwt")
|
const { options } = require("./middleware/passport/jwt")
|
||||||
const { createUserEmailView } = require("./db/views")
|
const { createUserEmailView } = require("./db/views")
|
||||||
const { Headers, UserStatus } = require("./constants")
|
const { Headers, UserStatus, Cookies } = require("./constants")
|
||||||
const {
|
const {
|
||||||
getGlobalDB,
|
getGlobalDB,
|
||||||
updateTenantId,
|
updateTenantId,
|
||||||
|
@ -19,6 +19,7 @@ const accounts = require("./cloud/accounts")
|
||||||
const { hash } = require("./hashing")
|
const { hash } = require("./hashing")
|
||||||
const userCache = require("./cache/user")
|
const userCache = require("./cache/user")
|
||||||
const env = require("./environment")
|
const env = require("./environment")
|
||||||
|
const { getUserSessions, invalidateSessions } = require("./security/sessions")
|
||||||
|
|
||||||
const APP_PREFIX = DocumentTypes.APP + SEPARATOR
|
const APP_PREFIX = DocumentTypes.APP + SEPARATOR
|
||||||
|
|
||||||
|
@ -235,3 +236,28 @@ exports.saveUser = async (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs a user out from budibase. Re-used across account portal and builder.
|
||||||
|
*/
|
||||||
|
exports.platformLogout = async ({ ctx, userId, keepActiveSession }) => {
|
||||||
|
if (!ctx) throw new Error("Koa context must be supplied to logout.")
|
||||||
|
|
||||||
|
const currentSession = this.getCookie(ctx, Cookies.Auth)
|
||||||
|
let sessions = await getUserSessions(userId)
|
||||||
|
|
||||||
|
if (keepActiveSession) {
|
||||||
|
sessions = sessions.filter(
|
||||||
|
session => session.sessionId !== currentSession.sessionId
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
// clear cookies
|
||||||
|
this.clearCookie(ctx, Cookies.Auth)
|
||||||
|
this.clearCookie(ctx, Cookies.CurrentApp)
|
||||||
|
}
|
||||||
|
|
||||||
|
await invalidateSessions(
|
||||||
|
userId,
|
||||||
|
sessions.map(({ sessionId }) => sessionId)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/bbui",
|
"name": "@budibase/bbui",
|
||||||
"description": "A UI solution used in the different Budibase projects.",
|
"description": "A UI solution used in the different Budibase projects.",
|
||||||
"version": "0.9.163",
|
"version": "0.9.166",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"svelte": "src/index.js",
|
"svelte": "src/index.js",
|
||||||
"module": "dist/bbui.es.js",
|
"module": "dist/bbui.es.js",
|
||||||
|
|
|
@ -5,11 +5,14 @@
|
||||||
import RelationshipRenderer from "./RelationshipRenderer.svelte"
|
import RelationshipRenderer from "./RelationshipRenderer.svelte"
|
||||||
import AttachmentRenderer from "./AttachmentRenderer.svelte"
|
import AttachmentRenderer from "./AttachmentRenderer.svelte"
|
||||||
import ArrayRenderer from "./ArrayRenderer.svelte"
|
import ArrayRenderer from "./ArrayRenderer.svelte"
|
||||||
|
import InternalRenderer from "./InternalRenderer.svelte"
|
||||||
|
|
||||||
export let row
|
export let row
|
||||||
export let schema
|
export let schema
|
||||||
export let value
|
export let value
|
||||||
export let customRenderers = []
|
export let customRenderers = []
|
||||||
|
|
||||||
|
let renderer
|
||||||
const typeMap = {
|
const typeMap = {
|
||||||
boolean: BooleanRenderer,
|
boolean: BooleanRenderer,
|
||||||
datetime: DateTimeRenderer,
|
datetime: DateTimeRenderer,
|
||||||
|
@ -20,7 +23,9 @@
|
||||||
number: StringRenderer,
|
number: StringRenderer,
|
||||||
longform: StringRenderer,
|
longform: StringRenderer,
|
||||||
array: ArrayRenderer,
|
array: ArrayRenderer,
|
||||||
|
internal: InternalRenderer,
|
||||||
}
|
}
|
||||||
|
|
||||||
$: type = schema?.type ?? "string"
|
$: type = schema?.type ?? "string"
|
||||||
$: customRenderer = customRenderers?.find(x => x.column === schema?.name)
|
$: customRenderer = customRenderers?.find(x => x.column === schema?.name)
|
||||||
$: renderer = customRenderer?.component ?? typeMap[type] ?? StringRenderer
|
$: renderer = customRenderer?.component ?? typeMap[type] ?? StringRenderer
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
<script>
|
||||||
|
import Icon from "../Icon/Icon.svelte"
|
||||||
|
import { notifications } from "../Stores/notifications"
|
||||||
|
export let value
|
||||||
|
|
||||||
|
const onClick = e => {
|
||||||
|
e.stopPropagation()
|
||||||
|
copyToClipboard(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
function copyToClipboard(value) {
|
||||||
|
navigator.clipboard.writeText(value).then(() => {
|
||||||
|
notifications.success("Copied")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div on:click|stopPropagation={onClick}>
|
||||||
|
<Icon size="S" name="Copy" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
div {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
width: 150px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -31,6 +31,7 @@ context("Create a Table", () => {
|
||||||
cy.contains("nameupdated ").should("contain", "nameupdated")
|
cy.contains("nameupdated ").should("contain", "nameupdated")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/*
|
||||||
it("edits a row", () => {
|
it("edits a row", () => {
|
||||||
cy.contains("button", "Edit").click({ force: true })
|
cy.contains("button", "Edit").click({ force: true })
|
||||||
cy.wait(1000)
|
cy.wait(1000)
|
||||||
|
@ -39,7 +40,7 @@ context("Create a Table", () => {
|
||||||
cy.contains("Save").click()
|
cy.contains("Save").click()
|
||||||
cy.contains("Updated").should("have.text", "Updated")
|
cy.contains("Updated").should("have.text", "Updated")
|
||||||
})
|
})
|
||||||
|
*/
|
||||||
it("deletes a row", () => {
|
it("deletes a row", () => {
|
||||||
cy.get(".spectrum-Checkbox-input").check({ force: true })
|
cy.get(".spectrum-Checkbox-input").check({ force: true })
|
||||||
cy.contains("Delete 1 row(s)").click()
|
cy.contains("Delete 1 row(s)").click()
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/builder",
|
"name": "@budibase/builder",
|
||||||
"version": "0.9.163",
|
"version": "0.9.166",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -65,10 +65,10 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/bbui": "^0.9.163",
|
"@budibase/bbui": "^0.9.166",
|
||||||
"@budibase/client": "^0.9.163",
|
"@budibase/client": "^0.9.166",
|
||||||
"@budibase/colorpicker": "1.1.2",
|
"@budibase/colorpicker": "1.1.2",
|
||||||
"@budibase/string-templates": "^0.9.163",
|
"@budibase/string-templates": "^0.9.166",
|
||||||
"@sentry/browser": "5.19.1",
|
"@sentry/browser": "5.19.1",
|
||||||
"@spectrum-css/page": "^3.0.1",
|
"@spectrum-css/page": "^3.0.1",
|
||||||
"@spectrum-css/vars": "^3.0.1",
|
"@spectrum-css/vars": "^3.0.1",
|
||||||
|
|
|
@ -14,7 +14,7 @@ export default class Automation {
|
||||||
}
|
}
|
||||||
|
|
||||||
addTestData(data) {
|
addTestData(data) {
|
||||||
this.automation.testData = data
|
this.automation.testData = { ...this.automation.testData, ...data }
|
||||||
}
|
}
|
||||||
|
|
||||||
addBlock(block, idx) {
|
addBlock(block, idx) {
|
||||||
|
|
|
@ -5,20 +5,24 @@
|
||||||
import { cloneDeep } from "lodash/fp"
|
import { cloneDeep } from "lodash/fp"
|
||||||
|
|
||||||
let failedParse = null
|
let failedParse = null
|
||||||
|
let trigger = {}
|
||||||
|
let schemaProperties = {}
|
||||||
|
|
||||||
// clone the trigger so we're not mutating the reference
|
// clone the trigger so we're not mutating the reference
|
||||||
let trigger = cloneDeep(
|
$: trigger = cloneDeep(
|
||||||
$automationStore.selectedAutomation.automation.definition.trigger
|
$automationStore.selectedAutomation.automation.definition.trigger
|
||||||
)
|
)
|
||||||
let schemaProperties = Object.entries(trigger.schema.outputs.properties || {})
|
|
||||||
|
// get the outputs so we can define the fields
|
||||||
|
$: schemaProperties = Object.entries(trigger?.schema?.outputs?.properties)
|
||||||
|
|
||||||
if (!$automationStore.selectedAutomation.automation.testData) {
|
if (!$automationStore.selectedAutomation.automation.testData) {
|
||||||
$automationStore.selectedAutomation.automation.testData = {}
|
$automationStore.selectedAutomation.automation.testData = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the outputs so we can define the fields
|
|
||||||
|
|
||||||
// check to see if there is existing test data in the store
|
// check to see if there is existing test data in the store
|
||||||
$: testData = $automationStore.selectedAutomation.automation.testData
|
$: testData = $automationStore.selectedAutomation.automation.testData || {}
|
||||||
|
|
||||||
// Check the schema to see if required fields have been entered
|
// Check the schema to see if required fields have been entered
|
||||||
$: isError = !trigger.schema.outputs.required.every(
|
$: isError = !trigger.schema.outputs.required.every(
|
||||||
required => testData[required]
|
required => testData[required]
|
||||||
|
@ -41,7 +45,6 @@
|
||||||
showConfirmButton={true}
|
showConfirmButton={true}
|
||||||
disabled={isError}
|
disabled={isError}
|
||||||
onConfirm={() => {
|
onConfirm={() => {
|
||||||
automationStore.actions.addTestDataToAutomation(testData)
|
|
||||||
automationStore.actions.test(
|
automationStore.actions.test(
|
||||||
$automationStore.selectedAutomation?.automation,
|
$automationStore.selectedAutomation?.automation,
|
||||||
testData
|
testData
|
||||||
|
@ -53,7 +56,7 @@
|
||||||
><Tab icon="Form" title="Form">
|
><Tab icon="Form" title="Form">
|
||||||
<div class="tab-content-padding">
|
<div class="tab-content-padding">
|
||||||
<AutomationBlockSetup
|
<AutomationBlockSetup
|
||||||
bind:testData
|
{testData}
|
||||||
{schemaProperties}
|
{schemaProperties}
|
||||||
isTestModal
|
isTestModal
|
||||||
block={trigger}
|
block={trigger}
|
||||||
|
|
|
@ -9,7 +9,10 @@
|
||||||
Label,
|
Label,
|
||||||
ActionButton,
|
ActionButton,
|
||||||
Drawer,
|
Drawer,
|
||||||
|
Modal,
|
||||||
} from "@budibase/bbui"
|
} from "@budibase/bbui"
|
||||||
|
import CreateWebhookModal from "components/automation/Shared/CreateWebhookModal.svelte"
|
||||||
|
|
||||||
import { automationStore } from "builderStore"
|
import { automationStore } from "builderStore"
|
||||||
import { tables } from "stores/backend"
|
import { tables } from "stores/backend"
|
||||||
import WebhookDisplay from "../Shared/WebhookDisplay.svelte"
|
import WebhookDisplay from "../Shared/WebhookDisplay.svelte"
|
||||||
|
@ -27,13 +30,14 @@
|
||||||
import { buildLuceneQuery } from "helpers/lucene"
|
import { buildLuceneQuery } from "helpers/lucene"
|
||||||
|
|
||||||
export let block
|
export let block
|
||||||
export let webhookModal
|
|
||||||
export let testData
|
export let testData
|
||||||
export let schemaProperties
|
export let schemaProperties
|
||||||
export let isTestModal = false
|
export let isTestModal = false
|
||||||
|
let webhookModal
|
||||||
let drawer
|
let drawer
|
||||||
let tempFilters = lookForFilters(schemaProperties) || []
|
let tempFilters = lookForFilters(schemaProperties) || []
|
||||||
let fillWidth = true
|
let fillWidth = true
|
||||||
|
|
||||||
$: stepId = block.stepId
|
$: stepId = block.stepId
|
||||||
$: bindings = getAvailableBindings(
|
$: bindings = getAvailableBindings(
|
||||||
block || $automationStore.selectedBlock,
|
block || $automationStore.selectedBlock,
|
||||||
|
@ -50,6 +54,18 @@
|
||||||
const onChange = debounce(
|
const onChange = debounce(
|
||||||
async function (e, key) {
|
async function (e, key) {
|
||||||
if (isTestModal) {
|
if (isTestModal) {
|
||||||
|
// Special case for webhook, as it requires a body, but the schema already brings back the body's contents
|
||||||
|
if (stepId === "WEBHOOK") {
|
||||||
|
automationStore.actions.addTestDataToAutomation({
|
||||||
|
body: {
|
||||||
|
[key]: e.detail,
|
||||||
|
...$automationStore.selectedAutomation.automation.testData.body,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
automationStore.actions.addTestDataToAutomation({
|
||||||
|
[key]: e.detail,
|
||||||
|
})
|
||||||
testData[key] = e.detail
|
testData[key] = e.detail
|
||||||
} else {
|
} else {
|
||||||
block.inputs[key] = e.detail
|
block.inputs[key] = e.detail
|
||||||
|
@ -206,7 +222,10 @@
|
||||||
{bindings}
|
{bindings}
|
||||||
/>
|
/>
|
||||||
{:else if value.customType === "webhookUrl"}
|
{:else if value.customType === "webhookUrl"}
|
||||||
<WebhookDisplay value={inputData[key]} />
|
<WebhookDisplay
|
||||||
|
on:change={e => onChange(e, key)}
|
||||||
|
value={inputData[key]}
|
||||||
|
/>
|
||||||
{:else if value.customType === "triggerSchema"}
|
{:else if value.customType === "triggerSchema"}
|
||||||
<SchemaSetup on:change={e => onChange(e, key)} value={inputData[key]} />
|
<SchemaSetup on:change={e => onChange(e, key)} value={inputData[key]} />
|
||||||
{:else if value.customType === "code"}
|
{:else if value.customType === "code"}
|
||||||
|
@ -249,6 +268,10 @@
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
<Modal bind:this={webhookModal} width="30%">
|
||||||
|
<CreateWebhookModal />
|
||||||
|
</Modal>
|
||||||
|
|
||||||
{#if stepId === "WEBHOOK"}
|
{#if stepId === "WEBHOOK"}
|
||||||
<Button secondary on:click={() => webhookModal.show()}>Set Up Webhook</Button>
|
<Button secondary on:click={() => webhookModal.show()}>Set Up Webhook</Button>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -5,16 +5,29 @@
|
||||||
import AutomationBindingPanel from "../../common/bindings/ServerBindingPanel.svelte"
|
import AutomationBindingPanel from "../../common/bindings/ServerBindingPanel.svelte"
|
||||||
import { createEventDispatcher } from "svelte"
|
import { createEventDispatcher } from "svelte"
|
||||||
import ModalBindableInput from "components/common/bindings/ModalBindableInput.svelte"
|
import ModalBindableInput from "components/common/bindings/ModalBindableInput.svelte"
|
||||||
|
import LinkedRowSelector from "components/common/LinkedRowSelector.svelte"
|
||||||
import { automationStore } from "builderStore"
|
import { automationStore } from "builderStore"
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
|
|
||||||
export let value
|
export let value
|
||||||
export let bindings
|
export let bindings
|
||||||
$: table = $tables.list.find(table => table._id === value?.tableId)
|
let table
|
||||||
$: schemaFields = Object.entries(table?.schema ?? {})
|
let schemaFields
|
||||||
|
|
||||||
|
$: {
|
||||||
|
table = $tables.list.find(table => table._id === value?.tableId)
|
||||||
|
schemaFields = Object.entries(table?.schema ?? {})
|
||||||
|
// surface the schema so the user can see it in the json
|
||||||
|
schemaFields.map(([, schema]) => {
|
||||||
|
if (!schema.autocolumn && !value[schema.name]) {
|
||||||
|
value[schema.name] = ""
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const onChangeTable = e => {
|
const onChangeTable = e => {
|
||||||
value = { tableId: e.detail }
|
value["tableId"] = e.detail
|
||||||
dispatch("change", value)
|
dispatch("change", value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,6 +82,8 @@
|
||||||
label={field}
|
label={field}
|
||||||
options={schema.constraints.inclusion}
|
options={schema.constraints.inclusion}
|
||||||
/>
|
/>
|
||||||
|
{:else if schema.type === "link"}
|
||||||
|
<LinkedRowSelector bind:linkedRows={value[field]} {schema} />
|
||||||
{:else if schema.type === "string" || schema.type === "number"}
|
{:else if schema.type === "string" || schema.type === "number"}
|
||||||
{#if $automationStore.selectedAutomation.automation.testData}
|
{#if $automationStore.selectedAutomation.automation.testData}
|
||||||
<ModalBindableInput
|
<ModalBindableInput
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { Icon } from "@budibase/bbui"
|
import { Icon } from "@budibase/bbui"
|
||||||
import { automationStore } from "builderStore"
|
import { automationStore } from "builderStore"
|
||||||
import { database } from "stores/backend"
|
|
||||||
import WebhookDisplay from "./WebhookDisplay.svelte"
|
import WebhookDisplay from "./WebhookDisplay.svelte"
|
||||||
import { ModalContent } from "@budibase/bbui"
|
import { ModalContent } from "@budibase/bbui"
|
||||||
import { onMount, onDestroy } from "svelte"
|
import { onMount, onDestroy } from "svelte"
|
||||||
|
@ -12,7 +11,6 @@
|
||||||
let schemaURL
|
let schemaURL
|
||||||
let propCount = 0
|
let propCount = 0
|
||||||
|
|
||||||
$: instanceId = $database._id
|
|
||||||
$: automation = $automationStore.selectedAutomation?.automation
|
$: automation = $automationStore.selectedAutomation?.automation
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
|
|
|
@ -16,11 +16,29 @@
|
||||||
import { Pagination } from "@budibase/bbui"
|
import { Pagination } from "@budibase/bbui"
|
||||||
|
|
||||||
let hideAutocolumns = true
|
let hideAutocolumns = true
|
||||||
|
let schema
|
||||||
$: isUsersTable = $tables.selected?._id === TableNames.USERS
|
$: isUsersTable = $tables.selected?._id === TableNames.USERS
|
||||||
$: schema = $tables.selected?.schema
|
|
||||||
$: type = $tables.selected?.type
|
$: type = $tables.selected?.type
|
||||||
$: isInternal = type !== "external"
|
$: isInternal = type !== "external"
|
||||||
|
$: {
|
||||||
|
schema = $tables.selected?.schema
|
||||||
|
|
||||||
|
// Manually add these as we don't want them to be 'real' auto-columns
|
||||||
|
schema._id = {
|
||||||
|
type: "internal",
|
||||||
|
editable: false,
|
||||||
|
displayName: "ID",
|
||||||
|
autocolumn: true,
|
||||||
|
}
|
||||||
|
if (isInternal) {
|
||||||
|
schema._rev = {
|
||||||
|
type: "internal",
|
||||||
|
editable: false,
|
||||||
|
displayName: "Revision",
|
||||||
|
autocolumn: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
$: id = $tables.selected?._id
|
$: id = $tables.selected?._id
|
||||||
$: search = searchTable(id)
|
$: search = searchTable(id)
|
||||||
$: columnOptions = Object.keys($search.schema || {})
|
$: columnOptions = Object.keys($search.schema || {})
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
const FORMULA_TYPE = FIELDS.FORMULA.type
|
const FORMULA_TYPE = FIELDS.FORMULA.type
|
||||||
const LINK_TYPE = FIELDS.LINK.type
|
const LINK_TYPE = FIELDS.LINK.type
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
|
const PROHIBITED_COLUMN_NAMES = ["type", "_id", "_rev", "tableId"]
|
||||||
const { hide } = getContext(Context.Modal)
|
const { hide } = getContext(Context.Modal)
|
||||||
let fieldDefinitions = cloneDeep(FIELDS)
|
let fieldDefinitions = cloneDeep(FIELDS)
|
||||||
|
|
||||||
|
@ -66,7 +67,11 @@
|
||||||
(field.type === LINK_TYPE && !field.tableId) ||
|
(field.type === LINK_TYPE && !field.tableId) ||
|
||||||
Object.keys($tables.draft?.schema ?? {}).some(
|
Object.keys($tables.draft?.schema ?? {}).some(
|
||||||
key => key !== originalName && key === field.name
|
key => key !== originalName && key === field.name
|
||||||
)
|
) ||
|
||||||
|
columnNameInvalid
|
||||||
|
$: columnNameInvalid = PROHIBITED_COLUMN_NAMES.some(
|
||||||
|
name => field.name === name
|
||||||
|
)
|
||||||
|
|
||||||
// used to select what different options can be displayed for column type
|
// used to select what different options can be displayed for column type
|
||||||
$: canBeSearched =
|
$: canBeSearched =
|
||||||
|
@ -200,6 +205,9 @@
|
||||||
label="Name"
|
label="Name"
|
||||||
bind:value={field.name}
|
bind:value={field.name}
|
||||||
disabled={uneditable || (linkEditDisabled && field.type === LINK_TYPE)}
|
disabled={uneditable || (linkEditDisabled && field.type === LINK_TYPE)}
|
||||||
|
error={columnNameInvalid
|
||||||
|
? `${PROHIBITED_COLUMN_NAMES.join(", ")} are not allowed as column names`
|
||||||
|
: ""}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Select
|
<Select
|
||||||
|
|
|
@ -1,10 +1,18 @@
|
||||||
<script>
|
<script>
|
||||||
import { Label, Input, Layout, Toggle, Button } from "@budibase/bbui"
|
import {
|
||||||
|
Label,
|
||||||
|
Input,
|
||||||
|
Layout,
|
||||||
|
Toggle,
|
||||||
|
Button,
|
||||||
|
TextArea,
|
||||||
|
} from "@budibase/bbui"
|
||||||
import KeyValueBuilder from "components/integration/KeyValueBuilder.svelte"
|
import KeyValueBuilder from "components/integration/KeyValueBuilder.svelte"
|
||||||
import { capitalise } from "helpers"
|
import { capitalise } from "helpers"
|
||||||
|
|
||||||
export let integration
|
export let integration
|
||||||
export let schema
|
export let schema
|
||||||
|
|
||||||
let addButton
|
let addButton
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -29,6 +37,15 @@
|
||||||
<Label>{capitalise(configKey)}</Label>
|
<Label>{capitalise(configKey)}</Label>
|
||||||
<Toggle text="" bind:value={integration[configKey]} />
|
<Toggle text="" bind:value={integration[configKey]} />
|
||||||
</div>
|
</div>
|
||||||
|
{:else if schema[configKey].type === "longForm"}
|
||||||
|
<div class="form-row">
|
||||||
|
<Label>{capitalise(configKey)}</Label>
|
||||||
|
<TextArea
|
||||||
|
type={schema[configKey].type}
|
||||||
|
on:change
|
||||||
|
bind:value={integration[configKey]}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<Label>{capitalise(configKey)}</Label>
|
<Label>{capitalise(configKey)}</Label>
|
||||||
|
|
|
@ -60,7 +60,7 @@
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
<Modal bind:this={externalDatasourceModal}>
|
<Modal bind:this={externalDatasourceModal}>
|
||||||
<DatasourceConfigModal {integration} />
|
<DatasourceConfigModal {integration} {modal} />
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
<Modal bind:this={modal}>
|
<Modal bind:this={modal}>
|
||||||
|
|
|
@ -64,7 +64,7 @@
|
||||||
? "Fetch tables from database"
|
? "Fetch tables from database"
|
||||||
: "Save and continue to query"}
|
: "Save and continue to query"}
|
||||||
cancelText="Back"
|
cancelText="Back"
|
||||||
size="M"
|
size="L"
|
||||||
>
|
>
|
||||||
<Layout noPadding>
|
<Layout noPadding>
|
||||||
<Body size="XS"
|
<Body size="XS"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/cli",
|
"name": "@budibase/cli",
|
||||||
"version": "0.9.163",
|
"version": "0.9.166",
|
||||||
"description": "Budibase CLI, for developers, self hosting and migrations.",
|
"description": "Budibase CLI, for developers, self hosting and migrations.",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/client",
|
"name": "@budibase/client",
|
||||||
"version": "0.9.163",
|
"version": "0.9.166",
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"module": "dist/budibase-client.js",
|
"module": "dist/budibase-client.js",
|
||||||
"main": "dist/budibase-client.js",
|
"main": "dist/budibase-client.js",
|
||||||
|
@ -19,9 +19,9 @@
|
||||||
"dev:builder": "rollup -cw"
|
"dev:builder": "rollup -cw"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/bbui": "^0.9.163",
|
"@budibase/bbui": "^0.9.166",
|
||||||
"@budibase/standard-components": "^0.9.139",
|
"@budibase/standard-components": "^0.9.139",
|
||||||
"@budibase/string-templates": "^0.9.163",
|
"@budibase/string-templates": "^0.9.166",
|
||||||
"regexparam": "^1.3.0",
|
"regexparam": "^1.3.0",
|
||||||
"shortid": "^2.2.15",
|
"shortid": "^2.2.15",
|
||||||
"svelte-spa-router": "^3.0.5"
|
"svelte-spa-router": "^3.0.5"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/server",
|
"name": "@budibase/server",
|
||||||
"email": "hi@budibase.com",
|
"email": "hi@budibase.com",
|
||||||
"version": "0.9.163",
|
"version": "0.9.166",
|
||||||
"description": "Budibase Web Server",
|
"description": "Budibase Web Server",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@ -68,9 +68,9 @@
|
||||||
"author": "Budibase",
|
"author": "Budibase",
|
||||||
"license": "AGPL-3.0-or-later",
|
"license": "AGPL-3.0-or-later",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/auth": "^0.9.163",
|
"@budibase/auth": "^0.9.166",
|
||||||
"@budibase/client": "^0.9.163",
|
"@budibase/client": "^0.9.166",
|
||||||
"@budibase/string-templates": "^0.9.163",
|
"@budibase/string-templates": "^0.9.166",
|
||||||
"@elastic/elasticsearch": "7.10.0",
|
"@elastic/elasticsearch": "7.10.0",
|
||||||
"@koa/router": "8.0.0",
|
"@koa/router": "8.0.0",
|
||||||
"@sendgrid/mail": "7.1.1",
|
"@sendgrid/mail": "7.1.1",
|
||||||
|
|
|
@ -77,7 +77,7 @@ exports.run = async function ({ inputs }) {
|
||||||
const { status, message } = await getFetchResponse(response)
|
const { status, message } = await getFetchResponse(response)
|
||||||
return {
|
return {
|
||||||
httpStatus: status,
|
httpStatus: status,
|
||||||
success: status === 200,
|
success: status === 200 || status === 204,
|
||||||
response: message,
|
response: message,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
jest.mock("../../utilities/usageQuota")
|
jest.mock("../../utilities/usageQuota")
|
||||||
jest.mock("../thread")
|
jest.mock("../thread")
|
||||||
|
jest.mock("../../utilities/redis", () => ({
|
||||||
|
init: jest.fn(),
|
||||||
|
checkTestFlag: () => {
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
|
||||||
jest.spyOn(global.console, "error")
|
jest.spyOn(global.console, "error")
|
||||||
|
|
||||||
require("../../environment")
|
require("../../environment")
|
||||||
|
|
|
@ -22,6 +22,7 @@ exports.definition = {
|
||||||
fields: {
|
fields: {
|
||||||
type: "object",
|
type: "object",
|
||||||
description: "Fields submitted from the app frontend",
|
description: "Fields submitted from the app frontend",
|
||||||
|
customType: "triggerSchema",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
required: ["fields"],
|
required: ["fields"],
|
||||||
|
|
|
@ -81,16 +81,20 @@ exports.externalTrigger = async function (
|
||||||
params,
|
params,
|
||||||
{ getResponses } = {}
|
{ getResponses } = {}
|
||||||
) {
|
) {
|
||||||
if (automation.definition != null && automation.definition.trigger != null) {
|
if (
|
||||||
if (automation.definition.trigger.stepId === "APP") {
|
automation.definition != null &&
|
||||||
// values are likely to be submitted as strings, so we shall convert to correct type
|
automation.definition.trigger != null &&
|
||||||
const coercedFields = {}
|
automation.definition.trigger.stepId === definitions.APP.stepId &&
|
||||||
const fields = automation.definition.trigger.inputs.fields
|
automation.definition.trigger.stepId === "APP" &&
|
||||||
for (let key of Object.keys(fields)) {
|
!checkTestFlag(automation._id)
|
||||||
coercedFields[key] = coerce(params.fields[key], fields[key])
|
) {
|
||||||
}
|
// values are likely to be submitted as strings, so we shall convert to correct type
|
||||||
params.fields = coercedFields
|
const coercedFields = {}
|
||||||
|
const fields = automation.definition.trigger.inputs.fields
|
||||||
|
for (let key of Object.keys(fields)) {
|
||||||
|
coercedFields[key] = coerce(params.fields[key], fields[key])
|
||||||
}
|
}
|
||||||
|
params.fields = coercedFields
|
||||||
}
|
}
|
||||||
const data = { automation, event: params }
|
const data = { automation, event: params }
|
||||||
if (getResponses) {
|
if (getResponses) {
|
||||||
|
|
|
@ -20,12 +20,14 @@ export enum QueryTypes {
|
||||||
|
|
||||||
export enum DatasourceFieldTypes {
|
export enum DatasourceFieldTypes {
|
||||||
STRING = "string",
|
STRING = "string",
|
||||||
|
LONGFORM = "longForm",
|
||||||
BOOLEAN = "boolean",
|
BOOLEAN = "boolean",
|
||||||
NUMBER = "number",
|
NUMBER = "number",
|
||||||
PASSWORD = "password",
|
PASSWORD = "password",
|
||||||
LIST = "list",
|
LIST = "list",
|
||||||
OBJECT = "object",
|
OBJECT = "object",
|
||||||
JSON = "json",
|
JSON = "json",
|
||||||
|
FILE = "file",
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum SourceNames {
|
export enum SourceNames {
|
||||||
|
|
|
@ -28,6 +28,8 @@ module PostgresModule {
|
||||||
user: string
|
user: string
|
||||||
password: string
|
password: string
|
||||||
ssl?: boolean
|
ssl?: boolean
|
||||||
|
ca?: string
|
||||||
|
rejectUnauthorized?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const SCHEMA: Integration = {
|
const SCHEMA: Integration = {
|
||||||
|
@ -67,6 +69,16 @@ module PostgresModule {
|
||||||
default: false,
|
default: false,
|
||||||
required: false,
|
required: false,
|
||||||
},
|
},
|
||||||
|
rejectUnauthorized: {
|
||||||
|
type: DatasourceFieldTypes.BOOLEAN,
|
||||||
|
default: false,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
ca: {
|
||||||
|
type: DatasourceFieldTypes.LONGFORM,
|
||||||
|
default: false,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
query: {
|
query: {
|
||||||
create: {
|
create: {
|
||||||
|
@ -144,7 +156,12 @@ module PostgresModule {
|
||||||
|
|
||||||
let newConfig = {
|
let newConfig = {
|
||||||
...this.config,
|
...this.config,
|
||||||
ssl: this.config.ssl ? { rejectUnauthorized: true } : undefined,
|
ssl: this.config.ssl
|
||||||
|
? {
|
||||||
|
rejectUnauthorized: this.config.rejectUnauthorized,
|
||||||
|
ca: this.config.ca,
|
||||||
|
}
|
||||||
|
: undefined,
|
||||||
}
|
}
|
||||||
if (!this.pool) {
|
if (!this.pool) {
|
||||||
this.pool = new Pool(newConfig)
|
this.pool = new Pool(newConfig)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/string-templates",
|
"name": "@budibase/string-templates",
|
||||||
"version": "0.9.163",
|
"version": "0.9.166",
|
||||||
"description": "Handlebars wrapper for Budibase templating.",
|
"description": "Handlebars wrapper for Budibase templating.",
|
||||||
"main": "src/index.cjs",
|
"main": "src/index.cjs",
|
||||||
"module": "dist/bundle.mjs",
|
"module": "dist/bundle.mjs",
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/worker",
|
"name": "@budibase/worker",
|
||||||
"email": "hi@budibase.com",
|
"email": "hi@budibase.com",
|
||||||
"version": "0.9.163",
|
"version": "0.9.166",
|
||||||
"description": "Budibase background service",
|
"description": "Budibase background service",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@ -29,8 +29,8 @@
|
||||||
"author": "Budibase",
|
"author": "Budibase",
|
||||||
"license": "AGPL-3.0-or-later",
|
"license": "AGPL-3.0-or-later",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/auth": "^0.9.163",
|
"@budibase/auth": "^0.9.166",
|
||||||
"@budibase/string-templates": "^0.9.163",
|
"@budibase/string-templates": "^0.9.166",
|
||||||
"@koa/router": "^8.0.0",
|
"@koa/router": "^8.0.0",
|
||||||
"@techpass/passport-openidconnect": "^0.3.0",
|
"@techpass/passport-openidconnect": "^0.3.0",
|
||||||
"aws-sdk": "^2.811.0",
|
"aws-sdk": "^2.811.0",
|
||||||
|
|
|
@ -3,8 +3,14 @@ const { google } = require("@budibase/auth/src/middleware")
|
||||||
const { oidc } = require("@budibase/auth/src/middleware")
|
const { oidc } = require("@budibase/auth/src/middleware")
|
||||||
const { Configs, EmailTemplatePurpose } = require("../../../constants")
|
const { Configs, EmailTemplatePurpose } = require("../../../constants")
|
||||||
const { sendEmail, isEmailConfigured } = require("../../../utilities/email")
|
const { sendEmail, isEmailConfigured } = require("../../../utilities/email")
|
||||||
const { setCookie, getCookie, clearCookie, getGlobalUserByEmail, hash } =
|
const {
|
||||||
authPkg.utils
|
setCookie,
|
||||||
|
getCookie,
|
||||||
|
clearCookie,
|
||||||
|
getGlobalUserByEmail,
|
||||||
|
hash,
|
||||||
|
platformLogout,
|
||||||
|
} = authPkg.utils
|
||||||
const { Cookies } = authPkg.constants
|
const { Cookies } = authPkg.constants
|
||||||
const { passport } = authPkg.auth
|
const { passport } = authPkg.auth
|
||||||
const { checkResetPasswordCode } = require("../../../utilities/redis")
|
const { checkResetPasswordCode } = require("../../../utilities/redis")
|
||||||
|
@ -121,8 +127,7 @@ exports.resetUpdate = async ctx => {
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.logout = async ctx => {
|
exports.logout = async ctx => {
|
||||||
clearCookie(ctx, Cookies.Auth)
|
await platformLogout({ ctx, userId: ctx.user._id })
|
||||||
clearCookie(ctx, Cookies.CurrentApp)
|
|
||||||
ctx.body = { message: "User logged out." }
|
ctx.body = { message: "User logged out." }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,8 @@ const {
|
||||||
StaticDatabases,
|
StaticDatabases,
|
||||||
generateNewUsageQuotaDoc,
|
generateNewUsageQuotaDoc,
|
||||||
} = require("@budibase/auth/db")
|
} = require("@budibase/auth/db")
|
||||||
const { hash, getGlobalUserByEmail, saveUser } = require("@budibase/auth").utils
|
const { hash, getGlobalUserByEmail, saveUser, platformLogout } =
|
||||||
|
require("@budibase/auth").utils
|
||||||
const { EmailTemplatePurpose } = require("../../../constants")
|
const { EmailTemplatePurpose } = require("../../../constants")
|
||||||
const { checkInviteCode } = require("../../../utilities/redis")
|
const { checkInviteCode } = require("../../../utilities/redis")
|
||||||
const { sendEmail } = require("../../../utilities/email")
|
const { sendEmail } = require("../../../utilities/email")
|
||||||
|
@ -173,7 +174,14 @@ exports.updateSelf = async ctx => {
|
||||||
const db = getGlobalDB()
|
const db = getGlobalDB()
|
||||||
const user = await db.get(ctx.user._id)
|
const user = await db.get(ctx.user._id)
|
||||||
if (ctx.request.body.password) {
|
if (ctx.request.body.password) {
|
||||||
|
// changing password
|
||||||
ctx.request.body.password = await hash(ctx.request.body.password)
|
ctx.request.body.password = await hash(ctx.request.body.password)
|
||||||
|
// Log all other sessions out apart from the current one
|
||||||
|
await platformLogout({
|
||||||
|
ctx,
|
||||||
|
userId: ctx.user._id,
|
||||||
|
keepActiveSession: true,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
// don't allow sending up an ID/Rev, always use the existing one
|
// don't allow sending up an ID/Rev, always use the existing one
|
||||||
delete ctx.request.body._id
|
delete ctx.request.body._id
|
||||||
|
|
Loading…
Reference in New Issue