fix: stop shadowing base_host() in the Spaces OAuth callbacks - #8
Merged
Merged
Conversation
The Google, GitHub and GitLab Spaces callbacks each opened with
base_host = request.session.get("host")
which shadows the base_host() imported at the top of the same module. Python
binds the name to the function's local scope, so every later
base_host(request=..., is_space=True) in that method calls a string and raises
TypeError: 'str' object is not callable. Eight call sites per file, covering
the success redirect, both guard branches, the allowed-host fallback and the
exception handler -- so any request reaching those callbacks fails with a 500
rather than the intended redirect.
The assigned value is never read. Removing the line is the whole fix; every
reference then resolves to the import again.
Unnoticed because nothing calls these endpoints: the Spaces frontend sends
OAuth through the /app endpoints, so /auth/spaces/<provider>/ has been
unreachable dead code. That is changing -- the Spaces OIDC button now uses its
own flow -- which is what makes this worth fixing rather than deleting.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
6 tasks
There was a problem hiding this comment.
🟢 Approval recommended
The change is a minimal, targeted removal of an unused local assignment that was definitively breaking these callbacks at runtime.
Pull request overview
Fixes a runtime crash in the Spaces OAuth callback endpoints caused by shadowing the imported base_host() helper with a session string, which would otherwise raise TypeError: 'str' object is not callable on redirect/error paths.
Changes:
- Removes the unused
base_host = request.session.get("host")assignment from Spaces OAuth callbacks sobase_host(...)resolves to the imported function. - Restores correct redirect/error handling behavior for Google, GitHub, and GitLab Spaces OAuth callbacks by preventing the shadowing-induced 500s.
File summaries
| File | Description |
|---|---|
| apps/api/plane/authentication/views/space/google.py | Removes local base_host shadow to ensure callback redirects use the imported base_host() helper. |
| apps/api/plane/authentication/views/space/github.py | Removes local base_host shadow to prevent TypeError during callback redirect/error handling. |
| apps/api/plane/authentication/views/space/gitlab.py | Removes local base_host shadow to keep callback redirect/error paths functional. |
Review details
- Files reviewed: 3/3 changed files
- Comments generated: 0
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
The Google, GitHub and GitLab Spaces callbacks each open with:
That shadows the
base_host()imported at the top of the same module. Python binds the name to the function's local scope, so every laterbase_host(request=..., is_space=True)in that method calls a string:Eight call sites per file are affected — the success redirect, both guard branches, the allowed-host fallback and the exception handler — so any request reaching these callbacks returns a 500 instead of the intended redirect.
Demonstrated in isolation:
The assigned value is never read. Deleting the line is the entire fix; every reference then resolves to the import again.
Why it went unnoticed
Nothing calls these endpoints. The Spaces frontend routes OAuth through the
/appendpoints —window.location.assign(${API_BASE_URL}/auth/google/…)— so/auth/spaces/<provider>/has been unreachable dead code, and a total crash inside code nothing executes stays invisible.That is changing: #1 points the Spaces OIDC button at its own
/auth/spaces/oidc/flow, which makes this worth fixing rather than deleting. (space/oidc.pydoes not carry the shadow, so OIDC itself is unaffected.)Type of Change
Screenshots and Media (if applicable)
Test Scenarios
Static: parsed each file with
ast— assignments tobase_hostwent 1 → 0, while the 8 calls per file remain, so every reference now resolves to the import.Behavioural: reproduced the shadowing in isolation (above) to confirm the failure mode and the fix.
Regression: backend unit suite matches the
previewbaseline exactly — 305 passed, with the same 36 database-dependent errors present onpreviewwhen Postgres is not running.ruff checkandruff formatclean.Manual, once #1 lands: trigger any error branch on a Spaces OAuth callback — e.g. open
/auth/spaces/google/callback/?code=x&state=ywith no matching session — and confirm it redirects with an error code rather than raising a 500.References
Found by Copilot on #3, where it was filed as a suppressed (low-confidence) comment. It is neither low-confidence nor caused by that PR: the assignment predates it and is untouched there.
Worth noting #3 partially fixes this by accident — replacing the f-string redirect with
space_redirect_url()removes one shadowed call from the success path — so the two are complementary and merge in either order.🤖 Generated with Claude Code