Implement comprehensive analytics and monitoring system with PostHog integration, complete observability stack (Prometheus, Grafana, Loki, Promtail), and CI/CD workflows for automated builds. Features: - Add PostHog telemetry integration with privacy-focused event tracking - Implement installation flow for opt-in telemetry configuration - Add telemetry management UI in admin panel with detailed transparency - Track key user events across all major features (projects, tasks, timer, etc.) Infrastructure: - Set up Prometheus for metrics collection - Configure Grafana for visualization dashboards - Integrate Loki and Promtail for log aggregation - Add separate analytics docker-compose configuration CI/CD: - Add GitHub Actions workflows for building and publishing Docker images - Implement separate dev and production build pipelines - Configure automated image publishing to registry Documentation: - Restructure documentation into organized docs/ directory - Add comprehensive guides for telemetry, analytics, and local development - Create transparency documentation for tracked events - Add CI/CD and build configuration guides Code improvements: - Integrate telemetry hooks across all route handlers - Add feature flags and configuration management - Refactor test suite for analytics functionality - Clean up root directory by moving docs and removing test artifacts Breaking changes: - Requires new environment variables for PostHog configuration - Docker compose setup now supports analytics stack Changes: 73 files changed, 955 insertions(+), 14126 deletions(-)
6.9 KiB
CSRF Token Fix Summary
Overview
Completed comprehensive CSRF (Cross-Site Request Forgery) protection audit and fixed all missing CSRF tokens throughout the TimeTracker application.
Background
Flask-WTF's CSRFProtect is enabled application-wide in app/__init__.py, which means all POST/PUT/DELETE/PATCH requests require a valid CSRF token. The API blueprint (api_bp) is explicitly exempted from CSRF protection.
Findings and Fixes
Total Statistics
- 67 CSRF token implementations across the application
- 54 POST forms reviewed and fixed
- 36 template files updated
- 0 JavaScript AJAX calls requiring fixes (all target exempted API endpoints)
Files Fixed
1. Projects Module
templates/projects/view.html - Added CSRF tokens to:
- Archive project form (line 38)
- Unarchive project form (line 45)
- Delete time entry modal form (line 547)
- Delete comment modal form (line 583)
- Delete cost modal form (line 617)
templates/projects/list.html - Added CSRF tokens to:
- Archive project form (line 218)
- Unarchive project form (line 225)
- Delete project modal form (line 286)
templates/projects/add_cost.html - Added CSRF token to:
- Add cost form (line 25)
templates/projects/edit_cost.html - Added CSRF token to:
- Edit cost form (line 32)
templates/projects/create.html - Already had CSRF token ✓
templates/projects/edit.html - Already had CSRF token ✓
2. Clients Module
templates/clients/view.html - Added CSRF tokens to:
- Archive client form (line 191)
- Activate client form (line 198)
templates/clients/create.html - Already had CSRF token ✓
templates/clients/edit.html - Already had CSRF token ✓
3. Tasks Module
app/templates/tasks/view.html - Added CSRF tokens to:
- Stop timer form (line 51)
- Delete time entry modal form (line 843)
- Delete comment modal form (line 879)
app/templates/tasks/list.html - Added CSRF tokens to:
- Stop timer form (line 235)
- Start timer form (line 240)
app/templates/tasks/my_tasks.html - Added CSRF token to:
- Stop timer form (line 318)
app/templates/tasks/_kanban.html - Added CSRF tokens to:
- Stop timer form (line 49)
- Start timer form (line 56)
app/templates/tasks/create.html - Already had CSRF token ✓
app/templates/tasks/edit.html - Already had CSRF token ✓
4. Invoices Module
templates/invoices/list.html - Added CSRF token to:
- Delete invoice form (line 290)
templates/invoices/view.html - Added CSRF token to:
- Update invoice status modal form (line 510)
templates/invoices/generate_from_time.html - Added CSRF token to:
- Time entries selection form (line 80)
templates/invoices/record_payment.html - Added CSRF token to:
- Record payment form (line 34)
templates/invoices/create.html - Already had CSRF token ✓
templates/invoices/edit.html - Already had CSRF token ✓
5. Timer Module
app/templates/main/dashboard.html - Already had CSRF tokens ✓
- Stop timer form
- Start timer modal form
- Delete entry modal form
templates/timer/manual_entry.html - Already had CSRF token ✓
templates/timer/edit_timer.html - Already had CSRF tokens ✓
templates/timer/bulk_entry.html - Already had CSRF token ✓
6. Comments Module
app/templates/comments/edit.html - Added CSRF token to:
- Edit comment form (line 63)
app/templates/comments/_comments_section.html - Added CSRF token to:
- Create comment form (line 21)
app/templates/comments/_comment.html - Added CSRF tokens to:
- Edit comment form (line 52)
- Reply to comment form (line 70)
7. Admin Module
templates/admin/users.html - Added CSRF token to:
- Delete user modal form (line 193)
templates/admin/settings.html - Already had CSRF tokens ✓
- Main settings form
- Remove logo form
templates/admin/user_form.html - Already had CSRF tokens ✓
templates/admin/create_user.html - Already had CSRF token ✓
8. Authentication Module
app/templates/auth/login.html - Already had CSRF token ✓
app/templates/auth/edit_profile.html - Already had CSRF token ✓
9. Search Module
app/templates/main/search.html - Added CSRF token to:
- Delete time entry form (line 66)
10. Other Templates
templates/projects/form.html - Uses Flask-WTF {{ form.hidden_tag() }} which automatically includes CSRF token ✓
JavaScript/AJAX Review
Files Reviewed
- app/static/commands.js - Uses
/api/timer/stopendpoint (exempted from CSRF) ✓ - app/static/idle.js - Uses
/api/timer/stop_atendpoint (exempted from CSRF) ✓ - app/static/enhanced-search.js - Only performs GET requests ✓
API Endpoints
All AJAX calls target the /api/* endpoints which are part of the api_bp blueprint. This blueprint is explicitly exempted from CSRF protection in app/__init__.py:
csrf.exempt(api_bp)
Configuration Verification
app/config.py
WTF_CSRF_ENABLED = True
WTF_CSRF_TIME_LIMIT = 3600 # 1 hour
app/init.py
csrf = CSRFProtect()
csrf.init_app(app)
@app.errorhandler(CSRFError)
def handle_csrf_error(e):
return ({"error": "csrf_token_missing_or_invalid"}, 400)
@app.context_processor
def inject_csrf_token():
return dict(csrf_token=lambda: generate_csrf())
csrf.exempt(api_bp)
Testing Recommendations
- Form Submissions: Test all forms to ensure they submit successfully without CSRF errors
- Timer Operations: Test start/stop timer functionality across all pages
- Delete Operations: Test all delete modals (projects, tasks, time entries, comments, users)
- Archive/Activate Operations: Test client and project archive/unarchive functionality
- Invoice Operations: Test invoice status updates, payment recording, and deletion
- Comment System: Test creating, editing, and replying to comments
- Admin Functions: Test user creation, editing, deletion, and settings updates
Impact
Security
- ✅ All POST forms now protected against CSRF attacks
- ✅ API endpoints appropriately exempted for JSON/AJAX operations
- ✅ Consistent CSRF protection across entire application
User Experience
- ✅ No breaking changes to existing functionality
- ✅ Form submissions will no longer fail with CSRF errors
- ✅ Seamless operation for all user interactions
Notes
- Flask-WTF Forms: Forms using
{{ form.hidden_tag() }}automatically include CSRF tokens - API Exemption: The
/api/*endpoints are intentionally exempted from CSRF as they use JSON and are designed for programmatic access - Token Expiration: CSRF tokens expire after 1 hour (
WTF_CSRF_TIME_LIMIT = 3600) - Error Handling: CSRF errors return a 400 status with JSON error message
Conclusion
The application now has comprehensive CSRF protection across all user-facing forms while maintaining appropriate exemptions for API endpoints. All 54 POST forms across 36 template files have been verified and fixed where necessary.