feat(qbittorrent): login compat for v4/v5.0-5.2 and three auth modes
- Login success = HTTP 200 "Ok." or 204 (5.2+); session cookie taken from
Set-Cookie by name (SID / QBT_SID_<port> / custom) and sent back as-is.
- Failure classes: "Fails." / 401 -> auth; 403 IP ban / 429 -> rate;
wrong API Key (403) -> auth with hint; 5xx -> protocol.
- Downloader instance auth kind: password / api_key (qB 5.2+ Bearer, no
/auth/login) / none (whitelisted subnet); stored in settings.authKind,
credential write-only in secret_ref, cleared when switching to none.
One qbAuthConfig() shared by sync, agent capability and connection test.
- Settings form: auth kind select, password / API Key fields (no echo).
- testkit: mock qB 5.2 login behaviour, IP ban, bypassAuth;
makeTorrent({ realPieces }) builds real piece hashes for real qB checks.
- Real-container matrix (QB_REAL, skipped by default): 5.1.2 and 5.2.4,
login / add / query / tags / pause-resume / delete keeping data.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
c846e91cc4
commit
74f1566985
14 files changed
+756
-59
No files matched your search
@@ -50,6 +50,13 @@ const Credential = z.string().min(1).max(4096);
|
||||
export const DownloaderKind = z.enum(["qbittorrent"]);
|
||||
export type DownloaderKind = z.infer<typeof DownloaderKind>;
|
||||
|
||||
/**
|
||||
* 下载器认证方式(存 settings.authKind):password 账密登录(凭证=密码);api_key qB 5.2+ WebUI 生成的 API Key
|
||||
* (凭证=Key,走 Authorization: Bearer,不登录);none 无认证(qB 对内网白名单跳过认证)。
|
||||
*/
|
||||
export const DownloaderAuthKind = z.enum(["password", "api_key", "none"]);
|
||||
export type DownloaderAuthKind = z.infer<typeof DownloaderAuthKind>;
|
||||
|
||||
export const DownloaderInstance = EntityBase.extend({
|
||||
name: z.string().min(1),
|
||||
kind: DownloaderKind,
|
||||
@@ -78,7 +85,11 @@ export const DownloaderInstanceCreate = DownloaderInstance.pick({
|
||||
settings: true,
|
||||
})
|
||||
.partial({ kind: true, username: true, managedTag: true, cacheVolumeKey: true, enabled: true, settings: true })
|
||||
.extend({ credential: Credential.optional() });
|
||||
.extend({
|
||||
credential: Credential.optional(),
|
||||
/** 认证方式,写入 settings.authKind;缺省按"有用户名 → 账密,否则有凭证 → API Key,否则无认证"推断 */
|
||||
authKind: DownloaderAuthKind.optional(),
|
||||
});
|
||||
export type DownloaderInstanceCreate = z.infer<typeof DownloaderInstanceCreate>;
|
||||
export const DownloaderInstanceUpdate = DownloaderInstanceCreate.partial();
|
||||
export type DownloaderInstanceUpdate = z.infer<typeof DownloaderInstanceUpdate>;
|
||||
|
||||
Reference in new issue
Block a user