Files
ReadMeABook/src/app/admin/settings/tabs/PathsTab/usePathsSettings.ts
T
kikootwo f9947b745e Add requireSetupIncompleteOrAdmin and adjust routes
Introduce a new middleware requireSetupIncompleteOrAdmin that allows unauthenticated access while the setup wizard is in progress but enforces admin authentication once setup is complete. Replace requireSetupIncomplete with the new guard in test-paths, test-abs and test-oidc API routes. Update the front-end hook to use fetchWithAuth for authenticated requests. Revise setup-guard tests to cover the new semantics: shared endpoints now return 401 when setup is complete and no auth is provided, return 403 for authenticated non-admin users, and allow admin access or unauthenticated access during setup/DB-unready conditions; also add jwt verification and user lookup mocks to the tests.
2026-02-09 21:45:37 -05:00

92 lines
2.5 KiB
TypeScript

/**
* Component: Paths Settings Tab - Custom Hook
* Documentation: documentation/settings-pages.md
*/
'use client';
import { useState } from 'react';
import { fetchWithAuth } from '@/lib/utils/api';
import type { PathsSettings, TestResult } from '../../lib/types';
interface UsePathsSettingsProps {
paths: PathsSettings;
onChange: (paths: PathsSettings) => void;
onValidationChange: (isValid: boolean) => void;
}
export function usePathsSettings({ paths, onChange, onValidationChange }: UsePathsSettingsProps) {
const [testing, setTesting] = useState(false);
const [testResult, setTestResult] = useState<TestResult | null>(null);
/**
* Update a single path field
*/
const updatePath = (field: keyof PathsSettings, value: string | boolean) => {
onChange({ ...paths, [field]: value });
onValidationChange(false);
};
/**
* Test if paths are valid and writable, including template validation
*/
const testPaths = async () => {
setTesting(true);
setTestResult(null);
try {
const response = await fetchWithAuth('/api/setup/test-paths', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
downloadDir: paths.downloadDir,
mediaDir: paths.mediaDir,
audiobookPathTemplate: paths.audiobookPathTemplate,
ebookPathTemplate: paths.ebookPathTemplate,
}),
});
const data = await response.json();
if (data.success) {
const result: TestResult = {
success: true,
message: 'All paths are valid and writable',
templateValidation: data.template
};
setTestResult(result);
onValidationChange(true);
return result;
} else {
const result: TestResult = {
success: false,
message: data.error || 'Path validation failed',
templateValidation: data.template
};
setTestResult(result);
// Only mark as valid if paths are valid AND template is valid (if provided)
const isValid = false;
onValidationChange(isValid);
return result;
}
} catch (error) {
const result: TestResult = {
success: false,
message: error instanceof Error ? error.message : 'Failed to test paths'
};
setTestResult(result);
onValidationChange(false);
return result;
} finally {
setTesting(false);
}
};
return {
testing,
testResult,
updatePath,
testPaths,
};
}