""" Admin configuration for reports app. """ from django.contrib import admin from django.utils.html import format_html from django import forms from .models import ScamTag, ScamReport, ScamVerification, SiteSettings, TakedownRequest @admin.register(ScamTag) class ScamTagAdmin(admin.ModelAdmin): """Scam tag admin.""" list_display = ('name', 'slug', 'color') prepopulated_fields = {'slug': ('name',)} search_fields = ('name',) @admin.register(ScamReport) class ScamReportAdmin(admin.ModelAdmin): """Scam report admin.""" list_display = ('title', 'reporter', 'scam_type', 'status', 'verification_score', 'created_at') list_filter = ('status', 'scam_type', 'is_public', 'created_at') search_fields = ('title', 'description', 'reported_url', 'reported_email', 'reported_phone') readonly_fields = ('created_at', 'updated_at', 'verified_at', 'reporter_ip') filter_horizontal = ('tags',) date_hierarchy = 'created_at' fieldsets = ( ('Report Information', { 'fields': ('title', 'description', 'scam_type', 'tags') }), ('Reported Entities', { 'fields': ('reported_url', 'reported_email', 'reported_phone', 'reported_company') }), ('Reporter', { 'fields': ('reporter', 'is_anonymous', 'reporter_ip') }), ('Status', { 'fields': ('status', 'verification_score', 'is_public', 'verified_at') }), ('Evidence', { 'fields': ('evidence_files',) }), ('Timestamps', { 'fields': ('created_at', 'updated_at') }), ) @admin.register(ScamVerification) class ScamVerificationAdmin(admin.ModelAdmin): """Scam verification admin.""" list_display = ('report', 'verification_method', 'confidence_score', 'verified_by', 'created_at') list_filter = ('verification_method', 'created_at') search_fields = ('report__title', 'notes') readonly_fields = ('created_at',) @admin.register(SiteSettings) class SiteSettingsAdmin(admin.ModelAdmin): """Site settings admin - singleton pattern.""" def has_add_permission(self, request): # Only allow one instance return not SiteSettings.objects.exists() def has_delete_permission(self, request, obj=None): # Prevent deletion return False fieldsets = ( ('Контактна Информация', { 'fields': ('contact_email', 'contact_phone', 'contact_address'), 'description': 'Тези настройки се използват навсякъде в сайта - в подножието, страницата за контакти, структурираните данни и др.' }), ('Настройки на Имейл Сървър', { 'fields': ( 'email_backend', 'email_host', 'email_port', 'email_use_tls', 'email_use_ssl', 'email_host_user', 'email_host_password', 'default_from_email', 'email_timeout', ), 'description': 'Настройки за SMTP сървър. Използват се за всички имейли в платформата - контактни форми, нулиране на пароли, уведомления и др. Паролата се криптира автоматично.' }), ('Информация', { 'fields': ('updated_at',), 'classes': ('collapse',) }), ) readonly_fields = ('updated_at',) def get_form(self, request, obj=None, **kwargs): """Customize form to handle password field.""" form = super().get_form(request, obj, **kwargs) # Make password field a password input form.base_fields['email_host_password'].widget = forms.PasswordInput(attrs={ 'class': 'vTextField', 'autocomplete': 'new-password' }) # Add help text form.base_fields['email_host_password'].help_text = 'Въведете нова парола или оставете празно, за да запазите текущата.' return form def save_model(self, request, obj, form, change): """Handle password encryption and clear cache.""" # If password field is empty and we're editing, keep the old password if change and not form.cleaned_data.get('email_host_password'): old_obj = self.model.objects.get(pk=obj.pk) obj.email_host_password = old_obj.email_host_password # Validate TLS/SSL are mutually exclusive if obj.email_use_tls and obj.email_use_ssl: from django.contrib import messages messages.warning(request, 'TLS и SSL не могат да бъдат активирани едновременно. SSL е деактивиран, използва се TLS.') obj.email_use_ssl = False # Save will encrypt the password if it's provided super().save_model(request, obj, form, change) # Clear email backend cache to reload settings from django.core.cache import cache cache.delete('site_settings') def changelist_view(self, request, extra_context=None): # Redirect to the single instance if it exists from django.shortcuts import redirect from django.urls import reverse if SiteSettings.objects.exists(): obj = SiteSettings.objects.get(pk=1) url = reverse('admin:reports_sitesettings_change', args=[str(obj.pk)]) return redirect(url) return super().changelist_view(request, extra_context) def response_change(self, request, obj): """Handle test email button.""" if "_test_email" in request.POST: try: from django.core.mail import send_mail from django.contrib import messages test_email = request.POST.get('test_email_address', request.user.email) if not test_email: messages.error(request, 'Моля, въведете имейл адрес за тест.') return super().response_change(request, obj) # Check if SMTP is configured if obj.email_backend == 'django.core.mail.backends.smtp.EmailBackend' and not obj.email_host: messages.warning(request, 'SMTP сървърът не е конфигуриран. Моля, въведете Email Host преди изпращане на тестов имейл.') return super().response_change(request, obj) # Get the connection to check backend type from django.core.mail import get_connection, EmailMessage connection = get_connection() backend_name = connection.__class__.__name__ import logging logger = logging.getLogger(__name__) logger.info(f"Using email backend: {backend_name}") # Check underlying backend if hasattr(connection, '_backend') and connection._backend: underlying_backend = connection._backend.__class__.__name__ logger.info(f"Underlying backend: {underlying_backend}") # Send email using EmailMessage for better error handling email = EmailMessage( subject='Тестов Имейл от Портал за Докладване на Измами', body='Това е тестов имейл за проверка на настройките на имейл сървъра. Ако получавате този имейл, настройките са правилни.', from_email=obj.default_from_email, to=[test_email], connection=connection, ) result = email.send(fail_silently=False) logger.info(f"Email send result: {result} (1 = success, 0 = failed)") # Check which backend was actually used if 'Console' in backend_name or 'console' in str(connection.__class__.__module__): messages.warning(request, f'Имейлът е изпратен чрез конзолен backend (за разработка). За реално изпращане, конфигурирайте SMTP настройките. Backend: {backend_name}') else: messages.success(request, f'Тестов имейл изпратен успешно до {test_email}! Използван backend: {backend_name}') except Exception as e: import logging logger = logging.getLogger(__name__) logger.exception("Error sending test email") error_msg = str(e) if 'authentication failed' in error_msg.lower(): messages.error(request, f'Грешка при удостоверяване: Проверете потребителското име и паролата.') elif 'connection' in error_msg.lower() or 'timeout' in error_msg.lower(): messages.error(request, f'Грешка при свързване: Проверете SMTP сървъра и порта.') else: messages.error(request, f'Грешка при изпращане на тестов имейл: {error_msg}') return super().response_change(request, obj) def changeform_view(self, request, object_id=None, form_url='', extra_context=None): extra_context = extra_context or {} if object_id: obj = self.get_object(request, object_id) if obj: extra_context['show_test_email'] = True return super().changeform_view(request, object_id, form_url, extra_context) @admin.register(TakedownRequest) class TakedownRequestAdmin(admin.ModelAdmin): """Takedown request admin.""" list_display = ('report', 'requester_name', 'requester_email', 'status', 'created_at', 'reviewed_by') list_filter = ('status', 'created_at', 'reviewed_at') search_fields = ('requester_name', 'requester_email', 'report__title', 'reason') readonly_fields = ('created_at', 'updated_at', 'ip_address', 'user_agent') date_hierarchy = 'created_at' fieldsets = ( ('Информация за Доклада', { 'fields': ('report',) }), ('Информация за Заявителя', { 'fields': ('requester_name', 'requester_email', 'requester_phone') }), ('Детайли на Заявката', { 'fields': ('reason', 'evidence') }), ('Статус и Преглед', { 'fields': ('status', 'reviewed_by', 'review_notes', 'reviewed_at') }), ('Техническа Информация', { 'fields': ('ip_address', 'user_agent', 'created_at', 'updated_at'), 'classes': ('collapse',) }), ) def save_model(self, request, obj, form, change): if change and 'status' in form.changed_data and obj.status in ['approved', 'rejected']: from django.utils import timezone obj.reviewed_by = request.user obj.reviewed_at = timezone.now() super().save_model(request, obj, form, change)