# apps/core/admin.py - Админка для управления системными настройками
from django import forms
from django.contrib import admin
from django.contrib import messages
from django.contrib.auth.hashers import make_password
from django.utils.html import format_html
from django.urls import reverse
from django.utils.safestring import mark_safe
from django.core.exceptions import ValidationError
from .models import SystemSettings, RoomActivityLog
class SystemSettingsForm(forms.ModelForm):
"""Кастомная форма для системных настроек"""
new_password = forms.CharField(
widget=forms.PasswordInput,
required=False,
label='Новый пароль',
help_text='Введите новый пароль для входа в систему (минимум 6 символов)'
)
confirm_password = forms.CharField(
widget=forms.PasswordInput,
required=False,
label='Подтвердите пароль',
help_text='Повторите новый пароль'
)
class Meta:
model = SystemSettings
fields = ['is_active']
def clean(self):
"""Валидация формы"""
cleaned_data = super().clean()
new_password = cleaned_data.get('new_password')
confirm_password = cleaned_data.get('confirm_password')
if new_password or confirm_password:
if not new_password:
raise ValidationError('Введите новый пароль')
if not confirm_password:
raise ValidationError('Подтвердите пароль')
if new_password != confirm_password:
raise ValidationError('Пароли не совпадают')
if len(new_password) < 6:
raise ValidationError('Пароль должен содержать минимум 6 символов')
return cleaned_data
@admin.register(SystemSettings)
class SystemSettingsAdmin(admin.ModelAdmin):
"""
Админ-интерфейс для управления системными настройками
"""
form = SystemSettingsForm
list_display = ('id', 'is_active', 'created_at', 'updated_at', 'password_status')
list_filter = ('is_active', 'created_at', 'updated_at')
readonly_fields = ('created_at', 'updated_at', 'password_hash_preview')
fieldsets = (
('Основные настройки', {
'fields': ('is_active',)
}),
('Безопасность', {
'fields': ('new_password', 'confirm_password', 'password_hash_preview'),
'description': 'Установите новый пароль для доступа к системе'
}),
('Информация', {
'fields': ('created_at', 'updated_at'),
'classes': ('collapse',)
})
)
def save_model(self, request, obj, form, change):
"""Обработка сохранения с проверкой пароля"""
new_password = form.cleaned_data.get('new_password')
if new_password:
obj.set_password(new_password)
self.message_user(
request,
'Пароль успешно изменен',
level=messages.SUCCESS
)
super().save_model(request, obj, form, change)
def password_status(self, obj):
"""Статус пароля"""
if obj.access_password_hash:
return format_html(
'✓ Установлен'
)
return format_html(
'✗ Не установлен'
)
password_status.short_description = 'Статус пароля'
def password_hash_preview(self, obj):
"""Превью хеша пароля"""
if obj.access_password_hash:
hash_preview = obj.access_password_hash[:20] + '...' if len(obj.access_password_hash) > 20 else obj.access_password_hash
return format_html(
'{}',
hash_preview
)
return 'Пароль не установлен'
password_hash_preview.short_description = 'Хеш пароля'
def has_add_permission(self, request):
"""Ограничиваем создание - должен быть только один экземпляр настроек"""
if SystemSettings.objects.exists():
return False
return True
def has_delete_permission(self, request, obj=None):
"""Запрещаем удаление системных настроек"""
return False
def get_queryset(self, request):
"""Возвращаем queryset"""
return super().get_queryset(request)
class Media:
css = {
'all': ('admin/css/custom_admin.css',)
}
@admin.register(RoomActivityLog)
class RoomActivityLogAdmin(admin.ModelAdmin):
"""
Админ-интерфейс для просмотра логов активности комнат
"""
list_display = ('room_id_short', 'action', 'participant_count', 'timestamp', 'ip_address')
list_filter = ('action', 'timestamp')
search_fields = ('room_id',)
readonly_fields = ('room_id', 'action', 'timestamp', 'participant_count', 'ip_address', 'user_agent_hash')
date_hierarchy = 'timestamp'
ordering = ('-timestamp',)
def room_id_short(self, obj):
"""Короткое отображение ID комнаты"""
if obj.room_id:
return f"{obj.room_id[:8]}..."
return 'N/A'
room_id_short.short_description = 'Room ID'
def has_add_permission(self, request):
"""Запрещаем ручное добавление логов"""
return False
def has_change_permission(self, request, obj=None):
"""Запрещаем изменение логов"""
return False
def has_delete_permission(self, request, obj=None):
"""Разрешаем удаление только суперпользователям"""
return request.user.is_superuser
# Дополнительные действия
actions = ['delete_old_logs']
def delete_old_logs(self, request, queryset):
"""Удаление старых логов"""
from datetime import datetime, timedelta
old_date = datetime.now() - timedelta(days=30)
count = RoomActivityLog.objects.filter(timestamp__lt=old_date).delete()[0]
self.message_user(request, f'Удалено {count} старых записей (старше 30 дней)')
delete_old_logs.short_description = 'Удалить логи старше 30 дней'
# Кастомизация админки
admin.site.site_header = 'Video Call Administration'
admin.site.site_title = 'Video Call Admin'
admin.site.index_title = 'Управление системой видеозвонков'