feat: Implement group-restricted Live Sessions & IP Monitoring and 1-click Admin Email Confirmation

This commit is contained in:
Richard
2026-08-01 12:26:44 +02:00
parent 4b13e57fcb
commit 7614163f78
15 changed files with 943 additions and 665 deletions
+67 -1
View File
@@ -1,10 +1,14 @@
from rest_framework import views, viewsets, permissions, status
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.authtoken.models import Token
from django.contrib.auth import authenticate, get_user_model
from django.shortcuts import get_object_or_404
from django.core.mail import get_connection, EmailMultiAlternatives
from .models import RegistrationDomainRule, RegistrationRestrictionSetting, GuestClaimToken, EmailVerificationToken, SMTPSetting
from .models import (
RegistrationDomainRule, RegistrationRestrictionSetting, GuestClaimToken,
EmailVerificationToken, SMTPSetting, UserActivity
)
from .serializers import (
UserSerializer, AdminUserSerializer, RegisterSerializer,
RegistrationDomainRuleSerializer, RegistrationRestrictionSettingSerializer, SMTPSettingSerializer
@@ -80,6 +84,17 @@ class AdminUserViewSet(viewsets.ModelViewSet):
user_to_delete.delete()
return Response({'message': f'Benutzer "{name}" wurde erfolgreich gelöscht.'})
@action(detail=True, methods=['post'], url_path='confirm-email')
def confirm_email(self, request, pk=None):
target_user = self.get_object()
target_user.is_email_verified = True
target_user.is_approved = True
target_user.save()
EmailVerificationToken.objects.filter(user=target_user).update(is_used=True)
return Response({
'message': f'E-Mail-Adresse von {target_user.get_display_name()} ({target_user.email}) wurde manuell von dir als bestätigt markiert.'
})
class RegisterView(views.APIView):
permission_classes = [permissions.AllowAny]
@@ -406,3 +421,54 @@ class UserListView(views.APIView):
def get(self, request):
users = User.objects.filter(is_active=True).order_by('username')
return Response(UserSerializer(users, many=True).data)
SESSION_MONITOR_GROUP = "Session Monitor"
class IsSessionMonitorGroupOrSuperuser(permissions.BasePermission):
def has_permission(self, request, view):
if not request.user or not request.user.is_authenticated:
return False
if request.user.is_superuser:
return True
return request.user.groups.filter(name=SESSION_MONITOR_GROUP).exists()
class ActiveSessionsView(views.APIView):
permission_classes = [IsSessionMonitorGroupOrSuperuser]
def get(self, request):
from datetime import timedelta
from django.utils import timezone
cutoff = timezone.now() - timedelta(hours=24)
activities = UserActivity.objects.filter(last_seen__gte=cutoff).select_related('user').order_by('-last_seen')
data = []
for act in activities:
user_info = None
if act.user:
user_info = {
'id': act.user.id,
'username': act.user.username,
'email': act.user.email,
'display_name': act.user.get_display_name(),
'is_admin': act.user.is_admin_user or act.user.is_staff or act.user.is_superuser,
}
data.append({
'id': act.id,
'user': user_info,
'guest_name': act.guest_name if not act.user else None,
'display_name': act.user.get_display_name() if act.user else (act.guest_name or "Unangemeldeter Gast"),
'session_key': act.session_key[:12] + '...',
'ip_address': act.ip_address or '127.0.0.1',
'user_agent': act.user_agent,
'last_path': act.last_path,
'last_seen': act.last_seen.isoformat(),
})
return Response({
'group_name': SESSION_MONITOR_GROUP,
'is_authorized': True,
'count': len(data),
'sessions': data
})