Реализовал систему разрешений

This commit is contained in:
2025-12-15 11:45:25 +03:00
parent ca7709ebff
commit 46dc79b93f
33 changed files with 1340 additions and 124 deletions

View File

@@ -32,12 +32,14 @@ from .models import (
Geo,
ObjItem,
CustomUser,
UserPermission,
Band,
Source,
TechAnalyze,
SourceRequest,
SourceRequestStatusHistory,
)
from .permissions import PERMISSIONS, DEFAULT_ROLE_PERMISSIONS
from .filters import (
GeoKupDistanceFilter,
GeoValidDistanceFilter,
@@ -99,6 +101,19 @@ class CustomUserInline(admin.StackedInline):
model = CustomUser
can_delete = False
verbose_name_plural = "Дополнительная информация пользователя"
filter_horizontal = ('user_permissions',)
fieldsets = (
(None, {
'fields': ('role',)
}),
('Индивидуальные разрешения', {
'fields': ('use_custom_permissions', 'user_permissions'),
'classes': ('collapse',),
'description': 'Если включено "Использовать индивидуальные разрешения", '
'будут использоваться выбранные разрешения вместо прав роли по умолчанию.'
}),
)
class LocationForm(forms.ModelForm):
@@ -195,6 +210,88 @@ class UserAdmin(BaseUserAdmin):
admin.site.register(User, UserAdmin)
class UserPermissionForm(forms.ModelForm):
"""Форма для UserPermission с выбором из списка разрешений."""
code = forms.ChoiceField(
choices=[],
label="Код разрешения",
help_text="Выберите разрешение из списка"
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['code'].choices = PERMISSIONS[:28] # Используем PERMISSION_CHOICES
# Преобразуем в формат (code, name)
self.fields['code'].choices = [(code, name) for code, name, _ in PERMISSIONS]
class Meta:
model = UserPermission
fields = ['code']
@admin.register(UserPermission)
class UserPermissionAdmin(BaseAdmin):
"""Админ-панель для модели UserPermission."""
form = UserPermissionForm
list_display = ('code', 'get_name', 'get_description')
search_fields = ('code',)
ordering = ('code',)
def get_name(self, obj):
"""Возвращает название разрешения."""
from .permissions import PERMISSION_CHOICES
choices_dict = dict(PERMISSION_CHOICES)
return choices_dict.get(obj.code, '-')
get_name.short_description = 'Название'
def get_description(self, obj):
"""Возвращает описание разрешения."""
from .permissions import PERMISSION_DESCRIPTIONS
return PERMISSION_DESCRIPTIONS.get(obj.code, '-')
get_description.short_description = 'Описание'
@admin.register(CustomUser)
class CustomUserAdmin(BaseAdmin):
"""Админ-панель для модели CustomUser с управлением разрешениями."""
list_display = ('user', 'role', 'use_custom_permissions', 'permissions_count')
list_filter = ('role', 'use_custom_permissions')
search_fields = ('user__username', 'user__first_name', 'user__last_name')
filter_horizontal = ('user_permissions',)
ordering = ('user__username',)
fieldsets = (
('Основная информация', {
'fields': ('user', 'role')
}),
('Индивидуальные разрешения', {
'fields': ('use_custom_permissions', 'user_permissions'),
'description': 'Если включено "Использовать индивидуальные разрешения", '
'будут использоваться выбранные разрешения вместо прав роли по умолчанию.'
}),
)
def permissions_count(self, obj):
"""Показывает количество индивидуальных разрешений."""
if obj.use_custom_permissions:
count = obj.user_permissions.count()
return f'{count} (индивид.)'
return f'По роли ({obj.role})'
permissions_count.short_description = 'Разрешения'
def get_readonly_fields(self, request, obj=None):
"""User поле только для чтения при редактировании."""
if obj:
return ('user',)
return ()
class Media:
js = ('admin/js/permissions_admin.js',)
# ============================================================================
# Custom Admin Actions
# ============================================================================