Merge branch 'master' into automations-fixes
This commit is contained in:
commit
700872395c
|
@ -3,18 +3,10 @@ import { Duration } from "../utils"
|
||||||
import env from "../environment"
|
import env from "../environment"
|
||||||
import { getTenantId } from "../context"
|
import { getTenantId } from "../context"
|
||||||
import * as redis from "../redis/init"
|
import * as redis from "../redis/init"
|
||||||
|
import { Invite, InviteWithCode } from "@budibase/types"
|
||||||
|
|
||||||
const TTL_SECONDS = Duration.fromDays(7).toSeconds()
|
const TTL_SECONDS = Duration.fromDays(7).toSeconds()
|
||||||
|
|
||||||
interface Invite {
|
|
||||||
email: string
|
|
||||||
info: any
|
|
||||||
}
|
|
||||||
|
|
||||||
interface InviteWithCode extends Invite {
|
|
||||||
code: string
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given an invite code and invite body, allow the update an existing/valid invite in redis
|
* Given an invite code and invite body, allow the update an existing/valid invite in redis
|
||||||
* @param code The invite code for an invite in redis
|
* @param code The invite code for an invite in redis
|
||||||
|
|
|
@ -56,7 +56,10 @@
|
||||||
.map(table => format.table(table, $datasources.list))
|
.map(table => format.table(table, $datasources.list))
|
||||||
.sort((a, b) => {
|
.sort((a, b) => {
|
||||||
// sort tables alphabetically, grouped by datasource
|
// sort tables alphabetically, grouped by datasource
|
||||||
const dsComparison = a.datasourceName.localeCompare(b.datasourceName)
|
const dsA = a.datasourceName ?? ""
|
||||||
|
const dsB = b.datasourceName ?? ""
|
||||||
|
|
||||||
|
const dsComparison = dsA.localeCompare(dsB)
|
||||||
if (dsComparison !== 0) {
|
if (dsComparison !== 0) {
|
||||||
return dsComparison
|
return dsComparison
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { downloadTemplate as dlTemplate } from "../../utilities/fileSystem"
|
||||||
import env from "../../environment"
|
import env from "../../environment"
|
||||||
import {
|
import {
|
||||||
DownloadTemplateResponse,
|
DownloadTemplateResponse,
|
||||||
FetchTemplateResponse,
|
FetchGlobalTemplateResponse,
|
||||||
UserCtx,
|
UserCtx,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ import {
|
||||||
const DEFAULT_TEMPLATES_BUCKET =
|
const DEFAULT_TEMPLATES_BUCKET =
|
||||||
"prod-budi-templates.s3-eu-west-1.amazonaws.com"
|
"prod-budi-templates.s3-eu-west-1.amazonaws.com"
|
||||||
|
|
||||||
export async function fetch(ctx: UserCtx<void, FetchTemplateResponse>) {
|
export async function fetch(ctx: UserCtx<void, FetchGlobalTemplateResponse>) {
|
||||||
let type = env.TEMPLATE_REPOSITORY
|
let type = env.TEMPLATE_REPOSITORY
|
||||||
let response,
|
let response,
|
||||||
error = false
|
error = false
|
||||||
|
|
|
@ -3,14 +3,28 @@ export interface LoginRequest {
|
||||||
password: string
|
password: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface LogoutResponse {
|
||||||
|
message: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SetInitInfoRequest extends Record<string, any> {}
|
||||||
|
|
||||||
|
export interface GetInitInfoResponse extends Record<string, any> {}
|
||||||
|
|
||||||
export interface PasswordResetRequest {
|
export interface PasswordResetRequest {
|
||||||
email: string
|
email: string
|
||||||
}
|
}
|
||||||
|
export interface PasswordResetResponse {
|
||||||
|
message: string
|
||||||
|
}
|
||||||
|
|
||||||
export interface PasswordResetUpdateRequest {
|
export interface PasswordResetUpdateRequest {
|
||||||
resetCode: string
|
resetCode: string
|
||||||
password: string
|
password: string
|
||||||
}
|
}
|
||||||
|
export interface PasswordResetUpdateResponse {
|
||||||
|
message: string
|
||||||
|
}
|
||||||
|
|
||||||
export interface UpdateSelfRequest {
|
export interface UpdateSelfRequest {
|
||||||
firstName?: string
|
firstName?: string
|
||||||
|
|
|
@ -1,4 +1,10 @@
|
||||||
import { SettingsConfig, SettingsInnerConfig } from "../../../documents"
|
import {
|
||||||
|
Config,
|
||||||
|
ConfigType,
|
||||||
|
SettingsBrandingConfig,
|
||||||
|
SettingsConfig,
|
||||||
|
SettingsInnerConfig,
|
||||||
|
} from "../../../documents"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Settings that aren't stored in the database - enriched at runtime.
|
* Settings that aren't stored in the database - enriched at runtime.
|
||||||
|
@ -22,3 +28,34 @@ export interface PublicOIDCConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
export type GetPublicOIDCConfigResponse = PublicOIDCConfig[]
|
export type GetPublicOIDCConfigResponse = PublicOIDCConfig[]
|
||||||
|
|
||||||
|
export interface SaveConfigRequest extends Config {}
|
||||||
|
export interface SaveConfigResponse {
|
||||||
|
type: ConfigType
|
||||||
|
_id: string
|
||||||
|
_rev: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DeleteConfigResponse {
|
||||||
|
message: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ChecklistItem {
|
||||||
|
checked: boolean
|
||||||
|
label: string
|
||||||
|
link: string
|
||||||
|
}
|
||||||
|
export interface ConfigChecklistResponse {
|
||||||
|
apps: ChecklistItem
|
||||||
|
smtp: ChecklistItem
|
||||||
|
adminUser: ChecklistItem
|
||||||
|
sso: ChecklistItem
|
||||||
|
branding: SettingsBrandingConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
export type FindConfigResponse = Config | {}
|
||||||
|
|
||||||
|
export interface UploadConfigFileResponse {
|
||||||
|
message: string
|
||||||
|
url: string
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
import { EmailAttachment, EmailInvite } from "../../../documents"
|
||||||
|
|
||||||
|
export enum EmailTemplatePurpose {
|
||||||
|
CORE = "core",
|
||||||
|
BASE = "base",
|
||||||
|
PASSWORD_RECOVERY = "password_recovery",
|
||||||
|
INVITATION = "invitation",
|
||||||
|
WELCOME = "welcome",
|
||||||
|
CUSTOM = "custom",
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SendEmailRequest {
|
||||||
|
workspaceId?: string
|
||||||
|
email: string
|
||||||
|
userId: string
|
||||||
|
purpose: EmailTemplatePurpose
|
||||||
|
contents?: string
|
||||||
|
from?: string
|
||||||
|
subject: string
|
||||||
|
cc?: boolean
|
||||||
|
bcc?: boolean
|
||||||
|
automation?: boolean
|
||||||
|
invite?: EmailInvite
|
||||||
|
attachments?: EmailAttachment[]
|
||||||
|
}
|
||||||
|
export interface SendEmailResponse extends Record<string, any> {
|
||||||
|
message: string
|
||||||
|
}
|
|
@ -5,3 +5,7 @@ export * from "./configs"
|
||||||
export * from "./scim"
|
export * from "./scim"
|
||||||
export * from "./license"
|
export * from "./license"
|
||||||
export * from "./oldMigration"
|
export * from "./oldMigration"
|
||||||
|
export * from "./email"
|
||||||
|
export * from "./role"
|
||||||
|
export * from "./self"
|
||||||
|
export * from "./template"
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
// LICENSE KEY
|
// LICENSE KEY
|
||||||
|
|
||||||
|
import { QuotaUsage } from "../../../documents"
|
||||||
|
|
||||||
export interface ActivateLicenseKeyRequest {
|
export interface ActivateLicenseKeyRequest {
|
||||||
licenseKey: string
|
licenseKey: string
|
||||||
}
|
}
|
||||||
|
@ -23,3 +25,5 @@ export interface GetOfflineLicenseTokenResponse {
|
||||||
export interface GetOfflineIdentifierResponse {
|
export interface GetOfflineIdentifierResponse {
|
||||||
identifierBase64: string
|
identifierBase64: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface GetQuotaUsageResponse extends QuotaUsage {}
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
import { Role } from "../../../documents"
|
||||||
|
|
||||||
|
interface GlobalRoleResponse {
|
||||||
|
roles: Role[]
|
||||||
|
name: string
|
||||||
|
version: string
|
||||||
|
url?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FetchGlobalRolesResponse
|
||||||
|
extends Record<string, GlobalRoleResponse> {}
|
||||||
|
|
||||||
|
export interface FindGlobalRoleResponse extends GlobalRoleResponse {}
|
||||||
|
|
||||||
|
export interface RemoveAppRoleResponse {
|
||||||
|
message: string
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
import { DevInfo, User } from "../../../documents"
|
||||||
|
|
||||||
|
export interface GenerateAPIKeyRequest {
|
||||||
|
userId: string
|
||||||
|
}
|
||||||
|
export interface GenerateAPIKeyResponse extends DevInfo {}
|
||||||
|
|
||||||
|
export interface FetchAPIKeyResponse extends DevInfo {}
|
||||||
|
|
||||||
|
export interface GetGlobalSelfResponse extends User {
|
||||||
|
flags?: Record<string, string>
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
import { Template } from "../../../documents"
|
||||||
|
|
||||||
|
export interface GlobalTemplateDefinition {
|
||||||
|
name: string
|
||||||
|
description: string
|
||||||
|
category: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GlobalTemplateBinding {
|
||||||
|
name: string
|
||||||
|
description: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FetchGlobalTemplateDefinitionResponse {
|
||||||
|
info: Record<string, GlobalTemplateDefinition>
|
||||||
|
bindings: Record<string, GlobalTemplateBinding[]>
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SaveGlobalTemplateRequest extends Template {}
|
||||||
|
export interface SaveGlobalTemplateResponse extends Template {}
|
||||||
|
|
||||||
|
export type FetchGlobalTemplateResponse = Template[]
|
||||||
|
export type FetchGlobalTemplateByTypeResponse = Template[]
|
||||||
|
export type FetchGlobalTemplateByOwnerIDResponse = Template[]
|
||||||
|
|
||||||
|
export interface FindGlobalTemplateResponse extends Template {}
|
||||||
|
|
||||||
|
export interface DeleteGlobalTemplateResponse {
|
||||||
|
message: string
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
import { Account, AccountMetadata } from "../../../documents"
|
||||||
|
|
||||||
|
export interface SaveAccountRequest extends Account {}
|
||||||
|
export interface SaveAccountResponse extends AccountMetadata {}
|
|
@ -1,8 +1,11 @@
|
||||||
export interface GetEnvironmentResponse {
|
export interface GetEnvironmentResponse {
|
||||||
multiTenancy: boolean
|
multiTenancy: boolean
|
||||||
|
offlineMode: boolean
|
||||||
cloud: boolean
|
cloud: boolean
|
||||||
accountPortalUrl: string
|
accountPortalUrl?: string
|
||||||
baseUrl: string
|
|
||||||
disableAccountPortal: boolean
|
disableAccountPortal: boolean
|
||||||
|
baseUrl?: string
|
||||||
isDev: boolean
|
isDev: boolean
|
||||||
|
maintenance: { type: string }[]
|
||||||
|
passwordMinLength?: string
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
export * from "./environment"
|
export * from "./environment"
|
||||||
export * from "./status"
|
export * from "./status"
|
||||||
export * from "./ops"
|
export * from "./ops"
|
||||||
|
export * from "./account"
|
||||||
|
export * from "./log"
|
||||||
|
export * from "./migration"
|
||||||
|
export * from "./restore"
|
||||||
|
export * from "./tenant"
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
export type GetLogResponse = Buffer
|
|
@ -0,0 +1,5 @@
|
||||||
|
import { MigrationDefinition, MigrationOptions } from "../../../sdk"
|
||||||
|
|
||||||
|
export interface RunGlobalMigrationRequest extends MigrationOptions {}
|
||||||
|
|
||||||
|
export type FetchMigrationDefinitionsResponse = MigrationDefinition[]
|
|
@ -0,0 +1,3 @@
|
||||||
|
export interface SystemRestoreResponse {
|
||||||
|
message: string
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
export interface GetTenantInfoResponse {
|
||||||
|
exists: boolean
|
||||||
|
}
|
|
@ -1,6 +1,15 @@
|
||||||
import { User } from "../../documents"
|
import { AccountMetadata, PlatformUser, User } from "../../documents"
|
||||||
import { SearchFilters } from "../../sdk"
|
import { SearchFilters } from "../../sdk"
|
||||||
|
|
||||||
|
export interface Invite {
|
||||||
|
email: string
|
||||||
|
info: any
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface InviteWithCode extends Invite {
|
||||||
|
code: string
|
||||||
|
}
|
||||||
|
|
||||||
export interface SaveUserResponse {
|
export interface SaveUserResponse {
|
||||||
_id: string
|
_id: string
|
||||||
_rev: string
|
_rev: string
|
||||||
|
@ -47,6 +56,11 @@ export interface InviteUserRequest {
|
||||||
email: string
|
email: string
|
||||||
userInfo: any
|
userInfo: any
|
||||||
}
|
}
|
||||||
|
export interface InviteUserResponse {
|
||||||
|
message: string
|
||||||
|
successful: { email: string }[]
|
||||||
|
unsuccessful: { email: string; reason: string }[]
|
||||||
|
}
|
||||||
|
|
||||||
export interface DeleteInviteUserRequest {
|
export interface DeleteInviteUserRequest {
|
||||||
code: string
|
code: string
|
||||||
|
@ -54,6 +68,9 @@ export interface DeleteInviteUserRequest {
|
||||||
|
|
||||||
export type InviteUsersRequest = InviteUserRequest[]
|
export type InviteUsersRequest = InviteUserRequest[]
|
||||||
export type DeleteInviteUsersRequest = DeleteInviteUserRequest[]
|
export type DeleteInviteUsersRequest = DeleteInviteUserRequest[]
|
||||||
|
export interface DeleteInviteUsersResponse {
|
||||||
|
message: string
|
||||||
|
}
|
||||||
|
|
||||||
export interface InviteUsersResponse {
|
export interface InviteUsersResponse {
|
||||||
successful: { email: string }[]
|
successful: { email: string }[]
|
||||||
|
@ -68,6 +85,17 @@ export interface SearchUsersRequest {
|
||||||
limit?: number
|
limit?: number
|
||||||
paginate?: boolean
|
paginate?: boolean
|
||||||
}
|
}
|
||||||
|
export interface SearchUsersResponse {
|
||||||
|
data: User[]
|
||||||
|
hasNextPage?: boolean
|
||||||
|
nextPage?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type FetchUsersResponse = User[]
|
||||||
|
|
||||||
|
export interface FindUserResponse extends User {}
|
||||||
|
|
||||||
|
export type LookupTenantUserResponse = PlatformUser
|
||||||
|
|
||||||
export interface CreateAdminUserRequest {
|
export interface CreateAdminUserRequest {
|
||||||
email: string
|
email: string
|
||||||
|
@ -106,3 +134,28 @@ export interface AcceptUserInviteResponse {
|
||||||
export interface SyncUserRequest {
|
export interface SyncUserRequest {
|
||||||
previousUser?: User
|
previousUser?: User
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface DeleteUserResponse {
|
||||||
|
message: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CountUserResponse {
|
||||||
|
userCount: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CheckInviteResponse {
|
||||||
|
email: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type GetUserInvitesResponse = InviteWithCode[]
|
||||||
|
|
||||||
|
export interface UpdateInviteRequest extends Omit<Invite, "email"> {
|
||||||
|
email?: string
|
||||||
|
builder?: {
|
||||||
|
apps: string[]
|
||||||
|
}
|
||||||
|
apps: string[]
|
||||||
|
}
|
||||||
|
export interface UpdateInviteResponse extends Invite {}
|
||||||
|
|
||||||
|
export type LookupAccountHolderResponse = AccountMetadata | null
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
import { Document } from "../document"
|
||||||
|
|
||||||
|
export interface DevInfo extends Document {
|
||||||
|
userId: string
|
||||||
|
apiKey?: string
|
||||||
|
}
|
|
@ -8,3 +8,4 @@ export * from "./templates"
|
||||||
export * from "./environmentVariables"
|
export * from "./environmentVariables"
|
||||||
export * from "./auditLogs"
|
export * from "./auditLogs"
|
||||||
export * from "./apikeys"
|
export * from "./apikeys"
|
||||||
|
export * from "./devInfo"
|
||||||
|
|
|
@ -16,8 +16,15 @@ import {
|
||||||
PasswordResetUpdateRequest,
|
PasswordResetUpdateRequest,
|
||||||
GoogleInnerConfig,
|
GoogleInnerConfig,
|
||||||
DatasourceAuthCookie,
|
DatasourceAuthCookie,
|
||||||
|
LogoutResponse,
|
||||||
|
UserCtx,
|
||||||
|
SetInitInfoRequest,
|
||||||
|
GetInitInfoResponse,
|
||||||
|
PasswordResetResponse,
|
||||||
|
PasswordResetUpdateResponse,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import env from "../../../environment"
|
import env from "../../../environment"
|
||||||
|
import { Next } from "koa"
|
||||||
|
|
||||||
import * as authSdk from "../../../sdk/auth"
|
import * as authSdk from "../../../sdk/auth"
|
||||||
import * as userSdk from "../../../sdk/users"
|
import * as userSdk from "../../../sdk/users"
|
||||||
|
@ -52,7 +59,7 @@ async function passportCallback(
|
||||||
ctx.set(Header.TOKEN, token)
|
ctx.set(Header.TOKEN, token)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const login = async (ctx: Ctx<LoginRequest>, next: any) => {
|
export const login = async (ctx: Ctx<LoginRequest, void>, next: Next) => {
|
||||||
const email = ctx.request.body.username
|
const email = ctx.request.body.username
|
||||||
|
|
||||||
const user = await userSdk.db.getUserByEmail(email)
|
const user = await userSdk.db.getUserByEmail(email)
|
||||||
|
@ -72,7 +79,7 @@ export const login = async (ctx: Ctx<LoginRequest>, next: any) => {
|
||||||
)(ctx, next)
|
)(ctx, next)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const logout = async (ctx: any) => {
|
export const logout = async (ctx: UserCtx<void, LogoutResponse>) => {
|
||||||
if (ctx.user && ctx.user._id) {
|
if (ctx.user && ctx.user._id) {
|
||||||
await authSdk.logout({ ctx, userId: ctx.user._id })
|
await authSdk.logout({ ctx, userId: ctx.user._id })
|
||||||
}
|
}
|
||||||
|
@ -81,13 +88,13 @@ export const logout = async (ctx: any) => {
|
||||||
|
|
||||||
// INIT
|
// INIT
|
||||||
|
|
||||||
export const setInitInfo = (ctx: any) => {
|
export const setInitInfo = (ctx: UserCtx<SetInitInfoRequest, void>) => {
|
||||||
const initInfo = ctx.request.body
|
const initInfo = ctx.request.body
|
||||||
setCookie(ctx, initInfo, Cookie.Init)
|
setCookie(ctx, initInfo, Cookie.Init)
|
||||||
ctx.status = 200
|
ctx.status = 200
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getInitInfo = (ctx: any) => {
|
export const getInitInfo = (ctx: UserCtx<void, GetInitInfoResponse>) => {
|
||||||
try {
|
try {
|
||||||
ctx.body = getCookie(ctx, Cookie.Init) || {}
|
ctx.body = getCookie(ctx, Cookie.Init) || {}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
@ -101,7 +108,9 @@ export const getInitInfo = (ctx: any) => {
|
||||||
/**
|
/**
|
||||||
* Reset the user password, used as part of a forgotten password flow.
|
* Reset the user password, used as part of a forgotten password flow.
|
||||||
*/
|
*/
|
||||||
export const reset = async (ctx: Ctx<PasswordResetRequest>) => {
|
export const reset = async (
|
||||||
|
ctx: Ctx<PasswordResetRequest, PasswordResetResponse>
|
||||||
|
) => {
|
||||||
const { email } = ctx.request.body
|
const { email } = ctx.request.body
|
||||||
|
|
||||||
await authSdk.reset(email)
|
await authSdk.reset(email)
|
||||||
|
@ -114,7 +123,9 @@ export const reset = async (ctx: Ctx<PasswordResetRequest>) => {
|
||||||
/**
|
/**
|
||||||
* Perform the user password update if the provided reset code is valid.
|
* Perform the user password update if the provided reset code is valid.
|
||||||
*/
|
*/
|
||||||
export const resetUpdate = async (ctx: Ctx<PasswordResetUpdateRequest>) => {
|
export const resetUpdate = async (
|
||||||
|
ctx: Ctx<PasswordResetUpdateRequest, PasswordResetUpdateResponse>
|
||||||
|
) => {
|
||||||
const { resetCode, password } = ctx.request.body
|
const { resetCode, password } = ctx.request.body
|
||||||
try {
|
try {
|
||||||
await authSdk.resetUpdate(resetCode, password)
|
await authSdk.resetUpdate(resetCode, password)
|
||||||
|
@ -130,7 +141,10 @@ export const resetUpdate = async (ctx: Ctx<PasswordResetUpdateRequest>) => {
|
||||||
|
|
||||||
// DATASOURCE
|
// DATASOURCE
|
||||||
|
|
||||||
export const datasourcePreAuth = async (ctx: any, next: any) => {
|
export const datasourcePreAuth = async (
|
||||||
|
ctx: UserCtx<void, void>,
|
||||||
|
next: Next
|
||||||
|
) => {
|
||||||
const provider = ctx.params.provider
|
const provider = ctx.params.provider
|
||||||
const { middleware } = require(`@budibase/backend-core`)
|
const { middleware } = require(`@budibase/backend-core`)
|
||||||
const handler = middleware.datasource[provider]
|
const handler = middleware.datasource[provider]
|
||||||
|
@ -147,7 +161,7 @@ export const datasourcePreAuth = async (ctx: any, next: any) => {
|
||||||
return handler.preAuth(passport, ctx, next)
|
return handler.preAuth(passport, ctx, next)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const datasourceAuth = async (ctx: any, next: any) => {
|
export const datasourceAuth = async (ctx: UserCtx<void, void>, next: Next) => {
|
||||||
const authStateCookie = getCookie<DatasourceAuthCookie>(
|
const authStateCookie = getCookie<DatasourceAuthCookie>(
|
||||||
ctx,
|
ctx,
|
||||||
Cookie.DatasourceAuth
|
Cookie.DatasourceAuth
|
||||||
|
@ -171,7 +185,7 @@ export async function googleCallbackUrl(config?: GoogleInnerConfig) {
|
||||||
* The initial call that google authentication makes to take you to the google login screen.
|
* The initial call that google authentication makes to take you to the google login screen.
|
||||||
* On a successful login, you will be redirected to the googleAuth callback route.
|
* On a successful login, you will be redirected to the googleAuth callback route.
|
||||||
*/
|
*/
|
||||||
export const googlePreAuth = async (ctx: any, next: any) => {
|
export const googlePreAuth = async (ctx: Ctx<void, void>, next: Next) => {
|
||||||
const config = await configs.getGoogleConfig()
|
const config = await configs.getGoogleConfig()
|
||||||
if (!config) {
|
if (!config) {
|
||||||
return ctx.throw(400, "Google config not found")
|
return ctx.throw(400, "Google config not found")
|
||||||
|
@ -190,7 +204,7 @@ export const googlePreAuth = async (ctx: any, next: any) => {
|
||||||
})(ctx, next)
|
})(ctx, next)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const googleCallback = async (ctx: any, next: any) => {
|
export const googleCallback = async (ctx: Ctx<void, void>, next: Next) => {
|
||||||
const config = await configs.getGoogleConfig()
|
const config = await configs.getGoogleConfig()
|
||||||
if (!config) {
|
if (!config) {
|
||||||
return ctx.throw(400, "Google config not found")
|
return ctx.throw(400, "Google config not found")
|
||||||
|
@ -241,7 +255,7 @@ export const oidcStrategyFactory = async (ctx: any) => {
|
||||||
* The initial call that OIDC authentication makes to take you to the configured OIDC login screen.
|
* The initial call that OIDC authentication makes to take you to the configured OIDC login screen.
|
||||||
* On a successful login, you will be redirected to the oidcAuth callback route.
|
* On a successful login, you will be redirected to the oidcAuth callback route.
|
||||||
*/
|
*/
|
||||||
export const oidcPreAuth = async (ctx: Ctx, next: any) => {
|
export const oidcPreAuth = async (ctx: Ctx<void, void>, next: Next) => {
|
||||||
const { configId } = ctx.params
|
const { configId } = ctx.params
|
||||||
if (!configId) {
|
if (!configId) {
|
||||||
ctx.throw(400, "OIDC config id is required")
|
ctx.throw(400, "OIDC config id is required")
|
||||||
|
@ -266,7 +280,7 @@ export const oidcPreAuth = async (ctx: Ctx, next: any) => {
|
||||||
})(ctx, next)
|
})(ctx, next)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const oidcCallback = async (ctx: any, next: any) => {
|
export const oidcCallback = async (ctx: Ctx<void, void>, next: Next) => {
|
||||||
const strategy = await oidcStrategyFactory(ctx)
|
const strategy = await oidcStrategyFactory(ctx)
|
||||||
|
|
||||||
return passport.authenticate(
|
return passport.authenticate(
|
||||||
|
|
|
@ -15,8 +15,11 @@ import {
|
||||||
AIConfig,
|
AIConfig,
|
||||||
AIInnerConfig,
|
AIInnerConfig,
|
||||||
Config,
|
Config,
|
||||||
|
ConfigChecklistResponse,
|
||||||
ConfigType,
|
ConfigType,
|
||||||
Ctx,
|
Ctx,
|
||||||
|
DeleteConfigResponse,
|
||||||
|
FindConfigResponse,
|
||||||
GetPublicOIDCConfigResponse,
|
GetPublicOIDCConfigResponse,
|
||||||
GetPublicSettingsResponse,
|
GetPublicSettingsResponse,
|
||||||
GoogleInnerConfig,
|
GoogleInnerConfig,
|
||||||
|
@ -29,11 +32,14 @@ import {
|
||||||
OIDCLogosConfig,
|
OIDCLogosConfig,
|
||||||
PASSWORD_REPLACEMENT,
|
PASSWORD_REPLACEMENT,
|
||||||
QuotaUsageType,
|
QuotaUsageType,
|
||||||
|
SaveConfigRequest,
|
||||||
|
SaveConfigResponse,
|
||||||
SettingsBrandingConfig,
|
SettingsBrandingConfig,
|
||||||
SettingsInnerConfig,
|
SettingsInnerConfig,
|
||||||
SSOConfig,
|
SSOConfig,
|
||||||
SSOConfigType,
|
SSOConfigType,
|
||||||
StaticQuotaName,
|
StaticQuotaName,
|
||||||
|
UploadConfigFileResponse,
|
||||||
UserCtx,
|
UserCtx,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import * as pro from "@budibase/pro"
|
import * as pro from "@budibase/pro"
|
||||||
|
@ -225,7 +231,9 @@ export async function verifyAIConfig(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function save(ctx: UserCtx<Config>) {
|
export async function save(
|
||||||
|
ctx: UserCtx<SaveConfigRequest, SaveConfigResponse>
|
||||||
|
) {
|
||||||
const body = ctx.request.body
|
const body = ctx.request.body
|
||||||
const type = body.type
|
const type = body.type
|
||||||
const config = body.config
|
const config = body.config
|
||||||
|
@ -337,7 +345,7 @@ function enrichOIDCLogos(oidcLogos: OIDCLogosConfig) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function find(ctx: UserCtx) {
|
export async function find(ctx: UserCtx<void, FindConfigResponse>) {
|
||||||
try {
|
try {
|
||||||
// Find the config with the most granular scope based on context
|
// Find the config with the most granular scope based on context
|
||||||
const type = ctx.params.type
|
const type = ctx.params.type
|
||||||
|
@ -473,7 +481,7 @@ export async function publicSettings(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function upload(ctx: UserCtx) {
|
export async function upload(ctx: UserCtx<void, UploadConfigFileResponse>) {
|
||||||
if (ctx.request.files == null || Array.isArray(ctx.request.files.file)) {
|
if (ctx.request.files == null || Array.isArray(ctx.request.files.file)) {
|
||||||
ctx.throw(400, "One file must be uploaded.")
|
ctx.throw(400, "One file must be uploaded.")
|
||||||
}
|
}
|
||||||
|
@ -518,7 +526,7 @@ export async function upload(ctx: UserCtx) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function destroy(ctx: UserCtx) {
|
export async function destroy(ctx: UserCtx<void, DeleteConfigResponse>) {
|
||||||
const db = tenancy.getGlobalDB()
|
const db = tenancy.getGlobalDB()
|
||||||
const { id, rev } = ctx.params
|
const { id, rev } = ctx.params
|
||||||
try {
|
try {
|
||||||
|
@ -537,14 +545,14 @@ export async function destroy(ctx: UserCtx) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function configChecklist(ctx: Ctx) {
|
export async function configChecklist(ctx: Ctx<void, ConfigChecklistResponse>) {
|
||||||
const tenantId = tenancy.getTenantId()
|
const tenantId = tenancy.getTenantId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ctx.body = await cache.withCache(
|
ctx.body = await cache.withCache(
|
||||||
cache.CacheKey.CHECKLIST,
|
cache.CacheKey.CHECKLIST,
|
||||||
env.CHECKLIST_CACHE_TTL,
|
env.CHECKLIST_CACHE_TTL,
|
||||||
async () => {
|
async (): Promise<ConfigChecklistResponse> => {
|
||||||
let apps = []
|
let apps = []
|
||||||
if (!env.MULTI_TENANCY || tenantId) {
|
if (!env.MULTI_TENANCY || tenantId) {
|
||||||
// Apps exist
|
// Apps exist
|
||||||
|
|
|
@ -1,8 +1,15 @@
|
||||||
import { sendEmail as sendEmailFn } from "../../../utilities/email"
|
import { sendEmail as sendEmailFn } from "../../../utilities/email"
|
||||||
import { tenancy } from "@budibase/backend-core"
|
import { tenancy } from "@budibase/backend-core"
|
||||||
import { BBContext, User } from "@budibase/types"
|
import {
|
||||||
|
UserCtx,
|
||||||
|
User,
|
||||||
|
SendEmailRequest,
|
||||||
|
SendEmailResponse,
|
||||||
|
} from "@budibase/types"
|
||||||
|
|
||||||
export async function sendEmail(ctx: BBContext) {
|
export async function sendEmail(
|
||||||
|
ctx: UserCtx<SendEmailRequest, SendEmailResponse>
|
||||||
|
) {
|
||||||
let {
|
let {
|
||||||
workspaceId,
|
workspaceId,
|
||||||
email,
|
email,
|
||||||
|
|
|
@ -5,6 +5,7 @@ import {
|
||||||
GetLicenseKeyResponse,
|
GetLicenseKeyResponse,
|
||||||
GetOfflineIdentifierResponse,
|
GetOfflineIdentifierResponse,
|
||||||
GetOfflineLicenseTokenResponse,
|
GetOfflineLicenseTokenResponse,
|
||||||
|
GetQuotaUsageResponse,
|
||||||
UserCtx,
|
UserCtx,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
|
||||||
|
@ -36,7 +37,7 @@ export async function deleteLicenseKey(ctx: UserCtx<void, void>) {
|
||||||
// OFFLINE LICENSE
|
// OFFLINE LICENSE
|
||||||
|
|
||||||
export async function activateOfflineLicenseToken(
|
export async function activateOfflineLicenseToken(
|
||||||
ctx: UserCtx<ActivateOfflineLicenseTokenRequest>
|
ctx: UserCtx<ActivateOfflineLicenseTokenRequest, void>
|
||||||
) {
|
) {
|
||||||
const { offlineLicenseToken } = ctx.request.body
|
const { offlineLicenseToken } = ctx.request.body
|
||||||
await licensing.offline.activateOfflineLicenseToken(offlineLicenseToken)
|
await licensing.offline.activateOfflineLicenseToken(offlineLicenseToken)
|
||||||
|
@ -70,14 +71,16 @@ export async function getOfflineLicenseIdentifier(
|
||||||
|
|
||||||
// LICENSES
|
// LICENSES
|
||||||
|
|
||||||
export const refresh = async (ctx: any) => {
|
export const refresh = async (ctx: UserCtx<void, void>) => {
|
||||||
await licensing.cache.refresh()
|
await licensing.cache.refresh()
|
||||||
ctx.status = 200
|
ctx.status = 200
|
||||||
}
|
}
|
||||||
|
|
||||||
// USAGE
|
// USAGE
|
||||||
|
|
||||||
export const getQuotaUsage = async (ctx: any) => {
|
export const getQuotaUsage = async (
|
||||||
|
ctx: UserCtx<void, GetQuotaUsageResponse>
|
||||||
|
) => {
|
||||||
ctx.body = await quotas.getQuotaUsage()
|
ctx.body = await quotas.getQuotaUsage()
|
||||||
ctx.status = 200
|
ctx.status = 200
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,15 @@ import {
|
||||||
tenancy,
|
tenancy,
|
||||||
} from "@budibase/backend-core"
|
} from "@budibase/backend-core"
|
||||||
import sdk from "../../../sdk"
|
import sdk from "../../../sdk"
|
||||||
import { Ctx, App } from "@budibase/types"
|
import {
|
||||||
|
Ctx,
|
||||||
|
App,
|
||||||
|
FetchGlobalRolesResponse,
|
||||||
|
FindGlobalRoleResponse,
|
||||||
|
RemoveAppRoleResponse,
|
||||||
|
} from "@budibase/types"
|
||||||
|
|
||||||
export async function fetch(ctx: Ctx) {
|
export async function fetch(ctx: Ctx<void, FetchGlobalRolesResponse>) {
|
||||||
const tenantId = ctx.user!.tenantId
|
const tenantId = ctx.user!.tenantId
|
||||||
// always use the dev apps as they'll be most up to date (true)
|
// 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 apps = (await dbCore.getAllApps({ tenantId, all: true })) as App[]
|
||||||
|
@ -31,7 +37,7 @@ export async function fetch(ctx: Ctx) {
|
||||||
ctx.body = response
|
ctx.body = response
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function find(ctx: Ctx) {
|
export async function find(ctx: Ctx<void, FindGlobalRoleResponse>) {
|
||||||
const appId = ctx.params.appId
|
const appId = ctx.params.appId
|
||||||
await context.doInAppContext(dbCore.getDevAppID(appId), async () => {
|
await context.doInAppContext(dbCore.getDevAppID(appId), async () => {
|
||||||
const db = context.getAppDB()
|
const db = context.getAppDB()
|
||||||
|
@ -45,7 +51,7 @@ export async function find(ctx: Ctx) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function removeAppRole(ctx: Ctx) {
|
export async function removeAppRole(ctx: Ctx<void, RemoveAppRoleResponse>) {
|
||||||
const { appId } = ctx.params
|
const { appId } = ctx.params
|
||||||
const db = tenancy.getGlobalDB()
|
const db = tenancy.getGlobalDB()
|
||||||
const users = await sdk.users.db.allUsers()
|
const users = await sdk.users.db.allUsers()
|
||||||
|
|
|
@ -10,6 +10,11 @@ import {
|
||||||
import env from "../../../environment"
|
import env from "../../../environment"
|
||||||
import { groups } from "@budibase/pro"
|
import { groups } from "@budibase/pro"
|
||||||
import {
|
import {
|
||||||
|
DevInfo,
|
||||||
|
FetchAPIKeyResponse,
|
||||||
|
GenerateAPIKeyRequest,
|
||||||
|
GenerateAPIKeyResponse,
|
||||||
|
GetGlobalSelfResponse,
|
||||||
UpdateSelfRequest,
|
UpdateSelfRequest,
|
||||||
UpdateSelfResponse,
|
UpdateSelfResponse,
|
||||||
User,
|
User,
|
||||||
|
@ -35,22 +40,24 @@ function cleanupDevInfo(info: any) {
|
||||||
return info
|
return info
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function generateAPIKey(ctx: any) {
|
export async function generateAPIKey(
|
||||||
|
ctx: UserCtx<GenerateAPIKeyRequest, GenerateAPIKeyResponse>
|
||||||
|
) {
|
||||||
let userId
|
let userId
|
||||||
let apiKey
|
let apiKey
|
||||||
if (env.isTest() && ctx.request.body.userId) {
|
if (env.isTest() && ctx.request.body.userId) {
|
||||||
userId = ctx.request.body.userId
|
userId = ctx.request.body.userId
|
||||||
apiKey = newTestApiKey()
|
apiKey = newTestApiKey()
|
||||||
} else {
|
} else {
|
||||||
userId = ctx.user._id
|
userId = ctx.user._id!
|
||||||
apiKey = newApiKey()
|
apiKey = newApiKey()
|
||||||
}
|
}
|
||||||
|
|
||||||
const db = tenancy.getGlobalDB()
|
const db = tenancy.getGlobalDB()
|
||||||
const id = dbCore.generateDevInfoID(userId)
|
const id = dbCore.generateDevInfoID(userId)
|
||||||
let devInfo
|
let devInfo: DevInfo
|
||||||
try {
|
try {
|
||||||
devInfo = await db.get<any>(id)
|
devInfo = await db.get<DevInfo>(id)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
devInfo = { _id: id, userId }
|
devInfo = { _id: id, userId }
|
||||||
}
|
}
|
||||||
|
@ -59,9 +66,9 @@ export async function generateAPIKey(ctx: any) {
|
||||||
ctx.body = cleanupDevInfo(devInfo)
|
ctx.body = cleanupDevInfo(devInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchAPIKey(ctx: any) {
|
export async function fetchAPIKey(ctx: UserCtx<void, FetchAPIKeyResponse>) {
|
||||||
const db = tenancy.getGlobalDB()
|
const db = tenancy.getGlobalDB()
|
||||||
const id = dbCore.generateDevInfoID(ctx.user._id)
|
const id = dbCore.generateDevInfoID(ctx.user._id!)
|
||||||
let devInfo
|
let devInfo
|
||||||
try {
|
try {
|
||||||
devInfo = await db.get(id)
|
devInfo = await db.get(id)
|
||||||
|
@ -87,11 +94,11 @@ const addSessionAttributesToUser = (ctx: any) => {
|
||||||
ctx.body.csrfToken = ctx.user.csrfToken
|
ctx.body.csrfToken = ctx.user.csrfToken
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getSelf(ctx: any) {
|
export async function getSelf(ctx: UserCtx<void, GetGlobalSelfResponse>) {
|
||||||
if (!ctx.user) {
|
if (!ctx.user) {
|
||||||
ctx.throw(403, "User not logged in")
|
ctx.throw(403, "User not logged in")
|
||||||
}
|
}
|
||||||
const userId = ctx.user._id
|
const userId = ctx.user._id!
|
||||||
ctx.params = {
|
ctx.params = {
|
||||||
id: userId,
|
id: userId,
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,25 @@ import {
|
||||||
TemplateBindings,
|
TemplateBindings,
|
||||||
GLOBAL_OWNER,
|
GLOBAL_OWNER,
|
||||||
} from "../../../constants"
|
} from "../../../constants"
|
||||||
import { getTemplates } from "../../../constants/templates"
|
import { getTemplateByID, getTemplates } from "../../../constants/templates"
|
||||||
import { tenancy, db as dbCore } from "@budibase/backend-core"
|
import { tenancy, db as dbCore } from "@budibase/backend-core"
|
||||||
|
import {
|
||||||
|
DeleteGlobalTemplateResponse,
|
||||||
|
FetchGlobalTemplateByOwnerIDResponse,
|
||||||
|
FetchGlobalTemplateByTypeResponse,
|
||||||
|
FetchGlobalTemplateDefinitionResponse,
|
||||||
|
FetchGlobalTemplateResponse,
|
||||||
|
FindGlobalTemplateResponse,
|
||||||
|
SaveGlobalTemplateRequest,
|
||||||
|
SaveGlobalTemplateResponse,
|
||||||
|
GlobalTemplateBinding,
|
||||||
|
GlobalTemplateDefinition,
|
||||||
|
UserCtx,
|
||||||
|
} from "@budibase/types"
|
||||||
|
|
||||||
export async function save(ctx: any) {
|
export async function save(
|
||||||
|
ctx: UserCtx<SaveGlobalTemplateRequest, SaveGlobalTemplateResponse>
|
||||||
|
) {
|
||||||
const db = tenancy.getGlobalDB()
|
const db = tenancy.getGlobalDB()
|
||||||
let template = ctx.request.body
|
let template = ctx.request.body
|
||||||
if (!template.ownerId) {
|
if (!template.ownerId) {
|
||||||
|
@ -23,9 +38,11 @@ export async function save(ctx: any) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function definitions(ctx: any) {
|
export async function definitions(
|
||||||
const bindings: any = {}
|
ctx: UserCtx<void, FetchGlobalTemplateDefinitionResponse>
|
||||||
const info: any = {}
|
) {
|
||||||
|
const bindings: Record<string, GlobalTemplateBinding[]> = {}
|
||||||
|
const info: Record<string, GlobalTemplateDefinition> = {}
|
||||||
for (let template of TemplateMetadata.email) {
|
for (let template of TemplateMetadata.email) {
|
||||||
bindings[template.purpose] = template.bindings
|
bindings[template.purpose] = template.bindings
|
||||||
info[template.purpose] = {
|
info[template.purpose] = {
|
||||||
|
@ -44,34 +61,35 @@ export async function definitions(ctx: any) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetch(ctx: any) {
|
export async function fetch(ctx: UserCtx<void, FetchGlobalTemplateResponse>) {
|
||||||
ctx.body = await getTemplates()
|
ctx.body = await getTemplates()
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchByType(ctx: any) {
|
export async function fetchByType(
|
||||||
// @ts-ignore
|
ctx: UserCtx<void, FetchGlobalTemplateByTypeResponse>
|
||||||
|
) {
|
||||||
ctx.body = await getTemplates({
|
ctx.body = await getTemplates({
|
||||||
type: ctx.params.type,
|
type: ctx.params.type,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchByOwner(ctx: any) {
|
export async function fetchByOwner(
|
||||||
|
ctx: UserCtx<void, FetchGlobalTemplateByOwnerIDResponse>
|
||||||
|
) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
ctx.body = await getTemplates({
|
ctx.body = await getTemplates({
|
||||||
ownerId: ctx.params.ownerId,
|
ownerId: ctx.params.ownerId,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function find(ctx: any) {
|
export async function find(ctx: UserCtx<void, FindGlobalTemplateResponse>) {
|
||||||
// @ts-ignore
|
ctx.body = await getTemplateByID(ctx.params.id)
|
||||||
ctx.body = await getTemplates({
|
|
||||||
id: ctx.params.id,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function destroy(ctx: any) {
|
export async function destroy(
|
||||||
|
ctx: UserCtx<void, DeleteGlobalTemplateResponse>
|
||||||
|
) {
|
||||||
const db = tenancy.getGlobalDB()
|
const db = tenancy.getGlobalDB()
|
||||||
await db.remove(ctx.params.id, ctx.params.rev)
|
await db.remove(ctx.params.id, ctx.params.rev)
|
||||||
ctx.message = `Template ${ctx.params.id} deleted.`
|
ctx.body = { message: `Template ${ctx.params.id} deleted.` }
|
||||||
ctx.status = 200
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,21 +6,34 @@ import {
|
||||||
AddSSoUserRequest,
|
AddSSoUserRequest,
|
||||||
BulkUserRequest,
|
BulkUserRequest,
|
||||||
BulkUserResponse,
|
BulkUserResponse,
|
||||||
|
CheckInviteResponse,
|
||||||
|
CountUserResponse,
|
||||||
CreateAdminUserRequest,
|
CreateAdminUserRequest,
|
||||||
CreateAdminUserResponse,
|
CreateAdminUserResponse,
|
||||||
Ctx,
|
Ctx,
|
||||||
DeleteInviteUserRequest,
|
DeleteInviteUserRequest,
|
||||||
DeleteInviteUsersRequest,
|
DeleteInviteUsersRequest,
|
||||||
|
DeleteInviteUsersResponse,
|
||||||
|
DeleteUserResponse,
|
||||||
|
FetchUsersResponse,
|
||||||
|
FindUserResponse,
|
||||||
|
GetUserInvitesResponse,
|
||||||
Hosting,
|
Hosting,
|
||||||
InviteUserRequest,
|
InviteUserRequest,
|
||||||
|
InviteUserResponse,
|
||||||
InviteUsersRequest,
|
InviteUsersRequest,
|
||||||
InviteUsersResponse,
|
InviteUsersResponse,
|
||||||
LockName,
|
LockName,
|
||||||
LockType,
|
LockType,
|
||||||
|
LookupAccountHolderResponse,
|
||||||
|
LookupTenantUserResponse,
|
||||||
MigrationType,
|
MigrationType,
|
||||||
PlatformUserByEmail,
|
PlatformUserByEmail,
|
||||||
SaveUserResponse,
|
SaveUserResponse,
|
||||||
SearchUsersRequest,
|
SearchUsersRequest,
|
||||||
|
SearchUsersResponse,
|
||||||
|
UpdateInviteRequest,
|
||||||
|
UpdateInviteResponse,
|
||||||
User,
|
User,
|
||||||
UserCtx,
|
UserCtx,
|
||||||
UserIdentifier,
|
UserIdentifier,
|
||||||
|
@ -80,7 +93,7 @@ export const save = async (ctx: UserCtx<User, SaveUserResponse>) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const addSsoSupport = async (ctx: Ctx<AddSSoUserRequest>) => {
|
export const addSsoSupport = async (ctx: Ctx<AddSSoUserRequest, void>) => {
|
||||||
const { email, ssoId } = ctx.request.body
|
const { email, ssoId } = ctx.request.body
|
||||||
try {
|
try {
|
||||||
// Status is changed to 404 from getUserDoc if user is not found
|
// Status is changed to 404 from getUserDoc if user is not found
|
||||||
|
@ -207,7 +220,7 @@ export const adminUser = async (
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const countByApp = async (ctx: any) => {
|
export const countByApp = async (ctx: UserCtx<void, CountUserResponse>) => {
|
||||||
const appId = ctx.params.appId
|
const appId = ctx.params.appId
|
||||||
try {
|
try {
|
||||||
ctx.body = await userSdk.db.countUsersByApp(appId)
|
ctx.body = await userSdk.db.countUsersByApp(appId)
|
||||||
|
@ -216,7 +229,7 @@ export const countByApp = async (ctx: any) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const destroy = async (ctx: any) => {
|
export const destroy = async (ctx: UserCtx<void, DeleteUserResponse>) => {
|
||||||
const id = ctx.params.id
|
const id = ctx.params.id
|
||||||
if (id === ctx.user._id) {
|
if (id === ctx.user._id) {
|
||||||
ctx.throw(400, "Unable to delete self.")
|
ctx.throw(400, "Unable to delete self.")
|
||||||
|
@ -239,7 +252,9 @@ export const getAppUsers = async (ctx: Ctx<SearchUsersRequest>) => {
|
||||||
ctx.body = { data: users }
|
ctx.body = { data: users }
|
||||||
}
|
}
|
||||||
|
|
||||||
export const search = async (ctx: Ctx<SearchUsersRequest>) => {
|
export const search = async (
|
||||||
|
ctx: Ctx<SearchUsersRequest, SearchUsersResponse>
|
||||||
|
) => {
|
||||||
const body = ctx.request.body
|
const body = ctx.request.body
|
||||||
|
|
||||||
// TODO: for now only two supported search keys; string.email and equal._id
|
// TODO: for now only two supported search keys; string.email and equal._id
|
||||||
|
@ -280,7 +295,7 @@ export const search = async (ctx: Ctx<SearchUsersRequest>) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// called internally by app server user fetch
|
// called internally by app server user fetch
|
||||||
export const fetch = async (ctx: any) => {
|
export const fetch = async (ctx: UserCtx<void, FetchUsersResponse>) => {
|
||||||
const all = await userSdk.db.allUsers()
|
const all = await userSdk.db.allUsers()
|
||||||
// user hashed password shouldn't ever be returned
|
// user hashed password shouldn't ever be returned
|
||||||
for (let user of all) {
|
for (let user of all) {
|
||||||
|
@ -292,11 +307,13 @@ export const fetch = async (ctx: any) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// called internally by app server user find
|
// called internally by app server user find
|
||||||
export const find = async (ctx: any) => {
|
export const find = async (ctx: UserCtx<void, FindUserResponse>) => {
|
||||||
ctx.body = await userSdk.db.getUser(ctx.params.id)
|
ctx.body = await userSdk.db.getUser(ctx.params.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const tenantUserLookup = async (ctx: any) => {
|
export const tenantUserLookup = async (
|
||||||
|
ctx: UserCtx<void, LookupTenantUserResponse>
|
||||||
|
) => {
|
||||||
const id = ctx.params.id
|
const id = ctx.params.id
|
||||||
// is email, check its valid
|
// is email, check its valid
|
||||||
if (id.includes("@") && !emailValidator.validate(id)) {
|
if (id.includes("@") && !emailValidator.validate(id)) {
|
||||||
|
@ -314,7 +331,9 @@ export const tenantUserLookup = async (ctx: any) => {
|
||||||
* This will be paginated to a default of the first 50 users,
|
* This will be paginated to a default of the first 50 users,
|
||||||
* So the account holder may not be found until further pagination has occurred
|
* So the account holder may not be found until further pagination has occurred
|
||||||
*/
|
*/
|
||||||
export const accountHolderLookup = async (ctx: Ctx) => {
|
export const accountHolderLookup = async (
|
||||||
|
ctx: Ctx<void, LookupAccountHolderResponse>
|
||||||
|
) => {
|
||||||
try {
|
try {
|
||||||
const users = await userSdk.core.getAllUsers()
|
const users = await userSdk.core.getAllUsers()
|
||||||
const response = await userSdk.core.getExistingAccounts(
|
const response = await userSdk.core.getExistingAccounts(
|
||||||
|
@ -366,7 +385,9 @@ export const onboardUsers = async (
|
||||||
ctx.body = { ...resp, created: true }
|
ctx.body = { ...resp, created: true }
|
||||||
}
|
}
|
||||||
|
|
||||||
export const invite = async (ctx: Ctx<InviteUserRequest>) => {
|
export const invite = async (
|
||||||
|
ctx: Ctx<InviteUserRequest, InviteUserResponse>
|
||||||
|
) => {
|
||||||
const request = ctx.request.body
|
const request = ctx.request.body
|
||||||
|
|
||||||
let multiRequest = [request]
|
let multiRequest = [request]
|
||||||
|
@ -389,12 +410,14 @@ export const invite = async (ctx: Ctx<InviteUserRequest>) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const inviteMultiple = async (ctx: Ctx<InviteUsersRequest>) => {
|
export const inviteMultiple = async (
|
||||||
|
ctx: Ctx<InviteUsersRequest, InviteUsersResponse>
|
||||||
|
) => {
|
||||||
ctx.body = await userSdk.invite(ctx.request.body)
|
ctx.body = await userSdk.invite(ctx.request.body)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const removeMultipleInvites = async (
|
export const removeMultipleInvites = async (
|
||||||
ctx: Ctx<DeleteInviteUsersRequest>
|
ctx: Ctx<DeleteInviteUsersRequest, DeleteInviteUsersResponse>
|
||||||
) => {
|
) => {
|
||||||
const inviteCodesToRemove = ctx.request.body.map(
|
const inviteCodesToRemove = ctx.request.body.map(
|
||||||
(invite: DeleteInviteUserRequest) => invite.code
|
(invite: DeleteInviteUserRequest) => invite.code
|
||||||
|
@ -407,7 +430,7 @@ export const removeMultipleInvites = async (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const checkInvite = async (ctx: any) => {
|
export const checkInvite = async (ctx: UserCtx<void, CheckInviteResponse>) => {
|
||||||
const { code } = ctx.params
|
const { code } = ctx.params
|
||||||
let invite
|
let invite
|
||||||
try {
|
try {
|
||||||
|
@ -422,7 +445,9 @@ export const checkInvite = async (ctx: any) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getUserInvites = async (ctx: any) => {
|
export const getUserInvites = async (
|
||||||
|
ctx: UserCtx<void, GetUserInvitesResponse>
|
||||||
|
) => {
|
||||||
try {
|
try {
|
||||||
// Restricted to the currently authenticated tenant
|
// Restricted to the currently authenticated tenant
|
||||||
ctx.body = await cache.invite.getInviteCodes()
|
ctx.body = await cache.invite.getInviteCodes()
|
||||||
|
@ -431,7 +456,9 @@ export const getUserInvites = async (ctx: any) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const updateInvite = async (ctx: any) => {
|
export const updateInvite = async (
|
||||||
|
ctx: UserCtx<UpdateInviteRequest, UpdateInviteResponse>
|
||||||
|
) => {
|
||||||
const { code } = ctx.params
|
const { code } = ctx.params
|
||||||
let updateBody = { ...ctx.request.body }
|
let updateBody = { ...ctx.request.body }
|
||||||
|
|
||||||
|
|
|
@ -1,53 +0,0 @@
|
||||||
import { tenancy, db as dbCore } from "@budibase/backend-core"
|
|
||||||
import { BBContext } from "@budibase/types"
|
|
||||||
|
|
||||||
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 = dbCore.generateWorkspaceID()
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await db.put(workspaceDoc)
|
|
||||||
ctx.body = {
|
|
||||||
_id: response.id,
|
|
||||||
_rev: response.rev,
|
|
||||||
}
|
|
||||||
} catch (err: any) {
|
|
||||||
ctx.throw(err.status, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function fetch(ctx: BBContext) {
|
|
||||||
const db = tenancy.getGlobalDB()
|
|
||||||
const response = await db.allDocs(
|
|
||||||
dbCore.getWorkspaceParams(undefined, {
|
|
||||||
include_docs: true,
|
|
||||||
})
|
|
||||||
)
|
|
||||||
ctx.body = response.rows.map(row => row.doc)
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function find(ctx: BBContext) {
|
|
||||||
const db = tenancy.getGlobalDB()
|
|
||||||
try {
|
|
||||||
ctx.body = await db.get(ctx.params.id)
|
|
||||||
} catch (err: any) {
|
|
||||||
ctx.throw(err.status, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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: any) {
|
|
||||||
ctx.throw(err.status, err)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +1,15 @@
|
||||||
import { Account, AccountMetadata, Ctx } from "@budibase/types"
|
import {
|
||||||
|
Account,
|
||||||
|
AccountMetadata,
|
||||||
|
Ctx,
|
||||||
|
SaveAccountRequest,
|
||||||
|
SaveAccountResponse,
|
||||||
|
} from "@budibase/types"
|
||||||
import * as accounts from "../../../sdk/accounts"
|
import * as accounts from "../../../sdk/accounts"
|
||||||
|
|
||||||
export const save = async (ctx: Ctx<Account, AccountMetadata>) => {
|
export const save = async (
|
||||||
|
ctx: Ctx<SaveAccountRequest, SaveAccountResponse>
|
||||||
|
) => {
|
||||||
const account = ctx.request.body as Account
|
const account = ctx.request.body as Account
|
||||||
let metadata: AccountMetadata = {
|
let metadata: AccountMetadata = {
|
||||||
_id: accounts.metadata.formatAccountMetadataId(account.accountId),
|
_id: accounts.metadata.formatAccountMetadataId(account.accountId),
|
||||||
|
@ -14,7 +22,7 @@ export const save = async (ctx: Ctx<Account, AccountMetadata>) => {
|
||||||
ctx.status = 200
|
ctx.status = 200
|
||||||
}
|
}
|
||||||
|
|
||||||
export const destroy = async (ctx: any) => {
|
export const destroy = async (ctx: Ctx<void, void>) => {
|
||||||
const accountId = accounts.metadata.formatAccountMetadataId(
|
const accountId = accounts.metadata.formatAccountMetadataId(
|
||||||
ctx.params.accountId
|
ctx.params.accountId
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Ctx, MaintenanceType } from "@budibase/types"
|
import { Ctx, GetEnvironmentResponse, MaintenanceType } from "@budibase/types"
|
||||||
import env from "../../../environment"
|
import env from "../../../environment"
|
||||||
import { env as coreEnv, db as dbCore } from "@budibase/backend-core"
|
import { env as coreEnv, db as dbCore } from "@budibase/backend-core"
|
||||||
import nodeFetch from "node-fetch"
|
import nodeFetch from "node-fetch"
|
||||||
|
@ -38,13 +38,13 @@ async function isSqsMissing() {
|
||||||
return !(await isSqsAvailable())
|
return !(await isSqsAvailable())
|
||||||
}
|
}
|
||||||
|
|
||||||
export const fetch = async (ctx: Ctx) => {
|
export const fetch = async (ctx: Ctx<void, GetEnvironmentResponse>) => {
|
||||||
ctx.body = {
|
ctx.body = {
|
||||||
multiTenancy: !!env.MULTI_TENANCY,
|
multiTenancy: !!env.MULTI_TENANCY,
|
||||||
offlineMode: !!coreEnv.OFFLINE_MODE,
|
offlineMode: !!coreEnv.OFFLINE_MODE,
|
||||||
cloud: !env.SELF_HOSTED,
|
cloud: !env.SELF_HOSTED,
|
||||||
accountPortalUrl: env.ACCOUNT_PORTAL_URL,
|
accountPortalUrl: env.ACCOUNT_PORTAL_URL,
|
||||||
disableAccountPortal: env.DISABLE_ACCOUNT_PORTAL,
|
disableAccountPortal: !!env.DISABLE_ACCOUNT_PORTAL,
|
||||||
baseUrl: env.PLATFORM_URL,
|
baseUrl: env.PLATFORM_URL,
|
||||||
isDev: env.isDev() && !env.isTest(),
|
isDev: env.isDev() && !env.isTest(),
|
||||||
maintenance: [],
|
maintenance: [],
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { UserCtx } from "@budibase/types"
|
import { GetLogResponse, UserCtx } from "@budibase/types"
|
||||||
import { installation, logging } from "@budibase/backend-core"
|
import { installation, logging } from "@budibase/backend-core"
|
||||||
|
|
||||||
export async function getLogs(ctx: UserCtx) {
|
export async function getLogs(ctx: UserCtx<void, GetLogResponse>) {
|
||||||
const logReadStream = logging.system.getLogReadStream()
|
const logReadStream = logging.system.getLogReadStream()
|
||||||
|
|
||||||
const { installId } = await installation.getInstall()
|
const { installId } = await installation.getInstall()
|
||||||
|
|
|
@ -1,13 +1,23 @@
|
||||||
|
import {
|
||||||
|
FetchMigrationDefinitionsResponse,
|
||||||
|
RunGlobalMigrationRequest,
|
||||||
|
UserCtx,
|
||||||
|
} from "@budibase/types"
|
||||||
|
|
||||||
const { migrate, MIGRATIONS } = require("../../../migrations")
|
const { migrate, MIGRATIONS } = require("../../../migrations")
|
||||||
|
|
||||||
export const runMigrations = async (ctx: any) => {
|
export const runMigrations = async (
|
||||||
|
ctx: UserCtx<RunGlobalMigrationRequest, void>
|
||||||
|
) => {
|
||||||
const options = ctx.request.body
|
const options = ctx.request.body
|
||||||
// don't await as can take a while, just return
|
// don't await as can take a while, just return
|
||||||
migrate(options)
|
migrate(options)
|
||||||
ctx.status = 200
|
ctx.status = 200
|
||||||
}
|
}
|
||||||
|
|
||||||
export const fetchDefinitions = async (ctx: any) => {
|
export const fetchDefinitions = async (
|
||||||
|
ctx: UserCtx<void, FetchMigrationDefinitionsResponse>
|
||||||
|
) => {
|
||||||
ctx.body = MIGRATIONS
|
ctx.body = MIGRATIONS
|
||||||
ctx.status = 200
|
ctx.status = 200
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
import env from "../../../environment"
|
import env from "../../../environment"
|
||||||
import { BBContext } from "@budibase/types"
|
import { SystemRestoreResponse, UserCtx } from "@budibase/types"
|
||||||
import { cache } from "@budibase/backend-core"
|
import { cache } from "@budibase/backend-core"
|
||||||
|
|
||||||
export async function systemRestored(ctx: BBContext) {
|
export async function systemRestored(
|
||||||
|
ctx: UserCtx<void, SystemRestoreResponse>
|
||||||
|
) {
|
||||||
if (!env.SELF_HOSTED) {
|
if (!env.SELF_HOSTED) {
|
||||||
ctx.throw(405, "This operation is not allowed in cloud.")
|
ctx.throw(405, "This operation is not allowed in cloud.")
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { UserCtx } from "@budibase/types"
|
import { GetTenantInfoResponse, UserCtx } from "@budibase/types"
|
||||||
import * as tenantSdk from "../../../sdk/tenants"
|
import * as tenantSdk from "../../../sdk/tenants"
|
||||||
|
|
||||||
export async function destroy(ctx: UserCtx) {
|
export async function destroy(ctx: UserCtx<void, void>) {
|
||||||
const user = ctx.user!
|
const user = ctx.user!
|
||||||
const tenantId = ctx.params.tenantId
|
const tenantId = ctx.params.tenantId
|
||||||
|
|
||||||
|
@ -18,6 +18,6 @@ export async function destroy(ctx: UserCtx) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function info(ctx: UserCtx) {
|
export async function info(ctx: UserCtx<void, GetTenantInfoResponse>) {
|
||||||
ctx.body = await tenantSdk.tenantInfo(ctx.params.tenantId)
|
ctx.body = await tenantSdk.tenantInfo(ctx.params.tenantId)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import Router from "@koa/router"
|
import Router from "@koa/router"
|
||||||
import * as controller from "../../controllers/global/email"
|
import * as controller from "../../controllers/global/email"
|
||||||
import { EmailTemplatePurpose } from "../../../constants"
|
|
||||||
import { auth } from "@budibase/backend-core"
|
import { auth } from "@budibase/backend-core"
|
||||||
|
import { EmailTemplatePurpose } from "@budibase/types"
|
||||||
import Joi from "joi"
|
import Joi from "joi"
|
||||||
|
|
||||||
const router: Router = new Router()
|
const router: Router = new Router()
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
jest.mock("nodemailer")
|
jest.mock("nodemailer")
|
||||||
|
import { EmailTemplatePurpose } from "@budibase/types"
|
||||||
import { TestConfiguration, mocks } from "../../../../tests"
|
import { TestConfiguration, mocks } from "../../../../tests"
|
||||||
|
|
||||||
const sendMailMock = mocks.email.mock()
|
const sendMailMock = mocks.email.mock()
|
||||||
import { EmailTemplatePurpose } from "../../../../constants"
|
|
||||||
|
|
||||||
describe("/api/global/email", () => {
|
describe("/api/global/email", () => {
|
||||||
const config = new TestConfiguration()
|
const config = new TestConfiguration()
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
jest.unmock("node-fetch")
|
jest.unmock("node-fetch")
|
||||||
import { TestConfiguration } from "../../../../tests"
|
import { TestConfiguration } from "../../../../tests"
|
||||||
import { EmailTemplatePurpose } from "../../../../constants"
|
|
||||||
import { objectStore } from "@budibase/backend-core"
|
import { objectStore } from "@budibase/backend-core"
|
||||||
import { helpers } from "@budibase/shared-core"
|
import { helpers } from "@budibase/shared-core"
|
||||||
|
|
||||||
import tk from "timekeeper"
|
import tk from "timekeeper"
|
||||||
import { EmailAttachment } from "@budibase/types"
|
import { EmailAttachment, EmailTemplatePurpose } from "@budibase/types"
|
||||||
|
|
||||||
const fetch = require("node-fetch")
|
const fetch = require("node-fetch")
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
import {
|
import { TemplateMetadata, TemplateType } from "../../../../constants"
|
||||||
EmailTemplatePurpose,
|
|
||||||
TemplateMetadata,
|
|
||||||
TemplateType,
|
|
||||||
} from "../../../../constants"
|
|
||||||
import { TestConfiguration } from "../../../../tests"
|
import { TestConfiguration } from "../../../../tests"
|
||||||
|
import { EmailTemplatePurpose } from "@budibase/types"
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
|
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
import Router from "@koa/router"
|
|
||||||
import * as controller from "../../controllers/global/workspaces"
|
|
||||||
import { auth } from "@budibase/backend-core"
|
|
||||||
import Joi from "joi"
|
|
||||||
|
|
||||||
const router: Router = new Router()
|
|
||||||
|
|
||||||
function buildWorkspaceSaveValidation() {
|
|
||||||
// prettier-ignore
|
|
||||||
return auth.joiValidator.body(Joi.object({
|
|
||||||
_id: Joi.string().optional(),
|
|
||||||
_rev: Joi.string().optional(),
|
|
||||||
name: Joi.string().required(),
|
|
||||||
users: Joi.array().required(),
|
|
||||||
managers: Joi.array().required(),
|
|
||||||
roles: Joi.object({
|
|
||||||
default: Joi.string().optional(),
|
|
||||||
app: Joi.object()
|
|
||||||
.pattern(/.*/, Joi.string())
|
|
||||||
.required()
|
|
||||||
.unknown(true),
|
|
||||||
}).unknown(true).optional(),
|
|
||||||
}).required().unknown(true))
|
|
||||||
}
|
|
||||||
|
|
||||||
router
|
|
||||||
.post(
|
|
||||||
"/api/global/workspaces",
|
|
||||||
auth.adminOnly,
|
|
||||||
buildWorkspaceSaveValidation(),
|
|
||||||
controller.save
|
|
||||||
)
|
|
||||||
.delete("/api/global/workspaces/:id", auth.adminOnly, controller.destroy)
|
|
||||||
.get("/api/global/workspaces", controller.fetch)
|
|
||||||
.get("/api/global/workspaces/:id", controller.find)
|
|
||||||
|
|
||||||
export default router
|
|
|
@ -2,7 +2,6 @@ import Router from "@koa/router"
|
||||||
import { api as pro } from "@budibase/pro"
|
import { api as pro } from "@budibase/pro"
|
||||||
import userRoutes from "./global/users"
|
import userRoutes from "./global/users"
|
||||||
import configRoutes from "./global/configs"
|
import configRoutes from "./global/configs"
|
||||||
import workspaceRoutes from "./global/workspaces"
|
|
||||||
import templateRoutes from "./global/templates"
|
import templateRoutes from "./global/templates"
|
||||||
import emailRoutes from "./global/email"
|
import emailRoutes from "./global/email"
|
||||||
import authRoutes from "./global/auth"
|
import authRoutes from "./global/auth"
|
||||||
|
@ -24,7 +23,6 @@ export const routes: Router[] = [
|
||||||
configRoutes,
|
configRoutes,
|
||||||
userRoutes,
|
userRoutes,
|
||||||
pro.users,
|
pro.users,
|
||||||
workspaceRoutes,
|
|
||||||
authRoutes,
|
authRoutes,
|
||||||
templateRoutes,
|
templateRoutes,
|
||||||
tenantsRoutes,
|
tenantsRoutes,
|
||||||
|
|
|
@ -22,7 +22,7 @@ describe("/api/system/environment", () => {
|
||||||
const env = await config.api.environment.getEnvironment()
|
const env = await config.api.environment.getEnvironment()
|
||||||
expect(env.body).toEqual({
|
expect(env.body).toEqual({
|
||||||
cloud: true,
|
cloud: true,
|
||||||
disableAccountPortal: 0,
|
disableAccountPortal: false,
|
||||||
isDev: false,
|
isDev: false,
|
||||||
multiTenancy: true,
|
multiTenancy: true,
|
||||||
baseUrl: "http://localhost:10000",
|
baseUrl: "http://localhost:10000",
|
||||||
|
@ -36,7 +36,7 @@ describe("/api/system/environment", () => {
|
||||||
const env = await config.api.environment.getEnvironment()
|
const env = await config.api.environment.getEnvironment()
|
||||||
expect(env.body).toEqual({
|
expect(env.body).toEqual({
|
||||||
cloud: false,
|
cloud: false,
|
||||||
disableAccountPortal: 0,
|
disableAccountPortal: false,
|
||||||
isDev: false,
|
isDev: false,
|
||||||
multiTenancy: true,
|
multiTenancy: true,
|
||||||
baseUrl: "http://localhost:10000",
|
baseUrl: "http://localhost:10000",
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { constants } from "@budibase/backend-core"
|
import { constants } from "@budibase/backend-core"
|
||||||
|
import { EmailTemplatePurpose } from "@budibase/types"
|
||||||
|
|
||||||
export const LOGO_URL =
|
export const LOGO_URL =
|
||||||
"https://d33wubrfki0l68.cloudfront.net/aac32159d7207b5085e74a7ef67afbb7027786c5/2b1fd/img/logo/bb-emblem.svg"
|
"https://d33wubrfki0l68.cloudfront.net/aac32159d7207b5085e74a7ef67afbb7027786c5/2b1fd/img/logo/bb-emblem.svg"
|
||||||
|
@ -19,15 +20,6 @@ export enum TemplateType {
|
||||||
EMAIL = "email",
|
EMAIL = "email",
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum EmailTemplatePurpose {
|
|
||||||
CORE = "core",
|
|
||||||
BASE = "base",
|
|
||||||
PASSWORD_RECOVERY = "password_recovery",
|
|
||||||
INVITATION = "invitation",
|
|
||||||
WELCOME = "welcome",
|
|
||||||
CUSTOM = "custom",
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum TemplateMetadataNames {
|
export enum TemplateMetadataNames {
|
||||||
BASE = "Base format",
|
BASE = "Base format",
|
||||||
PASSWORD_RECOVERY = "Password recovery",
|
PASSWORD_RECOVERY = "Password recovery",
|
||||||
|
|
|
@ -1,13 +1,8 @@
|
||||||
import { readStaticFile } from "../../utilities/fileSystem"
|
import { readStaticFile } from "../../utilities/fileSystem"
|
||||||
import {
|
import { TemplateType, TemplatePurpose, GLOBAL_OWNER } from "../index"
|
||||||
EmailTemplatePurpose,
|
|
||||||
TemplateType,
|
|
||||||
TemplatePurpose,
|
|
||||||
GLOBAL_OWNER,
|
|
||||||
} from "../index"
|
|
||||||
import { join } from "path"
|
import { join } from "path"
|
||||||
import { db as dbCore, tenancy } from "@budibase/backend-core"
|
import { db as dbCore, tenancy } from "@budibase/backend-core"
|
||||||
import { Template } from "@budibase/types"
|
import { Template, EmailTemplatePurpose } from "@budibase/types"
|
||||||
|
|
||||||
export const EmailTemplates = {
|
export const EmailTemplates = {
|
||||||
[EmailTemplatePurpose.PASSWORD_RECOVERY]: readStaticFile(
|
[EmailTemplatePurpose.PASSWORD_RECOVERY]: readStaticFile(
|
||||||
|
@ -53,8 +48,21 @@ export function addBaseTemplates(templates: Template[], type?: string) {
|
||||||
export async function getTemplates({
|
export async function getTemplates({
|
||||||
ownerId,
|
ownerId,
|
||||||
type,
|
type,
|
||||||
id,
|
}: { ownerId?: string; type?: string } = {}) {
|
||||||
}: { ownerId?: string; type?: string; id?: string } = {}) {
|
const db = tenancy.getGlobalDB()
|
||||||
|
const response = await db.allDocs<Template>(
|
||||||
|
dbCore.getTemplateParams(ownerId || GLOBAL_OWNER, undefined, {
|
||||||
|
include_docs: true,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
let templates = response.rows.map(row => row.doc!)
|
||||||
|
if (type) {
|
||||||
|
templates = templates.filter(template => template.type === type)
|
||||||
|
}
|
||||||
|
return addBaseTemplates(templates, type)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getTemplateByID(id: string, ownerId?: string) {
|
||||||
const db = tenancy.getGlobalDB()
|
const db = tenancy.getGlobalDB()
|
||||||
const response = await db.allDocs<Template>(
|
const response = await db.allDocs<Template>(
|
||||||
dbCore.getTemplateParams(ownerId || GLOBAL_OWNER, id, {
|
dbCore.getTemplateParams(ownerId || GLOBAL_OWNER, id, {
|
||||||
|
@ -63,16 +71,10 @@ export async function getTemplates({
|
||||||
)
|
)
|
||||||
let templates = response.rows.map(row => row.doc!)
|
let templates = response.rows.map(row => row.doc!)
|
||||||
// should only be one template with ID
|
// should only be one template with ID
|
||||||
if (id) {
|
|
||||||
return templates[0]
|
return templates[0]
|
||||||
}
|
}
|
||||||
if (type) {
|
|
||||||
templates = templates.filter(template => template.type === type)
|
|
||||||
}
|
|
||||||
return addBaseTemplates(templates, type)
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getTemplateByPurpose(type: string, purpose: string) {
|
export async function getTemplateByPurpose(type: string, purpose: string) {
|
||||||
const templates = (await getTemplates({ type })) as Template[]
|
const templates = await getTemplates({ type })
|
||||||
return templates.find((template: Template) => template.purpose === purpose)
|
return templates.find((template: Template) => template.purpose === purpose)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import env from "../environment"
|
import env from "../environment"
|
||||||
import { constants, utils } from "@budibase/backend-core"
|
import { constants, utils } from "@budibase/backend-core"
|
||||||
import { BBContext } from "@budibase/types"
|
import { UserCtx } from "@budibase/types"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a restricted endpoint in the cloud.
|
* This is a restricted endpoint in the cloud.
|
||||||
* Ensure that the correct API key has been supplied.
|
* Ensure that the correct API key has been supplied.
|
||||||
*/
|
*/
|
||||||
export default async (ctx: BBContext, next: any) => {
|
export default async (ctx: UserCtx, next: any) => {
|
||||||
if (!env.SELF_HOSTED && !env.DISABLE_ACCOUNT_PORTAL) {
|
if (!env.SELF_HOSTED && !env.DISABLE_ACCOUNT_PORTAL) {
|
||||||
const apiKey = ctx.request.headers[constants.Header.API_KEY]
|
const apiKey = ctx.request.headers[constants.Header.API_KEY]
|
||||||
if (!apiKey) {
|
if (!apiKey) {
|
||||||
|
|
|
@ -8,11 +8,10 @@ import {
|
||||||
utils as coreUtils,
|
utils as coreUtils,
|
||||||
cache,
|
cache,
|
||||||
} from "@budibase/backend-core"
|
} from "@budibase/backend-core"
|
||||||
import { PlatformLogoutOpts, User } from "@budibase/types"
|
import { PlatformLogoutOpts, User, EmailTemplatePurpose } from "@budibase/types"
|
||||||
import jwt from "jsonwebtoken"
|
import jwt from "jsonwebtoken"
|
||||||
import * as userSdk from "../users"
|
import * as userSdk from "../users"
|
||||||
import * as emails from "../../utilities/email"
|
import * as emails from "../../utilities/email"
|
||||||
import { EmailTemplatePurpose } from "../../constants"
|
|
||||||
|
|
||||||
// LOGIN / LOGOUT
|
// LOGIN / LOGOUT
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,9 @@ import {
|
||||||
InviteUserRequest,
|
InviteUserRequest,
|
||||||
InviteUsersRequest,
|
InviteUsersRequest,
|
||||||
InviteUsersResponse,
|
InviteUsersResponse,
|
||||||
|
EmailTemplatePurpose,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import { sendEmail } from "../../utilities/email"
|
import { sendEmail } from "../../utilities/email"
|
||||||
import { EmailTemplatePurpose } from "../../constants"
|
|
||||||
|
|
||||||
export async function invite(
|
export async function invite(
|
||||||
users: InviteUsersRequest
|
users: InviteUsersRequest
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
export * as email from "../api/controllers/global/email"
|
export * as email from "../api/controllers/global/email"
|
||||||
export * as workspaces from "../api/controllers/global/workspaces"
|
|
||||||
export * as config from "../api/controllers/global/configs"
|
export * as config from "../api/controllers/global/configs"
|
||||||
export * as templates from "../api/controllers/global/templates"
|
export * as templates from "../api/controllers/global/templates"
|
||||||
export * as users from "../api/controllers/global/users"
|
export * as users from "../api/controllers/global/users"
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
import env from "../environment"
|
import env from "../environment"
|
||||||
import { EmailTemplatePurpose, TemplateType } from "../constants"
|
import { TemplateType } from "../constants"
|
||||||
import { getTemplateByPurpose, EmailTemplates } from "../constants/templates"
|
import { getTemplateByPurpose, EmailTemplates } from "../constants/templates"
|
||||||
import { getSettingsTemplateContext } from "./templates"
|
import { getSettingsTemplateContext } from "./templates"
|
||||||
import { processString } from "@budibase/string-templates"
|
import { processString } from "@budibase/string-templates"
|
||||||
import { User, SendEmailOpts, SMTPInnerConfig } from "@budibase/types"
|
import {
|
||||||
|
User,
|
||||||
|
SendEmailOpts,
|
||||||
|
SMTPInnerConfig,
|
||||||
|
EmailTemplatePurpose,
|
||||||
|
} from "@budibase/types"
|
||||||
import { configs, cache, objectStore } from "@budibase/backend-core"
|
import { configs, cache, objectStore } from "@budibase/backend-core"
|
||||||
import ical from "ical-generator"
|
import ical from "ical-generator"
|
||||||
import _ from "lodash"
|
import _ from "lodash"
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
import { tenancy, configs } from "@budibase/backend-core"
|
import { tenancy, configs } from "@budibase/backend-core"
|
||||||
import {
|
import { EmailTemplatePurpose } from "@budibase/types"
|
||||||
InternalTemplateBinding,
|
import { InternalTemplateBinding, LOGO_URL } from "../constants"
|
||||||
LOGO_URL,
|
|
||||||
EmailTemplatePurpose,
|
|
||||||
} from "../constants"
|
|
||||||
import { checkSlashesInUrl } from "./index"
|
import { checkSlashesInUrl } from "./index"
|
||||||
|
|
||||||
const BASE_COMPANY = "Budibase"
|
const BASE_COMPANY = "Budibase"
|
||||||
|
|
Loading…
Reference in New Issue