feat: add user roles management UI with owner access control

- Added role management views (list, create, edit, delete)
- Created user_roles URL routing
- Added role management templates with Bootstrap styling
- Updated navbar with Roles link for owners and superusers
- Enhanced decorators and mixins with superuser bypass
- Added assign_owner_role.py utility script

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-12-01 21:24:27 +03:00
parent 9f48ae0a35
commit 14cc73722f
11 changed files with 479 additions and 2 deletions

View File

@@ -1,3 +1,110 @@
from django.shortcuts import render
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.contrib.auth import get_user_model
from user_roles.models import Role, UserRole
from user_roles.services import RoleService
from user_roles.decorators import owner_required
# Create your views here.
User = get_user_model()
@login_required
@owner_required
def user_role_list(request):
"""Список пользователей с их ролями"""
user_roles = UserRole.objects.select_related('user', 'role', 'created_by').all()
roles = Role.objects.all()
context = {
'user_roles': user_roles,
'roles': roles,
}
return render(request, 'user_roles/user_role_list.html', context)
@login_required
@owner_required
def user_role_create(request):
"""Создание нового пользователя с ролью"""
if request.method == 'POST':
email = request.POST.get('email')
name = request.POST.get('name')
role_code = request.POST.get('role')
password = request.POST.get('password', User.objects.make_random_password(12))
try:
# Создаем пользователя
user = User.objects.create_user(
email=email,
name=name,
password=password,
is_email_confirmed=True
)
# Назначаем роль
RoleService.assign_role_to_user(user, role_code, created_by=request.user)
messages.success(request, f'Пользователь {email} создан с ролью {role_code}. Пароль: {password}')
return redirect('user_roles:list')
except Exception as e:
messages.error(request, f'Ошибка при создании пользователя: {str(e)}')
roles = Role.objects.all()
context = {
'roles': roles,
}
return render(request, 'user_roles/user_role_create.html', context)
@login_required
@owner_required
def user_role_edit(request, pk):
"""Изменение роли пользователя"""
user_role = get_object_or_404(UserRole, pk=pk)
if request.method == 'POST':
role_code = request.POST.get('role')
is_active = request.POST.get('is_active') == 'on'
try:
# Обновляем роль
role = RoleService.get_role_by_code(role_code)
if not role:
raise ValueError(f"Роль '{role_code}' не найдена")
user_role.role = role
user_role.is_active = is_active
user_role.save()
messages.success(request, f'Роль пользователя {user_role.user.email} обновлена')
return redirect('user_roles:list')
except Exception as e:
messages.error(request, f'Ошибка при обновлении роли: {str(e)}')
roles = Role.objects.all()
context = {
'user_role': user_role,
'roles': roles,
}
return render(request, 'user_roles/user_role_edit.html', context)
@login_required
@owner_required
def user_role_delete(request, pk):
"""Удаление роли пользователя (отключение доступа)"""
user_role = get_object_or_404(UserRole, pk=pk)
if request.method == 'POST':
email = user_role.user.email
user_role.delete()
messages.success(request, f'Доступ пользователя {email} удален')
return redirect('user_roles:list')
context = {
'user_role': user_role,
}
return render(request, 'user_roles/user_role_delete.html', context)