From 45ecfc1f86cd8996452a0e1e37b2b6ddaa8a12f2 Mon Sep 17 00:00:00 2001 From: DaKheera47 Date: Thu, 22 Jan 2026 16:30:57 +0000 Subject: [PATCH] allow either one or both to be set for basicAuth --- orchestrator/src/client/pages/SettingsPage.tsx | 12 ++++++------ .../src/server/api/routes/settings.test.ts | 15 +++++++++++++++ orchestrator/src/shared/settings-schema.ts | 10 ++++++++++ 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/orchestrator/src/client/pages/SettingsPage.tsx b/orchestrator/src/client/pages/SettingsPage.tsx index 1702ba9..4c21f91 100644 --- a/orchestrator/src/client/pages/SettingsPage.tsx +++ b/orchestrator/src/client/pages/SettingsPage.tsx @@ -296,21 +296,21 @@ export const SettingsPage: React.FC = () => { const envPayload: Partial = {} - if (dirtyFields.rxresumeEmail) { + if (dirtyFields.rxresumeEmail || dirtyFields.rxresumePassword) { envPayload.rxresumeEmail = normalizeString(data.rxresumeEmail) } - if (dirtyFields.ukvisajobsEmail) { + if (dirtyFields.ukvisajobsEmail || dirtyFields.ukvisajobsPassword) { envPayload.ukvisajobsEmail = normalizeString(data.ukvisajobsEmail) } if (data.enableBasicAuth === false) { envPayload.basicAuthUser = null envPayload.basicAuthPassword = null - } else { - if (dirtyFields.basicAuthUser) { - envPayload.basicAuthUser = normalizeString(data.basicAuthUser) - } + } else if (dirtyFields.enableBasicAuth || dirtyFields.basicAuthUser || dirtyFields.basicAuthPassword) { + // If enabling basic auth or changing either field, ensure we send at least the username + // to keep the pair consistent in the backend. + envPayload.basicAuthUser = normalizeString(data.basicAuthUser) if (dirtyFields.basicAuthPassword) { const value = normalizePrivateInput(data.basicAuthPassword) diff --git a/orchestrator/src/server/api/routes/settings.test.ts b/orchestrator/src/server/api/routes/settings.test.ts index 312216a..06fd064 100644 --- a/orchestrator/src/server/api/routes/settings.test.ts +++ b/orchestrator/src/server/api/routes/settings.test.ts @@ -56,4 +56,19 @@ describe.sequential('Settings API routes', () => { expect(patchBody.data.rxresumeEmail).toBe('updated@example.com'); expect(patchBody.data.openrouterApiKeyHint).toBe('upda'); }); + + it('validates basic auth requirements', async () => { + const res = await fetch(`${baseUrl}/api/settings`, { + method: 'PATCH', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + enableBasicAuth: true, + basicAuthUser: '', + }), + }); + expect(res.status).toBe(400); + const body = await res.json(); + expect(body.success).toBe(false); + expect(body.error).toContain('Username is required'); + }); }); diff --git a/orchestrator/src/shared/settings-schema.ts b/orchestrator/src/shared/settings-schema.ts index 862e81d..4339eb7 100644 --- a/orchestrator/src/shared/settings-schema.ts +++ b/orchestrator/src/shared/settings-schema.ts @@ -33,6 +33,16 @@ export const updateSettingsSchema = z.object({ ukvisajobsPassword: z.string().trim().max(2000).nullable().optional(), webhookSecret: z.string().trim().max(2000).nullable().optional(), enableBasicAuth: z.boolean().optional(), +}).superRefine((data, ctx) => { + if (data.enableBasicAuth) { + if (!data.basicAuthUser || data.basicAuthUser.trim() === "") { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: "Username is required when basic auth is enabled", + path: ["basicAuthUser"], + }); + } + } }); export type UpdateSettingsInput = z.infer;