feat: private hub user accessible url setting (#4617)

* feat: private hub user accessible url setting

* improve UI
This commit is contained in:
HugoCasa
2024-11-01 11:20:31 +01:00
committed by GitHub
parent 3bc687bdfa
commit c803f9cdb2
5 changed files with 95 additions and 25 deletions
+2 -1
View File
@@ -31,7 +31,7 @@ use windmill_common::{
error::{self, JsonResult, Result},
global_settings::{
AUTOMATE_USERNAME_CREATION_SETTING, EMAIL_DOMAIN_SETTING, ENV_SETTINGS,
HUB_BASE_URL_SETTING,
HUB_ACCESSIBLE_URL_SETTING, HUB_BASE_URL_SETTING,
},
server::Smtp,
utils::send_email,
@@ -262,6 +262,7 @@ pub async fn get_global_setting(
&& !key.starts_with("default_success_handler_")
&& key != AUTOMATE_USERNAME_CREATION_SETTING
&& key != HUB_BASE_URL_SETTING
&& key != HUB_ACCESSIBLE_URL_SETTING
&& key != EMAIL_DOMAIN_SETTING
{
require_super_admin(&db, &authed.email).await?;
@@ -27,6 +27,7 @@ pub const OBJECT_STORE_CACHE_CONFIG_SETTING: &str = "object_store_cache_config";
pub const AUTOMATE_USERNAME_CREATION_SETTING: &str = "automate_username_creation";
pub const HUB_BASE_URL_SETTING: &str = "hub_base_url";
pub const HUB_ACCESSIBLE_URL_SETTING: &str = "hub_accessible_url";
pub const CRITICAL_ERROR_CHANNELS_SETTING: &str = "critical_error_channels";
pub const DEV_INSTANCE_SETTING: &str = "dev_instance";
pub const JWT_SECRET_SETTING: &str = "jwt_secret";
@@ -13,7 +13,7 @@
import KeycloakSetting from './KeycloakSetting.svelte'
import Alert from './common/alert/Alert.svelte'
import { isCloudHosted } from '$lib/cloud'
import { capitalize, classNames } from '$lib/utils'
import { capitalize, classNames, sleep } from '$lib/utils'
import { enterpriseLicense } from '$lib/stores'
import CustomOauth from './CustomOauth.svelte'
import {
@@ -111,6 +111,7 @@
}
export async function saveSettings() {
let shouldReloadPage = false
if (values) {
const allSettings = Object.values(settings).flatMap((x) => Object.entries(x))
let licenseKeySet = false
@@ -129,6 +130,9 @@
if (x.key == 'license_key') {
licenseKeySet = true
}
if (x.requiresReloadOnChange) {
shouldReloadPage = true
}
return await SettingService.setGlobal({
key: x.key,
requestBody: { value: values?.[x.key] }
@@ -158,8 +162,14 @@
} else {
console.error('Values not loaded')
}
sendUserToast('Settings updated')
dispatch('saved')
if (shouldReloadPage) {
sendUserToast('Settings updated, reloading page...')
await sleep(1000)
window.location.reload()
} else {
sendUserToast('Settings updated')
dispatch('saved')
}
}
let oauths: Record<string, any> = {}
@@ -548,7 +558,7 @@
<div>
<div class="flex-col flex gap-2 pb-4">
{#each settings[category] as setting}
{#if (!setting.cloudonly || isCloudHosted()) && showSetting(setting.key, values)}
{#if (!setting.cloudonly || isCloudHosted()) && showSetting(setting.key, values) && !(setting.hiddenIfNull && values[setting.key] == null)}
{#if setting.ee_only != undefined && !$enterpriseLicense}
<div class="flex text-xs items-center gap-1 text-yellow-500 whitespace-nowrap">
<AlertTriangle size={16} />
@@ -579,6 +589,20 @@
: ''}
bind:value={values[setting.key]}
/>
{#if setting.advancedToggle}
<div class="mt-1">
<Toggle
size="xs"
options={{ right: setting.advancedToggle.label }}
checked={setting.advancedToggle.checked(values)}
on:change={() => {
if (setting.advancedToggle) {
values = setting.advancedToggle.onChange(values)
}
}}
/>
</div>
{/if}
{:else if setting.fieldType == 'textarea'}
<textarea
rows="2"
+62 -19
View File
@@ -21,18 +21,26 @@ export interface Setting {
| 'slack_connect'
| 'smtp_connect'
storage: SettingStorage
advancedToggle?: {
label: string
onChange: (values: Record<string, any>) => Record<string, any>
checked: (values: Record<string, any>) => boolean
}
hiddenIfNull?: boolean
requiresReloadOnChange?: boolean
isValid?: (value: any) => boolean
error?: string
defaultValue?: () => any
}
export type SettingStorage = 'setting'
export type SettingStorage = 'setting'
export const settings: Record<string, Setting[]> = {
Core: [
{
label: 'Base url',
description: 'Public base url of the instance. <a href="https://www.windmill.dev/docs/advanced/instance_settings#global-users">Learn more</a>',
description:
'Public base url of the instance. <a href="https://www.windmill.dev/docs/advanced/instance_settings#global-users">Learn more</a>',
key: 'base_url',
fieldType: 'text',
placeholder: 'https://windmill.com',
@@ -67,14 +75,16 @@ export const settings: Record<string, Setting[]> = {
{
label: 'Default timeout',
key: 'job_default_timeout',
description: 'Default timeout for individual jobs. <a href="https://www.windmill.dev/docs/core_concepts/jobs#retention-policy">Learn more</a>',
description:
'Default timeout for individual jobs. <a href="https://www.windmill.dev/docs/core_concepts/jobs#retention-policy">Learn more</a>',
fieldType: 'seconds',
storage: 'setting',
cloudonly: false
},
{
label: 'Max timeout for sync endpoints',
description: 'Maximum amount of time (measured in seconds) that a <a href="https://www.windmill.dev/docs/core_concepts/webhooks">sync endpoint</a> is allowed to run before it is forcibly stopped or timed out.',
description:
'Maximum amount of time (measured in seconds) that a <a href="https://www.windmill.dev/docs/core_concepts/webhooks">sync endpoint</a> is allowed to run before it is forcibly stopped or timed out.',
key: 'timeout_wait_result',
cloudonly: true,
fieldType: 'seconds',
@@ -83,7 +93,8 @@ export const settings: Record<string, Setting[]> = {
},
{
label: 'License key',
description: 'License key required to use the EE (switch image for windmill-ee). <a href="https://www.windmill.dev/docs/advanced/instance_settings#license-key">Learn more</a>',
description:
'License key required to use the EE (switch image for windmill-ee). <a href="https://www.windmill.dev/docs/advanced/instance_settings#license-key">Learn more</a>',
key: 'license_key',
fieldType: 'license_key',
placeholder: 'only needed to prepare upgrade to EE',
@@ -91,7 +102,8 @@ export const settings: Record<string, Setting[]> = {
},
{
label: 'Non-prod instance',
description: 'Whether we should consider the reported usage of this instance as non-prod. <a href="https://www.windmill.dev/docs/advanced/instance_settings#non-prod-instance">Learn more</a>',
description:
'Whether we should consider the reported usage of this instance as non-prod. <a href="https://www.windmill.dev/docs/advanced/instance_settings#non-prod-instance">Learn more</a>',
key: 'dev_instance',
fieldType: 'boolean',
storage: 'setting'
@@ -99,7 +111,8 @@ export const settings: Record<string, Setting[]> = {
{
label: 'Retention period in secs',
key: 'retention_period_secs',
description: 'How long to keep the jobs data in the database (max 30 days on CE). <a href="https://www.windmill.dev/docs/advanced/instance_settings#retention-period-in-secs">Learn more</a>',
description:
'How long to keep the jobs data in the database (max 30 days on CE). <a href="https://www.windmill.dev/docs/advanced/instance_settings#retention-period-in-secs">Learn more</a>',
fieldType: 'seconds',
placeholder: '30',
storage: 'setting',
@@ -108,7 +121,8 @@ export const settings: Record<string, Setting[]> = {
},
{
label: 'Expose metrics',
description: 'Expose Prometheus metrics for workers and servers on port 8001 at /metrics. <a href="https://www.windmill.dev/docs/advanced/instance_settings#expose-metrics">Learn more</a>',
description:
'Expose Prometheus metrics for workers and servers on port 8001 at /metrics. <a href="https://www.windmill.dev/docs/advanced/instance_settings#expose-metrics">Learn more</a>',
key: 'expose_metrics',
fieldType: 'boolean',
storage: 'setting',
@@ -116,7 +130,8 @@ export const settings: Record<string, Setting[]> = {
},
{
label: 'Instance object storage',
description: ' S3/Azure bucket to store large logs and global cache for Python and Go. <a href="https://www.windmill.dev/docs/core_concepts/object_storage_in_windmill#instance-object-storage">Learn more</a>',
description:
' S3/Azure bucket to store large logs and global cache for Python and Go. <a href="https://www.windmill.dev/docs/core_concepts/object_storage_in_windmill#instance-object-storage">Learn more</a>',
key: 'object_store_cache_config',
fieldType: 'object_store_config',
storage: 'setting',
@@ -124,7 +139,8 @@ export const settings: Record<string, Setting[]> = {
},
{
label: 'Critical alert channels',
description: 'Channels to send critical alerts to. SMTP must be configured for the email channel. A Slack workspace must be connected to the instance for the Slack channel. <a href="https://www.windmill.dev/docs/core_concepts/critical_alert_channels">Learn more</a>',
description:
'Channels to send critical alerts to. SMTP must be configured for the email channel. A Slack workspace must be connected to the instance for the Slack channel. <a href="https://www.windmill.dev/docs/core_concepts/critical_alert_channels">Learn more</a>',
key: 'critical_error_channels',
fieldType: 'critical_error_channels',
storage: 'setting',
@@ -132,7 +148,8 @@ export const settings: Record<string, Setting[]> = {
},
{
label: 'Azure OpenAI base path',
description: 'All Windmill AI features will run on the specified deployed model. Format: https://{your-resource-name}.openai.azure.com/openai/deployments/{deployment-id}. <a href="https://www.windmill.dev/docs/core_concepts/ai_generation#azure-openai-advanced-models">Learn more</a>',
description:
'All Windmill AI features will run on the specified deployed model. Format: https://{your-resource-name}.openai.azure.com/openai/deployments/{deployment-id}. <a href="https://www.windmill.dev/docs/core_concepts/ai_generation#azure-openai-advanced-models">Learn more</a>',
key: 'openai_azure_base_path',
fieldType: 'text',
storage: 'setting',
@@ -140,12 +157,38 @@ export const settings: Record<string, Setting[]> = {
},
{
label: 'Private Hub base url',
description: 'Base url of your private Hub instance, without trailing slash. <a href="https://www.windmill.dev/docs/core_concepts/private_hub">Learn more</a>',
description:
'Base URL of your private Hub instance, without trailing slash. <a href="https://www.windmill.dev/docs/core_concepts/private_hub">Learn more</a>',
placeholder: 'https://hub.company.com',
key: 'hub_base_url',
fieldType: 'text',
storage: 'setting',
ee_only: ''
ee_only: '',
advancedToggle: {
label: 'I have a different URL for Hub access from end-user browsers',
onChange(values) {
if (values['hub_accessible_url']) {
values['hub_accessible_url'] = null
} else {
values['hub_accessible_url'] = values['hub_base_url'] || 'https://hub.company.com'
}
return values
},
checked: (values) => values['hub_accessible_url'] != null
},
requiresReloadOnChange: true
},
{
label: 'Private Hub accessible url',
description:
'Base URL accessible from end-user browsers, without trailing slash. <a href="https://www.windmill.dev/docs/core_concepts/private_hub">Learn more</a>',
key: 'hub_accessible_url',
fieldType: 'text',
hiddenIfNull: true,
storage: 'setting',
ee_only: '',
requiresReloadOnChange: true
}
],
'SSO/OAuth': [],
@@ -189,12 +232,12 @@ export const settings: Record<string, Setting[]> = {
}
],
SMTP: [
{
label: 'SMTP',
key: 'smtp_settings',
fieldType: 'smtp_connect',
storage: 'setting',
ee_only: '',
{
label: 'SMTP',
key: 'smtp_settings',
fieldType: 'smtp_connect',
storage: 'setting',
ee_only: ''
}
],
Slack: [
@@ -139,7 +139,8 @@
async function loadHubBaseUrl() {
$hubBaseUrlStore =
((await SettingService.getGlobal({ key: 'hub_base_url' })) as string) ??
((await SettingService.getGlobal({ key: 'hub_accessible_url' })) as string) ||
((await SettingService.getGlobal({ key: 'hub_base_url' })) as string) ||
'https://hub.windmill.dev'
}