From 0424a290085daba251318ba1da877112219f3b2c Mon Sep 17 00:00:00 2001 From: DaKheera47 Date: Thu, 22 Jan 2026 12:04:20 +0000 Subject: [PATCH] correct keys, and keys separated correctly --- .../src/client/pages/SettingsPage.tsx | 27 +- .../EnvironmentSettingsSection.test.tsx | 22 +- .../components/EnvironmentSettingsSection.tsx | 279 ++++++++---------- .../src/client/pages/settings/types.ts | 2 +- .../src/server/api/routes/settings.test.ts | 5 +- .../src/server/api/routes/settings.ts | 19 -- .../src/server/repositories/settings.ts | 3 - .../src/server/services/envSettings.ts | 10 +- orchestrator/src/shared/settings-schema.ts | 3 - orchestrator/src/shared/types.ts | 4 +- 10 files changed, 148 insertions(+), 226 deletions(-) diff --git a/orchestrator/src/client/pages/SettingsPage.tsx b/orchestrator/src/client/pages/SettingsPage.tsx index 5cee80d..cae31d2 100644 --- a/orchestrator/src/client/pages/SettingsPage.tsx +++ b/orchestrator/src/client/pages/SettingsPage.tsx @@ -49,10 +49,7 @@ const DEFAULT_FORM_VALUES: UpdateSettingsInput = { basicAuthPassword: "", ukvisajobsEmail: "", ukvisajobsPassword: "", - ukvisajobsHeadless: null, webhookSecret: "", - notionApiKey: "", - notionDatabaseId: "", } const NULL_SETTINGS_PAYLOAD: UpdateSettingsInput = { @@ -80,10 +77,7 @@ const NULL_SETTINGS_PAYLOAD: UpdateSettingsInput = { basicAuthPassword: null, ukvisajobsEmail: null, ukvisajobsPassword: null, - ukvisajobsHeadless: null, webhookSecret: null, - notionApiKey: null, - notionDatabaseId: null, } const mapSettingsToForm = (data: AppSettings): UpdateSettingsInput => ({ @@ -111,10 +105,7 @@ const mapSettingsToForm = (data: AppSettings): UpdateSettingsInput => ({ basicAuthPassword: "", ukvisajobsEmail: data.ukvisajobsEmail ?? "", ukvisajobsPassword: "", - ukvisajobsHeadless: data.ukvisajobsHeadless, webhookSecret: "", - notionApiKey: "", - notionDatabaseId: data.notionDatabaseId ?? "", }) const normalizeString = (value: string | null | undefined) => { @@ -214,8 +205,6 @@ const getDerivedSettings = (settings: AppSettings | null) => { rxresumeEmail: settings?.rxresumeEmail ?? "", ukvisajobsEmail: settings?.ukvisajobsEmail ?? "", basicAuthUser: settings?.basicAuthUser ?? "", - notionDatabaseId: settings?.notionDatabaseId ?? "", - ukvisajobsHeadless: settings?.ukvisajobsHeadless ?? true, }, private: { openrouterApiKeyHint: settings?.openrouterApiKeyHint ?? null, @@ -223,10 +212,11 @@ const getDerivedSettings = (settings: AppSettings | null) => { ukvisajobsPasswordHint: settings?.ukvisajobsPasswordHint ?? null, basicAuthPasswordHint: settings?.basicAuthPasswordHint ?? null, webhookSecretHint: settings?.webhookSecretHint ?? null, - notionApiKeyHint: settings?.notionApiKeyHint ?? null, }, + basicAuthActive: settings?.basicAuthActive ?? false, }, defaultResumeProjects: settings?.defaultResumeProjects ?? null, + profileProjects, maxProjectsTotal: profileProjects.length, } @@ -316,14 +306,6 @@ export const SettingsPage: React.FC = () => { envPayload.basicAuthUser = normalizeString(data.basicAuthUser) } - if (dirtyFields.notionDatabaseId) { - envPayload.notionDatabaseId = normalizeString(data.notionDatabaseId) - } - - if (dirtyFields.ukvisajobsHeadless) { - envPayload.ukvisajobsHeadless = data.ukvisajobsHeadless ?? null - } - if (dirtyFields.openrouterApiKey) { const value = normalizePrivateInput(data.openrouterApiKey) if (value !== undefined) envPayload.openrouterApiKey = value @@ -349,11 +331,6 @@ export const SettingsPage: React.FC = () => { if (value !== undefined) envPayload.webhookSecret = value } - if (dirtyFields.notionApiKey) { - const value = normalizePrivateInput(data.notionApiKey) - if (value !== undefined) envPayload.notionApiKey = value - } - const payload: UpdateSettingsInput = { model: normalizeString(data.model), modelScorer: normalizeString(data.modelScorer), diff --git a/orchestrator/src/client/pages/settings/components/EnvironmentSettingsSection.test.tsx b/orchestrator/src/client/pages/settings/components/EnvironmentSettingsSection.test.tsx index db7e703..ef117d6 100644 --- a/orchestrator/src/client/pages/settings/components/EnvironmentSettingsSection.test.tsx +++ b/orchestrator/src/client/pages/settings/components/EnvironmentSettingsSection.test.tsx @@ -11,14 +11,11 @@ const EnvironmentSettingsHarness = () => { rxresumeEmail: "resume@example.com", ukvisajobsEmail: "visa@example.com", basicAuthUser: "admin", - notionDatabaseId: "db-123", - ukvisajobsHeadless: false, openrouterApiKey: "", rxresumePassword: "", ukvisajobsPassword: "", basicAuthPassword: "", webhookSecret: "", - notionApiKey: "", } }) @@ -31,8 +28,6 @@ const EnvironmentSettingsHarness = () => { rxresumeEmail: "resume@example.com", ukvisajobsEmail: "visa@example.com", basicAuthUser: "admin", - notionDatabaseId: "db-123", - ukvisajobsHeadless: false, }, private: { openrouterApiKeyHint: "sk-1", @@ -40,8 +35,8 @@ const EnvironmentSettingsHarness = () => { ukvisajobsPasswordHint: "pass", basicAuthPasswordHint: "abcd", webhookSecretHint: "sec-", - notionApiKeyHint: "not-", }, + basicAuthActive: true, }} isLoading={false} isSaving={false} @@ -52,22 +47,25 @@ const EnvironmentSettingsHarness = () => { } describe("EnvironmentSettingsSection", () => { - it("renders readable values and masks private secrets with hints", () => { + it("renders values grouped logically and masks private secrets with hints", () => { render() expect(screen.getByDisplayValue("resume@example.com")).toBeInTheDocument() expect(screen.getByDisplayValue("visa@example.com")).toBeInTheDocument() - expect(screen.getByDisplayValue("admin")).toBeInTheDocument() - expect(screen.getByDisplayValue("db-123")).toBeInTheDocument() expect(screen.getByText("sk-1********")).toBeInTheDocument() expect(screen.getByText("pass********")).toBeInTheDocument() expect(screen.getByText("abcd********")).toBeInTheDocument() expect(screen.getByText("sec-********")).toBeInTheDocument() - expect(screen.getByText("not-********")).toBeInTheDocument() expect(screen.getByText("Not set")).toBeInTheDocument() - const headlessToggle = screen.getByLabelText("UKVisaJobs headless mode") - expect(headlessToggle).not.toBeChecked() + // Basic Auth + expect(screen.getByLabelText("Enable basic authentication")).toBeChecked() + expect(screen.getByDisplayValue("admin")).toBeInTheDocument() + + // Sections + expect(screen.getByText("External Services")).toBeInTheDocument() + expect(screen.getByText("Service Accounts")).toBeInTheDocument() + expect(screen.getByText("Security")).toBeInTheDocument() }) }) diff --git a/orchestrator/src/client/pages/settings/components/EnvironmentSettingsSection.tsx b/orchestrator/src/client/pages/settings/components/EnvironmentSettingsSection.tsx index fefdd72..683191d 100644 --- a/orchestrator/src/client/pages/settings/components/EnvironmentSettingsSection.tsx +++ b/orchestrator/src/client/pages/settings/components/EnvironmentSettingsSection.tsx @@ -1,4 +1,4 @@ -import React from "react" +import React, { useState, useEffect } from "react" import { useFormContext, Controller } from "react-hook-form" import { AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion" @@ -22,109 +22,27 @@ export const EnvironmentSettingsSection: React.FC { const { register, control, formState: { errors } } = useFormContext() - const { readable, private: privateValues } = values + const { readable, private: privateValues, basicAuthActive } = values + + const [isBasicAuthEnabled, setIsBasicAuthEnabled] = useState(basicAuthActive) + + useEffect(() => { + setIsBasicAuthEnabled(basicAuthActive) + }, [basicAuthActive]) return ( - Environment + Environment & Accounts -
+
+ {/* External Services */}
-
Readable values
+
External Services
-
RxResume email
- - {errors.rxresumeEmail &&

{errors.rxresumeEmail.message}

} -
- Used for RxResume PDF automation. -
-
- -
-
UKVisaJobs email
- - {errors.ukvisajobsEmail &&

{errors.ukvisajobsEmail.message}

} -
- Used for refreshing UKVisaJobs sessions. -
-
- -
-
Basic auth user
- - {errors.basicAuthUser &&

{errors.basicAuthUser.message}

} -
- Pair with a password to require auth on writes. -
-
- -
-
Notion database ID
- - {errors.notionDatabaseId &&

{errors.notionDatabaseId.message}

} -
- Destination database for applied job entries. -
-
- -
-
- ( - { - field.onChange(checked === "indeterminate" ? null : checked === true) - }} - disabled={isLoading || isSaving} - /> - )} - /> -
- -

- Disable to show the browser while authenticating. -

-
-
-
-
-
- - - -
-
Private values
-
-
-
OpenRouter API key
+
OpenRouter API key
-
RxResume password
- - {errors.rxresumePassword &&

{errors.rxresumePassword.message}

} -
- Current: {formatSecretHint(privateValues.rxresumePasswordHint)} -
-
- -
-
UKVisaJobs password
- - {errors.ukvisajobsPassword &&

{errors.ukvisajobsPassword.message}

} -
- Current: {formatSecretHint(privateValues.ukvisajobsPasswordHint)} -
-
- -
-
Basic auth password
- - {errors.basicAuthPassword &&

{errors.basicAuthPassword.message}

} -
- Current: {formatSecretHint(privateValues.basicAuthPasswordHint)} -
-
- -
-
Webhook secret
+
Webhook secret
{formatSecretHint(privateValues.webhookSecretHint)}
+
+
-
-
Notion API key
- - {errors.notionApiKey &&

{errors.notionApiKey.message}

} -
- Current: {formatSecretHint(privateValues.notionApiKeyHint)} + + + {/* Service Accounts */} +
+
Service Accounts
+ +
+
RxResume
+
+
+
Email
+ + {errors.rxresumeEmail &&

{errors.rxresumeEmail.message}

} +
+
+
Password
+ + {errors.rxresumePassword &&

{errors.rxresumePassword.message}

} +
+ Current: {formatSecretHint(privateValues.rxresumePasswordHint)} +
-
- Private values are write-only. Enter a new value to replace the stored secret. + +
+
UKVisaJobs
+
+
+
Email
+ + {errors.ukvisajobsEmail &&

{errors.ukvisajobsEmail.message}

} +
+
+
Password
+ + {errors.ukvisajobsPassword &&

{errors.ukvisajobsPassword.message}

} +
+ Current: {formatSecretHint(privateValues.ukvisajobsPasswordHint)} +
+
+
+ + + + {/* Security */} +
+
Security
+
+ setIsBasicAuthEnabled(checked === true)} + disabled={isLoading || isSaving} + /> +
+ +

+ Require a username and password for write operations. +

+
+
+ + {isBasicAuthEnabled && ( +
+
+
Username
+ + {errors.basicAuthUser &&

{errors.basicAuthUser.message}

} +
+ +
+
Password
+ + {errors.basicAuthPassword &&

{errors.basicAuthPassword.message}

} +
+ Current: {formatSecretHint(privateValues.basicAuthPasswordHint)} +
+
+
+ )} +
) } + diff --git a/orchestrator/src/client/pages/settings/types.ts b/orchestrator/src/client/pages/settings/types.ts index e424a7d..a0b2555 100644 --- a/orchestrator/src/client/pages/settings/types.ts +++ b/orchestrator/src/client/pages/settings/types.ts @@ -37,6 +37,6 @@ export type EnvSettingsValues = { ukvisajobsPasswordHint: string | null basicAuthPasswordHint: string | null webhookSecretHint: string | null - notionApiKeyHint: string | null } + basicAuthActive: boolean } diff --git a/orchestrator/src/server/api/routes/settings.test.ts b/orchestrator/src/server/api/routes/settings.test.ts index 6d2006b..312216a 100644 --- a/orchestrator/src/server/api/routes/settings.test.ts +++ b/orchestrator/src/server/api/routes/settings.test.ts @@ -13,7 +13,6 @@ describe.sequential('Settings API routes', () => { env: { OPENROUTER_API_KEY: 'secret-key', RXRESUME_EMAIL: 'resume@example.com', - UKVISAJOBS_HEADLESS: 'false', }, })); }); @@ -30,7 +29,7 @@ describe.sequential('Settings API routes', () => { expect(Array.isArray(body.data.searchTerms)).toBe(true); expect(body.data.rxresumeEmail).toBe('resume@example.com'); expect(body.data.openrouterApiKeyHint).toBe('secr'); - expect(body.data.ukvisajobsHeadless).toBe(false); + expect(body.data.basicAuthActive).toBe(false); }); it('rejects invalid settings updates and persists overrides', async () => { @@ -48,7 +47,6 @@ describe.sequential('Settings API routes', () => { searchTerms: ['engineer'], rxresumeEmail: 'updated@example.com', openrouterApiKey: 'updated-secret', - ukvisajobsHeadless: true, }), }); const patchBody = await patchRes.json(); @@ -57,6 +55,5 @@ describe.sequential('Settings API routes', () => { expect(patchBody.data.overrideSearchTerms).toEqual(['engineer']); expect(patchBody.data.rxresumeEmail).toBe('updated@example.com'); expect(patchBody.data.openrouterApiKeyHint).toBe('upda'); - expect(patchBody.data.ukvisajobsHeadless).toBe(true); }); }); diff --git a/orchestrator/src/server/api/routes/settings.ts b/orchestrator/src/server/api/routes/settings.ts index 082c6dd..0f5d687 100644 --- a/orchestrator/src/server/api/routes/settings.ts +++ b/orchestrator/src/server/api/routes/settings.ts @@ -307,31 +307,12 @@ settingsRouter.patch('/', async (req: Request, res: Response) => { applyEnvValue('UKVISAJOBS_PASSWORD', value); } - if ('ukvisajobsHeadless' in input) { - const value = input.ukvisajobsHeadless ?? null; - const serialized = serializeEnvBoolean(value); - await settingsRepo.setSetting('ukvisajobsHeadless', serialized); - applyEnvValue('UKVISAJOBS_HEADLESS', serialized); - } - if ('webhookSecret' in input) { const value = normalizeEnvInput(input.webhookSecret); await settingsRepo.setSetting('webhookSecret', value); applyEnvValue('WEBHOOK_SECRET', value); } - if ('notionApiKey' in input) { - const value = normalizeEnvInput(input.notionApiKey); - await settingsRepo.setSetting('notionApiKey', value); - applyEnvValue('NOTION_API_KEY', value); - } - - if ('notionDatabaseId' in input) { - const value = normalizeEnvInput(input.notionDatabaseId); - await settingsRepo.setSetting('notionDatabaseId', value); - applyEnvValue('NOTION_DATABASE_ID', value); - } - const overrideModel = await settingsRepo.getSetting('model'); const defaultModel = process.env.MODEL || 'openai/gpt-4o-mini'; const model = overrideModel || defaultModel; diff --git a/orchestrator/src/server/repositories/settings.ts b/orchestrator/src/server/repositories/settings.ts index 399581b..310c144 100644 --- a/orchestrator/src/server/repositories/settings.ts +++ b/orchestrator/src/server/repositories/settings.ts @@ -31,10 +31,7 @@ export type SettingKey = 'model' | 'basicAuthPassword' | 'ukvisajobsEmail' | 'ukvisajobsPassword' - | 'ukvisajobsHeadless' | 'webhookSecret' - | 'notionApiKey' - | 'notionDatabaseId' export async function getSetting(key: SettingKey): Promise { const [row] = await db.select().from(settings).where(eq(settings.key, key)) diff --git a/orchestrator/src/server/services/envSettings.ts b/orchestrator/src/server/services/envSettings.ts index 201f209..45eb77d 100644 --- a/orchestrator/src/server/services/envSettings.ts +++ b/orchestrator/src/server/services/envSettings.ts @@ -7,12 +7,9 @@ const readableStringConfig: { settingKey: SettingKey, envKey: string }[] = [ { settingKey: 'rxresumeEmail', envKey: 'RXRESUME_EMAIL' }, { settingKey: 'ukvisajobsEmail', envKey: 'UKVISAJOBS_EMAIL' }, { settingKey: 'basicAuthUser', envKey: 'BASIC_AUTH_USER' }, - { settingKey: 'notionDatabaseId', envKey: 'NOTION_DATABASE_ID' }, ]; -const readableBooleanConfig: { settingKey: SettingKey, envKey: string, defaultValue: boolean }[] = [ - { settingKey: 'ukvisajobsHeadless', envKey: 'UKVISAJOBS_HEADLESS', defaultValue: true }, -]; +const readableBooleanConfig: { settingKey: SettingKey, envKey: string, defaultValue: boolean }[] = []; const privateStringConfig: { settingKey: SettingKey, envKey: string, hintKey: string }[] = [ { settingKey: 'openrouterApiKey', envKey: 'OPENROUTER_API_KEY', hintKey: 'openrouterApiKeyHint' }, @@ -20,7 +17,6 @@ const privateStringConfig: { settingKey: SettingKey, envKey: string, hintKey: st { settingKey: 'ukvisajobsPassword', envKey: 'UKVISAJOBS_PASSWORD', hintKey: 'ukvisajobsPasswordHint' }, { settingKey: 'basicAuthPassword', envKey: 'BASIC_AUTH_PASSWORD', hintKey: 'basicAuthPasswordHint' }, { settingKey: 'webhookSecret', envKey: 'WEBHOOK_SECRET', hintKey: 'webhookSecretHint' }, - { settingKey: 'notionApiKey', envKey: 'NOTION_API_KEY', hintKey: 'notionApiKeyHint' }, ]; export function normalizeEnvInput(value: string | null | undefined): string | null { @@ -96,9 +92,13 @@ export async function getEnvSettingsData(): Promise; diff --git a/orchestrator/src/shared/types.ts b/orchestrator/src/shared/types.ts index 16d7bb0..fbafbf6 100644 --- a/orchestrator/src/shared/types.ts +++ b/orchestrator/src/shared/types.ts @@ -390,8 +390,6 @@ export interface AppSettings { basicAuthPasswordHint: string | null; ukvisajobsEmail: string | null; ukvisajobsPasswordHint: string | null; - ukvisajobsHeadless: boolean; webhookSecretHint: string | null; - notionApiKeyHint: string | null; - notionDatabaseId: string | null; + basicAuthActive: boolean; }