355 lines
14 KiB
Python
355 lines
14 KiB
Python
"""
|
|
Serializers for Collaboration & War Rooms models
|
|
"""
|
|
from rest_framework import serializers
|
|
from django.contrib.auth import get_user_model
|
|
|
|
from ..models import (
|
|
WarRoom, ConferenceBridge, IncidentCommandRole,
|
|
TimelineEvent, WarRoomMessage, IncidentDecision,
|
|
MessageReaction, ChatFile, ChatCommand, ChatBot
|
|
)
|
|
from incident_intelligence.serializers.incident import IncidentSerializer
|
|
from security.serializers.security import UserSerializer
|
|
|
|
User = get_user_model()
|
|
|
|
|
|
class WarRoomSerializer(serializers.ModelSerializer):
|
|
"""Serializer for WarRoom model"""
|
|
|
|
incident = IncidentSerializer(read_only=True)
|
|
incident_id = serializers.UUIDField(write_only=True)
|
|
allowed_users = UserSerializer(many=True, read_only=True)
|
|
allowed_user_ids = serializers.ListField(
|
|
child=serializers.UUIDField(),
|
|
write_only=True,
|
|
required=False
|
|
)
|
|
created_by = UserSerializer(read_only=True)
|
|
created_by_id = serializers.UUIDField(write_only=True, required=False)
|
|
|
|
class Meta:
|
|
model = WarRoom
|
|
fields = [
|
|
'id', 'name', 'description', 'incident', 'incident_id',
|
|
'status', 'privacy_level', 'slack_channel_id', 'teams_channel_id',
|
|
'discord_channel_id', 'allowed_users', 'allowed_user_ids',
|
|
'required_clearance_level', 'message_count', 'last_activity',
|
|
'active_participants', 'created_by', 'created_by_id',
|
|
'created_at', 'updated_at', 'archived_at'
|
|
]
|
|
read_only_fields = ['id', 'created_at', 'updated_at', 'message_count', 'last_activity', 'active_participants']
|
|
|
|
def create(self, validated_data):
|
|
"""Create war room with allowed users"""
|
|
allowed_user_ids = validated_data.pop('allowed_user_ids', [])
|
|
war_room = WarRoom.objects.create(**validated_data)
|
|
|
|
# Add allowed users
|
|
if allowed_user_ids:
|
|
users = User.objects.filter(id__in=allowed_user_ids)
|
|
war_room.allowed_users.set(users)
|
|
|
|
return war_room
|
|
|
|
def update(self, instance, validated_data):
|
|
"""Update war room with allowed users"""
|
|
allowed_user_ids = validated_data.pop('allowed_user_ids', None)
|
|
|
|
# Update war room fields
|
|
for attr, value in validated_data.items():
|
|
setattr(instance, attr, value)
|
|
instance.save()
|
|
|
|
# Update allowed users if provided
|
|
if allowed_user_ids is not None:
|
|
users = User.objects.filter(id__in=allowed_user_ids)
|
|
instance.allowed_users.set(users)
|
|
|
|
return instance
|
|
|
|
|
|
class ConferenceBridgeSerializer(serializers.ModelSerializer):
|
|
"""Serializer for ConferenceBridge model"""
|
|
|
|
incident = IncidentSerializer(read_only=True)
|
|
incident_id = serializers.UUIDField(write_only=True)
|
|
war_room = WarRoomSerializer(read_only=True)
|
|
war_room_id = serializers.UUIDField(write_only=True, required=False)
|
|
invited_participants = UserSerializer(many=True, read_only=True)
|
|
invited_participant_ids = serializers.ListField(
|
|
child=serializers.UUIDField(),
|
|
write_only=True,
|
|
required=False
|
|
)
|
|
active_participants = UserSerializer(many=True, read_only=True)
|
|
created_by = UserSerializer(read_only=True)
|
|
created_by_id = serializers.UUIDField(write_only=True, required=False)
|
|
|
|
class Meta:
|
|
model = ConferenceBridge
|
|
fields = [
|
|
'id', 'name', 'description', 'incident', 'incident_id',
|
|
'war_room', 'war_room_id', 'bridge_type', 'status',
|
|
'meeting_id', 'meeting_url', 'dial_in_number', 'access_code',
|
|
'scheduled_start', 'scheduled_end', 'actual_start', 'actual_end',
|
|
'invited_participants', 'invited_participant_ids',
|
|
'active_participants', 'max_participants',
|
|
'recording_enabled', 'recording_url', 'transcription_enabled',
|
|
'transcription_url', 'integration_config',
|
|
'created_by', 'created_by_id', 'created_at', 'updated_at'
|
|
]
|
|
read_only_fields = ['id', 'created_at', 'updated_at', 'actual_start', 'actual_end', 'active_participants']
|
|
|
|
def create(self, validated_data):
|
|
"""Create conference bridge with invited participants"""
|
|
invited_participant_ids = validated_data.pop('invited_participant_ids', [])
|
|
conference = ConferenceBridge.objects.create(**validated_data)
|
|
|
|
# Add invited participants
|
|
if invited_participant_ids:
|
|
users = User.objects.filter(id__in=invited_participant_ids)
|
|
conference.invited_participants.set(users)
|
|
|
|
return conference
|
|
|
|
def update(self, instance, validated_data):
|
|
"""Update conference bridge with invited participants"""
|
|
invited_participant_ids = validated_data.pop('invited_participant_ids', None)
|
|
|
|
# Update conference fields
|
|
for attr, value in validated_data.items():
|
|
setattr(instance, attr, value)
|
|
instance.save()
|
|
|
|
# Update invited participants if provided
|
|
if invited_participant_ids is not None:
|
|
users = User.objects.filter(id__in=invited_participant_ids)
|
|
instance.invited_participants.set(users)
|
|
|
|
return instance
|
|
|
|
|
|
class IncidentCommandRoleSerializer(serializers.ModelSerializer):
|
|
"""Serializer for IncidentCommandRole model"""
|
|
|
|
incident = IncidentSerializer(read_only=True)
|
|
incident_id = serializers.UUIDField(write_only=True)
|
|
war_room = WarRoomSerializer(read_only=True)
|
|
war_room_id = serializers.UUIDField(write_only=True, required=False)
|
|
assigned_user = UserSerializer(read_only=True)
|
|
assigned_user_id = serializers.UUIDField(write_only=True, required=False)
|
|
reassigned_by = UserSerializer(read_only=True)
|
|
created_by = UserSerializer(read_only=True)
|
|
created_by_id = serializers.UUIDField(write_only=True, required=False)
|
|
|
|
class Meta:
|
|
model = IncidentCommandRole
|
|
fields = [
|
|
'id', 'incident', 'incident_id', 'war_room', 'war_room_id',
|
|
'role_type', 'assigned_user', 'assigned_user_id', 'status',
|
|
'responsibilities', 'decision_authority', 'assigned_at',
|
|
'reassigned_at', 'reassigned_by', 'assignment_notes',
|
|
'decisions_made', 'communications_sent', 'last_activity',
|
|
'created_by', 'created_by_id', 'created_at', 'updated_at'
|
|
]
|
|
read_only_fields = [
|
|
'id', 'assigned_at', 'reassigned_at', 'reassigned_by',
|
|
'decisions_made', 'communications_sent', 'last_activity',
|
|
'created_at', 'updated_at'
|
|
]
|
|
|
|
|
|
class TimelineEventSerializer(serializers.ModelSerializer):
|
|
"""Serializer for TimelineEvent model"""
|
|
|
|
incident = IncidentSerializer(read_only=True)
|
|
incident_id = serializers.UUIDField(write_only=True)
|
|
related_user = UserSerializer(read_only=True)
|
|
related_user_id = serializers.UUIDField(write_only=True, required=False)
|
|
created_by = UserSerializer(read_only=True)
|
|
created_by_id = serializers.UUIDField(write_only=True, required=False)
|
|
|
|
class Meta:
|
|
model = TimelineEvent
|
|
fields = [
|
|
'id', 'incident', 'incident_id', 'event_type', 'title',
|
|
'description', 'source_type', 'event_time', 'created_at',
|
|
'related_user', 'related_user_id', 'event_data', 'tags',
|
|
'is_critical_event', 'postmortem_notes',
|
|
'created_by', 'created_by_id'
|
|
]
|
|
read_only_fields = ['id', 'created_at']
|
|
|
|
|
|
class MessageReactionSerializer(serializers.ModelSerializer):
|
|
"""Serializer for MessageReaction model"""
|
|
|
|
user = UserSerializer(read_only=True)
|
|
|
|
class Meta:
|
|
model = MessageReaction
|
|
fields = ['id', 'user', 'emoji', 'created_at']
|
|
read_only_fields = ['id', 'created_at']
|
|
|
|
|
|
class ChatFileSerializer(serializers.ModelSerializer):
|
|
"""Serializer for ChatFile model"""
|
|
|
|
uploaded_by = UserSerializer(read_only=True)
|
|
|
|
class Meta:
|
|
model = ChatFile
|
|
fields = [
|
|
'id', 'message', 'filename', 'original_filename', 'file_type',
|
|
'file_size', 'mime_type', 'file_path', 'file_url',
|
|
'data_classification', 'is_encrypted', 'file_hash',
|
|
'uploaded_by', 'uploaded_at', 'access_log'
|
|
]
|
|
read_only_fields = ['id', 'uploaded_at', 'access_log']
|
|
|
|
|
|
class ChatCommandSerializer(serializers.ModelSerializer):
|
|
"""Serializer for ChatCommand model"""
|
|
|
|
executed_by = UserSerializer(read_only=True)
|
|
|
|
class Meta:
|
|
model = ChatCommand
|
|
fields = [
|
|
'id', 'message', 'command_type', 'command_text', 'parameters',
|
|
'executed_by', 'executed_at', 'execution_status',
|
|
'execution_result', 'error_message', 'automation_execution'
|
|
]
|
|
read_only_fields = ['id', 'executed_at']
|
|
|
|
|
|
class ChatBotSerializer(serializers.ModelSerializer):
|
|
"""Serializer for ChatBot model"""
|
|
|
|
class Meta:
|
|
model = ChatBot
|
|
fields = [
|
|
'id', 'name', 'bot_type', 'description', 'is_active',
|
|
'auto_respond', 'response_triggers', 'knowledge_base',
|
|
'created_at', 'updated_at'
|
|
]
|
|
read_only_fields = ['id', 'created_at', 'updated_at']
|
|
|
|
|
|
class WarRoomMessageSerializer(serializers.ModelSerializer):
|
|
"""Serializer for WarRoomMessage model"""
|
|
|
|
war_room = WarRoomSerializer(read_only=True)
|
|
war_room_id = serializers.UUIDField(write_only=True)
|
|
sender = UserSerializer(read_only=True)
|
|
sender_id = serializers.UUIDField(write_only=True, required=False)
|
|
reply_to = serializers.PrimaryKeyRelatedField(
|
|
queryset=WarRoomMessage.objects.all(),
|
|
required=False
|
|
)
|
|
pinned_by = UserSerializer(read_only=True)
|
|
mentioned_users = UserSerializer(many=True, read_only=True)
|
|
mentioned_user_ids = serializers.ListField(
|
|
child=serializers.UUIDField(),
|
|
write_only=True,
|
|
required=False
|
|
)
|
|
reactions = MessageReactionSerializer(many=True, read_only=True)
|
|
chat_files = ChatFileSerializer(many=True, read_only=True)
|
|
chat_commands = ChatCommandSerializer(many=True, read_only=True)
|
|
reactions_summary = serializers.SerializerMethodField()
|
|
|
|
class Meta:
|
|
model = WarRoomMessage
|
|
fields = [
|
|
'id', 'war_room', 'war_room_id', 'message_type', 'content',
|
|
'sender', 'sender_id', 'sender_name', 'is_edited', 'edited_at',
|
|
'is_pinned', 'pinned_at', 'pinned_by', 'reply_to',
|
|
'attachments', 'mentioned_users', 'mentioned_user_ids',
|
|
'notification_sent', 'external_message_id', 'external_data',
|
|
'is_encrypted', 'encryption_key_id', 'reactions', 'reactions_summary',
|
|
'chat_files', 'chat_commands', 'created_at', 'updated_at'
|
|
]
|
|
read_only_fields = [
|
|
'id', 'is_edited', 'edited_at', 'pinned_at', 'pinned_by',
|
|
'notification_sent', 'created_at', 'updated_at'
|
|
]
|
|
|
|
def get_reactions_summary(self, obj):
|
|
"""Get reactions summary for the message"""
|
|
return obj.get_reactions_summary()
|
|
|
|
def create(self, validated_data):
|
|
"""Create message with mentioned users"""
|
|
mentioned_user_ids = validated_data.pop('mentioned_user_ids', [])
|
|
message = WarRoomMessage.objects.create(**validated_data)
|
|
|
|
# Add mentioned users
|
|
if mentioned_user_ids:
|
|
users = User.objects.filter(id__in=mentioned_user_ids)
|
|
message.mentioned_users.set(users)
|
|
|
|
return message
|
|
|
|
|
|
class IncidentDecisionSerializer(serializers.ModelSerializer):
|
|
"""Serializer for IncidentDecision model"""
|
|
|
|
incident = IncidentSerializer(read_only=True)
|
|
incident_id = serializers.UUIDField(write_only=True)
|
|
command_role = IncidentCommandRoleSerializer(read_only=True)
|
|
command_role_id = serializers.UUIDField(write_only=True)
|
|
approved_by = UserSerializer(read_only=True)
|
|
implemented_by = UserSerializer(read_only=True)
|
|
|
|
class Meta:
|
|
model = IncidentDecision
|
|
fields = [
|
|
'id', 'incident', 'incident_id', 'command_role', 'command_role_id',
|
|
'decision_type', 'title', 'description', 'rationale', 'status',
|
|
'requires_approval', 'approved_by', 'approved_at',
|
|
'implementation_notes', 'implemented_at', 'implemented_by',
|
|
'impact_assessment', 'success_metrics', 'created_at', 'updated_at'
|
|
]
|
|
read_only_fields = [
|
|
'id', 'approved_by', 'approved_at', 'implemented_at',
|
|
'implemented_by', 'created_at', 'updated_at'
|
|
]
|
|
|
|
|
|
class WarRoomSummarySerializer(serializers.ModelSerializer):
|
|
"""Simplified serializer for WarRoom list views"""
|
|
|
|
incident_title = serializers.CharField(source='incident.title', read_only=True)
|
|
incident_severity = serializers.CharField(source='incident.severity', read_only=True)
|
|
participant_count = serializers.SerializerMethodField()
|
|
|
|
class Meta:
|
|
model = WarRoom
|
|
fields = [
|
|
'id', 'name', 'incident_title', 'incident_severity',
|
|
'status', 'privacy_level', 'message_count', 'last_activity',
|
|
'participant_count', 'created_at'
|
|
]
|
|
|
|
def get_participant_count(self, obj):
|
|
"""Get count of allowed users"""
|
|
return obj.allowed_users.count()
|
|
|
|
|
|
class TimelineEventSummarySerializer(serializers.ModelSerializer):
|
|
"""Simplified serializer for TimelineEvent list views"""
|
|
|
|
incident_title = serializers.CharField(source='incident.title', read_only=True)
|
|
related_user_name = serializers.CharField(source='related_user.username', read_only=True)
|
|
|
|
class Meta:
|
|
model = TimelineEvent
|
|
fields = [
|
|
'id', 'incident_title', 'event_type', 'title', 'description',
|
|
'source_type', 'event_time', 'related_user_name',
|
|
'is_critical_event', 'created_at'
|
|
]
|