feat(logs): add workspace activity log api

This commit is contained in:
2026-04-28 16:42:37 +03:30
parent c8a118788b
commit 71924ce6fb
32 changed files with 1118 additions and 122 deletions

80
apps/logs/api/views.py Normal file
View File

@@ -0,0 +1,80 @@
from auditlog.models import LogEntry
from django.shortcuts import get_object_or_404
from rest_framework import status, viewsets
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from apps.logs.api.permissions import enforce_workspace_log_access
from apps.logs.api.serializers import (
WorkspaceLogDetailSerializer,
WorkspaceLogListSerializer,
WorkspaceLogQuerySerializer,
)
from apps.logs.services import (
WorkspaceLogFilters,
filter_workspace_logs,
get_log_workspace_id,
is_visible_workspace_log,
parse_filter_datetime,
)
from apps.workspaces.models import Workspace
from core.paginations.limit_offset import CustomLimitOffsetPagination
class WorkspaceLogViewSet(viewsets.ReadOnlyModelViewSet):
permission_classes = [IsAuthenticated]
pagination_class = CustomLimitOffsetPagination
def get_queryset(self):
return LogEntry.objects.select_related("actor", "content_type").order_by("-timestamp")
def get_serializer_class(self):
if self.action == "retrieve":
return WorkspaceLogDetailSerializer
return WorkspaceLogListSerializer
def list(self, request, *args, **kwargs):
query_data = request.query_params.copy()
if "from" in query_data:
query_data["from_date"] = query_data.get("from")
if "to" in query_data:
query_data["to_date"] = query_data.get("to")
query_serializer = WorkspaceLogQuerySerializer(data=query_data)
query_serializer.is_valid(raise_exception=True)
filters_data = query_serializer.validated_data
workspace = get_object_or_404(
Workspace,
id=filters_data["workspace"],
is_deleted=False,
)
enforce_workspace_log_access(request.user, workspace)
filters = WorkspaceLogFilters(
workspace_id=str(workspace.id),
section=filters_data.get("section"),
actor_id=str(filters_data["actor"]) if filters_data.get("actor") else None,
event=filters_data.get("event"),
search=filters_data.get("search") or None,
from_value=parse_filter_datetime(query_data.get("from")),
to_value=parse_filter_datetime(query_data.get("to"), is_end=True),
ordering=filters_data.get("ordering", "-timestamp"),
)
queryset = filter_workspace_logs(self.get_queryset(), filters)
page = self.paginate_queryset(queryset)
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
def retrieve(self, request, *args, **kwargs):
entry = self.get_object()
workspace_id = get_log_workspace_id(entry)
if not workspace_id:
return Response({"detail": "Not found."}, status=status.HTTP_404_NOT_FOUND)
workspace = get_object_or_404(Workspace, id=workspace_id, is_deleted=False)
enforce_workspace_log_access(request.user, workspace)
if not is_visible_workspace_log(entry):
return Response({"detail": "Not found."}, status=status.HTTP_404_NOT_FOUND)
serializer = self.get_serializer(entry)
return Response(serializer.data)