Merge branch 'master' into develop
This commit is contained in:
commit
0f98f2fcaa
|
@ -9,7 +9,11 @@ if [[ "${TARGETBUILD}" = "aas" ]]; then
|
||||||
chown -R couchdb:couchdb $DATA_DIR/couch/
|
chown -R couchdb:couchdb $DATA_DIR/couch/
|
||||||
apt update
|
apt update
|
||||||
apt-get install -y openssh-server
|
apt-get install -y openssh-server
|
||||||
sed -i "s/#Port 22/Port 2222/" /etc/ssh/sshd_config
|
echo "root:Docker!" | chpasswd
|
||||||
|
mkdir -p /tmp
|
||||||
|
chmod +x /tmp/ssh_setup.sh \
|
||||||
|
&& (sleep 1;/tmp/ssh_setup.sh 2>&1 > /dev/null)
|
||||||
|
cp /etc/sshd_config /etc/ssh/sshd_config
|
||||||
/etc/init.d/ssh restart
|
/etc/init.d/ssh restart
|
||||||
sed -i "s#DATA_DIR#/home#g" /opt/clouseau/clouseau.ini
|
sed -i "s#DATA_DIR#/home#g" /opt/clouseau/clouseau.ini
|
||||||
sed -i "s#DATA_DIR#/home#g" /opt/couchdb/etc/local.ini
|
sed -i "s#DATA_DIR#/home#g" /opt/couchdb/etc/local.ini
|
||||||
|
|
|
@ -29,23 +29,8 @@ ENV TARGETBUILD $TARGETBUILD
|
||||||
COPY --from=build /app /app
|
COPY --from=build /app /app
|
||||||
COPY --from=build /worker /worker
|
COPY --from=build /worker /worker
|
||||||
|
|
||||||
ENV \
|
# ENV CUSTOM_DOMAIN=budi001.custom.com \
|
||||||
APP_PORT=4001 \
|
# See runner.sh for Env Vars
|
||||||
ARCHITECTURE=amd \
|
|
||||||
BUDIBASE_ENVIRONMENT=PRODUCTION \
|
|
||||||
CLUSTER_PORT=80 \
|
|
||||||
# CUSTOM_DOMAIN=budi001.custom.com \
|
|
||||||
DATA_DIR=/data \
|
|
||||||
DEPLOYMENT_ENVIRONMENT=docker \
|
|
||||||
MINIO_URL=http://localhost:9000 \
|
|
||||||
POSTHOG_TOKEN=phc_bIjZL7oh2GEUd2vqvTBH8WvrX0fWTFQMs6H5KQxiUxU \
|
|
||||||
REDIS_URL=localhost:6379 \
|
|
||||||
SELF_HOSTED=1 \
|
|
||||||
TARGETBUILD=$TARGETBUILD \
|
|
||||||
WORKER_PORT=4002 \
|
|
||||||
WORKER_URL=http://localhost:4002 \
|
|
||||||
APPS_URL=http://localhost:4001
|
|
||||||
|
|
||||||
# These secret env variables are generated by the runner at startup
|
# These secret env variables are generated by the runner at startup
|
||||||
# their values can be overriden by the user, they will be written
|
# their values can be overriden by the user, they will be written
|
||||||
# to the .env file in the /data directory for use later on
|
# to the .env file in the /data directory for use later on
|
||||||
|
@ -117,6 +102,8 @@ RUN chmod +x ./build-target-paths.sh
|
||||||
|
|
||||||
# Script below sets the path for storing data based on $DATA_DIR
|
# Script below sets the path for storing data based on $DATA_DIR
|
||||||
# For Azure App Service install SSH & point data locations to /home
|
# For Azure App Service install SSH & point data locations to /home
|
||||||
|
ADD hosting/single/ssh/sshd_config /etc/
|
||||||
|
ADD hosting/single/ssh/ssh_setup.sh /tmp
|
||||||
RUN /build-target-paths.sh
|
RUN /build-target-paths.sh
|
||||||
|
|
||||||
# cleanup cache
|
# cleanup cache
|
||||||
|
@ -124,6 +111,8 @@ RUN yarn cache clean -f
|
||||||
|
|
||||||
EXPOSE 80
|
EXPOSE 80
|
||||||
EXPOSE 443
|
EXPOSE 443
|
||||||
|
# Expose port 2222 for SSH on Azure App Service build
|
||||||
|
EXPOSE 2222
|
||||||
VOLUME /data
|
VOLUME /data
|
||||||
|
|
||||||
# setup letsencrypt certificate
|
# setup letsencrypt certificate
|
||||||
|
|
|
@ -1,6 +1,21 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
declare -a ENV_VARS=("COUCHDB_USER" "COUCHDB_PASSWORD" "DATA_DIR" "MINIO_ACCESS_KEY" "MINIO_SECRET_KEY" "INTERNAL_API_KEY" "JWT_SECRET" "REDIS_PASSWORD")
|
declare -a ENV_VARS=("COUCHDB_USER" "COUCHDB_PASSWORD" "DATA_DIR" "MINIO_ACCESS_KEY" "MINIO_SECRET_KEY" "INTERNAL_API_KEY" "JWT_SECRET" "REDIS_PASSWORD")
|
||||||
|
declare -a DOCKER_VARS=("APP_PORT" "APPS_URL" "ARCHITECTURE" "BUDIBASE_ENVIRONMENT" "CLUSTER_PORT" "DEPLOYMENT_ENVIRONMENT" "MINIO_URL" "NODE_ENV" "POSTHOG_TOKEN" "REDIS_URL" "SELF_HOSTED" "WORKER_PORT" "WORKER_URL")
|
||||||
|
# Check the env vars set in Dockerfile have come through, AAS seems to drop them
|
||||||
|
[[ -z "${APP_PORT}" ]] && export APP_PORT=4001
|
||||||
|
[[ -z "${ARCHITECTURE}" ]] && export ARCHITECTURE=amd
|
||||||
|
[[ -z "${BUDIBASE_ENVIRONMENT}" ]] && export BUDIBASE_ENVIRONMENT=PRODUCTION
|
||||||
|
[[ -z "${CLUSTER_PORT}" ]] && export CLUSTER_PORT=80
|
||||||
|
[[ -z "${DEPLOYMENT_ENVIRONMENT}" ]] && export DEPLOYMENT_ENVIRONMENT=docker
|
||||||
|
[[ -z "${MINIO_URL}" ]] && export MINIO_URL=http://localhost:9000
|
||||||
|
[[ -z "${NODE_ENV}" ]] && export NODE_ENV=production
|
||||||
|
[[ -z "${POSTHOG_TOKEN}" ]] && export POSTHOG_TOKEN=phc_bIjZL7oh2GEUd2vqvTBH8WvrX0fWTFQMs6H5KQxiUxU
|
||||||
|
[[ -z "${REDIS_URL}" ]] && export REDIS_URL=localhost:6379
|
||||||
|
[[ -z "${SELF_HOSTED}" ]] && export SELF_HOSTED=1
|
||||||
|
[[ -z "${WORKER_PORT}" ]] && export WORKER_PORT=4002
|
||||||
|
[[ -z "${WORKER_URL}" ]] && export WORKER_URL=http://localhost:4002
|
||||||
|
[[ -z "${APPS_URL}" ]] && export APPS_URL=http://localhost:4001
|
||||||
|
# export CUSTOM_DOMAIN=budi001.custom.com
|
||||||
# Azure App Service customisations
|
# Azure App Service customisations
|
||||||
if [[ "${TARGETBUILD}" = "aas" ]]; then
|
if [[ "${TARGETBUILD}" = "aas" ]]; then
|
||||||
DATA_DIR=/home
|
DATA_DIR=/home
|
||||||
|
@ -10,9 +25,10 @@ else
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -f "${DATA_DIR}/.env" ]; then
|
if [ -f "${DATA_DIR}/.env" ]; then
|
||||||
export $(cat ${DATA_DIR}/.env | xargs)
|
# Read in the .env file and export the variables
|
||||||
|
for LINE in $(cat ${DATA_DIR}/.env); do export $LINE; done
|
||||||
fi
|
fi
|
||||||
# first randomise any unset environment variables
|
# randomise any unset environment variables
|
||||||
for ENV_VAR in "${ENV_VARS[@]}"
|
for ENV_VAR in "${ENV_VARS[@]}"
|
||||||
do
|
do
|
||||||
temp=$(eval "echo \$$ENV_VAR")
|
temp=$(eval "echo \$$ENV_VAR")
|
||||||
|
@ -30,11 +46,18 @@ if [ ! -f "${DATA_DIR}/.env" ]; then
|
||||||
temp=$(eval "echo \$$ENV_VAR")
|
temp=$(eval "echo \$$ENV_VAR")
|
||||||
echo "$ENV_VAR=$temp" >> ${DATA_DIR}/.env
|
echo "$ENV_VAR=$temp" >> ${DATA_DIR}/.env
|
||||||
done
|
done
|
||||||
|
for ENV_VAR in "${DOCKER_VARS[@]}"
|
||||||
|
do
|
||||||
|
temp=$(eval "echo \$$ENV_VAR")
|
||||||
|
echo "$ENV_VAR=$temp" >> ${DATA_DIR}/.env
|
||||||
|
done
|
||||||
echo "COUCH_DB_URL=${COUCH_DB_URL}" >> ${DATA_DIR}/.env
|
echo "COUCH_DB_URL=${COUCH_DB_URL}" >> ${DATA_DIR}/.env
|
||||||
fi
|
fi
|
||||||
|
|
||||||
export COUCH_DB_URL=http://$COUCHDB_USER:$COUCHDB_PASSWORD@localhost:5984
|
# Read in the .env file and export the variables
|
||||||
|
for LINE in $(cat ${DATA_DIR}/.env); do export $LINE; done
|
||||||
|
ln -s ${DATA_DIR}/.env /app/.env
|
||||||
|
ln -s ${DATA_DIR}/.env /worker/.env
|
||||||
# make these directories in runner, incase of mount
|
# make these directories in runner, incase of mount
|
||||||
mkdir -p ${DATA_DIR}/couch/{dbs,views}
|
mkdir -p ${DATA_DIR}/couch/{dbs,views}
|
||||||
mkdir -p ${DATA_DIR}/minio
|
mkdir -p ${DATA_DIR}/minio
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
ssh-keygen -A
|
||||||
|
|
||||||
|
#prepare run dir
|
||||||
|
if [ ! -d "/var/run/sshd" ]; then
|
||||||
|
mkdir -p /var/run/sshd
|
||||||
|
fi
|
|
@ -0,0 +1,12 @@
|
||||||
|
Port 2222
|
||||||
|
ListenAddress 0.0.0.0
|
||||||
|
LoginGraceTime 180
|
||||||
|
X11Forwarding yes
|
||||||
|
Ciphers aes128-cbc,3des-cbc,aes256-cbc,aes128-ctr,aes192-ctr,aes256-ctr
|
||||||
|
MACs hmac-sha1,hmac-sha1-96
|
||||||
|
StrictModes yes
|
||||||
|
SyslogFacility DAEMON
|
||||||
|
PasswordAuthentication yes
|
||||||
|
PermitEmptyPasswords no
|
||||||
|
PermitRootLogin yes
|
||||||
|
Subsystem sftp internal-sftp
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"version": "1.3.15-alpha.9",
|
"version": "1.3.18",
|
||||||
"npmClient": "yarn",
|
"npmClient": "yarn",
|
||||||
"packages": [
|
"packages": [
|
||||||
"packages/*"
|
"packages/*"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/backend-core",
|
"name": "@budibase/backend-core",
|
||||||
"version": "1.3.15-alpha.9",
|
"version": "1.3.18",
|
||||||
"description": "Budibase backend core libraries used in server and worker",
|
"description": "Budibase backend core libraries used in server and worker",
|
||||||
"main": "dist/src/index.js",
|
"main": "dist/src/index.js",
|
||||||
"types": "dist/src/index.d.ts",
|
"types": "dist/src/index.d.ts",
|
||||||
|
@ -20,7 +20,7 @@
|
||||||
"test:watch": "jest --watchAll"
|
"test:watch": "jest --watchAll"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/types": "1.3.15-alpha.9",
|
"@budibase/types": "^1.3.18",
|
||||||
"@shopify/jest-koa-mocks": "5.0.1",
|
"@shopify/jest-koa-mocks": "5.0.1",
|
||||||
"@techpass/passport-openidconnect": "0.3.2",
|
"@techpass/passport-openidconnect": "0.3.2",
|
||||||
"aws-sdk": "2.1030.0",
|
"aws-sdk": "2.1030.0",
|
||||||
|
|
|
@ -19,6 +19,7 @@ export enum ViewName {
|
||||||
ROUTING = "screen_routes",
|
ROUTING = "screen_routes",
|
||||||
AUTOMATION_LOGS = "automation_logs",
|
AUTOMATION_LOGS = "automation_logs",
|
||||||
ACCOUNT_BY_EMAIL = "account_by_email",
|
ACCOUNT_BY_EMAIL = "account_by_email",
|
||||||
|
PLATFORM_USERS_LOWERCASE = "platform_users_lowercase",
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DeprecatedViews = {
|
export const DeprecatedViews = {
|
||||||
|
|
|
@ -2,7 +2,8 @@ import { newid } from "../hashing"
|
||||||
import { DEFAULT_TENANT_ID, Configs } from "../constants"
|
import { DEFAULT_TENANT_ID, Configs } from "../constants"
|
||||||
import env from "../environment"
|
import env from "../environment"
|
||||||
import { SEPARATOR, DocumentType, UNICODE_MAX, ViewName } from "./constants"
|
import { SEPARATOR, DocumentType, UNICODE_MAX, ViewName } from "./constants"
|
||||||
import { getTenantId, getGlobalDBName, getGlobalDB } from "../tenancy"
|
import { getTenantId, getGlobalDB } from "../context"
|
||||||
|
import { getGlobalDBName } from "../tenancy/utils"
|
||||||
import fetch from "node-fetch"
|
import fetch from "node-fetch"
|
||||||
import { doWithDB, allDbs } from "./index"
|
import { doWithDB, allDbs } from "./index"
|
||||||
import { getCouchInfo } from "./pouch"
|
import { getCouchInfo } from "./pouch"
|
||||||
|
|
|
@ -1,203 +0,0 @@
|
||||||
const {
|
|
||||||
DocumentType,
|
|
||||||
ViewName,
|
|
||||||
DeprecatedViews,
|
|
||||||
SEPARATOR,
|
|
||||||
} = require("./utils")
|
|
||||||
const { getGlobalDB } = require("../tenancy")
|
|
||||||
const { StaticDatabases } = require("./constants")
|
|
||||||
const { doWithDB } = require("./")
|
|
||||||
|
|
||||||
const DESIGN_DB = "_design/database"
|
|
||||||
|
|
||||||
function DesignDoc() {
|
|
||||||
return {
|
|
||||||
_id: DESIGN_DB,
|
|
||||||
// view collation information, read before writing any complex views:
|
|
||||||
// https://docs.couchdb.org/en/master/ddocs/views/collation.html#collation-specification
|
|
||||||
views: {},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function removeDeprecated(db, viewName) {
|
|
||||||
if (!DeprecatedViews[viewName]) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const designDoc = await db.get(DESIGN_DB)
|
|
||||||
for (let deprecatedNames of DeprecatedViews[viewName]) {
|
|
||||||
delete designDoc.views[deprecatedNames]
|
|
||||||
}
|
|
||||||
await db.put(designDoc)
|
|
||||||
} catch (err) {
|
|
||||||
// doesn't exist, ignore
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.createNewUserEmailView = async () => {
|
|
||||||
const db = getGlobalDB()
|
|
||||||
let designDoc
|
|
||||||
try {
|
|
||||||
designDoc = await db.get(DESIGN_DB)
|
|
||||||
} catch (err) {
|
|
||||||
// no design doc, make one
|
|
||||||
designDoc = DesignDoc()
|
|
||||||
}
|
|
||||||
const view = {
|
|
||||||
// if using variables in a map function need to inject them before use
|
|
||||||
map: `function(doc) {
|
|
||||||
if (doc._id.startsWith("${DocumentType.USER}${SEPARATOR}")) {
|
|
||||||
emit(doc.email.toLowerCase(), doc._id)
|
|
||||||
}
|
|
||||||
}`,
|
|
||||||
}
|
|
||||||
designDoc.views = {
|
|
||||||
...designDoc.views,
|
|
||||||
[ViewName.USER_BY_EMAIL]: view,
|
|
||||||
}
|
|
||||||
await db.put(designDoc)
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.createAccountEmailView = async () => {
|
|
||||||
await doWithDB(StaticDatabases.PLATFORM_INFO.name, async db => {
|
|
||||||
let designDoc
|
|
||||||
try {
|
|
||||||
designDoc = await db.get(DESIGN_DB)
|
|
||||||
} catch (err) {
|
|
||||||
// no design doc, make one
|
|
||||||
designDoc = DesignDoc()
|
|
||||||
}
|
|
||||||
const view = {
|
|
||||||
// if using variables in a map function need to inject them before use
|
|
||||||
map: `function(doc) {
|
|
||||||
if (doc._id.startsWith("${DocumentType.ACCOUNT_METADATA}${SEPARATOR}")) {
|
|
||||||
emit(doc.email.toLowerCase(), doc._id)
|
|
||||||
}
|
|
||||||
}`,
|
|
||||||
}
|
|
||||||
designDoc.views = {
|
|
||||||
...designDoc.views,
|
|
||||||
[ViewName.ACCOUNT_BY_EMAIL]: view,
|
|
||||||
}
|
|
||||||
await db.put(designDoc)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.createUserAppView = async () => {
|
|
||||||
const db = getGlobalDB()
|
|
||||||
let designDoc
|
|
||||||
try {
|
|
||||||
designDoc = await db.get("_design/database")
|
|
||||||
} catch (err) {
|
|
||||||
// no design doc, make one
|
|
||||||
designDoc = DesignDoc()
|
|
||||||
}
|
|
||||||
const view = {
|
|
||||||
// if using variables in a map function need to inject them before use
|
|
||||||
map: `function(doc) {
|
|
||||||
if (doc._id.startsWith("${DocumentType.USER}${SEPARATOR}") && doc.roles) {
|
|
||||||
for (let prodAppId of Object.keys(doc.roles)) {
|
|
||||||
let emitted = prodAppId + "${SEPARATOR}" + doc._id
|
|
||||||
emit(emitted, null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}`,
|
|
||||||
}
|
|
||||||
designDoc.views = {
|
|
||||||
...designDoc.views,
|
|
||||||
[ViewName.USER_BY_APP]: view,
|
|
||||||
}
|
|
||||||
await db.put(designDoc)
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.createApiKeyView = async () => {
|
|
||||||
const db = getGlobalDB()
|
|
||||||
let designDoc
|
|
||||||
try {
|
|
||||||
designDoc = await db.get("_design/database")
|
|
||||||
} catch (err) {
|
|
||||||
designDoc = DesignDoc()
|
|
||||||
}
|
|
||||||
const view = {
|
|
||||||
map: `function(doc) {
|
|
||||||
if (doc._id.startsWith("${DocumentType.DEV_INFO}") && doc.apiKey) {
|
|
||||||
emit(doc.apiKey, doc.userId)
|
|
||||||
}
|
|
||||||
}`,
|
|
||||||
}
|
|
||||||
designDoc.views = {
|
|
||||||
...designDoc.views,
|
|
||||||
[ViewName.BY_API_KEY]: view,
|
|
||||||
}
|
|
||||||
await db.put(designDoc)
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.createUserBuildersView = async () => {
|
|
||||||
const db = getGlobalDB()
|
|
||||||
let designDoc
|
|
||||||
try {
|
|
||||||
designDoc = await db.get("_design/database")
|
|
||||||
} catch (err) {
|
|
||||||
// no design doc, make one
|
|
||||||
designDoc = DesignDoc()
|
|
||||||
}
|
|
||||||
const view = {
|
|
||||||
map: `function(doc) {
|
|
||||||
if (doc.builder && doc.builder.global === true) {
|
|
||||||
emit(doc._id, doc._id)
|
|
||||||
}
|
|
||||||
}`,
|
|
||||||
}
|
|
||||||
designDoc.views = {
|
|
||||||
...designDoc.views,
|
|
||||||
[ViewName.USER_BY_BUILDERS]: view,
|
|
||||||
}
|
|
||||||
await db.put(designDoc)
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.queryView = async (viewName, params, db, CreateFuncByName) => {
|
|
||||||
try {
|
|
||||||
let response = (await db.query(`database/${viewName}`, params)).rows
|
|
||||||
response = response.map(resp =>
|
|
||||||
params.include_docs ? resp.doc : resp.value
|
|
||||||
)
|
|
||||||
if (params.arrayResponse) {
|
|
||||||
return response
|
|
||||||
} else {
|
|
||||||
return response.length <= 1 ? response[0] : response
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
if (err != null && err.name === "not_found") {
|
|
||||||
const createFunc = CreateFuncByName[viewName]
|
|
||||||
await removeDeprecated(db, viewName)
|
|
||||||
await createFunc()
|
|
||||||
return exports.queryView(viewName, params, db, CreateFuncByName)
|
|
||||||
} else {
|
|
||||||
throw err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.queryPlatformView = async (viewName, params) => {
|
|
||||||
const CreateFuncByName = {
|
|
||||||
[ViewName.ACCOUNT_BY_EMAIL]: exports.createAccountEmailView,
|
|
||||||
}
|
|
||||||
|
|
||||||
return doWithDB(StaticDatabases.PLATFORM_INFO.name, async db => {
|
|
||||||
return exports.queryView(viewName, params, db, CreateFuncByName)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.queryGlobalView = async (viewName, params, db = null) => {
|
|
||||||
const CreateFuncByName = {
|
|
||||||
[ViewName.USER_BY_EMAIL]: exports.createNewUserEmailView,
|
|
||||||
[ViewName.BY_API_KEY]: exports.createApiKeyView,
|
|
||||||
[ViewName.USER_BY_BUILDERS]: exports.createUserBuildersView,
|
|
||||||
[ViewName.USER_BY_APP]: exports.createUserAppView,
|
|
||||||
}
|
|
||||||
// can pass DB in if working with something specific
|
|
||||||
if (!db) {
|
|
||||||
db = getGlobalDB()
|
|
||||||
}
|
|
||||||
return exports.queryView(viewName, params, db, CreateFuncByName)
|
|
||||||
}
|
|
|
@ -0,0 +1,260 @@
|
||||||
|
import { DocumentType, ViewName, DeprecatedViews, SEPARATOR } from "./utils"
|
||||||
|
import { getGlobalDB } from "../context"
|
||||||
|
import { StaticDatabases } from "./constants"
|
||||||
|
import { doWithDB } from "./"
|
||||||
|
|
||||||
|
const DESIGN_DB = "_design/database"
|
||||||
|
|
||||||
|
function DesignDoc() {
|
||||||
|
return {
|
||||||
|
_id: DESIGN_DB,
|
||||||
|
// view collation information, read before writing any complex views:
|
||||||
|
// https://docs.couchdb.org/en/master/ddocs/views/collation.html#collation-specification
|
||||||
|
views: {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DesignDocument {
|
||||||
|
views: any
|
||||||
|
}
|
||||||
|
|
||||||
|
async function removeDeprecated(db: PouchDB.Database, viewName: ViewName) {
|
||||||
|
// @ts-ignore
|
||||||
|
if (!DeprecatedViews[viewName]) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const designDoc = await db.get<DesignDocument>(DESIGN_DB)
|
||||||
|
// @ts-ignore
|
||||||
|
for (let deprecatedNames of DeprecatedViews[viewName]) {
|
||||||
|
delete designDoc.views[deprecatedNames]
|
||||||
|
}
|
||||||
|
await db.put(designDoc)
|
||||||
|
} catch (err) {
|
||||||
|
// doesn't exist, ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createNewUserEmailView = async () => {
|
||||||
|
const db = getGlobalDB()
|
||||||
|
let designDoc
|
||||||
|
try {
|
||||||
|
designDoc = await db.get(DESIGN_DB)
|
||||||
|
} catch (err) {
|
||||||
|
// no design doc, make one
|
||||||
|
designDoc = DesignDoc()
|
||||||
|
}
|
||||||
|
const view = {
|
||||||
|
// if using variables in a map function need to inject them before use
|
||||||
|
map: `function(doc) {
|
||||||
|
if (doc._id.startsWith("${DocumentType.USER}${SEPARATOR}")) {
|
||||||
|
emit(doc.email.toLowerCase(), doc._id)
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
}
|
||||||
|
designDoc.views = {
|
||||||
|
...designDoc.views,
|
||||||
|
[ViewName.USER_BY_EMAIL]: view,
|
||||||
|
}
|
||||||
|
await db.put(designDoc)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createAccountEmailView = async () => {
|
||||||
|
await doWithDB(
|
||||||
|
StaticDatabases.PLATFORM_INFO.name,
|
||||||
|
async (db: PouchDB.Database) => {
|
||||||
|
let designDoc
|
||||||
|
try {
|
||||||
|
designDoc = await db.get<DesignDocument>(DESIGN_DB)
|
||||||
|
} catch (err) {
|
||||||
|
// no design doc, make one
|
||||||
|
designDoc = DesignDoc()
|
||||||
|
}
|
||||||
|
const view = {
|
||||||
|
// if using variables in a map function need to inject them before use
|
||||||
|
map: `function(doc) {
|
||||||
|
if (doc._id.startsWith("${DocumentType.ACCOUNT_METADATA}${SEPARATOR}")) {
|
||||||
|
emit(doc.email.toLowerCase(), doc._id)
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
}
|
||||||
|
designDoc.views = {
|
||||||
|
...designDoc.views,
|
||||||
|
[ViewName.ACCOUNT_BY_EMAIL]: view,
|
||||||
|
}
|
||||||
|
await db.put(designDoc)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createUserAppView = async () => {
|
||||||
|
const db = getGlobalDB() as PouchDB.Database
|
||||||
|
let designDoc
|
||||||
|
try {
|
||||||
|
designDoc = await db.get<DesignDocument>("_design/database")
|
||||||
|
} catch (err) {
|
||||||
|
// no design doc, make one
|
||||||
|
designDoc = DesignDoc()
|
||||||
|
}
|
||||||
|
const view = {
|
||||||
|
// if using variables in a map function need to inject them before use
|
||||||
|
map: `function(doc) {
|
||||||
|
if (doc._id.startsWith("${DocumentType.USER}${SEPARATOR}") && doc.roles) {
|
||||||
|
for (let prodAppId of Object.keys(doc.roles)) {
|
||||||
|
let emitted = prodAppId + "${SEPARATOR}" + doc._id
|
||||||
|
emit(emitted, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
}
|
||||||
|
designDoc.views = {
|
||||||
|
...designDoc.views,
|
||||||
|
[ViewName.USER_BY_APP]: view,
|
||||||
|
}
|
||||||
|
await db.put(designDoc)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createApiKeyView = async () => {
|
||||||
|
const db = getGlobalDB()
|
||||||
|
let designDoc
|
||||||
|
try {
|
||||||
|
designDoc = await db.get("_design/database")
|
||||||
|
} catch (err) {
|
||||||
|
designDoc = DesignDoc()
|
||||||
|
}
|
||||||
|
const view = {
|
||||||
|
map: `function(doc) {
|
||||||
|
if (doc._id.startsWith("${DocumentType.DEV_INFO}") && doc.apiKey) {
|
||||||
|
emit(doc.apiKey, doc.userId)
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
}
|
||||||
|
designDoc.views = {
|
||||||
|
...designDoc.views,
|
||||||
|
[ViewName.BY_API_KEY]: view,
|
||||||
|
}
|
||||||
|
await db.put(designDoc)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createUserBuildersView = async () => {
|
||||||
|
const db = getGlobalDB()
|
||||||
|
let designDoc
|
||||||
|
try {
|
||||||
|
designDoc = await db.get("_design/database")
|
||||||
|
} catch (err) {
|
||||||
|
// no design doc, make one
|
||||||
|
designDoc = DesignDoc()
|
||||||
|
}
|
||||||
|
const view = {
|
||||||
|
map: `function(doc) {
|
||||||
|
if (doc.builder && doc.builder.global === true) {
|
||||||
|
emit(doc._id, doc._id)
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
}
|
||||||
|
designDoc.views = {
|
||||||
|
...designDoc.views,
|
||||||
|
[ViewName.USER_BY_BUILDERS]: view,
|
||||||
|
}
|
||||||
|
await db.put(designDoc)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createPlatformUserView = async () => {
|
||||||
|
await doWithDB(
|
||||||
|
StaticDatabases.PLATFORM_INFO.name,
|
||||||
|
async (db: PouchDB.Database) => {
|
||||||
|
let designDoc
|
||||||
|
try {
|
||||||
|
designDoc = await db.get<DesignDocument>(DESIGN_DB)
|
||||||
|
} catch (err) {
|
||||||
|
// no design doc, make one
|
||||||
|
designDoc = DesignDoc()
|
||||||
|
}
|
||||||
|
const view = {
|
||||||
|
// if using variables in a map function need to inject them before use
|
||||||
|
map: `function(doc) {
|
||||||
|
if (doc.tenantId) {
|
||||||
|
emit(doc._id.toLowerCase(), doc._id)
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
}
|
||||||
|
designDoc.views = {
|
||||||
|
...designDoc.views,
|
||||||
|
[ViewName.PLATFORM_USERS_LOWERCASE]: view,
|
||||||
|
}
|
||||||
|
await db.put(designDoc)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface QueryViewOptions {
|
||||||
|
arrayResponse?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export const queryView = async <T>(
|
||||||
|
viewName: ViewName,
|
||||||
|
params: PouchDB.Query.Options<T, T>,
|
||||||
|
db: PouchDB.Database,
|
||||||
|
CreateFuncByName: any,
|
||||||
|
opts?: QueryViewOptions
|
||||||
|
): Promise<T[] | T | undefined> => {
|
||||||
|
try {
|
||||||
|
let response = await db.query<T, T>(`database/${viewName}`, params)
|
||||||
|
const rows = response.rows
|
||||||
|
const docs = rows.map((resp: any) =>
|
||||||
|
params.include_docs ? resp.doc : resp.value
|
||||||
|
)
|
||||||
|
|
||||||
|
if (opts?.arrayResponse) {
|
||||||
|
return docs
|
||||||
|
} else {
|
||||||
|
return docs.length <= 1 ? docs[0] : docs
|
||||||
|
}
|
||||||
|
} catch (err: any) {
|
||||||
|
if (err != null && err.name === "not_found") {
|
||||||
|
const createFunc = CreateFuncByName[viewName]
|
||||||
|
await removeDeprecated(db, viewName)
|
||||||
|
await createFunc()
|
||||||
|
return queryView(viewName, params, db, CreateFuncByName, opts)
|
||||||
|
} else {
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const queryPlatformView = async <T>(
|
||||||
|
viewName: ViewName,
|
||||||
|
params: PouchDB.Query.Options<T, T>,
|
||||||
|
opts?: QueryViewOptions
|
||||||
|
): Promise<T[] | T | undefined> => {
|
||||||
|
const CreateFuncByName = {
|
||||||
|
[ViewName.ACCOUNT_BY_EMAIL]: createAccountEmailView,
|
||||||
|
[ViewName.PLATFORM_USERS_LOWERCASE]: createPlatformUserView,
|
||||||
|
}
|
||||||
|
|
||||||
|
return doWithDB(
|
||||||
|
StaticDatabases.PLATFORM_INFO.name,
|
||||||
|
async (db: PouchDB.Database) => {
|
||||||
|
return queryView(viewName, params, db, CreateFuncByName, opts)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const queryGlobalView = async <T>(
|
||||||
|
viewName: ViewName,
|
||||||
|
params: PouchDB.Query.Options<T, T>,
|
||||||
|
db?: PouchDB.Database,
|
||||||
|
opts?: QueryViewOptions
|
||||||
|
): Promise<T[] | T | undefined> => {
|
||||||
|
const CreateFuncByName = {
|
||||||
|
[ViewName.USER_BY_EMAIL]: createNewUserEmailView,
|
||||||
|
[ViewName.BY_API_KEY]: createApiKeyView,
|
||||||
|
[ViewName.USER_BY_BUILDERS]: createUserBuildersView,
|
||||||
|
[ViewName.USER_BY_APP]: createUserAppView,
|
||||||
|
}
|
||||||
|
// can pass DB in if working with something specific
|
||||||
|
if (!db) {
|
||||||
|
db = getGlobalDB() as PouchDB.Database
|
||||||
|
}
|
||||||
|
return queryView(viewName, params, db, CreateFuncByName, opts)
|
||||||
|
}
|
|
@ -1,9 +1,11 @@
|
||||||
import * as context from "../context"
|
import * as context from "../context"
|
||||||
import * as tenancy from "./tenancy"
|
import * as tenancy from "./tenancy"
|
||||||
|
import * as utils from "./utils"
|
||||||
|
|
||||||
const pkg = {
|
const pkg = {
|
||||||
...context,
|
...context,
|
||||||
...tenancy,
|
...tenancy,
|
||||||
|
...utils,
|
||||||
}
|
}
|
||||||
|
|
||||||
export = pkg
|
export = pkg
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { doWithDB } from "../db"
|
import { doWithDB } from "../db"
|
||||||
import { StaticDatabases } from "../db/constants"
|
import { queryPlatformView } from "../db/views"
|
||||||
import { baseGlobalDBName } from "./utils"
|
import { StaticDatabases, ViewName } from "../db/constants"
|
||||||
|
import { getGlobalDBName } from "./utils"
|
||||||
import {
|
import {
|
||||||
getTenantId,
|
getTenantId,
|
||||||
DEFAULT_TENANT_ID,
|
DEFAULT_TENANT_ID,
|
||||||
|
@ -8,6 +9,7 @@ import {
|
||||||
getTenantIDFromAppID,
|
getTenantIDFromAppID,
|
||||||
} from "../context"
|
} from "../context"
|
||||||
import env from "../environment"
|
import env from "../environment"
|
||||||
|
import { PlatformUser, PlatformUserByEmail } from "@budibase/types"
|
||||||
|
|
||||||
const TENANT_DOC = StaticDatabases.PLATFORM_INFO.docs.tenants
|
const TENANT_DOC = StaticDatabases.PLATFORM_INFO.docs.tenants
|
||||||
const PLATFORM_INFO_DB = StaticDatabases.PLATFORM_INFO.name
|
const PLATFORM_INFO_DB = StaticDatabases.PLATFORM_INFO.name
|
||||||
|
@ -87,15 +89,6 @@ export const tryAddTenant = async (
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getGlobalDBName = (tenantId?: string) => {
|
|
||||||
// tenant ID can be set externally, for example user API where
|
|
||||||
// new tenants are being created, this may be the case
|
|
||||||
if (!tenantId) {
|
|
||||||
tenantId = getTenantId()
|
|
||||||
}
|
|
||||||
return baseGlobalDBName(tenantId)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const doWithGlobalDB = (tenantId: string, cb: any) => {
|
export const doWithGlobalDB = (tenantId: string, cb: any) => {
|
||||||
return doWithDB(getGlobalDBName(tenantId), cb)
|
return doWithDB(getGlobalDBName(tenantId), cb)
|
||||||
}
|
}
|
||||||
|
@ -116,14 +109,16 @@ export const lookupTenantId = async (userId: string) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// lookup, could be email or userId, either will return a doc
|
// lookup, could be email or userId, either will return a doc
|
||||||
export const getTenantUser = async (identifier: string) => {
|
export const getTenantUser = async (
|
||||||
return doWithDB(PLATFORM_INFO_DB, async (db: any) => {
|
identifier: string
|
||||||
try {
|
): Promise<PlatformUser | null> => {
|
||||||
return await db.get(identifier)
|
// use the view here and allow to find anyone regardless of casing
|
||||||
} catch (err) {
|
// Use lowercase to ensure email login is case insensitive
|
||||||
return null
|
const response = queryPlatformView(ViewName.PLATFORM_USERS_LOWERCASE, {
|
||||||
}
|
keys: [identifier.toLowerCase()],
|
||||||
})
|
include_docs: true,
|
||||||
|
}) as Promise<PlatformUser>
|
||||||
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
export const isUserInAppTenant = (appId: string, user: any) => {
|
export const isUserInAppTenant = (appId: string, user: any) => {
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
const { DEFAULT_TENANT_ID } = require("../constants")
|
|
||||||
const { StaticDatabases, SEPARATOR } = require("../db/constants")
|
|
||||||
|
|
||||||
exports.baseGlobalDBName = tenantId => {
|
|
||||||
let dbName
|
|
||||||
if (!tenantId || tenantId === DEFAULT_TENANT_ID) {
|
|
||||||
dbName = StaticDatabases.GLOBAL.name
|
|
||||||
} else {
|
|
||||||
dbName = `${tenantId}${SEPARATOR}${StaticDatabases.GLOBAL.name}`
|
|
||||||
}
|
|
||||||
return dbName
|
|
||||||
}
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { DEFAULT_TENANT_ID } from "../constants"
|
||||||
|
import { StaticDatabases, SEPARATOR } from "../db/constants"
|
||||||
|
import { getTenantId } from "../context"
|
||||||
|
|
||||||
|
export const getGlobalDBName = (tenantId?: string) => {
|
||||||
|
// tenant ID can be set externally, for example user API where
|
||||||
|
// new tenants are being created, this may be the case
|
||||||
|
if (!tenantId) {
|
||||||
|
tenantId = getTenantId()
|
||||||
|
}
|
||||||
|
return baseGlobalDBName(tenantId)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const baseGlobalDBName = (tenantId: string | undefined | null) => {
|
||||||
|
let dbName
|
||||||
|
if (!tenantId || tenantId === DEFAULT_TENANT_ID) {
|
||||||
|
dbName = StaticDatabases.GLOBAL.name
|
||||||
|
} else {
|
||||||
|
dbName = `${tenantId}${SEPARATOR}${StaticDatabases.GLOBAL.name}`
|
||||||
|
}
|
||||||
|
return dbName
|
||||||
|
}
|
|
@ -1377,6 +1377,11 @@ bcrypt@5.0.1:
|
||||||
"@mapbox/node-pre-gyp" "^1.0.0"
|
"@mapbox/node-pre-gyp" "^1.0.0"
|
||||||
node-addon-api "^3.1.0"
|
node-addon-api "^3.1.0"
|
||||||
|
|
||||||
|
bcryptjs@2.4.3:
|
||||||
|
version "2.4.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/bcryptjs/-/bcryptjs-2.4.3.tgz#9ab5627b93e60621ff7cdac5da9733027df1d0cb"
|
||||||
|
integrity sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==
|
||||||
|
|
||||||
binary-extensions@^2.0.0:
|
binary-extensions@^2.0.0:
|
||||||
version "2.2.0"
|
version "2.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
|
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
|
||||||
|
|
|
@ -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": "1.3.15-alpha.9",
|
"version": "1.3.18",
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"svelte": "src/index.js",
|
"svelte": "src/index.js",
|
||||||
"module": "dist/bbui.es.js",
|
"module": "dist/bbui.es.js",
|
||||||
|
@ -38,7 +38,7 @@
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@adobe/spectrum-css-workflow-icons": "^1.2.1",
|
"@adobe/spectrum-css-workflow-icons": "^1.2.1",
|
||||||
"@budibase/string-templates": "1.3.15-alpha.9",
|
"@budibase/string-templates": "^1.3.18",
|
||||||
"@spectrum-css/actionbutton": "^1.0.1",
|
"@spectrum-css/actionbutton": "^1.0.1",
|
||||||
"@spectrum-css/actiongroup": "^1.0.1",
|
"@spectrum-css/actiongroup": "^1.0.1",
|
||||||
"@spectrum-css/avatar": "^3.0.2",
|
"@spectrum-css/avatar": "^3.0.2",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/builder",
|
"name": "@budibase/builder",
|
||||||
"version": "1.3.15-alpha.9",
|
"version": "1.3.18",
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -69,10 +69,10 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/bbui": "1.3.15-alpha.9",
|
"@budibase/bbui": "^1.3.18",
|
||||||
"@budibase/client": "1.3.15-alpha.9",
|
"@budibase/client": "^1.3.18",
|
||||||
"@budibase/frontend-core": "1.3.15-alpha.9",
|
"@budibase/frontend-core": "^1.3.18",
|
||||||
"@budibase/string-templates": "1.3.15-alpha.9",
|
"@budibase/string-templates": "^1.3.18",
|
||||||
"@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",
|
||||||
|
|
|
@ -50,7 +50,6 @@
|
||||||
type="string"
|
type="string"
|
||||||
{bindings}
|
{bindings}
|
||||||
fillWidth={true}
|
fillWidth={true}
|
||||||
allowJS={false}
|
|
||||||
/>
|
/>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -23,7 +23,8 @@
|
||||||
"dataprovider",
|
"dataprovider",
|
||||||
"repeater",
|
"repeater",
|
||||||
"table",
|
"table",
|
||||||
"dynamicfilter"
|
"dynamicfilter",
|
||||||
|
"daterangepicker"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -60,7 +61,6 @@
|
||||||
"booleanfield",
|
"booleanfield",
|
||||||
"longformfield",
|
"longformfield",
|
||||||
"attachmentfield",
|
"attachmentfield",
|
||||||
"daterangepicker",
|
|
||||||
"jsonfield",
|
"jsonfield",
|
||||||
"relationshipfield",
|
"relationshipfield",
|
||||||
"datetimefield",
|
"datetimefield",
|
||||||
|
@ -81,4 +81,3 @@
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/cli",
|
"name": "@budibase/cli",
|
||||||
"version": "1.3.15-alpha.9",
|
"version": "1.3.18",
|
||||||
"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": {
|
||||||
|
@ -26,9 +26,9 @@
|
||||||
"outputPath": "build"
|
"outputPath": "build"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/backend-core": "1.3.15-alpha.9",
|
"@budibase/backend-core": "1.3.18",
|
||||||
"@budibase/string-templates": "1.3.15-alpha.9",
|
"@budibase/string-templates": "1.3.18",
|
||||||
"@budibase/types": "1.3.15-alpha.9",
|
"@budibase/types": "1.3.18",
|
||||||
"axios": "0.21.2",
|
"axios": "0.21.2",
|
||||||
"chalk": "4.1.0",
|
"chalk": "4.1.0",
|
||||||
"cli-progress": "3.11.2",
|
"cli-progress": "3.11.2",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/client",
|
"name": "@budibase/client",
|
||||||
"version": "1.3.15-alpha.9",
|
"version": "1.3.18",
|
||||||
"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": "1.3.15-alpha.9",
|
"@budibase/bbui": "^1.3.18",
|
||||||
"@budibase/frontend-core": "1.3.15-alpha.9",
|
"@budibase/frontend-core": "^1.3.18",
|
||||||
"@budibase/string-templates": "1.3.15-alpha.9",
|
"@budibase/string-templates": "^1.3.18",
|
||||||
"@spectrum-css/button": "^3.0.3",
|
"@spectrum-css/button": "^3.0.3",
|
||||||
"@spectrum-css/card": "^3.0.3",
|
"@spectrum-css/card": "^3.0.3",
|
||||||
"@spectrum-css/divider": "^1.0.3",
|
"@spectrum-css/divider": "^1.0.3",
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/frontend-core",
|
"name": "@budibase/frontend-core",
|
||||||
"version": "1.3.15-alpha.9",
|
"version": "1.3.18",
|
||||||
"description": "Budibase frontend core libraries used in builder and client",
|
"description": "Budibase frontend core libraries used in builder and client",
|
||||||
"author": "Budibase",
|
"author": "Budibase",
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"svelte": "src/index.js",
|
"svelte": "src/index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/bbui": "1.3.15-alpha.9",
|
"@budibase/bbui": "^1.3.18",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"svelte": "^3.46.2"
|
"svelte": "^3.46.2"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/server",
|
"name": "@budibase/server",
|
||||||
"email": "hi@budibase.com",
|
"email": "hi@budibase.com",
|
||||||
"version": "1.3.15-alpha.9",
|
"version": "1.3.18",
|
||||||
"description": "Budibase Web Server",
|
"description": "Budibase Web Server",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@ -77,11 +77,11 @@
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@apidevtools/swagger-parser": "10.0.3",
|
"@apidevtools/swagger-parser": "10.0.3",
|
||||||
"@budibase/backend-core": "1.3.15-alpha.9",
|
"@budibase/backend-core": "^1.3.18",
|
||||||
"@budibase/client": "1.3.15-alpha.9",
|
"@budibase/client": "^1.3.18",
|
||||||
"@budibase/pro": "1.3.15-alpha.9",
|
"@budibase/pro": "1.3.18",
|
||||||
"@budibase/string-templates": "1.3.15-alpha.9",
|
"@budibase/string-templates": "^1.3.18",
|
||||||
"@budibase/types": "1.3.15-alpha.9",
|
"@budibase/types": "^1.3.18",
|
||||||
"@bull-board/api": "3.7.0",
|
"@bull-board/api": "3.7.0",
|
||||||
"@bull-board/koa": "3.9.4",
|
"@bull-board/koa": "3.9.4",
|
||||||
"@elastic/elasticsearch": "7.10.0",
|
"@elastic/elasticsearch": "7.10.0",
|
||||||
|
|
|
@ -371,7 +371,10 @@ module External {
|
||||||
const toColumn = `${linkedTable.name}.${relationship.to}`
|
const toColumn = `${linkedTable.name}.${relationship.to}`
|
||||||
// this is important when working with multiple relationships
|
// this is important when working with multiple relationships
|
||||||
// between the same tables, don't want to overlap/multiply the relations
|
// between the same tables, don't want to overlap/multiply the relations
|
||||||
if (!relationship.through && row[fromColumn] !== row[toColumn]) {
|
if (
|
||||||
|
!relationship.through &&
|
||||||
|
row[fromColumn]?.toString() !== row[toColumn]?.toString()
|
||||||
|
) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
let linked = basicProcessing(row, linkedTable)
|
let linked = basicProcessing(row, linkedTable)
|
||||||
|
|
|
@ -37,8 +37,8 @@ function parseIntSafe(number) {
|
||||||
let inThread = false
|
let inThread = false
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
// important
|
// important - prefer app port to generic port
|
||||||
PORT: process.env.PORT || process.env.APP_PORT,
|
PORT: process.env.APP_PORT || process.env.PORT,
|
||||||
JWT_SECRET: process.env.JWT_SECRET,
|
JWT_SECRET: process.env.JWT_SECRET,
|
||||||
COUCH_DB_URL: process.env.COUCH_DB_URL,
|
COUCH_DB_URL: process.env.COUCH_DB_URL,
|
||||||
MINIO_URL: process.env.MINIO_URL,
|
MINIO_URL: process.env.MINIO_URL,
|
||||||
|
|
|
@ -49,7 +49,15 @@ const DATASOURCE_PATH = join(budibaseTempDir(), "datasource")
|
||||||
exports.init = () => {
|
exports.init = () => {
|
||||||
const tempDir = budibaseTempDir()
|
const tempDir = budibaseTempDir()
|
||||||
if (!fs.existsSync(tempDir)) {
|
if (!fs.existsSync(tempDir)) {
|
||||||
|
// some test cases fire this quickly enough that
|
||||||
|
// synchronous cases can end up here at the same time
|
||||||
|
try {
|
||||||
fs.mkdirSync(tempDir)
|
fs.mkdirSync(tempDir)
|
||||||
|
} catch (err) {
|
||||||
|
if (!err || err.code !== "EEXIST") {
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const clientLibPath = join(budibaseTempDir(), "budibase-client.js")
|
const clientLibPath = join(budibaseTempDir(), "budibase-client.js")
|
||||||
if (env.isTest() && !fs.existsSync(clientLibPath)) {
|
if (env.isTest() && !fs.existsSync(clientLibPath)) {
|
||||||
|
|
|
@ -1094,17 +1094,16 @@
|
||||||
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
||||||
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
||||||
|
|
||||||
"@budibase/backend-core@1.3.15-alpha.9":
|
"@budibase/backend-core@1.3.18":
|
||||||
version "1.3.15-alpha.9"
|
version "1.3.18"
|
||||||
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.3.15-alpha.9.tgz#06c582d1aac93ba689a9738ea35939ccc5bac430"
|
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.3.18.tgz#5ef26e3283f46b321103766b0359ca72035c8942"
|
||||||
integrity sha512-uShQQVPE2EsfPY6BNZnl/yKQoR8VwJyiIfCNE/EYl5aIVvhrqva+vA7JeYAs4sf/vf8Y5kkZaJGzfvzEws4dHg==
|
integrity sha512-utux5ydlnejKavU2H2HlCJkIyymVmGj+rVJp+SR1JrtPW2wkzHzpYn2k9eXFOYnAwqTF8jpCj4FVOEeDTfQcbw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@budibase/types" "1.3.15-alpha.9"
|
"@budibase/types" "^1.3.18"
|
||||||
"@shopify/jest-koa-mocks" "5.0.1"
|
"@shopify/jest-koa-mocks" "5.0.1"
|
||||||
"@techpass/passport-openidconnect" "0.3.2"
|
"@techpass/passport-openidconnect" "0.3.2"
|
||||||
aws-sdk "2.1030.0"
|
aws-sdk "2.1030.0"
|
||||||
bcrypt "5.0.1"
|
bcrypt "5.0.1"
|
||||||
bcryptjs "2.4.3"
|
|
||||||
dotenv "16.0.1"
|
dotenv "16.0.1"
|
||||||
emitter-listener "1.1.2"
|
emitter-listener "1.1.2"
|
||||||
ioredis "4.28.0"
|
ioredis "4.28.0"
|
||||||
|
@ -1180,13 +1179,13 @@
|
||||||
svelte-flatpickr "^3.2.3"
|
svelte-flatpickr "^3.2.3"
|
||||||
svelte-portal "^1.0.0"
|
svelte-portal "^1.0.0"
|
||||||
|
|
||||||
"@budibase/pro@1.3.15-alpha.9":
|
"@budibase/pro@1.3.18":
|
||||||
version "1.3.15-alpha.9"
|
version "1.3.18"
|
||||||
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.3.15-alpha.9.tgz#cb0ab3041df4c412eed9a8c7950f20ca0e3b62c5"
|
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.3.18.tgz#35a59e86c00971dd77a0b196e381a5ffd3be767c"
|
||||||
integrity sha512-1eE7O/bYeHxSoG8V61B2OZN3bGD44RAinAFJLHvBK7ncHZSTOOH4fe5HLvFiWPm0gV5ONDHpqr9W5Vs6ZBXukQ==
|
integrity sha512-aFGUr/ut4Ki56qLSdFaDLoEIPmwMqT5dGmY1xBT3Bwvhoq7hXevk1bcPFGj0rWBJnYG9zg/jmik9V4mE/lUOag==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@budibase/backend-core" "1.3.15-alpha.9"
|
"@budibase/backend-core" "1.3.18"
|
||||||
"@budibase/types" "1.3.15-alpha.9"
|
"@budibase/types" "1.3.18"
|
||||||
"@koa/router" "8.0.8"
|
"@koa/router" "8.0.8"
|
||||||
joi "17.6.0"
|
joi "17.6.0"
|
||||||
node-fetch "^2.6.1"
|
node-fetch "^2.6.1"
|
||||||
|
@ -1209,10 +1208,10 @@
|
||||||
svelte-apexcharts "^1.0.2"
|
svelte-apexcharts "^1.0.2"
|
||||||
svelte-flatpickr "^3.1.0"
|
svelte-flatpickr "^3.1.0"
|
||||||
|
|
||||||
"@budibase/types@1.3.15-alpha.9":
|
"@budibase/types@1.3.18", "@budibase/types@^1.3.18":
|
||||||
version "1.3.15-alpha.9"
|
version "1.3.18"
|
||||||
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-1.3.15-alpha.9.tgz#443cab0ca757a37af7a45f99caac35643fe273e5"
|
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-1.3.18.tgz#cd65213f476a2f37065796d0ccba18c8e8e07504"
|
||||||
integrity sha512-r1Z2PLPF3nR/bGzVyZ0/6RcOYb4Csmk4J/b1KJ57wzTeDdsRwgVgGO6QS+XYdwZctsKDNOm9FvpIQj3tNM8Rjw==
|
integrity sha512-bMtS2RbbI3Ztl5aAwEVlsK+2PQ0vRSZm8n6YDRjC9Arc94B4GDl/sqowRndKYqVtUeA/gVW0HH8x+qzhuMX6Dw==
|
||||||
|
|
||||||
"@bull-board/api@3.7.0":
|
"@bull-board/api@3.7.0":
|
||||||
version "3.7.0"
|
version "3.7.0"
|
||||||
|
@ -2325,6 +2324,11 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@sinonjs/commons" "^1.7.0"
|
"@sinonjs/commons" "^1.7.0"
|
||||||
|
|
||||||
|
"@socket.io/component-emitter@~3.1.0":
|
||||||
|
version "3.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz#96116f2a912e0c02817345b3c10751069920d553"
|
||||||
|
integrity sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==
|
||||||
|
|
||||||
"@spectrum-css/actionbutton@^1.0.1":
|
"@spectrum-css/actionbutton@^1.0.1":
|
||||||
version "1.1.14"
|
version "1.1.14"
|
||||||
resolved "https://registry.yarnpkg.com/@spectrum-css/actionbutton/-/actionbutton-1.1.14.tgz#4e12eb7f482fb5944c3d97547591964baebeb1d4"
|
resolved "https://registry.yarnpkg.com/@spectrum-css/actionbutton/-/actionbutton-1.1.14.tgz#4e12eb7f482fb5944c3d97547591964baebeb1d4"
|
||||||
|
@ -2676,11 +2680,6 @@
|
||||||
resolved "https://registry.yarnpkg.com/@types/caseless/-/caseless-0.12.2.tgz#f65d3d6389e01eeb458bd54dc8f52b95a9463bc8"
|
resolved "https://registry.yarnpkg.com/@types/caseless/-/caseless-0.12.2.tgz#f65d3d6389e01eeb458bd54dc8f52b95a9463bc8"
|
||||||
integrity sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w==
|
integrity sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w==
|
||||||
|
|
||||||
"@types/component-emitter@^1.2.10":
|
|
||||||
version "1.2.11"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/component-emitter/-/component-emitter-1.2.11.tgz#50d47d42b347253817a39709fef03ce66a108506"
|
|
||||||
integrity sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ==
|
|
||||||
|
|
||||||
"@types/connect@*":
|
"@types/connect@*":
|
||||||
version "3.4.35"
|
version "3.4.35"
|
||||||
resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1"
|
resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1"
|
||||||
|
@ -2927,9 +2926,9 @@
|
||||||
integrity sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==
|
integrity sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==
|
||||||
|
|
||||||
"@types/node@>=10.0.0":
|
"@types/node@>=10.0.0":
|
||||||
version "18.7.6"
|
version "18.7.18"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.7.6.tgz#31743bc5772b6ac223845e18c3fc26f042713c83"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.7.18.tgz#633184f55c322e4fb08612307c274ee6d5ed3154"
|
||||||
integrity sha512-EdxgKRXgYsNITy5mjjXjVE/CS8YENSdhiagGrLqjG0pvA2owgJ6i4l7wy/PFZGC0B1/H20lWKN7ONVDNYDZm7A==
|
integrity sha512-m+6nTEOadJZuTPkKR/SYK3A2d7FZrgElol9UP1Kae90VVU4a6mxnPuLiIW1m4Cq4gZ/nWb9GrdVXJCoCazDAbg==
|
||||||
|
|
||||||
"@types/node@>=8.0.0 <15":
|
"@types/node@>=8.0.0 <15":
|
||||||
version "14.18.21"
|
version "14.18.21"
|
||||||
|
@ -4800,7 +4799,7 @@ commoner@^0.10.1:
|
||||||
q "^1.1.2"
|
q "^1.1.2"
|
||||||
recast "^0.11.17"
|
recast "^0.11.17"
|
||||||
|
|
||||||
component-emitter@^1.2.0, component-emitter@^1.2.1, component-emitter@~1.3.0:
|
component-emitter@^1.2.0, component-emitter@^1.2.1:
|
||||||
version "1.3.0"
|
version "1.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0"
|
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0"
|
||||||
integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==
|
integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==
|
||||||
|
@ -12849,26 +12848,25 @@ socket.io-adapter@~2.4.0:
|
||||||
resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.4.0.tgz#b50a4a9ecdd00c34d4c8c808224daa1a786152a6"
|
resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.4.0.tgz#b50a4a9ecdd00c34d4c8c808224daa1a786152a6"
|
||||||
integrity sha512-W4N+o69rkMEGVuk2D/cvca3uYsvGlMwsySWV447y99gUPghxq42BxqLNMndb+a1mm/5/7NeXVQS7RLa2XyXvYg==
|
integrity sha512-W4N+o69rkMEGVuk2D/cvca3uYsvGlMwsySWV447y99gUPghxq42BxqLNMndb+a1mm/5/7NeXVQS7RLa2XyXvYg==
|
||||||
|
|
||||||
socket.io-parser@~4.0.4:
|
socket.io-parser@~4.2.0:
|
||||||
version "4.0.5"
|
version "4.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.0.5.tgz#cb404382c32324cc962f27f3a44058cf6e0552df"
|
resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.2.1.tgz#01c96efa11ded938dcb21cbe590c26af5eff65e5"
|
||||||
integrity sha512-sNjbT9dX63nqUFIOv95tTVm6elyIU4RvB1m8dOeZt+IgWwcWklFDOdmGcfo3zSiRsnR/3pJkjY5lfoGqEe4Eig==
|
integrity sha512-V4GrkLy+HeF1F/en3SpUaM+7XxYXpuMUWLGde1kSSh5nQMN4hLrbPIkD+otwh6q9R6NOQBN4AMaOZ2zVjui82g==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/component-emitter" "^1.2.10"
|
"@socket.io/component-emitter" "~3.1.0"
|
||||||
component-emitter "~1.3.0"
|
|
||||||
debug "~4.3.1"
|
debug "~4.3.1"
|
||||||
|
|
||||||
socket.io@^4.5.1:
|
socket.io@^4.5.1:
|
||||||
version "4.5.1"
|
version "4.5.2"
|
||||||
resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.5.1.tgz#aa7e73f8a6ce20ee3c54b2446d321bbb6b1a9029"
|
resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.5.2.tgz#1eb25fd380ab3d63470aa8279f8e48d922d443ac"
|
||||||
integrity sha512-0y9pnIso5a9i+lJmsCdtmTTgJFFSvNQKDnPQRz28mGNnxbmqYg2QPtJTLFxhymFZhAIn50eHAKzJeiNaKr+yUQ==
|
integrity sha512-6fCnk4ARMPZN448+SQcnn1u8OHUC72puJcNtSgg2xS34Cu7br1gQ09YKkO1PFfDn/wyUE9ZgMAwosJed003+NQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
accepts "~1.3.4"
|
accepts "~1.3.4"
|
||||||
base64id "~2.0.0"
|
base64id "~2.0.0"
|
||||||
debug "~4.3.2"
|
debug "~4.3.2"
|
||||||
engine.io "~6.2.0"
|
engine.io "~6.2.0"
|
||||||
socket.io-adapter "~2.4.0"
|
socket.io-adapter "~2.4.0"
|
||||||
socket.io-parser "~4.0.4"
|
socket.io-parser "~4.2.0"
|
||||||
|
|
||||||
sonic-boom@^1.0.2:
|
sonic-boom@^1.0.2:
|
||||||
version "1.4.1"
|
version "1.4.1"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/string-templates",
|
"name": "@budibase/string-templates",
|
||||||
"version": "1.3.15-alpha.9",
|
"version": "1.3.18",
|
||||||
"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,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/types",
|
"name": "@budibase/types",
|
||||||
"version": "1.3.15-alpha.9",
|
"version": "1.3.18",
|
||||||
"description": "Budibase types",
|
"description": "Budibase types",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
|
|
|
@ -7,3 +7,12 @@ export interface PlatformUserByEmail extends Document {
|
||||||
tenantId: string
|
tenantId: string
|
||||||
userId: string
|
userId: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* doc id is userId
|
||||||
|
*/
|
||||||
|
export interface PlatformUserById extends Document {
|
||||||
|
tenantId: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type PlatformUser = PlatformUserByEmail | PlatformUserById
|
||||||
|
|
|
@ -47,6 +47,7 @@ export enum MigrationName {
|
||||||
EVENT_GLOBAL_BACKFILL = "event_global_backfill",
|
EVENT_GLOBAL_BACKFILL = "event_global_backfill",
|
||||||
EVENT_INSTALLATION_BACKFILL = "event_installation_backfill",
|
EVENT_INSTALLATION_BACKFILL = "event_installation_backfill",
|
||||||
GLOBAL_INFO_SYNC_USERS = "global_info_sync_users",
|
GLOBAL_INFO_SYNC_USERS = "global_info_sync_users",
|
||||||
|
PLATFORM_USERS_EMAIL_CASING = "platform_users_email_casing",
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MigrationDefinition {
|
export interface MigrationDefinition {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/worker",
|
"name": "@budibase/worker",
|
||||||
"email": "hi@budibase.com",
|
"email": "hi@budibase.com",
|
||||||
"version": "1.3.15-alpha.9",
|
"version": "1.3.18",
|
||||||
"description": "Budibase background service",
|
"description": "Budibase background service",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@ -23,6 +23,7 @@
|
||||||
"dev:stack:init": "node ./scripts/dev/manage.js init",
|
"dev:stack:init": "node ./scripts/dev/manage.js init",
|
||||||
"dev:builder": "npm run dev:stack:init && nodemon",
|
"dev:builder": "npm run dev:stack:init && nodemon",
|
||||||
"test": "jest --runInBand",
|
"test": "jest --runInBand",
|
||||||
|
"test:watch": "jest --watch",
|
||||||
"env:multi:enable": "node scripts/multiTenancy.js enable",
|
"env:multi:enable": "node scripts/multiTenancy.js enable",
|
||||||
"env:multi:disable": "node scripts/multiTenancy.js disable",
|
"env:multi:disable": "node scripts/multiTenancy.js disable",
|
||||||
"env:selfhost:enable": "node scripts/selfhost.js enable",
|
"env:selfhost:enable": "node scripts/selfhost.js enable",
|
||||||
|
@ -35,10 +36,10 @@
|
||||||
"author": "Budibase",
|
"author": "Budibase",
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/backend-core": "1.3.15-alpha.9",
|
"@budibase/backend-core": "^1.3.18",
|
||||||
"@budibase/pro": "1.3.15-alpha.9",
|
"@budibase/pro": "1.3.18",
|
||||||
"@budibase/string-templates": "1.3.15-alpha.9",
|
"@budibase/string-templates": "^1.3.18",
|
||||||
"@budibase/types": "1.3.15-alpha.9",
|
"@budibase/types": "^1.3.18",
|
||||||
"@koa/router": "8.0.8",
|
"@koa/router": "8.0.8",
|
||||||
"@sentry/node": "6.17.7",
|
"@sentry/node": "6.17.7",
|
||||||
"@techpass/passport-openidconnect": "0.3.2",
|
"@techpass/passport-openidconnect": "0.3.2",
|
||||||
|
|
|
@ -242,6 +242,26 @@ describe("/api/global/users", () => {
|
||||||
expect(response.body.message).toBe(`Unavailable`)
|
expect(response.body.message).toBe(`Unavailable`)
|
||||||
expect(events.user.created).toBeCalledTimes(0)
|
expect(events.user.created).toBeCalledTimes(0)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("should not be able to create a user with the same email and different casing", async () => {
|
||||||
|
const user = structures.users.user()
|
||||||
|
await api.users.saveUser(user)
|
||||||
|
|
||||||
|
user.email = user.email.toUpperCase()
|
||||||
|
await api.users.saveUser(user, 400)
|
||||||
|
|
||||||
|
expect(events.user.created).toBeCalledTimes(1)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should not be able to bulk create a user with the same email and different casing", async () => {
|
||||||
|
const user = structures.users.user()
|
||||||
|
await api.users.saveUser(user)
|
||||||
|
|
||||||
|
user.email = user.email.toUpperCase()
|
||||||
|
await api.users.bulkCreateUsers([user])
|
||||||
|
|
||||||
|
expect(events.user.created).toBeCalledTimes(1)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("update", () => {
|
describe("update", () => {
|
||||||
|
|
|
@ -43,7 +43,8 @@ const env = {
|
||||||
PLATFORM_URL: process.env.PLATFORM_URL,
|
PLATFORM_URL: process.env.PLATFORM_URL,
|
||||||
APPS_URL: process.env.APPS_URL,
|
APPS_URL: process.env.APPS_URL,
|
||||||
// ports
|
// ports
|
||||||
PORT: process.env.PORT || process.env.WORKER_PORT,
|
// prefer worker port to generic port
|
||||||
|
PORT: process.env.WORKER_PORT || process.env.PORT,
|
||||||
CLUSTER_PORT: process.env.CLUSTER_PORT,
|
CLUSTER_PORT: process.env.CLUSTER_PORT,
|
||||||
// flags
|
// flags
|
||||||
NODE_ENV: process.env.NODE_ENV,
|
NODE_ENV: process.env.NODE_ENV,
|
||||||
|
|
|
@ -278,39 +278,61 @@ export const addTenant = async (
|
||||||
}
|
}
|
||||||
|
|
||||||
const getExistingTenantUsers = async (emails: string[]): Promise<User[]> => {
|
const getExistingTenantUsers = async (emails: string[]): Promise<User[]> => {
|
||||||
return dbUtils.queryGlobalView(ViewName.USER_BY_EMAIL, {
|
const lcEmails = emails.map(email => email.toLowerCase())
|
||||||
keys: emails,
|
const params = {
|
||||||
|
keys: lcEmails,
|
||||||
include_docs: true,
|
include_docs: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
const opts = {
|
||||||
arrayResponse: true,
|
arrayResponse: true,
|
||||||
})
|
}
|
||||||
|
|
||||||
|
return dbUtils.queryGlobalView(
|
||||||
|
ViewName.USER_BY_EMAIL,
|
||||||
|
params,
|
||||||
|
undefined,
|
||||||
|
opts
|
||||||
|
) as Promise<User[]>
|
||||||
}
|
}
|
||||||
|
|
||||||
const getExistingPlatformUsers = async (
|
const getExistingPlatformUsers = async (
|
||||||
emails: string[]
|
emails: string[]
|
||||||
): Promise<PlatformUserByEmail[]> => {
|
): Promise<PlatformUserByEmail[]> => {
|
||||||
return dbUtils.doWithDB(
|
const lcEmails = emails.map(email => email.toLowerCase())
|
||||||
StaticDatabases.PLATFORM_INFO.name,
|
const params = {
|
||||||
async (infoDb: any) => {
|
keys: lcEmails,
|
||||||
const response: AllDocsResponse<PlatformUserByEmail> =
|
|
||||||
await infoDb.allDocs({
|
|
||||||
keys: emails,
|
|
||||||
include_docs: true,
|
include_docs: true,
|
||||||
})
|
|
||||||
return response.rows
|
|
||||||
.filter(row => row.doc && (row.error !== "not_found") !== null)
|
|
||||||
.map((row: any) => row.doc)
|
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
const opts = {
|
||||||
|
arrayResponse: true,
|
||||||
|
}
|
||||||
|
return dbUtils.queryPlatformView(
|
||||||
|
ViewName.PLATFORM_USERS_LOWERCASE,
|
||||||
|
params,
|
||||||
|
opts
|
||||||
|
) as Promise<PlatformUserByEmail[]>
|
||||||
}
|
}
|
||||||
|
|
||||||
const getExistingAccounts = async (
|
const getExistingAccounts = async (
|
||||||
emails: string[]
|
emails: string[]
|
||||||
): Promise<AccountMetadata[]> => {
|
): Promise<AccountMetadata[]> => {
|
||||||
return dbUtils.queryPlatformView(ViewName.ACCOUNT_BY_EMAIL, {
|
const lcEmails = emails.map(email => email.toLowerCase())
|
||||||
keys: emails,
|
const params = {
|
||||||
|
keys: lcEmails,
|
||||||
include_docs: true,
|
include_docs: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
const opts = {
|
||||||
arrayResponse: true,
|
arrayResponse: true,
|
||||||
})
|
}
|
||||||
|
|
||||||
|
return dbUtils.queryPlatformView(
|
||||||
|
ViewName.ACCOUNT_BY_EMAIL,
|
||||||
|
params,
|
||||||
|
opts
|
||||||
|
) as Promise<AccountMetadata[]>
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -332,7 +354,7 @@ const searchExistingEmails = async (emails: string[]) => {
|
||||||
const existingAccounts = await getExistingAccounts(emails)
|
const existingAccounts = await getExistingAccounts(emails)
|
||||||
matchedEmails.push(...existingAccounts.map(account => account.email))
|
matchedEmails.push(...existingAccounts.map(account => account.email))
|
||||||
|
|
||||||
return [...new Set(matchedEmails)]
|
return [...new Set(matchedEmails.map(email => email.toLowerCase()))]
|
||||||
}
|
}
|
||||||
|
|
||||||
export const bulkCreate = async (
|
export const bulkCreate = async (
|
||||||
|
@ -351,8 +373,10 @@ export const bulkCreate = async (
|
||||||
|
|
||||||
for (const newUser of newUsersRequested) {
|
for (const newUser of newUsersRequested) {
|
||||||
if (
|
if (
|
||||||
newUsers.find((x: any) => x.email === newUser.email) ||
|
newUsers.find(
|
||||||
existingEmails.includes(newUser.email)
|
(x: User) => x.email.toLowerCase() === newUser.email.toLowerCase()
|
||||||
|
) ||
|
||||||
|
existingEmails.includes(newUser.email.toLowerCase())
|
||||||
) {
|
) {
|
||||||
unsuccessful.push({
|
unsuccessful.push({
|
||||||
email: newUser.email,
|
email: newUser.email,
|
||||||
|
|
|
@ -291,17 +291,16 @@
|
||||||
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
||||||
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
||||||
|
|
||||||
"@budibase/backend-core@1.3.15-alpha.9":
|
"@budibase/backend-core@1.3.18":
|
||||||
version "1.3.15-alpha.9"
|
version "1.3.18"
|
||||||
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.3.15-alpha.9.tgz#06c582d1aac93ba689a9738ea35939ccc5bac430"
|
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.3.18.tgz#5ef26e3283f46b321103766b0359ca72035c8942"
|
||||||
integrity sha512-uShQQVPE2EsfPY6BNZnl/yKQoR8VwJyiIfCNE/EYl5aIVvhrqva+vA7JeYAs4sf/vf8Y5kkZaJGzfvzEws4dHg==
|
integrity sha512-utux5ydlnejKavU2H2HlCJkIyymVmGj+rVJp+SR1JrtPW2wkzHzpYn2k9eXFOYnAwqTF8jpCj4FVOEeDTfQcbw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@budibase/types" "1.3.15-alpha.9"
|
"@budibase/types" "^1.3.18"
|
||||||
"@shopify/jest-koa-mocks" "5.0.1"
|
"@shopify/jest-koa-mocks" "5.0.1"
|
||||||
"@techpass/passport-openidconnect" "0.3.2"
|
"@techpass/passport-openidconnect" "0.3.2"
|
||||||
aws-sdk "2.1030.0"
|
aws-sdk "2.1030.0"
|
||||||
bcrypt "5.0.1"
|
bcrypt "5.0.1"
|
||||||
bcryptjs "2.4.3"
|
|
||||||
dotenv "16.0.1"
|
dotenv "16.0.1"
|
||||||
emitter-listener "1.1.2"
|
emitter-listener "1.1.2"
|
||||||
ioredis "4.28.0"
|
ioredis "4.28.0"
|
||||||
|
@ -327,21 +326,21 @@
|
||||||
uuid "8.3.2"
|
uuid "8.3.2"
|
||||||
zlib "1.0.5"
|
zlib "1.0.5"
|
||||||
|
|
||||||
"@budibase/pro@1.3.15-alpha.9":
|
"@budibase/pro@1.3.18":
|
||||||
version "1.3.15-alpha.9"
|
version "1.3.18"
|
||||||
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.3.15-alpha.9.tgz#cb0ab3041df4c412eed9a8c7950f20ca0e3b62c5"
|
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.3.18.tgz#35a59e86c00971dd77a0b196e381a5ffd3be767c"
|
||||||
integrity sha512-1eE7O/bYeHxSoG8V61B2OZN3bGD44RAinAFJLHvBK7ncHZSTOOH4fe5HLvFiWPm0gV5ONDHpqr9W5Vs6ZBXukQ==
|
integrity sha512-aFGUr/ut4Ki56qLSdFaDLoEIPmwMqT5dGmY1xBT3Bwvhoq7hXevk1bcPFGj0rWBJnYG9zg/jmik9V4mE/lUOag==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@budibase/backend-core" "1.3.15-alpha.9"
|
"@budibase/backend-core" "1.3.18"
|
||||||
"@budibase/types" "1.3.15-alpha.9"
|
"@budibase/types" "1.3.18"
|
||||||
"@koa/router" "8.0.8"
|
"@koa/router" "8.0.8"
|
||||||
joi "17.6.0"
|
joi "17.6.0"
|
||||||
node-fetch "^2.6.1"
|
node-fetch "^2.6.1"
|
||||||
|
|
||||||
"@budibase/types@1.3.15-alpha.9":
|
"@budibase/types@1.3.18", "@budibase/types@^1.3.18":
|
||||||
version "1.3.15-alpha.9"
|
version "1.3.18"
|
||||||
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-1.3.15-alpha.9.tgz#443cab0ca757a37af7a45f99caac35643fe273e5"
|
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-1.3.18.tgz#cd65213f476a2f37065796d0ccba18c8e8e07504"
|
||||||
integrity sha512-r1Z2PLPF3nR/bGzVyZ0/6RcOYb4Csmk4J/b1KJ57wzTeDdsRwgVgGO6QS+XYdwZctsKDNOm9FvpIQj3tNM8Rjw==
|
integrity sha512-bMtS2RbbI3Ztl5aAwEVlsK+2PQ0vRSZm8n6YDRjC9Arc94B4GDl/sqowRndKYqVtUeA/gVW0HH8x+qzhuMX6Dw==
|
||||||
|
|
||||||
"@cspotcode/source-map-consumer@0.8.0":
|
"@cspotcode/source-map-consumer@0.8.0":
|
||||||
version "0.8.0"
|
version "0.8.0"
|
||||||
|
|
Loading…
Reference in New Issue