""" Legal compliance and GDPR models. """ from django.db import models from django.contrib.auth import get_user_model from django.utils import timezone User = get_user_model() class ConsentRecord(models.Model): """ Track user consent for GDPR compliance. """ CONSENT_TYPE_CHOICES = [ ('privacy_policy', 'Privacy Policy'), ('terms_of_service', 'Terms of Service'), ('data_processing', 'Data Processing'), ('marketing', 'Marketing Communications'), ('cookies', 'Cookie Consent'), ] user = models.ForeignKey( User, on_delete=models.CASCADE, related_name='consents', null=True, blank=True ) consent_type = models.CharField( max_length=50, choices=CONSENT_TYPE_CHOICES ) consent_given = models.BooleanField(default=False) ip_address = models.GenericIPAddressField(null=True, blank=True) user_agent = models.TextField(blank=True) timestamp = models.DateTimeField(auto_now_add=True) version = models.CharField( max_length=20, blank=True, help_text='Version of the policy/terms' ) class Meta: db_table = 'legal_consentrecord' verbose_name = 'Consent Record' verbose_name_plural = 'Consent Records' ordering = ['-timestamp'] indexes = [ models.Index(fields=['user', 'consent_type']), models.Index(fields=['consent_type', 'timestamp']), ] def __str__(self): status = "Given" if self.consent_given else "Not Given" return f"{self.get_consent_type_display()} - {status} - {self.timestamp}" class DataRequest(models.Model): """ GDPR data subject requests (access, deletion, portability). """ REQUEST_TYPE_CHOICES = [ ('access', 'Data Access Request'), ('deletion', 'Data Deletion Request'), ('portability', 'Data Portability Request'), ('rectification', 'Data Rectification Request'), ('objection', 'Objection to Processing'), ('restriction', 'Restriction of Processing'), ] STATUS_CHOICES = [ ('pending', 'Pending'), ('in_progress', 'In Progress'), ('completed', 'Completed'), ('rejected', 'Rejected'), ] user = models.ForeignKey( User, on_delete=models.CASCADE, related_name='data_requests' ) request_type = models.CharField( max_length=50, choices=REQUEST_TYPE_CHOICES ) status = models.CharField( max_length=20, choices=STATUS_CHOICES, default='pending' ) description = models.TextField( blank=True, help_text='Additional details about the request' ) requested_at = models.DateTimeField(auto_now_add=True) completed_at = models.DateTimeField(null=True, blank=True) response_data = models.JSONField( default=dict, blank=True, help_text='Response data (e.g., exported data)' ) response_file = models.FileField( upload_to='data_requests/', blank=True, null=True, help_text='File containing requested data' ) handled_by = models.ForeignKey( User, on_delete=models.SET_NULL, null=True, blank=True, related_name='handled_data_requests', limit_choices_to={'role': 'admin'} ) notes = models.TextField( blank=True, help_text='Internal notes about handling the request' ) class Meta: db_table = 'legal_datarequest' verbose_name = 'Data Request' verbose_name_plural = 'Data Requests' ordering = ['-requested_at'] indexes = [ models.Index(fields=['user', 'status']), models.Index(fields=['request_type', 'status']), models.Index(fields=['status', 'requested_at']), ] def __str__(self): return f"{self.get_request_type_display()} by {self.user.username} - {self.get_status_display()}" class SecurityEvent(models.Model): """ Security event logging for compliance and monitoring. """ EVENT_TYPE_CHOICES = [ ('login_success', 'Successful Login'), ('login_failed', 'Failed Login'), ('password_change', 'Password Changed'), ('account_locked', 'Account Locked'), ('suspicious_activity', 'Suspicious Activity'), ('data_breach', 'Data Breach'), ('unauthorized_access', 'Unauthorized Access Attempt'), ('file_upload', 'File Upload'), ('data_export', 'Data Export'), ('admin_action', 'Admin Action'), ] SEVERITY_CHOICES = [ ('low', 'Low'), ('medium', 'Medium'), ('high', 'High'), ('critical', 'Critical'), ] event_type = models.CharField( max_length=50, choices=EVENT_TYPE_CHOICES ) user = models.ForeignKey( User, on_delete=models.SET_NULL, null=True, blank=True, related_name='security_events' ) ip_address = models.GenericIPAddressField(null=True, blank=True) user_agent = models.TextField(blank=True) details = models.JSONField( default=dict, blank=True, help_text='Additional event details' ) severity = models.CharField( max_length=20, choices=SEVERITY_CHOICES, default='low' ) timestamp = models.DateTimeField(auto_now_add=True) resolved = models.BooleanField(default=False) resolved_at = models.DateTimeField(null=True, blank=True) resolved_by = models.ForeignKey( User, on_delete=models.SET_NULL, null=True, blank=True, related_name='resolved_security_events', limit_choices_to={'role': 'admin'} ) class Meta: db_table = 'security_securityevent' verbose_name = 'Security Event' verbose_name_plural = 'Security Events' ordering = ['-timestamp'] indexes = [ models.Index(fields=['event_type', 'timestamp']), models.Index(fields=['severity', 'timestamp']), models.Index(fields=['user', 'timestamp']), models.Index(fields=['resolved', 'timestamp']), ] def __str__(self): return f"{self.get_event_type_display()} - {self.get_severity_display()} - {self.timestamp}"