fix(bhr): 🐞 KVIFF BHR of routes.py and blueprints#133
Open
dvorka wants to merge 1 commit into
Open
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR applies a set of BHR-driven hardening fixes across routes.py and multiple blueprints/templates, focusing on preventing unsafe state changes via GET, improving input validation (400/404 instead of 500), fixing cloning/copy behavior for blob-backed activity media, and standardizing ASCII-only punctuation across the codebase.
Changes:
- Enforce POST + CSRF for state-changing endpoints (clone/copy/merge/reset/sync) and update templates accordingly.
- Add safer helpers in
routes.pyfor route param parsing, same-host redirects, and numeric pace sorting; improve 404/400 behavior for common error cases. - Add regression tests for the above fixes and expand defensive handling across CRUD/import/task flows.
Reviewed changes
Copilot reviewed 71 out of 71 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/test_bhr_routes_fixes.py | Adds regression tests for routes fixes (blob reset on clone/copy, 400 parsing, pace sorting, safe redirect, CSRF enforcement, ASCII scan). |
| tests/test_bhr_blueprints_fixes.py | Adds regression tests for blueprint fixes (login CSRF validation, outfit empty activity types, gear component delete redirect). |
| mytral/utils.py | Replaces typographic dash with ASCII dash in docs. |
| mytral/templates/tools-optimize.html | Converts state-changing tool links to POST forms with CSRF tokens. |
| mytral/templates/tools-merge-join.html | Converts merge-all action to POST form with CSRF token. |
| mytral/templates/strava-api-secrets.html | Converts secrets reset action to POST form with CSRF token. |
| mytral/templates/strava-api-developer.html | Converts Strava sync/reset actions to POST forms with CSRF token. |
| mytral/templates/insight-gear-performance.html | Converts Strava gear merge action to POST form with CSRF token. |
| mytral/templates/activity-get.html | Converts clone-to-new action to POST form with CSRF token. |
| mytral/tasks/storage.py | ASCII punctuation cleanup in docstrings. |
| mytral/tasks/manager.py | ASCII punctuation cleanup in docstrings/comments. |
| mytral/tasks/locks.py | ASCII punctuation cleanup in module docstring. |
| mytral/tasks/do/tabpfn_download.py | ASCII punctuation cleanup; display-name normalization. |
| mytral/tasks/do/strava_resync_all.py | ASCII punctuation cleanup; display-name normalization. |
| mytral/tasks/do/strava_new_activities_sync.py | ASCII punctuation cleanup; display-name normalization. |
| mytral/tasks/do/strava_gear_sync.py | ASCII punctuation cleanup; display-name normalization. |
| mytral/tasks/do/strava_archive_import.py | ASCII punctuation cleanup in logs/comments. |
| mytral/tasks/do/strava_activity_sync.py | ASCII punctuation cleanup; display-name normalization. |
| mytral/tasks/do/polar_hrm_import.py | ASCII punctuation cleanup in logs/errors. |
| mytral/tasks/do/gpx_directory_import.py | ASCII punctuation cleanup in comments. |
| mytral/tasks/do/fit_directory_import.py | ASCII punctuation cleanup in comments/docstrings. |
| mytral/tasks/bulldozer/_base.py | ASCII punctuation cleanup in logs. |
| mytral/stats.py | ASCII punctuation cleanup in docstrings/comments. |
| mytral/settings.py | ASCII punctuation cleanup; replaces degree glyphs with ASCII wording. |
| mytral/security.py | ASCII punctuation cleanup in comments. |
| mytral/routes.py | Adds helpers (_reset_activity_blobs/_int_or_400/_safe_redirect_target/_pace_to_seconds); hardens many endpoints (CSRF/POST-only, better 400/404, safe redirects, correct pace sort, task 404 behavior). |
| mytral/recordings/parquet_converter.py | ASCII punctuation cleanup in schema docs. |
| mytral/recordings/gpx_extractor.py | ASCII punctuation cleanup in comments. |
| mytral/recordings/fit_extractor.py | ASCII punctuation cleanup in comments. |
| mytral/muscle_groups.py | ASCII punctuation cleanup in descriptions. |
| mytral/ml/icl/predictions/sick.py | ASCII punctuation cleanup in docstring. |
| mytral/ml/icl/predictions/fatigue.py | ASCII punctuation cleanup in docstring. |
| mytral/ml/icl/model.py | ASCII punctuation cleanup in docstring. |
| mytral/migrations.py | ASCII punctuation cleanup in comments. |
| mytral/loggers.py | ASCII punctuation cleanup in docstring. |
| mytral/integrations/tcx_recording.py | ASCII punctuation cleanup in log message. |
| mytral/integrations/strava.py | Adds state to Strava OAuth URL generation; URL-encodes state. |
| mytral/integrations/strava_user_archive.py | ASCII punctuation cleanup in comment. |
| mytral/integrations/polar_hrm.py | ASCII punctuation cleanup in comments. |
| mytral/integrations/gpx_recording.py | ASCII punctuation cleanup in log message. |
| mytral/integrations/fit_recording.py | ASCII punctuation cleanup in log message. |
| mytral/integrations/concept2.py | ASCII punctuation cleanup in doc comment. |
| mytral/forms.py | Improves upload validation (avatar FileAllowed), ASCII label/description normalization (degC, dashes), and minor wording fixes. |
| mytral/config.py | Replaces box-drawing Unicode with ASCII separators; ASCII punctuation cleanup in comments. |
| mytral/charts.py | ASCII punctuation cleanup in titles/comments/tooltips. |
| mytral/blueprints/tools_uri_space.py | Makes tool endpoints POST-only with CSRF; fixes dataset switch persistence on merge; updates a profile update call signature. |
| mytral/blueprints/tabpfn_uri_space.py | ASCII punctuation cleanup in flash message. |
| mytral/blueprints/strava_api_uri_space.py | Adds anti-CSRF state handling to Strava OAuth; makes reset/sync endpoints POST-only with CSRF. |
| mytral/blueprints/outfit_crud.py | Guards against empty activity type choices; normalizes optional description. |
| mytral/blueprints/lap_types_crud.py | Removes unused form field; normalizes optional description. |
| mytral/blueprints/import_uri_space.py | Adds warning for unhandled entity types; refactors FIT/GPX/TCX import into helper with rollback on failure. |
| mytral/blueprints/goal_crud.py | Handles missing goal key gracefully during photo upload. |
| mytral/blueprints/gear_crud.py | Removes unused form field; handles missing gear key gracefully; fixes nested validation; improves delete flow resilience. |
| mytral/blueprints/gear_components_crud.py | Removes unused API endpoint; catches missing gear on service update/delete and flashes errors. |
| mytral/blueprints/export_uri_space.py | Ensures temporary export ZIP is cleaned up after response is sent. |
| mytral/blueprints/exercise_types_crud.py | Corrects create form usage; makes numeric fields optional; handles missing exercise key on photo upload. |
| mytral/blueprints/auth_uri_space.py | Validates login form (CSRF/validators) before auth; avoids user enumeration via error messaging; redirects more consistently. |
| mytral/blueprints/activity_types_crud.py | Prevents user-created activity types from being flagged as built-in. |
| mytral/blueprints/acoach_uri_space.py | ASCII punctuation cleanup in UI strings/docstrings. |
| mytral/blobstore/filesystem.py | ASCII punctuation cleanup in comments. |
| mytral/blobstore/avatar_service.py | ASCII punctuation cleanup in docstrings. |
| mytral/blobstore/activity_service.py | ASCII punctuation cleanup in comments/docstrings. |
| mytral/blobstore/abc.py | ASCII punctuation cleanup in docstring. |
| mytral/backends/entities.py | ASCII punctuation cleanup in validation docs/comments. |
| mytral/backends/dataset.py | ASCII punctuation cleanup in docstrings/comments. |
| mytral/athlete_metrics.py | ASCII punctuation cleanup in comments/docstrings. |
| mytral/ai/settings.py | ASCII punctuation cleanup in prompts/format instructions. |
| mytral/ai/context.py | ASCII punctuation cleanup in comments/text. |
| mytral/ai/agent.py | ASCII punctuation cleanup in comments/strings. |
| mytral/init.py | ASCII punctuation cleanup in comments. |
| CHANGELOG.md | Documents the fixed behaviors covered by this PR. |
Comment on lines
+249
to
+260
| forbidden = { | ||
| "—": "em dash", | ||
| "–": "en dash", | ||
| "→": "arrow", | ||
| "’": "smart quote", | ||
| "─": "box drawing", | ||
| "×": "multiplication sign", | ||
| "≈": "almost equal", | ||
| "°": "degree sign", | ||
| "℃": "degree celsius", | ||
| "±": "plus-minus", | ||
| } |
| return fallback | ||
|
|
||
|
|
||
| def _pace_to_seconds(pace: str) -> int: |
Comment on lines
+544
to
+547
| except Exception as exc: | ||
| app_logger.exception( | ||
| f"Failed to queue {source_label} import task", error=str(exc) | ||
| ) |
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.
This PR brings BHR-based fixes primarily focused on
routes.py.