Refactoring worker, converting all controllers/routes to Typescript and all imports of backend-core to new style.
This commit is contained in:
parent
c79f7506c1
commit
1b408e60f2
|
@ -4,7 +4,7 @@ const JwtStrategy = require("passport-jwt").Strategy
|
|||
import { getGlobalDB } from "./tenancy"
|
||||
const refresh = require("passport-oauth2-refresh")
|
||||
import { Config } from "./constants"
|
||||
import { getScopedConfig } from "./db/utils"
|
||||
import { getScopedConfig } from "./db"
|
||||
import {
|
||||
jwt,
|
||||
local,
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
const { objectStore } = require("@budibase/backend-core")
|
||||
const fs = require("fs")
|
||||
const { join } = require("path")
|
||||
const { TEMP_DIR, MINIO_DIR } = require("./utils")
|
||||
const { progressBar } = require("../utils")
|
||||
const {
|
||||
ObjectStoreBuckets,
|
||||
ObjectStore,
|
||||
retrieve,
|
||||
uploadDirectory,
|
||||
makeSureBucketExists,
|
||||
} = require("@budibase/backend-core/objectStore")
|
||||
const fs = require("fs")
|
||||
const { join } = require("path")
|
||||
const { TEMP_DIR, MINIO_DIR } = require("./utils")
|
||||
const { progressBar } = require("../utils")
|
||||
} = objectStore
|
||||
|
||||
const bucketList = Object.values(ObjectStoreBuckets)
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ const { getSkeleton, fleshOutSkeleton } = require("./skeleton")
|
|||
const questions = require("../questions")
|
||||
const fs = require("fs")
|
||||
const { PLUGIN_TYPE_ARR } = require("@budibase/types")
|
||||
const { validate } = require("@budibase/backend-core/plugins")
|
||||
const { plugins } = require("@budibase/backend-core")
|
||||
const { runPkgCommand } = require("../exec")
|
||||
const { join } = require("path")
|
||||
const { success, error, info, moveDirectory } = require("../utils")
|
||||
|
@ -107,7 +107,7 @@ async function verify() {
|
|||
}
|
||||
name = pkgJson.name
|
||||
version = pkgJson.version
|
||||
validate(schemaJson)
|
||||
plugins.validate(schemaJson)
|
||||
return { name, version }
|
||||
} catch (err) {
|
||||
if (err && err.message && err.message.includes("not valid JSON")) {
|
||||
|
|
|
@ -62,7 +62,9 @@ export const isOIDCConfig = (config: Config): config is OIDCConfig =>
|
|||
|
||||
export enum ConfigType {
|
||||
SETTINGS = "settings",
|
||||
ACCOUNT = "account",
|
||||
SMTP = "smtp",
|
||||
GOOGLE = "google",
|
||||
OIDC = "oidc",
|
||||
OIDC_LOGOS = "logos_oidc",
|
||||
}
|
||||
|
|
|
@ -4,3 +4,4 @@ export * from "./userGroup"
|
|||
export * from "./plugin"
|
||||
export * from "./quotas"
|
||||
export * from "./schedule"
|
||||
export * from "./templates"
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
import { Document } from "../document"
|
||||
|
||||
export interface Template extends Document {
|
||||
ownerId?: string
|
||||
name?: string
|
||||
contents: string
|
||||
purpose: string
|
||||
type?: string
|
||||
}
|
|
@ -1,25 +1,25 @@
|
|||
import core from "@budibase/backend-core"
|
||||
import { utils, constants, auth, db as dbCore } from "@budibase/backend-core"
|
||||
import {
|
||||
events,
|
||||
users as usersCore,
|
||||
context,
|
||||
tenancy,
|
||||
} from "@budibase/backend-core"
|
||||
import { Config, EmailTemplatePurpose } from "../../../constants"
|
||||
import { EmailTemplatePurpose } from "../../../constants"
|
||||
import { sendEmail, isEmailConfigured } from "../../../utilities/email"
|
||||
import { checkResetPasswordCode } from "../../../utilities/redis"
|
||||
import env from "../../../environment"
|
||||
import sdk from "../../../sdk"
|
||||
import { User } from "@budibase/types"
|
||||
const { setCookie, getCookie, clearCookie, hash, platformLogout } = core.utils
|
||||
const { Cookie, Header } = core.constants
|
||||
const { passport, ssoCallbackUrl, google, oidc } = core.auth
|
||||
import { User, Config, ConfigType } from "@budibase/types"
|
||||
const { setCookie, getCookie, clearCookie, hash, platformLogout } = utils
|
||||
const { Cookie, Header } = constants
|
||||
const { passport, ssoCallbackUrl, google, oidc } = auth
|
||||
|
||||
export const googleCallbackUrl = async (config: any) => {
|
||||
export async function googleCallbackUrl(config?: Config) {
|
||||
return ssoCallbackUrl(tenancy.getGlobalDB(), config, "google")
|
||||
}
|
||||
|
||||
export const oidcCallbackUrl = async (config: any) => {
|
||||
export async function oidcCallbackUrl(config?: Config) {
|
||||
return ssoCallbackUrl(tenancy.getGlobalDB(), config, "oidc")
|
||||
}
|
||||
|
||||
|
@ -135,7 +135,7 @@ export const logout = async (ctx: any) => {
|
|||
|
||||
export const datasourcePreAuth = async (ctx: any, next: any) => {
|
||||
const provider = ctx.params.provider
|
||||
const middleware = require(`@budibase/backend-core/middleware`)
|
||||
const { middleware } = require(`@budibase/backend-core`)
|
||||
const handler = middleware.datasource[provider]
|
||||
|
||||
setCookie(
|
||||
|
@ -154,7 +154,7 @@ export const datasourcePreAuth = async (ctx: any, next: any) => {
|
|||
export const datasourceAuth = async (ctx: any, next: any) => {
|
||||
const authStateCookie = getCookie(ctx, Cookie.DatasourceAuth)
|
||||
const provider = authStateCookie.provider
|
||||
const middleware = require(`@budibase/backend-core/middleware`)
|
||||
const { middleware } = require(`@budibase/backend-core`)
|
||||
const handler = middleware.datasource[provider]
|
||||
return handler.postAuth(passport, ctx, next)
|
||||
}
|
||||
|
@ -166,11 +166,11 @@ export const datasourceAuth = async (ctx: any, next: any) => {
|
|||
export const googlePreAuth = async (ctx: any, next: any) => {
|
||||
const db = tenancy.getGlobalDB()
|
||||
|
||||
const config = await core.db.getScopedConfig(db, {
|
||||
type: Config.GOOGLE,
|
||||
const config = await dbCore.getScopedConfig(db, {
|
||||
type: ConfigType.GOOGLE,
|
||||
workspace: ctx.query.workspace,
|
||||
})
|
||||
let callbackUrl = await exports.googleCallbackUrl(config)
|
||||
let callbackUrl = await googleCallbackUrl(config)
|
||||
const strategy = await google.strategyFactory(
|
||||
config,
|
||||
callbackUrl,
|
||||
|
@ -187,11 +187,11 @@ export const googlePreAuth = async (ctx: any, next: any) => {
|
|||
export const googleAuth = async (ctx: any, next: any) => {
|
||||
const db = tenancy.getGlobalDB()
|
||||
|
||||
const config = await core.db.getScopedConfig(db, {
|
||||
type: Config.GOOGLE,
|
||||
const config = await dbCore.getScopedConfig(db, {
|
||||
type: ConfigType.GOOGLE,
|
||||
workspace: ctx.query.workspace,
|
||||
})
|
||||
const callbackUrl = await exports.googleCallbackUrl(config)
|
||||
const callbackUrl = await googleCallbackUrl(config)
|
||||
const strategy = await google.strategyFactory(
|
||||
config,
|
||||
callbackUrl,
|
||||
|
@ -213,13 +213,13 @@ export const googleAuth = async (ctx: any, next: any) => {
|
|||
|
||||
export const oidcStrategyFactory = async (ctx: any, configId: any) => {
|
||||
const db = tenancy.getGlobalDB()
|
||||
const config = await core.db.getScopedConfig(db, {
|
||||
type: Config.OIDC,
|
||||
const config = await dbCore.getScopedConfig(db, {
|
||||
type: ConfigType.OIDC,
|
||||
group: ctx.query.group,
|
||||
})
|
||||
|
||||
const chosenConfig = config.configs.filter((c: any) => c.uuid === configId)[0]
|
||||
let callbackUrl = await exports.oidcCallbackUrl(chosenConfig)
|
||||
let callbackUrl = await oidcCallbackUrl(chosenConfig)
|
||||
|
||||
//Remote Config
|
||||
const enrichedConfig = await oidc.fetchStrategyConfig(
|
||||
|
@ -240,8 +240,8 @@ export const oidcPreAuth = async (ctx: any, next: any) => {
|
|||
setCookie(ctx, configId, Cookie.OIDC_CONFIG)
|
||||
|
||||
const db = tenancy.getGlobalDB()
|
||||
const config = await core.db.getScopedConfig(db, {
|
||||
type: Config.OIDC,
|
||||
const config = await dbCore.getScopedConfig(db, {
|
||||
type: ConfigType.OIDC,
|
||||
group: ctx.query.group,
|
||||
})
|
||||
|
||||
|
|
|
@ -1,28 +1,26 @@
|
|||
const {
|
||||
generateConfigID,
|
||||
getConfigParams,
|
||||
getScopedFullConfig,
|
||||
getAllApps,
|
||||
} = require("@budibase/backend-core/db")
|
||||
const { Config } = require("../../../constants")
|
||||
const email = require("../../../utilities/email")
|
||||
const {
|
||||
upload,
|
||||
ObjectStoreBuckets,
|
||||
} = require("@budibase/backend-core/objectStore")
|
||||
const { getGlobalDB, getTenantId } = require("@budibase/backend-core/tenancy")
|
||||
const env = require("../../../environment")
|
||||
const { googleCallbackUrl, oidcCallbackUrl } = require("./auth")
|
||||
const {
|
||||
withCache,
|
||||
CacheKeys,
|
||||
bustCache,
|
||||
import * as email from "../../../utilities/email"
|
||||
import env from "../../../environment"
|
||||
import { googleCallbackUrl, oidcCallbackUrl } from "./auth"
|
||||
import {
|
||||
events,
|
||||
cache,
|
||||
} = require("@budibase/backend-core/cache")
|
||||
const { events } = require("@budibase/backend-core")
|
||||
const { checkAnyUserExists } = require("../../../utilities/users")
|
||||
objectStore,
|
||||
tenancy,
|
||||
db as dbCore,
|
||||
} from "@budibase/backend-core"
|
||||
import { checkAnyUserExists } from "../../../utilities/users"
|
||||
import {
|
||||
Database,
|
||||
Config as ConfigDoc,
|
||||
ConfigType,
|
||||
SSOType,
|
||||
GoogleConfig,
|
||||
OIDCConfig,
|
||||
SettingsConfig,
|
||||
BBContext,
|
||||
} from "@budibase/types"
|
||||
|
||||
const getEventFns = async (db, config) => {
|
||||
const getEventFns = async (db: Database, config: ConfigDoc) => {
|
||||
const fns = []
|
||||
const type = config.type
|
||||
|
||||
|
@ -31,41 +29,45 @@ const getEventFns = async (db, config) => {
|
|||
existing = await db.get(config._id)
|
||||
}
|
||||
|
||||
const ssoType = type as SSOType
|
||||
if (!existing) {
|
||||
switch (config.type) {
|
||||
case Config.SMTP: {
|
||||
case ConfigType.SMTP: {
|
||||
fns.push(events.email.SMTPCreated)
|
||||
break
|
||||
}
|
||||
case Config.GOOGLE: {
|
||||
fns.push(() => events.auth.SSOCreated(type))
|
||||
if (config.config.activated) {
|
||||
fns.push(() => events.auth.SSOActivated(type))
|
||||
case ConfigType.GOOGLE: {
|
||||
const googleCfg = config as GoogleConfig
|
||||
fns.push(() => events.auth.SSOCreated(ssoType))
|
||||
if (googleCfg.config.activated) {
|
||||
fns.push(() => events.auth.SSOActivated(ssoType))
|
||||
}
|
||||
break
|
||||
}
|
||||
case Config.OIDC: {
|
||||
fns.push(() => events.auth.SSOCreated(type))
|
||||
if (config.config.configs[0].activated) {
|
||||
fns.push(() => events.auth.SSOActivated(type))
|
||||
case ConfigType.OIDC: {
|
||||
const oidcCfg = config as OIDCConfig
|
||||
fns.push(() => events.auth.SSOCreated(ssoType))
|
||||
if (oidcCfg.config.configs[0].activated) {
|
||||
fns.push(() => events.auth.SSOActivated(ssoType))
|
||||
}
|
||||
break
|
||||
}
|
||||
case Config.SETTINGS: {
|
||||
case ConfigType.SETTINGS: {
|
||||
// company
|
||||
const company = config.config.company
|
||||
const settingsCfg = config as SettingsConfig
|
||||
const company = settingsCfg.config.company
|
||||
if (company && company !== "Budibase") {
|
||||
fns.push(events.org.nameUpdated)
|
||||
}
|
||||
|
||||
// logo
|
||||
const logoUrl = config.config.logoUrl
|
||||
const logoUrl = settingsCfg.config.logoUrl
|
||||
if (logoUrl) {
|
||||
fns.push(events.org.logoUpdated)
|
||||
}
|
||||
|
||||
// platform url
|
||||
const platformUrl = config.config.platformUrl
|
||||
const platformUrl = settingsCfg.config.platformUrl
|
||||
if (
|
||||
platformUrl &&
|
||||
platformUrl !== "http://localhost:10000" &&
|
||||
|
@ -78,52 +80,55 @@ const getEventFns = async (db, config) => {
|
|||
}
|
||||
} else {
|
||||
switch (config.type) {
|
||||
case Config.SMTP: {
|
||||
case ConfigType.SMTP: {
|
||||
fns.push(events.email.SMTPUpdated)
|
||||
break
|
||||
}
|
||||
case Config.GOOGLE: {
|
||||
fns.push(() => events.auth.SSOUpdated(type))
|
||||
if (!existing.config.activated && config.config.activated) {
|
||||
fns.push(() => events.auth.SSOActivated(type))
|
||||
} else if (existing.config.activated && !config.config.activated) {
|
||||
fns.push(() => events.auth.SSODeactivated(type))
|
||||
case ConfigType.GOOGLE: {
|
||||
const googleCfg = config as GoogleConfig
|
||||
fns.push(() => events.auth.SSOUpdated(ssoType))
|
||||
if (!existing.config.activated && googleCfg.config.activated) {
|
||||
fns.push(() => events.auth.SSOActivated(ssoType))
|
||||
} else if (existing.config.activated && !googleCfg.config.activated) {
|
||||
fns.push(() => events.auth.SSODeactivated(ssoType))
|
||||
}
|
||||
break
|
||||
}
|
||||
case Config.OIDC: {
|
||||
fns.push(() => events.auth.SSOUpdated(type))
|
||||
case ConfigType.OIDC: {
|
||||
const oidcCfg = config as OIDCConfig
|
||||
fns.push(() => events.auth.SSOUpdated(ssoType))
|
||||
if (
|
||||
!existing.config.configs[0].activated &&
|
||||
config.config.configs[0].activated
|
||||
oidcCfg.config.configs[0].activated
|
||||
) {
|
||||
fns.push(() => events.auth.SSOActivated(type))
|
||||
fns.push(() => events.auth.SSOActivated(ssoType))
|
||||
} else if (
|
||||
existing.config.configs[0].activated &&
|
||||
!config.config.configs[0].activated
|
||||
!oidcCfg.config.configs[0].activated
|
||||
) {
|
||||
fns.push(() => events.auth.SSODeactivated(type))
|
||||
fns.push(() => events.auth.SSODeactivated(ssoType))
|
||||
}
|
||||
break
|
||||
}
|
||||
case Config.SETTINGS: {
|
||||
case ConfigType.SETTINGS: {
|
||||
// company
|
||||
const settingsCfg = config as SettingsConfig
|
||||
const existingCompany = existing.config.company
|
||||
const company = config.config.company
|
||||
const company = settingsCfg.config.company
|
||||
if (company && company !== "Budibase" && existingCompany !== company) {
|
||||
fns.push(events.org.nameUpdated)
|
||||
}
|
||||
|
||||
// logo
|
||||
const existingLogoUrl = existing.config.logoUrl
|
||||
const logoUrl = config.config.logoUrl
|
||||
const logoUrl = settingsCfg.config.logoUrl
|
||||
if (logoUrl && existingLogoUrl !== logoUrl) {
|
||||
fns.push(events.org.logoUpdated)
|
||||
}
|
||||
|
||||
// platform url
|
||||
const existingPlatformUrl = existing.config.platformUrl
|
||||
const platformUrl = config.config.platformUrl
|
||||
const platformUrl = settingsCfg.config.platformUrl
|
||||
if (
|
||||
platformUrl &&
|
||||
platformUrl !== "http://localhost:10000" &&
|
||||
|
@ -140,13 +145,13 @@ const getEventFns = async (db, config) => {
|
|||
return fns
|
||||
}
|
||||
|
||||
exports.save = async function (ctx) {
|
||||
const db = getGlobalDB()
|
||||
export async function save(ctx: BBContext) {
|
||||
const db = tenancy.getGlobalDB()
|
||||
const { type, workspace, user, config } = ctx.request.body
|
||||
let eventFns = await getEventFns(db, ctx.request.body)
|
||||
// Config does not exist yet
|
||||
if (!ctx.request.body._id) {
|
||||
ctx.request.body._id = generateConfigID({
|
||||
ctx.request.body._id = dbCore.generateConfigID({
|
||||
type,
|
||||
workspace,
|
||||
user,
|
||||
|
@ -155,18 +160,18 @@ exports.save = async function (ctx) {
|
|||
try {
|
||||
// verify the configuration
|
||||
switch (type) {
|
||||
case Config.SMTP:
|
||||
case ConfigType.SMTP:
|
||||
await email.verifyConfig(config)
|
||||
break
|
||||
}
|
||||
} catch (err) {
|
||||
} catch (err: any) {
|
||||
ctx.throw(400, err)
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await db.put(ctx.request.body)
|
||||
await bustCache(CacheKeys.CHECKLIST)
|
||||
await bustCache(CacheKeys.ANALYTICS_ENABLED)
|
||||
await cache.bustCache(cache.CacheKeys.CHECKLIST)
|
||||
await cache.bustCache(cache.CacheKeys.ANALYTICS_ENABLED)
|
||||
|
||||
for (const fn of eventFns) {
|
||||
await fn()
|
||||
|
@ -177,15 +182,15 @@ exports.save = async function (ctx) {
|
|||
_id: response.id,
|
||||
_rev: response.rev,
|
||||
}
|
||||
} catch (err) {
|
||||
} catch (err: any) {
|
||||
ctx.throw(400, err)
|
||||
}
|
||||
}
|
||||
|
||||
exports.fetch = async function (ctx) {
|
||||
const db = getGlobalDB()
|
||||
export async function fetch(ctx: BBContext) {
|
||||
const db = tenancy.getGlobalDB()
|
||||
const response = await db.allDocs(
|
||||
getConfigParams(
|
||||
dbCore.getConfigParams(
|
||||
{ type: ctx.params.type },
|
||||
{
|
||||
include_docs: true,
|
||||
|
@ -199,23 +204,23 @@ exports.fetch = async function (ctx) {
|
|||
* Gets the most granular config for a particular configuration type.
|
||||
* The hierarchy is type -> workspace -> user.
|
||||
*/
|
||||
exports.find = async function (ctx) {
|
||||
const db = getGlobalDB()
|
||||
export async function find(ctx: BBContext) {
|
||||
const db = tenancy.getGlobalDB()
|
||||
|
||||
const { userId, workspaceId } = ctx.query
|
||||
if (workspaceId && userId) {
|
||||
const workspace = await db.get(workspaceId)
|
||||
const workspace = await db.get(workspaceId as string)
|
||||
const userInWorkspace = workspace.users.some(
|
||||
workspaceUser => workspaceUser === userId
|
||||
(workspaceUser: any) => workspaceUser === userId
|
||||
)
|
||||
if (!ctx.user.admin && !userInWorkspace) {
|
||||
if (!ctx.user!.admin && !userInWorkspace) {
|
||||
ctx.throw(400, `User is not in specified workspace: ${workspace}.`)
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// Find the config with the most granular scope based on context
|
||||
const scopedConfig = await getScopedFullConfig(db, {
|
||||
const scopedConfig = await dbCore.getScopedFullConfig(db, {
|
||||
type: ctx.params.type,
|
||||
user: userId,
|
||||
workspace: workspaceId,
|
||||
|
@ -227,48 +232,48 @@ exports.find = async function (ctx) {
|
|||
// don't throw an error, there simply is nothing to return
|
||||
ctx.body = {}
|
||||
}
|
||||
} catch (err) {
|
||||
ctx.throw(err.status, err)
|
||||
} catch (err: any) {
|
||||
ctx.throw(err?.status || 400, err)
|
||||
}
|
||||
}
|
||||
|
||||
exports.publicOidc = async function (ctx) {
|
||||
const db = getGlobalDB()
|
||||
export async function publicOidc(ctx: BBContext) {
|
||||
const db = tenancy.getGlobalDB()
|
||||
try {
|
||||
// Find the config with the most granular scope based on context
|
||||
const oidcConfig = await getScopedFullConfig(db, {
|
||||
type: Config.OIDC,
|
||||
const oidcConfig = await dbCore.getScopedFullConfig(db, {
|
||||
type: ConfigType.OIDC,
|
||||
})
|
||||
|
||||
if (!oidcConfig) {
|
||||
ctx.body = {}
|
||||
} else {
|
||||
ctx.body = oidcConfig.config.configs.map(config => ({
|
||||
ctx.body = oidcConfig.config.configs.map((config: any) => ({
|
||||
logo: config.logo,
|
||||
name: config.name,
|
||||
uuid: config.uuid,
|
||||
}))
|
||||
}
|
||||
} catch (err) {
|
||||
} catch (err: any) {
|
||||
ctx.throw(err.status, err)
|
||||
}
|
||||
}
|
||||
|
||||
exports.publicSettings = async function (ctx) {
|
||||
const db = getGlobalDB()
|
||||
export async function publicSettings(ctx: BBContext) {
|
||||
const db = tenancy.getGlobalDB()
|
||||
|
||||
try {
|
||||
// Find the config with the most granular scope based on context
|
||||
const publicConfig = await getScopedFullConfig(db, {
|
||||
type: Config.SETTINGS,
|
||||
const publicConfig = await dbCore.getScopedFullConfig(db, {
|
||||
type: ConfigType.SETTINGS,
|
||||
})
|
||||
|
||||
const googleConfig = await getScopedFullConfig(db, {
|
||||
type: Config.GOOGLE,
|
||||
const googleConfig = await dbCore.getScopedFullConfig(db, {
|
||||
type: ConfigType.GOOGLE,
|
||||
})
|
||||
|
||||
const oidcConfig = await getScopedFullConfig(db, {
|
||||
type: Config.OIDC,
|
||||
const oidcConfig = await dbCore.getScopedFullConfig(db, {
|
||||
type: ConfigType.OIDC,
|
||||
})
|
||||
|
||||
let config
|
||||
|
@ -301,12 +306,12 @@ exports.publicSettings = async function (ctx) {
|
|||
}
|
||||
|
||||
ctx.body = config
|
||||
} catch (err) {
|
||||
} catch (err: any) {
|
||||
ctx.throw(err.status, err)
|
||||
}
|
||||
}
|
||||
|
||||
exports.upload = async function (ctx) {
|
||||
export async function upload(ctx: BBContext) {
|
||||
if (ctx.request.files == null || ctx.request.files.file.length > 1) {
|
||||
ctx.throw(400, "One file must be uploaded.")
|
||||
}
|
||||
|
@ -315,19 +320,19 @@ exports.upload = async function (ctx) {
|
|||
|
||||
let bucket
|
||||
if (env.SELF_HOSTED) {
|
||||
bucket = ObjectStoreBuckets.GLOBAL
|
||||
bucket = objectStore.ObjectStoreBuckets.GLOBAL
|
||||
} else {
|
||||
bucket = ObjectStoreBuckets.GLOBAL_CLOUD
|
||||
bucket = objectStore.ObjectStoreBuckets.GLOBAL_CLOUD
|
||||
}
|
||||
|
||||
let key
|
||||
if (env.MULTI_TENANCY) {
|
||||
key = `${getTenantId()}/${type}/${name}`
|
||||
key = `${tenancy.getTenantId()}/${type}/${name}`
|
||||
} else {
|
||||
key = `${type}/${name}`
|
||||
}
|
||||
|
||||
await upload({
|
||||
await objectStore.upload({
|
||||
bucket,
|
||||
filename: key,
|
||||
path: file.path,
|
||||
|
@ -336,11 +341,11 @@ exports.upload = async function (ctx) {
|
|||
|
||||
// add to configuration structure
|
||||
// TODO: right now this only does a global level
|
||||
const db = getGlobalDB()
|
||||
let cfgStructure = await getScopedFullConfig(db, { type })
|
||||
const db = tenancy.getGlobalDB()
|
||||
let cfgStructure = await dbCore.getScopedFullConfig(db, { type })
|
||||
if (!cfgStructure) {
|
||||
cfgStructure = {
|
||||
_id: generateConfigID({ type }),
|
||||
_id: dbCore.generateConfigID({ type }),
|
||||
config: {},
|
||||
}
|
||||
}
|
||||
|
@ -361,49 +366,49 @@ exports.upload = async function (ctx) {
|
|||
}
|
||||
}
|
||||
|
||||
exports.destroy = async function (ctx) {
|
||||
const db = getGlobalDB()
|
||||
export async function destroy(ctx: BBContext) {
|
||||
const db = tenancy.getGlobalDB()
|
||||
const { id, rev } = ctx.params
|
||||
try {
|
||||
await db.remove(id, rev)
|
||||
await cache.delete(CacheKeys.CHECKLIST)
|
||||
await cache.delete(cache.CacheKeys.CHECKLIST)
|
||||
ctx.body = { message: "Config deleted successfully" }
|
||||
} catch (err) {
|
||||
} catch (err: any) {
|
||||
ctx.throw(err.status, err)
|
||||
}
|
||||
}
|
||||
|
||||
exports.configChecklist = async function (ctx) {
|
||||
const db = getGlobalDB()
|
||||
const tenantId = getTenantId()
|
||||
export async function configChecklist(ctx: BBContext) {
|
||||
const db = tenancy.getGlobalDB()
|
||||
const tenantId = tenancy.getTenantId()
|
||||
|
||||
try {
|
||||
ctx.body = await withCache(
|
||||
CacheKeys.CHECKLIST,
|
||||
ctx.body = await cache.withCache(
|
||||
cache.CacheKeys.CHECKLIST,
|
||||
env.CHECKLIST_CACHE_TTL,
|
||||
async () => {
|
||||
let apps = []
|
||||
if (!env.MULTI_TENANCY || tenantId) {
|
||||
// Apps exist
|
||||
apps = await getAllApps({ idsOnly: true, efficient: true })
|
||||
apps = await dbCore.getAllApps({ idsOnly: true, efficient: true })
|
||||
}
|
||||
|
||||
// They have set up SMTP
|
||||
const smtpConfig = await getScopedFullConfig(db, {
|
||||
type: Config.SMTP,
|
||||
const smtpConfig = await dbCore.getScopedFullConfig(db, {
|
||||
type: ConfigType.SMTP,
|
||||
})
|
||||
|
||||
// They have set up Google Auth
|
||||
const googleConfig = await getScopedFullConfig(db, {
|
||||
type: Config.GOOGLE,
|
||||
const googleConfig = await dbCore.getScopedFullConfig(db, {
|
||||
type: ConfigType.GOOGLE,
|
||||
})
|
||||
|
||||
// They have set up OIDC
|
||||
const oidcConfig = await getScopedFullConfig(db, {
|
||||
type: Config.OIDC,
|
||||
const oidcConfig = await dbCore.getScopedFullConfig(db, {
|
||||
type: ConfigType.OIDC,
|
||||
})
|
||||
|
||||
// They have set up an global user
|
||||
// They have set up a global user
|
||||
const userExists = await checkAnyUserExists()
|
||||
return {
|
||||
apps: {
|
||||
|
@ -429,7 +434,7 @@ exports.configChecklist = async function (ctx) {
|
|||
}
|
||||
}
|
||||
)
|
||||
} catch (err) {
|
||||
} catch (err: any) {
|
||||
ctx.throw(err.status, err)
|
||||
}
|
||||
}
|
|
@ -1,7 +1,8 @@
|
|||
const { sendEmail } = require("../../../utilities/email")
|
||||
const { getGlobalDB } = require("@budibase/backend-core/tenancy")
|
||||
import { sendEmail as sendEmailFn } from "../../../utilities/email"
|
||||
import { tenancy } from "@budibase/backend-core"
|
||||
import { BBContext } from "@budibase/types"
|
||||
|
||||
exports.sendEmail = async ctx => {
|
||||
export async function sendEmail(ctx: BBContext) {
|
||||
let {
|
||||
workspaceId,
|
||||
email,
|
||||
|
@ -16,10 +17,10 @@ exports.sendEmail = async ctx => {
|
|||
} = ctx.request.body
|
||||
let user
|
||||
if (userId) {
|
||||
const db = getGlobalDB()
|
||||
const db = tenancy.getGlobalDB()
|
||||
user = await db.get(userId)
|
||||
}
|
||||
const response = await sendEmail(email, purpose, {
|
||||
const response = await sendEmailFn(email, purpose, {
|
||||
workspaceId,
|
||||
user,
|
||||
contents,
|
|
@ -1,68 +0,0 @@
|
|||
const { getAllRoles } = require("@budibase/backend-core/roles")
|
||||
const {
|
||||
getAllApps,
|
||||
getProdAppID,
|
||||
getDevAppID,
|
||||
DocumentType,
|
||||
} = require("@budibase/backend-core/db")
|
||||
const { doInAppContext, getAppDB } = require("@budibase/backend-core/context")
|
||||
const { user: userCache } = require("@budibase/backend-core/cache")
|
||||
const { getGlobalDB } = require("@budibase/backend-core/tenancy")
|
||||
const { allUsers } = require("../../../sdk/users")
|
||||
|
||||
exports.fetch = async ctx => {
|
||||
const tenantId = ctx.user.tenantId
|
||||
// always use the dev apps as they'll be most up to date (true)
|
||||
const apps = await getAllApps({ tenantId, all: true })
|
||||
const promises = []
|
||||
for (let app of apps) {
|
||||
// use dev app IDs
|
||||
promises.push(getAllRoles(app.appId))
|
||||
}
|
||||
const roles = await Promise.all(promises)
|
||||
const response = {}
|
||||
for (let app of apps) {
|
||||
const deployedAppId = getProdAppID(app.appId)
|
||||
response[deployedAppId] = {
|
||||
roles: roles.shift(),
|
||||
name: app.name,
|
||||
version: app.version,
|
||||
url: app.url,
|
||||
}
|
||||
}
|
||||
ctx.body = response
|
||||
}
|
||||
|
||||
exports.find = async ctx => {
|
||||
const appId = ctx.params.appId
|
||||
await doInAppContext(getDevAppID(appId), async () => {
|
||||
const db = getAppDB()
|
||||
const app = await db.get(DocumentType.APP_METADATA)
|
||||
ctx.body = {
|
||||
roles: await getAllRoles(),
|
||||
name: app.name,
|
||||
version: app.version,
|
||||
url: app.url,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
exports.removeAppRole = async ctx => {
|
||||
const { appId } = ctx.params
|
||||
const db = getGlobalDB()
|
||||
const users = await allUsers(ctx)
|
||||
const bulk = []
|
||||
const cacheInvalidations = []
|
||||
for (let user of users) {
|
||||
if (user.roles[appId]) {
|
||||
cacheInvalidations.push(userCache.invalidateUser(user._id))
|
||||
delete user.roles[appId]
|
||||
bulk.push(user)
|
||||
}
|
||||
}
|
||||
await db.bulkDocs(bulk)
|
||||
await Promise.all(cacheInvalidations)
|
||||
ctx.body = {
|
||||
message: "App role removed from all users",
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
import {
|
||||
db as dbCore,
|
||||
roles,
|
||||
context,
|
||||
cache,
|
||||
tenancy,
|
||||
} from "@budibase/backend-core"
|
||||
import { BBContext, App } from "@budibase/types"
|
||||
import { allUsers } from "../../../sdk/users"
|
||||
|
||||
export async function fetch(ctx: BBContext) {
|
||||
const tenantId = ctx.user!.tenantId
|
||||
// always use the dev apps as they'll be most up to date (true)
|
||||
const apps = (await dbCore.getAllApps({ tenantId, all: true })) as App[]
|
||||
const promises = []
|
||||
for (let app of apps) {
|
||||
// use dev app IDs
|
||||
promises.push(roles.getAllRoles(app.appId))
|
||||
}
|
||||
const roleList = await Promise.all(promises)
|
||||
const response: any = {}
|
||||
for (let app of apps) {
|
||||
const deployedAppId = dbCore.getProdAppID(app.appId)
|
||||
response[deployedAppId] = {
|
||||
roles: roleList.shift(),
|
||||
name: app.name,
|
||||
version: app.version,
|
||||
url: app.url,
|
||||
}
|
||||
}
|
||||
ctx.body = response
|
||||
}
|
||||
|
||||
export async function find(ctx: BBContext) {
|
||||
const appId = ctx.params.appId
|
||||
await context.doInAppContext(dbCore.getDevAppID(appId), async () => {
|
||||
const db = context.getAppDB()
|
||||
const app = await db.get(dbCore.DocumentType.APP_METADATA)
|
||||
ctx.body = {
|
||||
roles: await roles.getAllRoles(),
|
||||
name: app.name,
|
||||
version: app.version,
|
||||
url: app.url,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export async function removeAppRole(ctx: BBContext) {
|
||||
const { appId } = ctx.params
|
||||
const db = tenancy.getGlobalDB()
|
||||
const users = await allUsers()
|
||||
const bulk = []
|
||||
const cacheInvalidations = []
|
||||
for (let user of users) {
|
||||
if (user.roles[appId]) {
|
||||
cacheInvalidations.push(cache.user.invalidateUser(user._id))
|
||||
delete user.roles[appId]
|
||||
bulk.push(user)
|
||||
}
|
||||
}
|
||||
await db.bulkDocs(bulk)
|
||||
await Promise.all(cacheInvalidations)
|
||||
ctx.body = {
|
||||
message: "App role removed from all users",
|
||||
}
|
||||
}
|
|
@ -1,16 +1,13 @@
|
|||
const {
|
||||
getWorkspaceParams,
|
||||
generateWorkspaceID,
|
||||
} = require("@budibase/backend-core/db")
|
||||
const { getGlobalDB } = require("@budibase/backend-core/tenancy")
|
||||
import { tenancy, db as dbCore } from "@budibase/backend-core"
|
||||
import { BBContext } from "@budibase/types"
|
||||
|
||||
exports.save = async function (ctx) {
|
||||
const db = getGlobalDB()
|
||||
export async function save(ctx: BBContext) {
|
||||
const db = tenancy.getGlobalDB()
|
||||
const workspaceDoc = ctx.request.body
|
||||
|
||||
// workspace does not exist yet
|
||||
if (!workspaceDoc._id) {
|
||||
workspaceDoc._id = generateWorkspaceID()
|
||||
workspaceDoc._id = dbCore.generateWorkspaceID()
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -19,38 +16,38 @@ exports.save = async function (ctx) {
|
|||
_id: response.id,
|
||||
_rev: response.rev,
|
||||
}
|
||||
} catch (err) {
|
||||
} catch (err: any) {
|
||||
ctx.throw(err.status, err)
|
||||
}
|
||||
}
|
||||
|
||||
exports.fetch = async function (ctx) {
|
||||
const db = getGlobalDB()
|
||||
export async function fetch(ctx: BBContext) {
|
||||
const db = tenancy.getGlobalDB()
|
||||
const response = await db.allDocs(
|
||||
getWorkspaceParams(undefined, {
|
||||
dbCore.getWorkspaceParams(undefined, {
|
||||
include_docs: true,
|
||||
})
|
||||
)
|
||||
ctx.body = response.rows.map(row => row.doc)
|
||||
}
|
||||
|
||||
exports.find = async function (ctx) {
|
||||
const db = getGlobalDB()
|
||||
export async function find(ctx: BBContext) {
|
||||
const db = tenancy.getGlobalDB()
|
||||
try {
|
||||
ctx.body = await db.get(ctx.params.id)
|
||||
} catch (err) {
|
||||
} catch (err: any) {
|
||||
ctx.throw(err.status, err)
|
||||
}
|
||||
}
|
||||
|
||||
exports.destroy = async function (ctx) {
|
||||
const db = getGlobalDB()
|
||||
export async function destroy(ctx: BBContext) {
|
||||
const db = tenancy.getGlobalDB()
|
||||
const { id, rev } = ctx.params
|
||||
|
||||
try {
|
||||
await db.remove(id, rev)
|
||||
ctx.body = { message: "Workspace deleted successfully" }
|
||||
} catch (err) {
|
||||
} catch (err: any) {
|
||||
ctx.throw(err.status, err)
|
||||
}
|
||||
}
|
|
@ -104,7 +104,7 @@ const NO_TENANCY_ENDPOINTS = [
|
|||
// add them all to be safe
|
||||
const NO_CSRF_ENDPOINTS = [...PUBLIC_ENDPOINTS]
|
||||
|
||||
const router = new Router()
|
||||
const router: Router = new Router()
|
||||
router
|
||||
.use(
|
||||
compress({
|
||||
|
@ -163,4 +163,4 @@ for (let route of routes) {
|
|||
router.use(route.allowedMethods())
|
||||
}
|
||||
|
||||
module.exports = router
|
||||
export = router
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
const Router = require("@koa/router")
|
||||
const authController = require("../../controllers/global/auth")
|
||||
const { joiValidator } = require("@budibase/backend-core/auth")
|
||||
const Joi = require("joi")
|
||||
import Router from "@koa/router"
|
||||
import * as authController from "../../controllers/global/auth"
|
||||
import { auth } from "@budibase/backend-core"
|
||||
import Joi from "joi"
|
||||
|
||||
const router = new Router()
|
||||
const router: Router = new Router()
|
||||
|
||||
function buildAuthValidation() {
|
||||
// prettier-ignore
|
||||
return joiValidator.body(Joi.object({
|
||||
return auth.joiValidator.body(Joi.object({
|
||||
username: Joi.string().required(),
|
||||
password: Joi.string().required(),
|
||||
}).required().unknown(false))
|
||||
|
@ -15,14 +15,14 @@ function buildAuthValidation() {
|
|||
|
||||
function buildResetValidation() {
|
||||
// prettier-ignore
|
||||
return joiValidator.body(Joi.object({
|
||||
return auth.joiValidator.body(Joi.object({
|
||||
email: Joi.string().required(),
|
||||
}).required().unknown(false))
|
||||
}
|
||||
|
||||
function buildResetUpdateValidation() {
|
||||
// prettier-ignore
|
||||
return joiValidator.body(Joi.object({
|
||||
return auth.joiValidator.body(Joi.object({
|
||||
resetCode: Joi.string().required(),
|
||||
password: Joi.string().required(),
|
||||
}).required().unknown(false))
|
||||
|
@ -85,4 +85,4 @@ router
|
|||
.get("/api/global/auth/oidc/callback", authController.oidcAuth)
|
||||
.get("/api/admin/auth/oidc/callback", authController.oidcAuth)
|
||||
|
||||
module.exports = router
|
||||
export = router
|
|
@ -1,11 +1,10 @@
|
|||
const Router = require("@koa/router")
|
||||
const controller = require("../../controllers/global/configs")
|
||||
const { joiValidator } = require("@budibase/backend-core/auth")
|
||||
const { adminOnly } = require("@budibase/backend-core/auth")
|
||||
const Joi = require("joi")
|
||||
const { Config } = require("@budibase/backend-core/constants")
|
||||
import Router from "@koa/router"
|
||||
import * as controller from "../../controllers/global/configs"
|
||||
import { auth } from "@budibase/backend-core"
|
||||
import Joi from "joi"
|
||||
import { ConfigType } from "@budibase/types"
|
||||
|
||||
const router = new Router()
|
||||
const router: Router = new Router()
|
||||
|
||||
function smtpValidation() {
|
||||
// prettier-ignore
|
||||
|
@ -55,27 +54,27 @@ function oidcValidation() {
|
|||
activated: Joi.boolean().required(),
|
||||
scopes: Joi.array().optional()
|
||||
})
|
||||
).required(true)
|
||||
).required()
|
||||
}).unknown(true)
|
||||
}
|
||||
|
||||
function buildConfigSaveValidation() {
|
||||
// prettier-ignore
|
||||
return joiValidator.body(Joi.object({
|
||||
return auth.joiValidator.body(Joi.object({
|
||||
_id: Joi.string().optional(),
|
||||
_rev: Joi.string().optional(),
|
||||
workspace: Joi.string().optional(),
|
||||
type: Joi.string().valid(...Object.values(Config)).required(),
|
||||
type: Joi.string().valid(...Object.values(ConfigType)).required(),
|
||||
createdAt: Joi.string().optional(),
|
||||
updatedAt: Joi.string().optional(),
|
||||
config: Joi.alternatives()
|
||||
.conditional("type", {
|
||||
switch: [
|
||||
{ is: Config.SMTP, then: smtpValidation() },
|
||||
{ is: Config.SETTINGS, then: settingValidation() },
|
||||
{ is: Config.ACCOUNT, then: Joi.object().unknown(true) },
|
||||
{ is: Config.GOOGLE, then: googleValidation() },
|
||||
{ is: Config.OIDC, then: oidcValidation() }
|
||||
{ is: ConfigType.SMTP, then: smtpValidation() },
|
||||
{ is: ConfigType.SETTINGS, then: settingValidation() },
|
||||
{ is: ConfigType.ACCOUNT, then: Joi.object().unknown(true) },
|
||||
{ is: ConfigType.GOOGLE, then: googleValidation() },
|
||||
{ is: ConfigType.OIDC, then: oidcValidation() }
|
||||
],
|
||||
}),
|
||||
}).required().unknown(true),
|
||||
|
@ -84,27 +83,27 @@ function buildConfigSaveValidation() {
|
|||
|
||||
function buildUploadValidation() {
|
||||
// prettier-ignore
|
||||
return joiValidator.params(Joi.object({
|
||||
type: Joi.string().valid(...Object.values(Config)).required(),
|
||||
return auth.joiValidator.params(Joi.object({
|
||||
type: Joi.string().valid(...Object.values(ConfigType)).required(),
|
||||
name: Joi.string().required(),
|
||||
}).required().unknown(true))
|
||||
}
|
||||
|
||||
function buildConfigGetValidation() {
|
||||
// prettier-ignore
|
||||
return joiValidator.params(Joi.object({
|
||||
type: Joi.string().valid(...Object.values(Config)).required()
|
||||
return auth.joiValidator.params(Joi.object({
|
||||
type: Joi.string().valid(...Object.values(ConfigType)).required()
|
||||
}).required().unknown(true))
|
||||
}
|
||||
|
||||
router
|
||||
.post(
|
||||
"/api/global/configs",
|
||||
adminOnly,
|
||||
auth.adminOnly,
|
||||
buildConfigSaveValidation(),
|
||||
controller.save
|
||||
)
|
||||
.delete("/api/global/configs/:id/:rev", adminOnly, controller.destroy)
|
||||
.delete("/api/global/configs/:id/:rev", auth.adminOnly, controller.destroy)
|
||||
.get("/api/global/configs", controller.fetch)
|
||||
.get("/api/global/configs/checklist", controller.configChecklist)
|
||||
.get(
|
||||
|
@ -117,9 +116,9 @@ router
|
|||
.get("/api/global/configs/:type", buildConfigGetValidation(), controller.find)
|
||||
.post(
|
||||
"/api/global/configs/upload/:type/:name",
|
||||
adminOnly,
|
||||
auth.adminOnly,
|
||||
buildUploadValidation(),
|
||||
controller.upload
|
||||
)
|
||||
|
||||
module.exports = router
|
||||
export = router
|
|
@ -1,15 +1,14 @@
|
|||
const Router = require("@koa/router")
|
||||
const controller = require("../../controllers/global/email")
|
||||
const { EmailTemplatePurpose } = require("../../../constants")
|
||||
const { joiValidator } = require("@budibase/backend-core/auth")
|
||||
const { adminOnly } = require("@budibase/backend-core/auth")
|
||||
const Joi = require("joi")
|
||||
import Router from "@koa/router"
|
||||
import * as controller from "../../controllers/global/email"
|
||||
import { EmailTemplatePurpose } from "../../../constants"
|
||||
import { auth } from "@budibase/backend-core"
|
||||
import Joi from "joi"
|
||||
|
||||
const router = new Router()
|
||||
const router: Router = new Router()
|
||||
|
||||
function buildEmailSendValidation() {
|
||||
// prettier-ignore
|
||||
return joiValidator.body(Joi.object({
|
||||
return auth.joiValidator.body(Joi.object({
|
||||
email: Joi.string().email({
|
||||
multiple: true,
|
||||
}),
|
||||
|
@ -30,8 +29,8 @@ function buildEmailSendValidation() {
|
|||
router.post(
|
||||
"/api/global/email/send",
|
||||
buildEmailSendValidation(),
|
||||
adminOnly,
|
||||
auth.adminOnly,
|
||||
controller.sendEmail
|
||||
)
|
||||
|
||||
module.exports = router
|
||||
export = router
|
|
@ -1,7 +1,7 @@
|
|||
import Router from "@koa/router"
|
||||
import * as controller from "../../controllers/global/license"
|
||||
|
||||
const router = new Router()
|
||||
const router: Router = new Router()
|
||||
|
||||
router
|
||||
.post("/api/global/license/activate", controller.activate)
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
const Router = require("@koa/router")
|
||||
const controller = require("../../controllers/global/roles")
|
||||
const { builderOrAdmin } = require("@budibase/backend-core/auth")
|
||||
|
||||
const router = new Router()
|
||||
|
||||
router
|
||||
.get("/api/global/roles", builderOrAdmin, controller.fetch)
|
||||
.get("/api/global/roles/:appId", builderOrAdmin, controller.find)
|
||||
.delete("/api/global/roles/:appId", builderOrAdmin, controller.removeAppRole)
|
||||
|
||||
module.exports = router
|
|
@ -0,0 +1,16 @@
|
|||
import Router from "@koa/router"
|
||||
import * as controller from "../../controllers/global/roles"
|
||||
import { auth } from "@budibase/backend-core"
|
||||
|
||||
const router: Router = new Router()
|
||||
|
||||
router
|
||||
.get("/api/global/roles", auth.builderOrAdmin, controller.fetch)
|
||||
.get("/api/global/roles/:appId", auth.builderOrAdmin, controller.find)
|
||||
.delete(
|
||||
"/api/global/roles/:appId",
|
||||
auth.builderOrAdmin,
|
||||
controller.removeAppRole
|
||||
)
|
||||
|
||||
export = router
|
|
@ -3,7 +3,7 @@ import * as controller from "../../controllers/global/self"
|
|||
import { auth } from "@budibase/backend-core"
|
||||
import { users } from "../validation"
|
||||
|
||||
const router = new Router()
|
||||
const router: Router = new Router()
|
||||
|
||||
router
|
||||
.post("/api/global/self/api_key", auth.builderOnly, controller.generateAPIKey)
|
||||
|
@ -15,4 +15,4 @@ router
|
|||
controller.updateSelf
|
||||
)
|
||||
|
||||
export default router as any
|
||||
export = router
|
||||
|
|
|
@ -5,7 +5,7 @@ import { auth as authCore } from "@budibase/backend-core"
|
|||
import Joi from "joi"
|
||||
const { adminOnly, joiValidator } = authCore
|
||||
|
||||
const router = new Router()
|
||||
const router: Router = new Router()
|
||||
|
||||
function buildTemplateSaveValidation() {
|
||||
// prettier-ignore
|
||||
|
@ -34,4 +34,4 @@ router
|
|||
.get("/api/global/template/:id", controller.find)
|
||||
.delete("/api/global/template/:id/:rev", adminOnly, controller.destroy)
|
||||
|
||||
export default router
|
||||
export = router
|
||||
|
|
|
@ -1,17 +1,15 @@
|
|||
const Router = require("@koa/router")
|
||||
const controller = require("../../controllers/global/users")
|
||||
const { joiValidator } = require("@budibase/backend-core/auth")
|
||||
const { adminOnly } = require("@budibase/backend-core/auth")
|
||||
const Joi = require("joi")
|
||||
const cloudRestricted = require("../../../middleware/cloudRestricted")
|
||||
const { users } = require("../validation")
|
||||
const selfController = require("../../controllers/global/self")
|
||||
const { builderOrAdmin } = require("@budibase/backend-core/auth")
|
||||
import Router from "@koa/router"
|
||||
import * as controller from "../../controllers/global/users"
|
||||
import { auth } from "@budibase/backend-core"
|
||||
import Joi from "joi"
|
||||
import cloudRestricted from "../../../middleware/cloudRestricted"
|
||||
import { users } from "../validation"
|
||||
import * as selfController from "../../controllers/global/self"
|
||||
|
||||
const router = new Router()
|
||||
const router: Router = new Router()
|
||||
|
||||
function buildAdminInitValidation() {
|
||||
return joiValidator.body(
|
||||
return auth.joiValidator.body(
|
||||
Joi.object({
|
||||
email: Joi.string().required(),
|
||||
password: Joi.string(),
|
||||
|
@ -24,7 +22,7 @@ function buildAdminInitValidation() {
|
|||
|
||||
function buildInviteValidation() {
|
||||
// prettier-ignore
|
||||
return joiValidator.body(Joi.object({
|
||||
return auth.joiValidator.body(Joi.object({
|
||||
email: Joi.string().required(),
|
||||
userInfo: Joi.object().optional(),
|
||||
}).required())
|
||||
|
@ -32,7 +30,7 @@ function buildInviteValidation() {
|
|||
|
||||
function buildInviteMultipleValidation() {
|
||||
// prettier-ignore
|
||||
return joiValidator.body(Joi.array().required().items(
|
||||
return auth.joiValidator.body(Joi.array().required().items(
|
||||
Joi.object({
|
||||
email: Joi.string(),
|
||||
userInfo: Joi.object().optional(),
|
||||
|
@ -42,7 +40,7 @@ function buildInviteMultipleValidation() {
|
|||
|
||||
function buildInviteAcceptValidation() {
|
||||
// prettier-ignore
|
||||
return joiValidator.body(Joi.object({
|
||||
return auth.joiValidator.body(Joi.object({
|
||||
inviteCode: Joi.string().required(),
|
||||
password: Joi.string().required(),
|
||||
}).required().unknown(true))
|
||||
|
@ -51,31 +49,35 @@ function buildInviteAcceptValidation() {
|
|||
router
|
||||
.post(
|
||||
"/api/global/users",
|
||||
adminOnly,
|
||||
auth.adminOnly,
|
||||
users.buildUserSaveValidation(),
|
||||
controller.save
|
||||
)
|
||||
.post(
|
||||
"/api/global/users/bulk",
|
||||
adminOnly,
|
||||
auth.adminOnly,
|
||||
users.buildUserBulkUserValidation(),
|
||||
controller.bulkUpdate
|
||||
)
|
||||
|
||||
.get("/api/global/users", builderOrAdmin, controller.fetch)
|
||||
.post("/api/global/users/search", builderOrAdmin, controller.search)
|
||||
.delete("/api/global/users/:id", adminOnly, controller.destroy)
|
||||
.get("/api/global/users/count/:appId", builderOrAdmin, controller.countByApp)
|
||||
.get("/api/global/users", auth.builderOrAdmin, controller.fetch)
|
||||
.post("/api/global/users/search", auth.builderOrAdmin, controller.search)
|
||||
.delete("/api/global/users/:id", auth.adminOnly, controller.destroy)
|
||||
.get(
|
||||
"/api/global/users/count/:appId",
|
||||
auth.builderOrAdmin,
|
||||
controller.countByApp
|
||||
)
|
||||
.get("/api/global/roles/:appId")
|
||||
.post(
|
||||
"/api/global/users/invite",
|
||||
adminOnly,
|
||||
auth.adminOnly,
|
||||
buildInviteValidation(),
|
||||
controller.invite
|
||||
)
|
||||
.post(
|
||||
"/api/global/users/multi/invite",
|
||||
adminOnly,
|
||||
auth.adminOnly,
|
||||
buildInviteMultipleValidation(),
|
||||
controller.inviteMultiple
|
||||
)
|
||||
|
@ -94,7 +96,7 @@ router
|
|||
)
|
||||
.get("/api/global/users/tenant/:id", controller.tenantUserLookup)
|
||||
// global endpoint but needs to come at end (blocks other endpoints otherwise)
|
||||
.get("/api/global/users/:id", builderOrAdmin, controller.find)
|
||||
.get("/api/global/users/:id", auth.builderOrAdmin, controller.find)
|
||||
// DEPRECATED - use new versions with self API
|
||||
.get("/api/global/users/self", selfController.getSelf)
|
||||
.post(
|
||||
|
@ -103,4 +105,4 @@ router
|
|||
selfController.updateSelf
|
||||
)
|
||||
|
||||
module.exports = router
|
||||
export = router
|
|
@ -1,14 +1,13 @@
|
|||
const Router = require("@koa/router")
|
||||
const controller = require("../../controllers/global/workspaces")
|
||||
const { joiValidator } = require("@budibase/backend-core/auth")
|
||||
const { adminOnly } = require("@budibase/backend-core/auth")
|
||||
const Joi = require("joi")
|
||||
import Router from "@koa/router"
|
||||
import * as controller from "../../controllers/global/workspaces"
|
||||
import { auth } from "@budibase/backend-core"
|
||||
import Joi from "joi"
|
||||
|
||||
const router = new Router()
|
||||
const router: Router = new Router()
|
||||
|
||||
function buildWorkspaceSaveValidation() {
|
||||
// prettier-ignore
|
||||
return joiValidator.body(Joi.object({
|
||||
return auth.joiValidator.body(Joi.object({
|
||||
_id: Joi.string().optional(),
|
||||
_rev: Joi.string().optional(),
|
||||
name: Joi.string().required(),
|
||||
|
@ -27,12 +26,12 @@ function buildWorkspaceSaveValidation() {
|
|||
router
|
||||
.post(
|
||||
"/api/global/workspaces",
|
||||
adminOnly,
|
||||
auth.adminOnly,
|
||||
buildWorkspaceSaveValidation(),
|
||||
controller.save
|
||||
)
|
||||
.delete("/api/global/workspaces/:id", adminOnly, controller.destroy)
|
||||
.delete("/api/global/workspaces/:id", auth.adminOnly, controller.destroy)
|
||||
.get("/api/global/workspaces", controller.fetch)
|
||||
.get("/api/global/workspaces/:id", controller.find)
|
||||
|
||||
module.exports = router
|
||||
export = router
|
|
@ -1,3 +1,4 @@
|
|||
import Router from "@koa/router"
|
||||
import { api } from "@budibase/pro"
|
||||
import userRoutes from "./global/users"
|
||||
import configRoutes from "./global/configs"
|
||||
|
@ -16,7 +17,7 @@ import accountRoutes from "./system/accounts"
|
|||
import restoreRoutes from "./system/restore"
|
||||
|
||||
let userGroupRoutes = api.groups
|
||||
export const routes = [
|
||||
export const routes: Router[] = [
|
||||
configRoutes,
|
||||
userRoutes,
|
||||
workspaceRoutes,
|
||||
|
|
|
@ -2,7 +2,7 @@ import Router from "@koa/router"
|
|||
import * as controller from "../../controllers/system/accounts"
|
||||
import { middleware } from "@budibase/backend-core"
|
||||
|
||||
const router = new Router()
|
||||
const router: Router = new Router()
|
||||
|
||||
router
|
||||
.put(
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import Router from "@koa/router"
|
||||
import * as controller from "../../controllers/system/environment"
|
||||
|
||||
const router = new Router()
|
||||
const router: Router = new Router()
|
||||
|
||||
router.get("/api/system/environment", controller.fetch)
|
||||
|
||||
export default router
|
||||
export = router
|
||||
|
|
|
@ -2,7 +2,7 @@ import Router from "@koa/router"
|
|||
import * as migrationsController from "../../controllers/system/migrations"
|
||||
import { auth } from "@budibase/backend-core"
|
||||
|
||||
const router = new Router()
|
||||
const router: Router = new Router()
|
||||
|
||||
router
|
||||
.post(
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import * as controller from "../../controllers/system/restore"
|
||||
import Router from "@koa/router"
|
||||
|
||||
const router = new Router()
|
||||
const router: Router = new Router()
|
||||
|
||||
router.post("/api/system/restored", controller.systemRestored)
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import Router from "@koa/router"
|
||||
import * as controller from "../../controllers/system/status"
|
||||
|
||||
const router = new Router()
|
||||
const router: Router = new Router()
|
||||
|
||||
router.get("/api/system/status", controller.fetch)
|
||||
|
||||
export default router
|
||||
export = router
|
||||
|
|
|
@ -2,7 +2,7 @@ import Router from "@koa/router"
|
|||
import * as controller from "../../controllers/system/tenants"
|
||||
import { middleware } from "@budibase/backend-core"
|
||||
|
||||
const router = new Router()
|
||||
const router: Router = new Router()
|
||||
|
||||
router.delete(
|
||||
"/api/system/tenants/:tenantId",
|
||||
|
@ -10,4 +10,4 @@ router.delete(
|
|||
controller.delete
|
||||
)
|
||||
|
||||
export default router
|
||||
export = router
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const { joiValidator } = require("@budibase/backend-core/auth")
|
||||
import { auth } from "@budibase/backend-core"
|
||||
import Joi from "joi"
|
||||
|
||||
let schema: any = {
|
||||
|
@ -25,7 +25,7 @@ export const buildUserSaveValidation = (isSelf = false) => {
|
|||
_rev: Joi.string(),
|
||||
}
|
||||
}
|
||||
return joiValidator.body(Joi.object(schema).required().unknown(true))
|
||||
return auth.joiValidator.body(Joi.object(schema).required().unknown(true))
|
||||
}
|
||||
|
||||
export const buildUserBulkUserValidation = (isSelf = false) => {
|
||||
|
@ -46,5 +46,5 @@ export const buildUserBulkUserValidation = (isSelf = false) => {
|
|||
}),
|
||||
}
|
||||
|
||||
return joiValidator.body(Joi.object(bulkSchema).required().unknown(true))
|
||||
return auth.joiValidator.body(Joi.object(bulkSchema).required().unknown(true))
|
||||
}
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
const { readStaticFile } = require("../../utilities/fileSystem")
|
||||
const {
|
||||
import { readStaticFile } from "../../utilities/fileSystem"
|
||||
import {
|
||||
EmailTemplatePurpose,
|
||||
TemplateType,
|
||||
TemplatePurpose,
|
||||
GLOBAL_OWNER,
|
||||
} = require("../index")
|
||||
const { join } = require("path")
|
||||
const { getTemplateParams } = require("@budibase/backend-core/db")
|
||||
const { getGlobalDB } = require("@budibase/backend-core/tenancy")
|
||||
} from "../index"
|
||||
import { join } from "path"
|
||||
import { db as dbCore, tenancy } from "@budibase/backend-core"
|
||||
import { Template } from "@budibase/types"
|
||||
|
||||
exports.EmailTemplates = {
|
||||
export const EmailTemplates = {
|
||||
[EmailTemplatePurpose.PASSWORD_RECOVERY]: readStaticFile(
|
||||
join(__dirname, "passwordRecovery.hbs")
|
||||
),
|
||||
|
@ -23,7 +23,7 @@ exports.EmailTemplates = {
|
|||
[EmailTemplatePurpose.CUSTOM]: readStaticFile(join(__dirname, "custom.hbs")),
|
||||
}
|
||||
|
||||
exports.addBaseTemplates = (templates, type = null) => {
|
||||
export function addBaseTemplates(templates: Template[], type?: string) {
|
||||
let purposeList
|
||||
switch (type) {
|
||||
case TemplateType.EMAIL:
|
||||
|
@ -38,9 +38,9 @@ exports.addBaseTemplates = (templates, type = null) => {
|
|||
if (templates.find(template => template.purpose === purpose)) {
|
||||
continue
|
||||
}
|
||||
if (exports.EmailTemplates[purpose]) {
|
||||
if (EmailTemplates[purpose]) {
|
||||
templates.push({
|
||||
contents: exports.EmailTemplates[purpose],
|
||||
contents: EmailTemplates[purpose],
|
||||
purpose,
|
||||
type,
|
||||
})
|
||||
|
@ -49,10 +49,14 @@ exports.addBaseTemplates = (templates, type = null) => {
|
|||
return templates
|
||||
}
|
||||
|
||||
exports.getTemplates = async ({ ownerId, type, id } = {}) => {
|
||||
const db = getGlobalDB()
|
||||
export async function getTemplates({
|
||||
ownerId,
|
||||
type,
|
||||
id,
|
||||
}: { ownerId?: string; type?: string; id?: string } = {}) {
|
||||
const db = tenancy.getGlobalDB()
|
||||
const response = await db.allDocs(
|
||||
getTemplateParams(ownerId || GLOBAL_OWNER, id, {
|
||||
dbCore.getTemplateParams(ownerId || GLOBAL_OWNER, id, {
|
||||
include_docs: true,
|
||||
})
|
||||
)
|
||||
|
@ -64,10 +68,10 @@ exports.getTemplates = async ({ ownerId, type, id } = {}) => {
|
|||
if (type) {
|
||||
templates = templates.filter(template => template.type === type)
|
||||
}
|
||||
return exports.addBaseTemplates(templates, type)
|
||||
return addBaseTemplates(templates, type)
|
||||
}
|
||||
|
||||
exports.getTemplateByPurpose = async (type, purpose) => {
|
||||
const templates = await exports.getTemplates({ type })
|
||||
return templates.find(template => template.purpose === purpose)
|
||||
export async function getTemplateByPurpose(type: string, purpose: string) {
|
||||
const templates = await getTemplates({ type })
|
||||
return templates.find((template: Template) => template.purpose === purpose)
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
// need to load environment first
|
||||
const env = require("./environment")
|
||||
import env from "./environment"
|
||||
|
||||
// enable APM if configured
|
||||
if (process.env.ELASTIC_APM_ENABLED) {
|
||||
|
@ -14,19 +14,17 @@ import { Event } from "@sentry/types/dist/event"
|
|||
import Application from "koa"
|
||||
import { bootstrap } from "global-agent"
|
||||
import * as db from "./db"
|
||||
import { auth, logging, events, pinoSettings } from "@budibase/backend-core"
|
||||
db.init()
|
||||
const Koa = require("koa")
|
||||
const destroyable = require("server-destroy")
|
||||
const koaBody = require("koa-body")
|
||||
import Koa from "koa"
|
||||
import koaBody from "koa-body"
|
||||
import http from "http"
|
||||
import * as api from "./api"
|
||||
import * as redis from "./utilities/redis"
|
||||
import Sentry from "@sentry/node"
|
||||
const koaSession = require("koa-session")
|
||||
const { passport } = require("@budibase/backend-core/auth")
|
||||
const { logAlert } = require("@budibase/backend-core/logging")
|
||||
const logger = require("koa-pino-logger")
|
||||
const http = require("http")
|
||||
const api = require("./api")
|
||||
const redis = require("./utilities/redis")
|
||||
const Sentry = require("@sentry/node")
|
||||
import { events, pinoSettings } from "@budibase/backend-core"
|
||||
const destroyable = require("server-destroy")
|
||||
|
||||
// this will setup http and https proxies form env variables
|
||||
bootstrap()
|
||||
|
@ -41,8 +39,8 @@ app.use(koaSession(app))
|
|||
app.use(logger(pinoSettings()))
|
||||
|
||||
// authentication
|
||||
app.use(passport.initialize())
|
||||
app.use(passport.session())
|
||||
app.use(auth.passport.initialize())
|
||||
app.use(auth.passport.session())
|
||||
|
||||
// api routes
|
||||
app.use(api.routes())
|
||||
|
@ -81,17 +79,18 @@ server.on("close", async () => {
|
|||
|
||||
const shutdown = () => {
|
||||
server.close()
|
||||
// @ts-ignore
|
||||
server.destroy()
|
||||
}
|
||||
|
||||
export = server.listen(parseInt(env.PORT || 4002), async () => {
|
||||
export = server.listen(parseInt(env.PORT || "4002"), async () => {
|
||||
console.log(`Worker running on ${JSON.stringify(server.address())}`)
|
||||
await redis.init()
|
||||
})
|
||||
|
||||
process.on("uncaughtException", err => {
|
||||
errCode = -1
|
||||
logAlert("Uncaught exception.", err)
|
||||
logging.logAlert("Uncaught exception.", err)
|
||||
shutdown()
|
||||
})
|
||||
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
const env = require("../environment")
|
||||
const { Header } = require("@budibase/backend-core/constants")
|
||||
import env from "../environment"
|
||||
import { constants } from "@budibase/backend-core"
|
||||
import { BBContext } from "@budibase/types"
|
||||
|
||||
/**
|
||||
* This is a restricted endpoint in the cloud.
|
||||
* Ensure that the correct API key has been supplied.
|
||||
*/
|
||||
module.exports = async (ctx, next) => {
|
||||
export = async (ctx: BBContext, next: any) => {
|
||||
if (!env.SELF_HOSTED && !env.DISABLE_ACCOUNT_PORTAL) {
|
||||
const apiKey = ctx.request.headers[Header.API_KEY]
|
||||
const apiKey = ctx.request.headers[constants.Header.API_KEY]
|
||||
if (apiKey !== env.INTERNAL_API_KEY) {
|
||||
ctx.throw(403, "Unauthorized")
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
const fetch = require("node-fetch")
|
||||
const { Header } = require("@budibase/backend-core/constants")
|
||||
const { getTenantId, isTenantIdSet } = require("@budibase/backend-core/tenancy")
|
||||
const { checkSlashesInUrl } = require("../utilities")
|
||||
const env = require("../environment")
|
||||
|
||||
async function makeAppRequest(url, method, body) {
|
||||
if (env.isTest()) {
|
||||
return
|
||||
}
|
||||
const request = { headers: {} }
|
||||
request.headers[Header.API_KEY] = env.INTERNAL_API_KEY
|
||||
if (isTenantIdSet()) {
|
||||
request.headers[Header.TENANT_ID] = getTenantId()
|
||||
}
|
||||
if (body) {
|
||||
request.headers["Content-Type"] = "application/json"
|
||||
request.body = JSON.stringify(body)
|
||||
}
|
||||
request.method = method
|
||||
return fetch(checkSlashesInUrl(env.APPS_URL + url), request)
|
||||
}
|
||||
|
||||
exports.syncUserInApps = async userId => {
|
||||
const response = await makeAppRequest(
|
||||
`/api/users/metadata/sync/${userId}`,
|
||||
"POST",
|
||||
{}
|
||||
)
|
||||
if (response && response.status !== 200) {
|
||||
throw "Unable to sync user."
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
import fetch from "node-fetch"
|
||||
import { constants, tenancy } from "@budibase/backend-core"
|
||||
import { checkSlashesInUrl } from "../utilities"
|
||||
import env from "../environment"
|
||||
|
||||
async function makeAppRequest(url: string, method: string, body: any) {
|
||||
if (env.isTest()) {
|
||||
return
|
||||
}
|
||||
const request: any = { headers: {} }
|
||||
request.headers[constants.Header.API_KEY] = env.INTERNAL_API_KEY
|
||||
if (tenancy.isTenantIdSet()) {
|
||||
request.headers[constants.Header.TENANT_ID] = tenancy.getTenantId()
|
||||
}
|
||||
if (body) {
|
||||
request.headers["Content-Type"] = "application/json"
|
||||
request.body = JSON.stringify(body)
|
||||
}
|
||||
request.method = method
|
||||
return fetch(checkSlashesInUrl(env.APPS_URL + url), request)
|
||||
}
|
||||
|
||||
export async function syncUserInApps(userId: string) {
|
||||
const response = await makeAppRequest(
|
||||
`/api/users/metadata/sync/${userId}`,
|
||||
"POST",
|
||||
{}
|
||||
)
|
||||
if (response && response.status !== 200) {
|
||||
throw "Unable to sync user."
|
||||
}
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
const { readFileSync } = require("fs")
|
||||
|
||||
exports.readStaticFile = path => {
|
||||
return readFileSync(path, "utf-8")
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
import { readFileSync } from "fs"
|
||||
|
||||
export function readStaticFile(path: string) {
|
||||
return readFileSync(path, "utf-8")
|
||||
}
|
|
@ -4,6 +4,6 @@
|
|||
* @param {string} url The URL to test and remove any extra double slashes.
|
||||
* @return {string} The updated url.
|
||||
*/
|
||||
exports.checkSlashesInUrl = url => {
|
||||
export function checkSlashesInUrl(url: string) {
|
||||
return url.replace(/(https?:\/\/)|(\/)+/g, "$1$2")
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
const { getGlobalDB } = require("@budibase/backend-core/tenancy")
|
||||
const { getGlobalUserParams } = require("@budibase/backend-core/db")
|
||||
|
||||
exports.checkAnyUserExists = async () => {
|
||||
try {
|
||||
const db = getGlobalDB()
|
||||
const users = await db.allDocs(
|
||||
getGlobalUserParams(null, {
|
||||
include_docs: true,
|
||||
limit: 1,
|
||||
})
|
||||
)
|
||||
return users && users.rows.length >= 1
|
||||
} catch (err) {
|
||||
throw new Error("Unable to retrieve user list")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
import { tenancy, db as dbCore } from "@budibase/backend-core"
|
||||
|
||||
export async function checkAnyUserExists() {
|
||||
try {
|
||||
const db = tenancy.getGlobalDB()
|
||||
const users = await db.allDocs(
|
||||
dbCore.getGlobalUserParams(null, {
|
||||
include_docs: true,
|
||||
limit: 1,
|
||||
})
|
||||
)
|
||||
return users && users.rows.length >= 1
|
||||
} catch (err) {
|
||||
throw new Error("Unable to retrieve user list")
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue