snapshot: modularize workflow views by domain
This commit is contained in:
160
backend/workflows/observability_views.py
Normal file
160
backend/workflows/observability_views.py
Normal file
@@ -0,0 +1,160 @@
|
||||
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 .notifications import notify_user
|
||||
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):
|
||||
try:
|
||||
result = create_backup_bundle()
|
||||
audit_fn(
|
||||
request,
|
||||
'backup_created',
|
||||
target_type='backup_bundle',
|
||||
target_label=result['name'],
|
||||
details={'path': result['path']},
|
||||
)
|
||||
notify_user(
|
||||
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(
|
||||
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):
|
||||
try:
|
||||
result = verify_backup_bundle(backup_name)
|
||||
audit_fn(
|
||||
request,
|
||||
'backup_verified',
|
||||
target_type='backup_bundle',
|
||||
target_label=backup_name,
|
||||
details={'summary': result['summary']},
|
||||
)
|
||||
notify_user(
|
||||
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(
|
||||
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')
|
||||
Reference in New Issue
Block a user