mirror of
https://github.com/DRYTRIX/TimeTracker.git
synced 2026-01-07 20:20:30 -06:00
Implement a complete audit logging system to track all changes made to tracked entities, providing full compliance and accountability capabilities. Features: - Automatic tracking of create, update, and delete operations on 25+ models - Detailed field-level change tracking with old/new value comparison - User attribution with IP address, user agent, and request path logging - Web UI for viewing and filtering audit logs with pagination - REST API endpoints for programmatic access - Entity-specific history views - Comprehensive test coverage (unit, model, route, and smoke tests) Core Components: - AuditLog model with JSON-encoded value storage and decoding helpers - SQLAlchemy event listeners for automatic change detection - Audit utility module with defensive programming for table existence checks - Blueprint routes for audit log viewing and API access - Jinja2 templates for audit log list, detail, and entity history views - Database migration (044) creating audit_logs table with proper indexes Technical Implementation: - Uses SQLAlchemy 'after_flush' event listener to capture changes - Tracks 25+ models including Projects, Tasks, TimeEntries, Invoices, Clients, Users, etc. - Excludes sensitive fields (passwords) and system fields (id, timestamps) - Implements lazy import pattern to avoid circular dependencies - Graceful error handling to prevent audit logging from breaking core functionality - Transaction-safe logging that integrates with main application transactions Fixes: - Resolved login errors caused by premature transaction commits - Fixed circular import issues with lazy model loading - Added table existence checks to prevent errors before migrations - Improved error handling with debug-level logging for non-critical failures UI/UX: - Added "Audit Logs" link to admin dropdown menu - Organized admin menu into logical sections for better usability - Filterable audit log views by entity type, user, action, and date range - Color-coded action badges and side-by-side old/new value display - Pagination support for large audit log datasets Documentation: - Added comprehensive feature documentation - Included troubleshooting guide and data examples - Created diagnostic scripts for verifying audit log setup Testing: - Unit tests for AuditLog model and value encoding/decoding - Route tests for all audit log endpoints - Integration tests for audit logging functionality - Smoke tests for end-to-end audit trail verification This implementation provides a robust foundation for compliance tracking and change accountability without impacting application performance or requiring code changes in existing routes/models.
64 lines
1.9 KiB
Python
64 lines
1.9 KiB
Python
#!/usr/bin/env python
|
|
"""Test script to verify audit log routes are registered"""
|
|
|
|
import sys
|
|
import os
|
|
|
|
# Add the parent directory to the path so we can import app
|
|
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
|
|
|
|
try:
|
|
from app import create_app
|
|
|
|
app = create_app()
|
|
|
|
print("=" * 60)
|
|
print("Checking Audit Log Routes")
|
|
print("=" * 60)
|
|
|
|
# Get all routes
|
|
audit_routes = []
|
|
for rule in app.url_map.iter_rules():
|
|
if 'audit' in rule.rule.lower():
|
|
audit_routes.append({
|
|
'rule': rule.rule,
|
|
'endpoint': rule.endpoint,
|
|
'methods': list(rule.methods)
|
|
})
|
|
|
|
if audit_routes:
|
|
print(f"\n✓ Found {len(audit_routes)} audit log route(s):\n")
|
|
for route in audit_routes:
|
|
print(f" Route: {route['rule']}")
|
|
print(f" Endpoint: {route['endpoint']}")
|
|
print(f" Methods: {', '.join(route['methods'])}")
|
|
print()
|
|
else:
|
|
print("\n✗ No audit log routes found!")
|
|
print("\nChecking for import errors...")
|
|
|
|
# Try to import the blueprint
|
|
try:
|
|
from app.routes.audit_logs import audit_logs_bp
|
|
print("✓ Blueprint imported successfully")
|
|
print(f" Blueprint name: {audit_logs_bp.name}")
|
|
print(f" Blueprint routes: {len(audit_logs_bp.deferred_functions)}")
|
|
except Exception as e:
|
|
print(f"✗ Error importing blueprint: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
|
|
print("\n" + "=" * 60)
|
|
print("All routes containing 'audit':")
|
|
print("=" * 60)
|
|
for rule in app.url_map.iter_rules():
|
|
if 'audit' in rule.rule.lower():
|
|
print(f" {rule.rule} -> {rule.endpoint} ({', '.join(rule.methods)})")
|
|
|
|
except Exception as e:
|
|
print(f"Error: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
sys.exit(1)
|
|
|