diff --git a/orchestrator/src/client/pages/SettingsPage.tsx b/orchestrator/src/client/pages/SettingsPage.tsx index c1daf9d..1df8f43 100644 --- a/orchestrator/src/client/pages/SettingsPage.tsx +++ b/orchestrator/src/client/pages/SettingsPage.tsx @@ -237,7 +237,7 @@ export const SettingsPage: React.FC = () => { defaultValues: DEFAULT_FORM_VALUES, }) - const { handleSubmit, reset, watch, formState: { isDirty, errors, isValid, dirtyFields } } = methods + const { handleSubmit, reset, setError, watch, formState: { isDirty, errors, isValid, dirtyFields } } = methods useEffect(() => { let isMounted = true @@ -286,6 +286,16 @@ export const SettingsPage: React.FC = () => { const onSave = async (data: UpdateSettingsInput) => { if (!settings) return + if (data.enableBasicAuth && !settings.basicAuthActive) { + const password = data.basicAuthPassword?.trim() ?? "" + if (!password) { + setError("basicAuthPassword", { + type: "manual", + message: "Password is required when basic auth is enabled", + }) + return + } + } try { setIsSaving(true) diff --git a/orchestrator/src/client/pages/settings/components/EnvironmentSettingsSection.tsx b/orchestrator/src/client/pages/settings/components/EnvironmentSettingsSection.tsx index f4bee27..d0e97cf 100644 --- a/orchestrator/src/client/pages/settings/components/EnvironmentSettingsSection.tsx +++ b/orchestrator/src/client/pages/settings/components/EnvironmentSettingsSection.tsx @@ -6,6 +6,7 @@ import { Checkbox } from "@/components/ui/checkbox" import { Separator } from "@/components/ui/separator" import { UpdateSettingsInput } from "@shared/settings-schema" import type { EnvSettingsValues } from "@client/pages/settings/types" +import { formatSecretHint } from "@client/pages/settings/utils" import { SettingsInput } from "@client/pages/settings/components/SettingsInput" type EnvironmentSettingsSectionProps = { @@ -14,8 +15,6 @@ type EnvironmentSettingsSectionProps = { isSaving: boolean } -const formatSecretHint = (hint: string | null) => (hint ? `${hint}********` : "Not set") - export const EnvironmentSettingsSection: React.FC = ({ values, isLoading, diff --git a/orchestrator/src/client/pages/settings/components/WebhooksSection.tsx b/orchestrator/src/client/pages/settings/components/WebhooksSection.tsx index cf23bcd..305488f 100644 --- a/orchestrator/src/client/pages/settings/components/WebhooksSection.tsx +++ b/orchestrator/src/client/pages/settings/components/WebhooksSection.tsx @@ -6,6 +6,7 @@ import { Separator } from "@/components/ui/separator" import { UpdateSettingsInput } from "@shared/settings-schema" import type { WebhookValues } from "@client/pages/settings/types" import { SettingsInput } from "@client/pages/settings/components/SettingsInput" +import { formatSecretHint } from "@client/pages/settings/utils" type WebhooksSectionProps = { pipelineWebhook: WebhookValues @@ -24,8 +25,6 @@ export const WebhooksSection: React.FC = ({ }) => { const { register, formState: { errors } } = useFormContext() - const formatSecretHint = (hint: string | null) => (hint ? `${hint}********` : "Not set") - return ( diff --git a/orchestrator/src/client/pages/settings/utils.ts b/orchestrator/src/client/pages/settings/utils.ts index 181d985..20752ff 100644 --- a/orchestrator/src/client/pages/settings/utils.ts +++ b/orchestrator/src/client/pages/settings/utils.ts @@ -12,3 +12,5 @@ export function resumeProjectsEqual(a: ResumeProjectsSettings, b: ResumeProjects arraysEqual(a.aiSelectableProjectIds, b.aiSelectableProjectIds) ) } + +export const formatSecretHint = (hint: string | null) => (hint ? `${hint}********` : "Not set") diff --git a/orchestrator/src/server/services/envSettings.ts b/orchestrator/src/server/services/envSettings.ts index d94fb78..6137ccb 100644 --- a/orchestrator/src/server/services/envSettings.ts +++ b/orchestrator/src/server/services/envSettings.ts @@ -92,7 +92,13 @@ export async function getEnvSettingsData( for (const { settingKey, envKey, hintKey } of privateStringConfig) { const override = activeOverrides[settingKey] ?? null; const rawValue = override ?? process.env[envKey]; - privateValues[hintKey] = rawValue ? rawValue.slice(0, 4) : null; + if (!rawValue) { + privateValues[hintKey] = null; + continue; + } + + const hintLength = rawValue.length > 4 ? 4 : Math.max(rawValue.length - 1, 1); + privateValues[hintKey] = rawValue.slice(0, hintLength); } const basicAuthUser = activeOverrides['basicAuthUser'] ?? process.env.BASIC_AUTH_USER; diff --git a/orchestrator/src/shared/settings-schema.ts b/orchestrator/src/shared/settings-schema.ts index 7b5d7ee..4339eb7 100644 --- a/orchestrator/src/shared/settings-schema.ts +++ b/orchestrator/src/shared/settings-schema.ts @@ -42,13 +42,6 @@ export const updateSettingsSchema = z.object({ path: ["basicAuthUser"], }); } - if (!data.basicAuthPassword || data.basicAuthPassword.trim() === "") { - ctx.addIssue({ - code: z.ZodIssueCode.custom, - message: "Password is required when basic auth is enabled", - path: ["basicAuthPassword"], - }); - } } });