Updates
This commit is contained in:
1
ETB-API/collaboration_war_rooms/views/__init__.py
Normal file
1
ETB-API/collaboration_war_rooms/views/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
# Views for Collaboration & War Rooms module
|
||||
Binary file not shown.
Binary file not shown.
646
ETB-API/collaboration_war_rooms/views/collaboration.py
Normal file
646
ETB-API/collaboration_war_rooms/views/collaboration.py
Normal file
@@ -0,0 +1,646 @@
|
||||
"""
|
||||
Views for Collaboration & War Rooms module
|
||||
"""
|
||||
from rest_framework import viewsets, status, permissions
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.response import Response
|
||||
from django_filters.rest_framework import DjangoFilterBackend
|
||||
from rest_framework.filters import SearchFilter, OrderingFilter
|
||||
from django.db.models import Q
|
||||
from django.utils import timezone
|
||||
|
||||
from ..models import (
|
||||
WarRoom, ConferenceBridge, IncidentCommandRole,
|
||||
TimelineEvent, WarRoomMessage, IncidentDecision,
|
||||
MessageReaction, ChatFile, ChatCommand, ChatBot
|
||||
)
|
||||
from ..serializers.collaboration import (
|
||||
WarRoomSerializer, ConferenceBridgeSerializer, IncidentCommandRoleSerializer,
|
||||
TimelineEventSerializer, WarRoomMessageSerializer, IncidentDecisionSerializer,
|
||||
WarRoomSummarySerializer, TimelineEventSummarySerializer,
|
||||
MessageReactionSerializer, ChatFileSerializer, ChatCommandSerializer, ChatBotSerializer
|
||||
)
|
||||
from incident_intelligence.models import Incident
|
||||
|
||||
|
||||
class WarRoomViewSet(viewsets.ModelViewSet):
|
||||
"""ViewSet for WarRoom model"""
|
||||
|
||||
queryset = WarRoom.objects.all()
|
||||
serializer_class = WarRoomSerializer
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
|
||||
filterset_fields = ['status', 'privacy_level', 'incident__severity']
|
||||
search_fields = ['name', 'description', 'incident__title']
|
||||
ordering_fields = ['created_at', 'last_activity', 'message_count']
|
||||
ordering = ['-created_at']
|
||||
|
||||
def get_queryset(self):
|
||||
"""Filter war rooms based on user access"""
|
||||
queryset = super().get_queryset()
|
||||
user = self.request.user
|
||||
|
||||
# Filter by user access
|
||||
accessible_war_rooms = []
|
||||
for war_room in queryset:
|
||||
if war_room.can_user_access(user):
|
||||
accessible_war_rooms.append(war_room.id)
|
||||
|
||||
return queryset.filter(id__in=accessible_war_rooms)
|
||||
|
||||
def get_serializer_class(self):
|
||||
"""Return appropriate serializer based on action"""
|
||||
if self.action == 'list':
|
||||
return WarRoomSummarySerializer
|
||||
return WarRoomSerializer
|
||||
|
||||
@action(detail=True, methods=['post'])
|
||||
def add_participant(self, request, pk=None):
|
||||
"""Add a participant to the war room"""
|
||||
war_room = self.get_object()
|
||||
user_id = request.data.get('user_id')
|
||||
|
||||
if not user_id:
|
||||
return Response(
|
||||
{'error': 'user_id is required'},
|
||||
status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
|
||||
try:
|
||||
from django.contrib.auth import get_user_model
|
||||
User = get_user_model()
|
||||
user = User.objects.get(id=user_id)
|
||||
|
||||
if war_room.can_user_access(user):
|
||||
war_room.add_participant(user)
|
||||
return Response({'message': 'Participant added successfully'})
|
||||
else:
|
||||
return Response(
|
||||
{'error': 'User does not have access to this war room'},
|
||||
status=status.HTTP_403_FORBIDDEN
|
||||
)
|
||||
except User.DoesNotExist:
|
||||
return Response(
|
||||
{'error': 'User not found'},
|
||||
status=status.HTTP_404_NOT_FOUND
|
||||
)
|
||||
|
||||
@action(detail=True, methods=['post'])
|
||||
def remove_participant(self, request, pk=None):
|
||||
"""Remove a participant from the war room"""
|
||||
war_room = self.get_object()
|
||||
user_id = request.data.get('user_id')
|
||||
|
||||
if not user_id:
|
||||
return Response(
|
||||
{'error': 'user_id is required'},
|
||||
status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
|
||||
try:
|
||||
from django.contrib.auth import get_user_model
|
||||
User = get_user_model()
|
||||
user = User.objects.get(id=user_id)
|
||||
|
||||
war_room.remove_participant(user)
|
||||
return Response({'message': 'Participant removed successfully'})
|
||||
except User.DoesNotExist:
|
||||
return Response(
|
||||
{'error': 'User not found'},
|
||||
status=status.HTTP_404_NOT_FOUND
|
||||
)
|
||||
|
||||
@action(detail=True, methods=['get'])
|
||||
def messages(self, request, pk=None):
|
||||
"""Get messages for a war room"""
|
||||
war_room = self.get_object()
|
||||
messages = war_room.messages.all().order_by('created_at')
|
||||
|
||||
# Apply pagination
|
||||
page = self.paginate_queryset(messages)
|
||||
if page is not None:
|
||||
serializer = WarRoomMessageSerializer(page, many=True)
|
||||
return self.get_paginated_response(serializer.data)
|
||||
|
||||
serializer = WarRoomMessageSerializer(messages, many=True)
|
||||
return Response(serializer.data)
|
||||
|
||||
@action(detail=True, methods=['get'])
|
||||
def pinned_messages(self, request, pk=None):
|
||||
"""Get pinned messages for a war room"""
|
||||
war_room = self.get_object()
|
||||
pinned_messages = war_room.messages.filter(is_pinned=True).order_by('-pinned_at')
|
||||
|
||||
serializer = WarRoomMessageSerializer(pinned_messages, many=True)
|
||||
return Response(serializer.data)
|
||||
|
||||
@action(detail=True, methods=['post'])
|
||||
def create_chat_room(self, request, pk=None):
|
||||
"""Auto-create chat room for incident"""
|
||||
incident = self.get_object()
|
||||
|
||||
# Check if war room already exists for this incident
|
||||
existing_war_room = WarRoom.objects.filter(incident=incident).first()
|
||||
if existing_war_room:
|
||||
return Response(
|
||||
{'message': 'War room already exists for this incident', 'war_room_id': existing_war_room.id},
|
||||
status=status.HTTP_200_OK
|
||||
)
|
||||
|
||||
# Create new war room
|
||||
war_room = WarRoom.objects.create(
|
||||
name=f"Incident Chat - {incident.title}",
|
||||
description=f"Chat room for incident: {incident.title}",
|
||||
incident=incident,
|
||||
created_by=request.user,
|
||||
privacy_level='PRIVATE'
|
||||
)
|
||||
|
||||
# Add incident reporter and assignee to war room
|
||||
if incident.reporter:
|
||||
war_room.add_participant(incident.reporter)
|
||||
if incident.assigned_to:
|
||||
war_room.add_participant(incident.assigned_to)
|
||||
|
||||
# Create timeline event
|
||||
TimelineEvent.create_system_event(
|
||||
incident=incident,
|
||||
event_type='WAR_ROOM_CREATED',
|
||||
title='War Room Created',
|
||||
description=f'War room "{war_room.name}" was automatically created for incident collaboration',
|
||||
event_data={'war_room_id': str(war_room.id)}
|
||||
)
|
||||
|
||||
serializer = WarRoomSerializer(war_room)
|
||||
return Response(serializer.data, status=status.HTTP_201_CREATED)
|
||||
|
||||
|
||||
class ConferenceBridgeViewSet(viewsets.ModelViewSet):
|
||||
"""ViewSet for ConferenceBridge model"""
|
||||
|
||||
queryset = ConferenceBridge.objects.all()
|
||||
serializer_class = ConferenceBridgeSerializer
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
|
||||
filterset_fields = ['bridge_type', 'status', 'incident__severity']
|
||||
search_fields = ['name', 'description', 'incident__title']
|
||||
ordering_fields = ['scheduled_start', 'created_at']
|
||||
ordering = ['-scheduled_start']
|
||||
|
||||
def get_queryset(self):
|
||||
"""Filter conference bridges based on user access"""
|
||||
queryset = super().get_queryset()
|
||||
user = self.request.user
|
||||
|
||||
# Filter by user access
|
||||
accessible_conferences = []
|
||||
for conference in queryset:
|
||||
if conference.can_user_join(user):
|
||||
accessible_conferences.append(conference.id)
|
||||
|
||||
return queryset.filter(id__in=accessible_conferences)
|
||||
|
||||
@action(detail=True, methods=['post'])
|
||||
def join_conference(self, request, pk=None):
|
||||
"""Join a conference"""
|
||||
conference = self.get_object()
|
||||
user = request.user
|
||||
|
||||
if conference.can_user_join(user):
|
||||
conference.add_participant(user)
|
||||
return Response({'message': 'Successfully joined conference'})
|
||||
else:
|
||||
return Response(
|
||||
{'error': 'You do not have permission to join this conference'},
|
||||
status=status.HTTP_403_FORBIDDEN
|
||||
)
|
||||
|
||||
@action(detail=True, methods=['post'])
|
||||
def start_conference(self, request, pk=None):
|
||||
"""Start a conference"""
|
||||
conference = self.get_object()
|
||||
|
||||
if conference.status == 'SCHEDULED':
|
||||
conference.status = 'ACTIVE'
|
||||
conference.actual_start = timezone.now()
|
||||
conference.save()
|
||||
|
||||
return Response({'message': 'Conference started successfully'})
|
||||
else:
|
||||
return Response(
|
||||
{'error': 'Conference cannot be started in current status'},
|
||||
status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
|
||||
@action(detail=True, methods=['post'])
|
||||
def end_conference(self, request, pk=None):
|
||||
"""End a conference"""
|
||||
conference = self.get_object()
|
||||
|
||||
if conference.status == 'ACTIVE':
|
||||
conference.status = 'ENDED'
|
||||
conference.actual_end = timezone.now()
|
||||
conference.save()
|
||||
|
||||
return Response({'message': 'Conference ended successfully'})
|
||||
else:
|
||||
return Response(
|
||||
{'error': 'Conference cannot be ended in current status'},
|
||||
status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
|
||||
|
||||
class IncidentCommandRoleViewSet(viewsets.ModelViewSet):
|
||||
"""ViewSet for IncidentCommandRole model"""
|
||||
|
||||
queryset = IncidentCommandRole.objects.all()
|
||||
serializer_class = IncidentCommandRoleSerializer
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
|
||||
filterset_fields = ['role_type', 'status', 'incident__severity']
|
||||
search_fields = ['incident__title', 'assigned_user__username']
|
||||
ordering_fields = ['assigned_at', 'created_at']
|
||||
ordering = ['-assigned_at']
|
||||
|
||||
def get_queryset(self):
|
||||
"""Filter command roles based on user access"""
|
||||
queryset = super().get_queryset()
|
||||
user = self.request.user
|
||||
|
||||
# Filter by incident access
|
||||
accessible_incidents = []
|
||||
for role in queryset:
|
||||
if role.incident.is_accessible_by_user(user):
|
||||
accessible_incidents.append(role.incident.id)
|
||||
|
||||
return queryset.filter(incident_id__in=accessible_incidents)
|
||||
|
||||
@action(detail=True, methods=['post'])
|
||||
def reassign_role(self, request, pk=None):
|
||||
"""Reassign a command role to a new user"""
|
||||
command_role = self.get_object()
|
||||
new_user_id = request.data.get('new_user_id')
|
||||
notes = request.data.get('notes', '')
|
||||
|
||||
if not new_user_id:
|
||||
return Response(
|
||||
{'error': 'new_user_id is required'},
|
||||
status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
|
||||
try:
|
||||
from django.contrib.auth import get_user_model
|
||||
User = get_user_model()
|
||||
new_user = User.objects.get(id=new_user_id)
|
||||
|
||||
command_role.reassign_role(new_user, request.user, notes)
|
||||
return Response({'message': 'Role reassigned successfully'})
|
||||
except User.DoesNotExist:
|
||||
return Response(
|
||||
{'error': 'User not found'},
|
||||
status=status.HTTP_404_NOT_FOUND
|
||||
)
|
||||
|
||||
|
||||
class TimelineEventViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""ViewSet for TimelineEvent model (read-only)"""
|
||||
|
||||
queryset = TimelineEvent.objects.all()
|
||||
serializer_class = TimelineEventSerializer
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
|
||||
filterset_fields = ['event_type', 'source_type', 'is_critical_event', 'incident__severity']
|
||||
search_fields = ['title', 'description', 'incident__title']
|
||||
ordering_fields = ['event_time', 'created_at']
|
||||
ordering = ['event_time']
|
||||
|
||||
def get_serializer_class(self):
|
||||
"""Return appropriate serializer based on action"""
|
||||
if self.action == 'list':
|
||||
return TimelineEventSummarySerializer
|
||||
return TimelineEventSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
"""Filter timeline events based on user access"""
|
||||
queryset = super().get_queryset()
|
||||
user = self.request.user
|
||||
|
||||
# Filter by incident access
|
||||
accessible_incidents = []
|
||||
for event in queryset:
|
||||
if event.incident.is_accessible_by_user(user):
|
||||
accessible_incidents.append(event.incident.id)
|
||||
|
||||
return queryset.filter(incident_id__in=accessible_incidents)
|
||||
|
||||
@action(detail=False, methods=['get'])
|
||||
def critical_events(self, request):
|
||||
"""Get critical events for postmortem analysis"""
|
||||
queryset = self.get_queryset().filter(is_critical_event=True)
|
||||
|
||||
# Apply pagination
|
||||
page = self.paginate_queryset(queryset)
|
||||
if page is not None:
|
||||
serializer = self.get_serializer(page, many=True)
|
||||
return self.get_paginated_response(serializer.data)
|
||||
|
||||
serializer = self.get_serializer(queryset, many=True)
|
||||
return Response(serializer.data)
|
||||
|
||||
|
||||
class WarRoomMessageViewSet(viewsets.ModelViewSet):
|
||||
"""ViewSet for WarRoomMessage model"""
|
||||
|
||||
queryset = WarRoomMessage.objects.all()
|
||||
serializer_class = WarRoomMessageSerializer
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
|
||||
filterset_fields = ['message_type', 'war_room', 'sender', 'is_pinned']
|
||||
search_fields = ['content', 'sender_name']
|
||||
ordering_fields = ['created_at', 'pinned_at']
|
||||
ordering = ['created_at']
|
||||
|
||||
def get_queryset(self):
|
||||
"""Filter messages based on war room access"""
|
||||
queryset = super().get_queryset()
|
||||
user = self.request.user
|
||||
|
||||
# Filter by war room access
|
||||
accessible_war_rooms = []
|
||||
for message in queryset:
|
||||
if message.war_room.can_user_access(user):
|
||||
accessible_war_rooms.append(message.war_room.id)
|
||||
|
||||
return queryset.filter(war_room_id__in=accessible_war_rooms)
|
||||
|
||||
@action(detail=True, methods=['post'])
|
||||
def pin_message(self, request, pk=None):
|
||||
"""Pin a message"""
|
||||
message = self.get_object()
|
||||
message.pin_message(request.user)
|
||||
|
||||
# Create timeline event
|
||||
TimelineEvent.create_user_event(
|
||||
incident=message.war_room.incident,
|
||||
user=request.user,
|
||||
event_type='MANUAL_EVENT',
|
||||
title='Message Pinned',
|
||||
description=f'Message "{message.content[:50]}..." was pinned by {request.user.username}',
|
||||
event_data={'message_id': str(message.id), 'action': 'pinned'}
|
||||
)
|
||||
|
||||
return Response({'message': 'Message pinned successfully'})
|
||||
|
||||
@action(detail=True, methods=['post'])
|
||||
def unpin_message(self, request, pk=None):
|
||||
"""Unpin a message"""
|
||||
message = self.get_object()
|
||||
message.unpin_message()
|
||||
|
||||
return Response({'message': 'Message unpinned successfully'})
|
||||
|
||||
@action(detail=True, methods=['post'])
|
||||
def add_reaction(self, request, pk=None):
|
||||
"""Add a reaction to a message"""
|
||||
message = self.get_object()
|
||||
emoji = request.data.get('emoji')
|
||||
|
||||
if not emoji:
|
||||
return Response(
|
||||
{'error': 'emoji is required'},
|
||||
status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
|
||||
reaction = message.add_reaction(request.user, emoji)
|
||||
serializer = MessageReactionSerializer(reaction)
|
||||
return Response(serializer.data)
|
||||
|
||||
@action(detail=True, methods=['post'])
|
||||
def remove_reaction(self, request, pk=None):
|
||||
"""Remove a reaction from a message"""
|
||||
message = self.get_object()
|
||||
emoji = request.data.get('emoji')
|
||||
|
||||
if not emoji:
|
||||
return Response(
|
||||
{'error': 'emoji is required'},
|
||||
status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
|
||||
message.remove_reaction(request.user, emoji)
|
||||
return Response({'message': 'Reaction removed successfully'})
|
||||
|
||||
@action(detail=True, methods=['post'])
|
||||
def execute_command(self, request, pk=None):
|
||||
"""Execute a ChatOps command"""
|
||||
message = self.get_object()
|
||||
command_text = request.data.get('command_text')
|
||||
|
||||
if not command_text:
|
||||
return Response(
|
||||
{'error': 'command_text is required'},
|
||||
status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
|
||||
# Parse command
|
||||
command_type = self._parse_command_type(command_text)
|
||||
parameters = self._parse_command_parameters(command_text)
|
||||
|
||||
# Create chat command
|
||||
chat_command = ChatCommand.objects.create(
|
||||
message=message,
|
||||
command_type=command_type,
|
||||
command_text=command_text,
|
||||
parameters=parameters
|
||||
)
|
||||
|
||||
# Execute command
|
||||
result = chat_command.execute_command(request.user)
|
||||
|
||||
serializer = ChatCommandSerializer(chat_command)
|
||||
return Response(serializer.data)
|
||||
|
||||
def _parse_command_type(self, command_text):
|
||||
"""Parse command type from command text"""
|
||||
command_text = command_text.lower().strip()
|
||||
|
||||
if command_text.startswith('/status'):
|
||||
return 'STATUS'
|
||||
elif command_text.startswith('/runbook'):
|
||||
return 'RUNBOOK'
|
||||
elif command_text.startswith('/escalate'):
|
||||
return 'ESCALATE'
|
||||
elif command_text.startswith('/assign'):
|
||||
return 'ASSIGN'
|
||||
elif command_text.startswith('/update'):
|
||||
return 'UPDATE'
|
||||
else:
|
||||
return 'CUSTOM'
|
||||
|
||||
def _parse_command_parameters(self, command_text):
|
||||
"""Parse command parameters from command text"""
|
||||
parts = command_text.split()
|
||||
if len(parts) > 1:
|
||||
return {'args': parts[1:]}
|
||||
return {}
|
||||
|
||||
|
||||
class IncidentDecisionViewSet(viewsets.ModelViewSet):
|
||||
"""ViewSet for IncidentDecision model"""
|
||||
|
||||
queryset = IncidentDecision.objects.all()
|
||||
serializer_class = IncidentDecisionSerializer
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
|
||||
filterset_fields = ['decision_type', 'status', 'incident__severity']
|
||||
search_fields = ['title', 'description', 'incident__title']
|
||||
ordering_fields = ['created_at', 'approved_at', 'implemented_at']
|
||||
ordering = ['-created_at']
|
||||
|
||||
def get_queryset(self):
|
||||
"""Filter decisions based on incident access"""
|
||||
queryset = super().get_queryset()
|
||||
user = self.request.user
|
||||
|
||||
# Filter by incident access
|
||||
accessible_incidents = []
|
||||
for decision in queryset:
|
||||
if decision.incident.is_accessible_by_user(user):
|
||||
accessible_incidents.append(decision.incident.id)
|
||||
|
||||
return queryset.filter(incident_id__in=accessible_incidents)
|
||||
|
||||
@action(detail=True, methods=['post'])
|
||||
def approve_decision(self, request, pk=None):
|
||||
"""Approve a decision"""
|
||||
decision = self.get_object()
|
||||
|
||||
if decision.status == 'PENDING':
|
||||
decision.approve(request.user)
|
||||
return Response({'message': 'Decision approved successfully'})
|
||||
else:
|
||||
return Response(
|
||||
{'error': 'Decision cannot be approved in current status'},
|
||||
status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
|
||||
@action(detail=True, methods=['post'])
|
||||
def implement_decision(self, request, pk=None):
|
||||
"""Mark a decision as implemented"""
|
||||
decision = self.get_object()
|
||||
notes = request.data.get('notes', '')
|
||||
|
||||
if decision.status == 'APPROVED':
|
||||
decision.implement(request.user, notes)
|
||||
return Response({'message': 'Decision implemented successfully'})
|
||||
else:
|
||||
return Response(
|
||||
{'error': 'Decision must be approved before implementation'},
|
||||
status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
|
||||
|
||||
class MessageReactionViewSet(viewsets.ModelViewSet):
|
||||
"""ViewSet for MessageReaction model"""
|
||||
|
||||
queryset = MessageReaction.objects.all()
|
||||
serializer_class = MessageReactionSerializer
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
|
||||
filterset_fields = ['message', 'user', 'emoji']
|
||||
ordering_fields = ['created_at']
|
||||
ordering = ['created_at']
|
||||
|
||||
|
||||
class ChatFileViewSet(viewsets.ModelViewSet):
|
||||
"""ViewSet for ChatFile model"""
|
||||
|
||||
queryset = ChatFile.objects.all()
|
||||
serializer_class = ChatFileSerializer
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
|
||||
filterset_fields = ['message', 'file_type', 'data_classification']
|
||||
search_fields = ['filename', 'original_filename']
|
||||
ordering_fields = ['uploaded_at', 'file_size']
|
||||
ordering = ['-uploaded_at']
|
||||
|
||||
def get_queryset(self):
|
||||
"""Filter files based on message access"""
|
||||
queryset = super().get_queryset()
|
||||
user = self.request.user
|
||||
|
||||
# Filter by message access
|
||||
accessible_messages = []
|
||||
for file_obj in queryset:
|
||||
if file_obj.message.war_room.can_user_access(user):
|
||||
accessible_messages.append(file_obj.message.id)
|
||||
|
||||
return queryset.filter(message_id__in=accessible_messages)
|
||||
|
||||
@action(detail=True, methods=['post'])
|
||||
def log_access(self, request, pk=None):
|
||||
"""Log file access for audit trail"""
|
||||
file_obj = self.get_object()
|
||||
file_obj.log_access(request.user)
|
||||
return Response({'message': 'Access logged successfully'})
|
||||
|
||||
|
||||
class ChatCommandViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
"""ViewSet for ChatCommand model (read-only)"""
|
||||
|
||||
queryset = ChatCommand.objects.all()
|
||||
serializer_class = ChatCommandSerializer
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
|
||||
filterset_fields = ['command_type', 'execution_status', 'executed_by']
|
||||
search_fields = ['command_text']
|
||||
ordering_fields = ['executed_at', 'created_at']
|
||||
ordering = ['-executed_at']
|
||||
|
||||
def get_queryset(self):
|
||||
"""Filter commands based on message access"""
|
||||
queryset = super().get_queryset()
|
||||
user = self.request.user
|
||||
|
||||
# Filter by message access
|
||||
accessible_messages = []
|
||||
for command in queryset:
|
||||
if command.message.war_room.can_user_access(user):
|
||||
accessible_messages.append(command.message.id)
|
||||
|
||||
return queryset.filter(message_id__in=accessible_messages)
|
||||
|
||||
|
||||
class ChatBotViewSet(viewsets.ModelViewSet):
|
||||
"""ViewSet for ChatBot model"""
|
||||
|
||||
queryset = ChatBot.objects.all()
|
||||
serializer_class = ChatBotSerializer
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
|
||||
filterset_fields = ['bot_type', 'is_active']
|
||||
search_fields = ['name', 'description']
|
||||
ordering_fields = ['name', 'created_at']
|
||||
ordering = ['name']
|
||||
|
||||
@action(detail=True, methods=['post'])
|
||||
def generate_response(self, request, pk=None):
|
||||
"""Generate AI response to a message"""
|
||||
bot = self.get_object()
|
||||
message_id = request.data.get('message_id')
|
||||
|
||||
if not message_id:
|
||||
return Response(
|
||||
{'error': 'message_id is required'},
|
||||
status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
|
||||
try:
|
||||
message = WarRoomMessage.objects.get(id=message_id)
|
||||
response = bot.generate_response(message, request.data.get('context', {}))
|
||||
return Response(response)
|
||||
except WarRoomMessage.DoesNotExist:
|
||||
return Response(
|
||||
{'error': 'Message not found'},
|
||||
status=status.HTTP_404_NOT_FOUND
|
||||
)
|
||||
Reference in New Issue
Block a user