from datetime import timedelta from django.contrib import messages from django.db.models import Count, Q from django.shortcuts import redirect, render from django.utils import timezone from django.utils.translation import gettext as _ from .backup_ops import create_backup_bundle, latest_backup_health_snapshot, list_backup_bundles, verify_backup_bundle from .models import AdminAuditLog, AsyncTaskLog, UserNotification, UserProfile from .roles import user_has_capability def job_monitor_page_impl(request): status_filter = (request.GET.get('status') or '').strip() task_filter = (request.GET.get('task') or '').strip() logs = AsyncTaskLog.objects.all() if status_filter: logs = logs.filter(status=status_filter) if task_filter: logs = logs.filter(task_name=task_filter) logs = logs.order_by('-started_at', '-id')[:200] task_names = list(AsyncTaskLog.objects.order_by('task_name').values_list('task_name', flat=True).distinct()) since = timezone.now() - timedelta(hours=24) recent_logs = AsyncTaskLog.objects.filter(started_at__gte=since) counts = {row['status']: row['count'] for row in recent_logs.values('status').annotate(count=Count('id'))} recent_failed = list(AsyncTaskLog.objects.filter(status='failed').order_by('-started_at', '-id')[:5]) can_manage_backups = user_has_capability(request.user, 'manage_backups') return render( request, 'workflows/job_monitor.html', { 'logs': logs, 'status_filter': status_filter, 'task_filter': task_filter, 'task_names': task_names, 'status_choices': [('started', _('Gestartet')), ('succeeded', _('Erfolgreich')), ('failed', _('Fehlgeschlagen'))], 'job_summary': { 'started_count_24h': counts.get('started', 0), 'success_count_24h': counts.get('succeeded', 0), 'failed_count_24h': counts.get('failed', 0), 'recent_failed': recent_failed, 'can_manage_backups': can_manage_backups, 'backup_health': latest_backup_health_snapshot() if can_manage_backups else None, }, }, ) def audit_log_page_impl(request): action = (request.GET.get('action') or '').strip() user_query = (request.GET.get('user') or '').strip() date_from = (request.GET.get('date_from') or '').strip() date_to = (request.GET.get('date_to') or '').strip() rows_qs = AdminAuditLog.objects.select_related('actor').all() if action: rows_qs = rows_qs.filter(action=action) if user_query: rows_qs = rows_qs.filter( Q(actor_display__icontains=user_query) | Q(actor__username__icontains=user_query) | Q(actor__email__icontains=user_query) ) if date_from: rows_qs = rows_qs.filter(created_at__date__gte=date_from) if date_to: rows_qs = rows_qs.filter(created_at__date__lte=date_to) rows = list(rows_qs[:300]) action_choices = AdminAuditLog.objects.order_by('action').values_list('action', flat=True).distinct() return render( request, 'workflows/audit_log.html', { 'rows': rows, 'action_choices': action_choices, 'selected_action': action, 'user_query': user_query, 'date_from': date_from, 'date_to': date_to, }, ) def backup_recovery_page_impl(request): rows = list_backup_bundles() return render( request, 'workflows/backup_recovery.html', { 'rows': rows, 'backup_health': latest_backup_health_snapshot(), }, ) def create_backup_from_admin_impl(request, *, audit_fn, notify_user_fn, create_backup_bundle_fn): try: result = create_backup_bundle_fn() audit_fn( request, 'backup_created', target_type='backup_bundle', target_label=result['name'], details={'path': result['path']}, ) notify_user_fn( user=request.user, title=_('Backup erstellt: %(name)s') % {'name': result['name']}, body=_('Das Backup-Bundle wurde erfolgreich erstellt.'), level=UserNotification.LEVEL_SUCCESS, link_url='/admin-tools/backups/', event_key=UserProfile.NOTIFICATION_BACKUP_SUCCESS, ) messages.success(request, _('Backup wurde erstellt: %(name)s') % {'name': result['name']}) except Exception as exc: notify_user_fn( user=request.user, title=_('Backup fehlgeschlagen'), body=str(exc), level=UserNotification.LEVEL_ERROR, link_url='/admin-tools/backups/', event_key=UserProfile.NOTIFICATION_BACKUP_FAILURE, ) messages.error(request, _('Backup konnte nicht erstellt werden: %(error)s') % {'error': exc}) return redirect('backup_recovery_page') def verify_backup_from_admin_impl(request, backup_name: str, *, audit_fn, notify_user_fn, verify_backup_bundle_fn): try: result = verify_backup_bundle_fn(backup_name) audit_fn( request, 'backup_verified', target_type='backup_bundle', target_label=backup_name, details={'summary': result['summary']}, ) notify_user_fn( user=request.user, title=_('Backup verifiziert: %(name)s') % {'name': result['name']}, body=result.get('summary') or _('Das Backup wurde erfolgreich verifiziert.'), level=UserNotification.LEVEL_SUCCESS, link_url='/admin-tools/backups/', event_key=UserProfile.NOTIFICATION_BACKUP_SUCCESS, ) messages.success(request, _('Backup wurde verifiziert: %(name)s') % {'name': result['name']}) except Exception as exc: notify_user_fn( user=request.user, title=_('Backup-Verifikation fehlgeschlagen'), body=str(exc), level=UserNotification.LEVEL_ERROR, link_url='/admin-tools/backups/', event_key=UserProfile.NOTIFICATION_BACKUP_FAILURE, ) messages.error(request, _('Backup-Verifikation fehlgeschlagen: %(error)s') % {'error': exc}) return redirect('backup_recovery_page')