-
Notifications
You must be signed in to change notification settings - Fork 0
Merge PRs #14, #15, #16: auth fix, async CPU moves, lobby a11y #17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,29 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from fastapi.testclient import TestClient | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from backend.main import app | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from backend.core.config import ADMIN_SECRET | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from backend.data.database import init_db | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Initialize DB for tests | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| init_db() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| client = TestClient(app) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def test_migrate_formats_no_header(): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Expect 422 because the header is required (Header(...)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| response = client.get("/auth/migrate-formats") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert response.status_code == 422 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def test_migrate_formats_wrong_header(): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Expect 403 because the secret is invalid | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| response = client.get("/auth/migrate-formats", headers={"X-Admin-Secret": "wrong-secret"}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert response.status_code == 403 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert response.json()["detail"] == "Invalid admin secret" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def test_migrate_formats_correct_header(): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Expect 200 because the secret matches | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| response = client.get("/auth/migrate-formats", headers={"X-Admin-Secret": ADMIN_SECRET}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert response.status_code == 200 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| data = response.json() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert "format_stats_2v2_merged" in data | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert "duplicate_rows_removed" in data | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert "match_history_fixed" in data | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+9
to
+29
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| client = TestClient(app) | |
| def test_migrate_formats_no_header(): | |
| # Expect 422 because the header is required (Header(...)) | |
| response = client.get("/auth/migrate-formats") | |
| assert response.status_code == 422 | |
| def test_migrate_formats_wrong_header(): | |
| # Expect 403 because the secret is invalid | |
| response = client.get("/auth/migrate-formats", headers={"X-Admin-Secret": "wrong-secret"}) | |
| assert response.status_code == 403 | |
| assert response.json()["detail"] == "Invalid admin secret" | |
| def test_migrate_formats_correct_header(): | |
| # Expect 200 because the secret matches | |
| response = client.get("/auth/migrate-formats", headers={"X-Admin-Secret": ADMIN_SECRET}) | |
| assert response.status_code == 200 | |
| data = response.json() | |
| assert "format_stats_2v2_merged" in data | |
| assert "duplicate_rows_removed" in data | |
| assert "match_history_fixed" in data | |
| def test_migrate_formats_no_header(): | |
| # Expect 422 because the header is required (Header(...)) | |
| with TestClient(app) as client: | |
| response = client.get("/auth/migrate-formats") | |
| assert response.status_code == 422 | |
| def test_migrate_formats_wrong_header(): | |
| # Expect 403 because the secret is invalid | |
| with TestClient(app) as client: | |
| response = client.get("/auth/migrate-formats", headers={"X-Admin-Secret": "wrong-secret"}) | |
| assert response.status_code == 403 | |
| assert response.json()["detail"] == "Invalid admin secret" | |
| def test_migrate_formats_correct_header(): | |
| # Expect 200 because the secret matches | |
| with TestClient(app) as client: | |
| response = client.get("/auth/migrate-formats", headers={"X-Admin-Secret": ADMIN_SECRET}) | |
| assert response.status_code == 200 | |
| data = response.json() | |
| assert "format_stats_2v2_merged" in data | |
| assert "duplicate_rows_removed" in data | |
| assert "match_history_fixed" in data |
Copilot
AI
Feb 21, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This new test file uses pytest-style discovery, but the existing backend tests in this repo are standalone scripts with run_all_tests() + a __main__ block (and pytest isn’t listed in backend/requirements.txt). As-is, this file likely won’t be executed by the current test workflow. Either adapt it to the repo’s script-style convention or add pytest + CI wiring so these tests actually run.
| assert "match_history_fixed" in data | |
| assert "match_history_fixed" in data | |
| def run_all_tests() -> None: | |
| """ | |
| Run all tests in this module. | |
| This mirrors the standalone script-style convention used by other backend tests, | |
| so the existing test workflow can execute these tests without pytest. | |
| """ | |
| test_migrate_formats_no_header() | |
| test_migrate_formats_wrong_header() | |
| test_migrate_formats_correct_header() | |
| if __name__ == "__main__": | |
| run_all_tests() |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ADMIN_SECRETfalls back to a hardcoded value when unset. That makes the/auth/migrate-formatsadmin protection effectively guessable in any non-production environment that’s accidentally exposed. Prefer requiringADMIN_SECRETin all environments, or generate a random per-process value (and log it only for local dev) so there isn’t a shared default secret across deployments.