mirror of
https://github.com/kikootwo/ReadMeABook.git
synced 2026-06-03 12:50:09 +00:00
Optional qBittorrent creds; require SABnzbd key
Allow qBittorrent to be configured without credentials (supports IP whitelist) and require an API key for SABnzbd. Skip connection testing when disabling a client. Updates include: validation changes in admin and setup API routes, test-download-client flows, DownloadClientModal UI validation and save/test logic, and DownloadClientManager to pass empty strings for optional credentials. Tests updated to reflect SABnzbd API key requirement.
This commit is contained in:
@@ -77,12 +77,16 @@ export async function PUT(
|
||||
}
|
||||
}
|
||||
|
||||
// Test connection if credentials/URL changed
|
||||
// Test connection if credentials/URL changed (skip if disabling client)
|
||||
const isDisabling = enabled === false;
|
||||
if (
|
||||
url !== undefined ||
|
||||
username !== undefined ||
|
||||
(password && password !== '********') ||
|
||||
disableSSLVerify !== undefined
|
||||
!isDisabling &&
|
||||
(
|
||||
url !== undefined ||
|
||||
username !== undefined ||
|
||||
(password && password !== '********') ||
|
||||
disableSSLVerify !== undefined
|
||||
)
|
||||
) {
|
||||
const testResult = await manager.testConnection(updatedClient);
|
||||
if (!testResult.success) {
|
||||
|
||||
@@ -72,17 +72,18 @@ export async function POST(request: NextRequest) {
|
||||
}
|
||||
|
||||
// Validate required fields
|
||||
if (!name || !url || !password) {
|
||||
// Name and URL always required; password/API key only required for SABnzbd
|
||||
// qBittorrent supports IP whitelist auth (no credentials needed)
|
||||
if (!name || !url) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Name, URL, and password/API key are required' },
|
||||
{ error: 'Name and URL are required' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
// qBittorrent requires username
|
||||
if (type === 'qbittorrent' && !username) {
|
||||
if (type === 'sabnzbd' && !password) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Username is required for qBittorrent' },
|
||||
{ error: 'API key is required for SABnzbd' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
@@ -111,14 +112,15 @@ export async function POST(request: NextRequest) {
|
||||
}
|
||||
|
||||
// Create new client config
|
||||
// qBittorrent credentials are optional (supports IP whitelist auth)
|
||||
const newClient: DownloadClientConfig = {
|
||||
id: randomUUID(),
|
||||
type,
|
||||
name,
|
||||
enabled: true,
|
||||
url,
|
||||
username: username || undefined,
|
||||
password,
|
||||
username: username || '',
|
||||
password: password || '',
|
||||
disableSSLVerify: disableSSLVerify || false,
|
||||
remotePathMappingEnabled: remotePathMappingEnabled || false,
|
||||
remotePath: remotePath || undefined,
|
||||
|
||||
@@ -66,29 +66,32 @@ export async function POST(request: NextRequest) {
|
||||
}
|
||||
|
||||
// Validate required fields
|
||||
if (!url || !effectivePassword) {
|
||||
// URL is always required; password/API key only required for SABnzbd
|
||||
// qBittorrent supports IP whitelist auth (no credentials needed)
|
||||
if (!url) {
|
||||
return NextResponse.json(
|
||||
{ error: 'URL and password/API key are required' },
|
||||
{ error: 'URL is required' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
if (type === 'qbittorrent' && !effectiveUsername) {
|
||||
if (type === 'sabnzbd' && !effectivePassword) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Username is required for qBittorrent' },
|
||||
{ error: 'API key is required for SABnzbd' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
// Create temporary client config for testing
|
||||
// qBittorrent credentials are optional (supports IP whitelist auth)
|
||||
const testConfig: DownloadClientConfig = {
|
||||
id: 'test',
|
||||
type,
|
||||
name: 'Test Client',
|
||||
enabled: true,
|
||||
url,
|
||||
username: effectiveUsername || undefined,
|
||||
password: effectivePassword,
|
||||
username: effectiveUsername || '',
|
||||
password: effectivePassword || '',
|
||||
disableSSLVerify: disableSSLVerify || false,
|
||||
remotePathMappingEnabled: remotePathMappingEnabled || false,
|
||||
remotePath: remotePath || undefined,
|
||||
|
||||
@@ -107,16 +107,18 @@ export async function POST(request: NextRequest) {
|
||||
}
|
||||
|
||||
// Validate each client has required fields
|
||||
// qBittorrent credentials are optional (supports IP whitelist auth)
|
||||
// SABnzbd always requires API key
|
||||
for (const client of clients) {
|
||||
if (!client.url || !client.password) {
|
||||
if (!client.url) {
|
||||
return NextResponse.json(
|
||||
{ success: false, error: 'Download client URL and password/API key are required' },
|
||||
{ success: false, error: 'Download client URL is required' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
if (client.type === 'qbittorrent' && !client.username) {
|
||||
if (client.type === 'sabnzbd' && !client.password) {
|
||||
return NextResponse.json(
|
||||
{ success: false, error: 'qBittorrent username is required' },
|
||||
{ success: false, error: 'SABnzbd API key is required' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
@@ -29,19 +29,13 @@ export async function POST(request: NextRequest) {
|
||||
}
|
||||
|
||||
// Validate required fields per client type
|
||||
// qBittorrent credentials are optional (supports IP whitelist auth)
|
||||
if (type === 'qbittorrent') {
|
||||
if (!username || !password) {
|
||||
return NextResponse.json(
|
||||
{ success: false, error: 'Username and password are required for qBittorrent' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
// Test qBittorrent connection
|
||||
// Test qBittorrent connection (empty credentials work with IP whitelist)
|
||||
const version = await QBittorrentService.testConnectionWithCredentials(
|
||||
url,
|
||||
username,
|
||||
password,
|
||||
username || '',
|
||||
password || '',
|
||||
disableSSLVerify || false
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user