fix(auth): avoid logout on license activation errors#602
Conversation
WalkthroughThe API client introduces centralized error handling by extracting error messages from responses and delegating authentication errors to a new handler, replacing per-endpoint redirect logic. Empty responses are now handled by returning undefined. Four private helper methods manage error extraction, auth error handling, logout determination, and auth-endpoint identification. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant ApiClient
participant Server
participant ErrorHandler
participant Router
Client->>ApiClient: fetch(endpoint)
ApiClient->>Server: HTTP request
alt Success Response
Server-->>ApiClient: 200 OK / Data
ApiClient->>Client: Return data
else Empty Response
Server-->>ApiClient: 204 / Content-Length: 0
ApiClient->>Client: Return undefined
else Error Response
Server-->>ApiClient: Non-OK status
ApiClient->>ApiClient: extractErrorMessage()
ApiClient->>ApiClient: shouldForceLogout(status, endpoint, message)
alt Auth Error Detected
ApiClient->>ErrorHandler: handleAuthError(status, endpoint, message)
ErrorHandler->>Router: Redirect to login
ErrorHandler-->>ApiClient: Throw error
else Other Error
ApiClient-->>Client: Throw error with message
end
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
web/src/lib/api.ts (1)
116-142:extractErrorMessageis robust; consider optional support for additional fieldsThis helper is nicely defensive: it handles empty bodies, JSON with
error/message, plain-text bodies, and falls back to a generic status string without risking double body reads.If your backend ever emits error details under other keys (e.g.
detailor nestederrors[0].message), you could extend the JSON parsing to check those as well, but that’s purely optional and can be added when needed.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
web/src/lib/api.ts(2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
web/src/lib/api.ts (1)
web/src/lib/base-url.ts (1)
withBasePath(24-29)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Run tests
🔇 Additional comments (2)
web/src/lib/api.ts (2)
103-114: Centralized error handling and empty-response handling inrequestlook goodWiring
extractErrorMessageandhandleAuthErrorintorequestis clean and gives you a single place to manage auth vs. non-auth failures. Treating 204 /content-length: "0"asundefinedalso pairs nicely with callers likegetLatestVersionthat already doresponse ?? null.No issues from my side here.
1045-1047: Reusing shared auth/error handling inexportTorrentis a good improvementHooking
exportTorrentintoextractErrorMessage+handleAuthErrormakes its error behavior consistent with the rest of the client, including proper session-expiry redirects and better error messages for other failures. The explicit endpoint string you pass intohandleAuthErroralso ensuresisAuthCheckEndpointand future endpoint-based checks behave predictably.Looks good as-is.
This PR contains the following updates: | Package | Update | Change | |---|---|---| | [ghcr.io/autobrr/qui](https://github.com/autobrr/qui) | minor | `v1.7.0` -> `v1.8.1` | --- ### Release Notes <details> <summary>autobrr/qui (ghcr.io/autobrr/qui)</summary> ### [`v1.8.1`](https://github.com/autobrr/qui/releases/tag/v1.8.1) [Compare Source](autobrr/qui@v1.8.0...v1.8.1) #### Changelog ##### Bug Fixes - [`61c87e1`](autobrr/qui@61c87e1): fix(torznab): use detached context for indexer tests ([#​659](autobrr/qui#659)) ([@​s0up4200](https://github.com/s0up4200)) **Full Changelog**: <autobrr/qui@v1.8.0...v1.8.1> #### Docker images - `docker pull ghcr.io/autobrr/qui:v1.8.1` - `docker pull ghcr.io/autobrr/qui:latest` #### What to do next? - Join our [Discord server](https://discord.autobrr.com/qui) Thank you for using qui! ### [`v1.8.0`](https://github.com/autobrr/qui/releases/tag/v1.8.0) [Compare Source](autobrr/qui@v1.7.0...v1.8.0) #### Changelog ##### New Features - [`6903812`](autobrr/qui@6903812): feat(crossseed): batch torrent file lookups end-to-end ([#​625](autobrr/qui#625)) ([@​s0up4200](https://github.com/s0up4200)) - [`336ce48`](autobrr/qui@336ce48): feat(crossseed): persist seeded search settings ([#​618](autobrr/qui#618)) ([@​s0up4200](https://github.com/s0up4200)) - [`7b0b292`](autobrr/qui@7b0b292): feat(docker): add curl to Dockerfiles ([#​570](autobrr/qui#570)) ([@​onedr0p](https://github.com/onedr0p)) - [`91e1677`](autobrr/qui@91e1677): feat(filters): default-hide empty status/category/tag groups ([#​581](autobrr/qui#581)) ([@​s0up4200](https://github.com/s0up4200)) - [`f07bb8d`](autobrr/qui@f07bb8d): feat(header): add missing links to header burger menu ([#​624](autobrr/qui#624)) ([@​nuxencs](https://github.com/nuxencs)) - [`ee4c16b`](autobrr/qui@ee4c16b): feat(instances): allow disabling qbit instances ([#​582](autobrr/qui#582)) ([@​s0up4200](https://github.com/s0up4200)) - [`477db14`](autobrr/qui@477db14): feat(search): column filters ([#​633](autobrr/qui#633)) ([@​nuxencs](https://github.com/nuxencs)) - [`cd6db45`](autobrr/qui@cd6db45): feat(themes): add basic variation support ([#​569](autobrr/qui#569)) ([@​jabloink](https://github.com/jabloink)) - [`979a0d4`](autobrr/qui@979a0d4): feat(torrents): add clear filters action for empty filtered state ([#​627](autobrr/qui#627)) ([@​s0up4200](https://github.com/s0up4200)) - [`e06acb7`](autobrr/qui@e06acb7): feat(torrents): add cross-seeding and search ([#​553](autobrr/qui#553)) ([@​KyleSanderson](https://github.com/KyleSanderson)) - [`95cef23`](autobrr/qui@95cef23): feat(torrents): add reannounce monitor ([#​606](autobrr/qui#606)) ([@​s0up4200](https://github.com/s0up4200)) - [`098fdb0`](autobrr/qui@098fdb0): feat(torrents): add rename functionality in TorrentDetailsPanel ([#​590](autobrr/qui#590)) ([@​s0up4200](https://github.com/s0up4200)) - [`6e8fdbd`](autobrr/qui@6e8fdbd): feat(torrents): implement drag-and-drop file upload to add torrents ([#​568](autobrr/qui#568)) ([@​dthinhle](https://github.com/dthinhle)) - [`9240545`](autobrr/qui@9240545): feat(ui): add dense view mode for compact table display ([#​643](autobrr/qui#643)) ([@​s0up4200](https://github.com/s0up4200)) - [`77fad15`](autobrr/qui@77fad15): feat(ui): improve torrent details panel file tree and rename UX ([#​650](autobrr/qui#650)) ([@​s0up4200](https://github.com/s0up4200)) - [`8b1e70e`](autobrr/qui@8b1e70e): feat(web): Use original qBittorrent status names ([#​595](autobrr/qui#595)) ([@​FibreTTP](https://github.com/FibreTTP)) - [`01dd553`](autobrr/qui@01dd553): feat(web): show listening port in connectable status tooltip ([#​635](autobrr/qui#635)) ([@​s0up4200](https://github.com/s0up4200)) - [`3140739`](autobrr/qui@3140739): feat: make tracker icon column sortable ([#​513](autobrr/qui#513)) ([@​s0up4200](https://github.com/s0up4200)) ##### Bug Fixes - [`240b40d`](autobrr/qui@240b40d): fix(auth): avoid logout on license activation errors ([#​602](autobrr/qui#602)) ([@​s0up4200](https://github.com/s0up4200)) - [`7185408`](autobrr/qui@7185408): fix(backups): do not persist ZIPs to disk ([#​632](autobrr/qui#632)) ([@​KyleSanderson](https://github.com/KyleSanderson)) - [`de0e00a`](autobrr/qui@de0e00a): fix(content): use Hints for detection ([#​621](autobrr/qui#621)) ([@​KyleSanderson](https://github.com/KyleSanderson)) - [`5f016a8`](autobrr/qui@5f016a8): fix(cross): performance improvements ([#​629](autobrr/qui#629)) ([@​KyleSanderson](https://github.com/KyleSanderson)) - [`82c74ba`](autobrr/qui@82c74ba): fix(crossseed): flip deduplication to maps ([#​622](autobrr/qui#622)) ([@​KyleSanderson](https://github.com/KyleSanderson)) - [`b78a079`](autobrr/qui@b78a079): fix(crossseed): inherit TMM state from matched torrent ([#​654](autobrr/qui#654)) ([@​s0up4200](https://github.com/s0up4200)) - [`2438fc6`](autobrr/qui@2438fc6): fix(crossseed): process full RSS feeds ([#​615](autobrr/qui#615)) ([@​s0up4200](https://github.com/s0up4200)) - [`6f57090`](autobrr/qui@6f57090): fix(database): do not release mutex on tx err ([#​571](autobrr/qui#571)) ([@​KyleSanderson](https://github.com/KyleSanderson)) - [`74509d4`](autobrr/qui@74509d4): fix(incognito): prevent categories leaking ([#​592](autobrr/qui#592)) ([@​s0up4200](https://github.com/s0up4200)) - [`f08eff2`](autobrr/qui@f08eff2): fix(instances): support empty username for localhost bypass ([#​575](autobrr/qui#575)) ([@​s0up4200](https://github.com/s0up4200)) - [`cd3caaf`](autobrr/qui@cd3caaf): fix(license): cap 7d offline grace, ignore transient errors ([#​617](autobrr/qui#617)) ([@​s0up4200](https://github.com/s0up4200)) - [`59c747b`](autobrr/qui@59c747b): fix(reannounce): validate number fields and show min hints ([#​613](autobrr/qui#613)) ([@​s0up4200](https://github.com/s0up4200)) - [`f6bd1e6`](autobrr/qui@f6bd1e6): fix(themes): correct Nightwalker description from purple to blue ([#​648](autobrr/qui#648)) ([@​s0up4200](https://github.com/s0up4200)) - [`2b641c5`](autobrr/qui@2b641c5): fix(torznab): filter Prowlarr autodiscovery to enabled torrent indexers ([#​638](autobrr/qui#638)) ([@​s0up4200](https://github.com/s0up4200)) - [`1995783`](autobrr/qui@1995783): fix(ui): improve cross-seed mobile responsiveness ([#​647](autobrr/qui#647)) ([@​s0up4200](https://github.com/s0up4200)) - [`b83aebe`](autobrr/qui@b83aebe): fix(web): align CrossSeedDialog indexers with search flows ([#​619](autobrr/qui#619)) ([@​s0up4200](https://github.com/s0up4200)) - [`3b60821`](autobrr/qui@3b60821): fix(web): indent subcategories in SetCategoryDialog ([#​636](autobrr/qui#636)) ([@​s0up4200](https://github.com/s0up4200)) - [`82850cd`](autobrr/qui@82850cd): fix: glob pattern formatting in tooltip content ([#​579](autobrr/qui#579)) ([@​onedr0p](https://github.com/onedr0p)) ##### Other Changes - [`c20bc0a`](autobrr/qui@c20bc0a): build(vite): enable default minification ([#​574](autobrr/qui#574)) ([@​s0up4200](https://github.com/s0up4200)) - [`ceac8ca`](autobrr/qui@ceac8ca): chore(ci): upgrade Claude Code workflow to Opus 4.5 ([@​s0up4200](https://github.com/s0up4200)) - [`9d6c10e`](autobrr/qui@9d6c10e): chore(deps): bump actions/checkout from 5 to 6 in the github group ([#​628](autobrr/qui#628)) ([@​dependabot](https://github.com/dependabot)\[bot]) - [`f5704de`](autobrr/qui@f5704de): chore(deps): bump golang.org/x/crypto from 0.43.0 to 0.45.0 ([#​611](autobrr/qui#611)) ([@​dependabot](https://github.com/dependabot)\[bot]) - [`0aae9aa`](autobrr/qui@0aae9aa): chore(deps): bump the golang group with 3 updates ([#​546](autobrr/qui#546)) ([@​dependabot](https://github.com/dependabot)\[bot]) - [`0d97087`](autobrr/qui@0d97087): chore(themes): add crypto instructions in-app ([#​620](autobrr/qui#620)) ([@​s0up4200](https://github.com/s0up4200)) - [`e778865`](autobrr/qui@e778865): docs(funding): add donation methods and crypto addresses ([#​583](autobrr/qui#583)) ([@​s0up4200](https://github.com/s0up4200)) - [`563645c`](autobrr/qui@563645c): docs: update qui image ([#​655](autobrr/qui#655)) ([@​s0up4200](https://github.com/s0up4200)) **Full Changelog**: <autobrr/qui@v1.7.0...v1.8.0> #### Docker images - `docker pull ghcr.io/autobrr/qui:v1.8.0` - `docker pull ghcr.io/autobrr/qui:latest` #### What to do next? - Join our [Discord server](https://discord.autobrr.com/qui) Thank you for using qui! </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi41LjAiLCJ1cGRhdGVkSW5WZXIiOiI0Mi41LjAiLCJ0YXJnZXRCcmFuY2giOiJtYWluIiwibGFiZWxzIjpbImltYWdlIl19--> Reviewed-on: https://gitea.alexlebens.dev/alexlebens/infrastructure/pulls/2211 Co-authored-by: Renovate Bot <renovate-bot@alexlebens.net> Co-committed-by: Renovate Bot <renovate-bot@alexlebens.net>
qui would logout on license activation errors due to shared status codes
Summary by CodeRabbit