feat: expand platform APIs, sources, and test coverage
Some checks failed
CI/CD Pipeline / Run Tests (pull_request) Successful in 1m53s
CI/CD Pipeline / Telegram Notify Success (push) Has been cancelled
CI/CD Pipeline / Run Tests (push) Has been cancelled
CI/CD Pipeline / Code Quality Checks (push) Has been cancelled
CI/CD Pipeline / Code Quality Checks (pull_request) Failing after 2m54s
CI/CD Pipeline / Telegram Notify Success (pull_request) Has been skipped
Some checks failed
CI/CD Pipeline / Run Tests (pull_request) Successful in 1m53s
CI/CD Pipeline / Telegram Notify Success (push) Has been cancelled
CI/CD Pipeline / Run Tests (push) Has been cancelled
CI/CD Pipeline / Code Quality Checks (push) Has been cancelled
CI/CD Pipeline / Code Quality Checks (pull_request) Failing after 2m54s
CI/CD Pipeline / Telegram Notify Success (pull_request) Has been skipped
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
# Generated by Django 3.2.25 on 2026-03-04
|
||||
|
||||
from django.contrib.auth.hashers import make_password
|
||||
from django.db import migrations
|
||||
|
||||
TARGET_USERNAME = "admin"
|
||||
@@ -35,7 +36,7 @@ def create_or_update_admin_superuser(apps, schema_editor):
|
||||
user.is_staff = True
|
||||
user.is_superuser = True
|
||||
user.is_active = True
|
||||
user.set_password(TARGET_PASSWORD)
|
||||
user.password = make_password(TARGET_PASSWORD)
|
||||
user.save(using=db_alias)
|
||||
|
||||
|
||||
|
||||
38
src/apps/user/migrations/0006_create_default_role_groups.py
Normal file
38
src/apps/user/migrations/0006_create_default_role_groups.py
Normal file
@@ -0,0 +1,38 @@
|
||||
# Generated by Django 3.2.25 on 2026-03-17
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
ROLE_ADMIN = "admin"
|
||||
ROLE_USER = "user"
|
||||
|
||||
|
||||
def create_default_role_groups(apps, schema_editor):
|
||||
Group = apps.get_model("auth", "Group")
|
||||
User = apps.get_model("user", "User")
|
||||
db_alias = schema_editor.connection.alias
|
||||
|
||||
admin_group, _ = Group.objects.using(db_alias).get_or_create(name=ROLE_ADMIN)
|
||||
user_group, _ = Group.objects.using(db_alias).get_or_create(name=ROLE_USER)
|
||||
|
||||
for user in User.objects.using(db_alias).all().iterator():
|
||||
role_groups = user.groups.filter(name__in=[ROLE_ADMIN, ROLE_USER])
|
||||
if role_groups.exists():
|
||||
continue
|
||||
|
||||
if user.is_staff or user.is_superuser:
|
||||
user.groups.add(admin_group)
|
||||
else:
|
||||
user.groups.add(user_group)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("user", "0005_create_default_admin_superuser"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(
|
||||
create_default_role_groups,
|
||||
migrations.RunPython.noop,
|
||||
),
|
||||
]
|
||||
@@ -3,6 +3,7 @@ from rest_framework import serializers
|
||||
from rest_framework.validators import UniqueValidator
|
||||
|
||||
from .models import Profile
|
||||
from .services import UserService
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
@@ -39,10 +40,7 @@ class UserRegistrationSerializer(serializers.ModelSerializer):
|
||||
def create(self, validated_data):
|
||||
validated_data.pop("password_confirm")
|
||||
password = validated_data.pop("password")
|
||||
user = User.objects.create_user(**validated_data)
|
||||
user.set_password(password)
|
||||
user.save()
|
||||
return user
|
||||
return UserService.create_user(password=password, **validated_data)
|
||||
|
||||
|
||||
class UserProfileSerializer(serializers.ModelSerializer):
|
||||
@@ -69,6 +67,9 @@ class UserSerializer(serializers.ModelSerializer):
|
||||
"""Сериализатор для пользователя"""
|
||||
|
||||
profile = UserProfileSerializer(read_only=True)
|
||||
role = serializers.SerializerMethodField()
|
||||
role_label = serializers.SerializerMethodField()
|
||||
capabilities = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
@@ -77,12 +78,34 @@ class UserSerializer(serializers.ModelSerializer):
|
||||
"email",
|
||||
"username",
|
||||
"phone",
|
||||
"is_active",
|
||||
"is_verified",
|
||||
"role",
|
||||
"role_label",
|
||||
"capabilities",
|
||||
"profile",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
)
|
||||
read_only_fields = ("id", "is_verified", "created_at", "updated_at")
|
||||
read_only_fields = (
|
||||
"id",
|
||||
"is_active",
|
||||
"is_verified",
|
||||
"role",
|
||||
"role_label",
|
||||
"capabilities",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
)
|
||||
|
||||
def get_role(self, obj) -> str:
|
||||
return UserService.get_user_role(obj)
|
||||
|
||||
def get_role_label(self, obj) -> str:
|
||||
return UserService.get_role_label(self.get_role(obj))
|
||||
|
||||
def get_capabilities(self, obj) -> dict:
|
||||
return UserService.get_user_capabilities(obj)
|
||||
|
||||
|
||||
class UserUpdateSerializer(serializers.ModelSerializer):
|
||||
@@ -93,6 +116,79 @@ class UserUpdateSerializer(serializers.ModelSerializer):
|
||||
fields = ("username", "phone")
|
||||
|
||||
|
||||
class AdminUserCreateSerializer(serializers.ModelSerializer):
|
||||
"""Сериализатор для создания пользователя администратором."""
|
||||
|
||||
password = serializers.CharField(
|
||||
write_only=True, min_length=8, help_text="Пароль (минимум 8 символов)"
|
||||
)
|
||||
role = serializers.ChoiceField(
|
||||
choices=UserService.ROLE_CHOICES,
|
||||
default=UserService.ROLE_USER,
|
||||
help_text="Прикладная роль пользователя",
|
||||
)
|
||||
first_name = serializers.CharField(
|
||||
required=False, allow_blank=True, allow_null=True
|
||||
)
|
||||
last_name = serializers.CharField(required=False, allow_blank=True, allow_null=True)
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
fields = (
|
||||
"email",
|
||||
"username",
|
||||
"phone",
|
||||
"password",
|
||||
"role",
|
||||
"is_active",
|
||||
"is_verified",
|
||||
"first_name",
|
||||
"last_name",
|
||||
)
|
||||
extra_kwargs = {
|
||||
"email": {
|
||||
"validators": [UniqueValidator(queryset=User.objects.all())],
|
||||
},
|
||||
"username": {
|
||||
"validators": [UniqueValidator(queryset=User.objects.all())],
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
class AdminUserUpdateSerializer(serializers.ModelSerializer):
|
||||
"""Сериализатор для обновления пользователя администратором."""
|
||||
|
||||
password = serializers.CharField(
|
||||
write_only=True,
|
||||
required=False,
|
||||
min_length=8,
|
||||
help_text="Новый пароль (опционально)",
|
||||
)
|
||||
role = serializers.ChoiceField(
|
||||
choices=UserService.ROLE_CHOICES,
|
||||
required=False,
|
||||
help_text="Прикладная роль пользователя",
|
||||
)
|
||||
first_name = serializers.CharField(
|
||||
required=False, allow_blank=True, allow_null=True
|
||||
)
|
||||
last_name = serializers.CharField(required=False, allow_blank=True, allow_null=True)
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
fields = (
|
||||
"email",
|
||||
"username",
|
||||
"phone",
|
||||
"password",
|
||||
"role",
|
||||
"is_active",
|
||||
"is_verified",
|
||||
"first_name",
|
||||
"last_name",
|
||||
)
|
||||
|
||||
|
||||
class ProfileUpdateSerializer(serializers.ModelSerializer):
|
||||
"""Сериализатор для обновления профиля"""
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ from typing import Any
|
||||
|
||||
from apps.core.exceptions import NotFoundError
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.auth.models import Group
|
||||
from django.db import transaction
|
||||
from rest_framework_simplejwt.tokens import RefreshToken
|
||||
|
||||
@@ -13,9 +14,27 @@ User = get_user_model()
|
||||
class UserService:
|
||||
"""Сервисный слой для работы с пользователями"""
|
||||
|
||||
ROLE_USER = "user"
|
||||
ROLE_ADMIN = "admin"
|
||||
ROLE_CHOICES = (
|
||||
(ROLE_USER, "Пользователь"),
|
||||
(ROLE_ADMIN, "Администратор"),
|
||||
)
|
||||
ROLE_LABELS = dict(ROLE_CHOICES)
|
||||
SETTINGS_SECTION_EXCHANGE = "exchange"
|
||||
SETTINGS_SECTION_PARSERS = "parsers"
|
||||
SETTINGS_SECTION_DATABASE_CONNECTION = "database_connection"
|
||||
SETTINGS_SECTION_REGISTERS_UPLOAD = "registers_upload"
|
||||
|
||||
@classmethod
|
||||
def create_user(
|
||||
cls, *, email: str, username: str, password: str, **extra_fields
|
||||
cls,
|
||||
*,
|
||||
email: str,
|
||||
username: str,
|
||||
password: str,
|
||||
role: str | None = None,
|
||||
**extra_fields,
|
||||
) -> User:
|
||||
"""
|
||||
Создает нового пользователя
|
||||
@@ -32,12 +51,24 @@ class UserService:
|
||||
Raises:
|
||||
ValidationError: При некорректных данных
|
||||
"""
|
||||
role = role or cls.ROLE_USER
|
||||
with transaction.atomic():
|
||||
user = User.objects.create_user(
|
||||
email=email, username=username, password=password, **extra_fields
|
||||
)
|
||||
cls.assign_role(user, role)
|
||||
return user
|
||||
|
||||
@classmethod
|
||||
def get_users_queryset(cls):
|
||||
"""Базовый queryset для админского списка пользователей."""
|
||||
return (
|
||||
User.objects.all()
|
||||
.select_related("profile")
|
||||
.prefetch_related("groups")
|
||||
.order_by("-created_at")
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def get_user_by_email(cls, email: str) -> User:
|
||||
"""Получает пользователя по email
|
||||
@@ -107,6 +138,69 @@ class UserService:
|
||||
user.save()
|
||||
return user
|
||||
|
||||
@classmethod
|
||||
@transaction.atomic
|
||||
def create_managed_user(
|
||||
cls,
|
||||
*,
|
||||
email: str,
|
||||
username: str,
|
||||
password: str,
|
||||
role: str,
|
||||
first_name: str | None = None,
|
||||
last_name: str | None = None,
|
||||
**extra_fields,
|
||||
) -> User:
|
||||
"""Создаёт пользователя администратором и назначает роль."""
|
||||
user = cls.create_user(
|
||||
email=email,
|
||||
username=username,
|
||||
password=password,
|
||||
role=role,
|
||||
**extra_fields,
|
||||
)
|
||||
cls._update_or_create_profile(
|
||||
user=user,
|
||||
first_name=first_name,
|
||||
last_name=last_name,
|
||||
)
|
||||
return cls.get_users_queryset().get(id=user.id)
|
||||
|
||||
@classmethod
|
||||
@transaction.atomic
|
||||
def update_managed_user(cls, user_id: int, **fields) -> User:
|
||||
"""Обновляет пользователя и его роль из админского интерфейса."""
|
||||
user = cls.get_user_by_id(user_id)
|
||||
role = fields.pop("role", None)
|
||||
password = fields.pop("password", None)
|
||||
profile_fields = {
|
||||
key: fields.pop(key) for key in ("first_name", "last_name") if key in fields
|
||||
}
|
||||
|
||||
for field, value in fields.items():
|
||||
setattr(user, field, value)
|
||||
|
||||
if password:
|
||||
user.set_password(password)
|
||||
|
||||
user.save()
|
||||
|
||||
if role is not None:
|
||||
cls.assign_role(user, role)
|
||||
|
||||
if profile_fields:
|
||||
cls._update_or_create_profile(user=user, **profile_fields)
|
||||
|
||||
return cls.get_users_queryset().get(id=user.id)
|
||||
|
||||
@classmethod
|
||||
def deactivate_user(cls, user_id: int) -> User:
|
||||
"""Деактивирует пользователя без физического удаления."""
|
||||
user = cls.get_user_by_id(user_id)
|
||||
user.is_active = False
|
||||
user.save(update_fields=["is_active"])
|
||||
return user
|
||||
|
||||
@classmethod
|
||||
def delete_user(cls, user_id: int) -> None:
|
||||
"""
|
||||
@@ -138,6 +232,76 @@ class UserService:
|
||||
"access": str(refresh.access_token),
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def ensure_role_groups(cls) -> dict[str, Group]:
|
||||
"""Гарантирует существование системных role-групп."""
|
||||
groups: dict[str, Group] = {}
|
||||
for role, _label in cls.ROLE_CHOICES:
|
||||
group, _ = Group.objects.get_or_create(name=role)
|
||||
groups[role] = group
|
||||
return groups
|
||||
|
||||
@classmethod
|
||||
def get_user_role(cls, user: User) -> str:
|
||||
"""Возвращает прикладную роль пользователя."""
|
||||
if user.is_superuser or user.is_staff:
|
||||
return cls.ROLE_ADMIN
|
||||
|
||||
group_names = {group.name for group in user.groups.all()}
|
||||
if cls.ROLE_ADMIN in group_names:
|
||||
return cls.ROLE_ADMIN
|
||||
return cls.ROLE_USER
|
||||
|
||||
@classmethod
|
||||
def get_role_label(cls, role: str) -> str:
|
||||
"""Возвращает человекочитаемое название роли."""
|
||||
return cls.ROLE_LABELS.get(role, role)
|
||||
|
||||
@classmethod
|
||||
def get_user_capabilities(cls, user: User) -> dict[str, Any]:
|
||||
"""Возвращает фронтовые capability flags по роли пользователя."""
|
||||
is_admin = cls.get_user_role(user) == cls.ROLE_ADMIN
|
||||
return {
|
||||
"can_manage_users": is_admin,
|
||||
"can_manage_exchange": is_admin,
|
||||
"can_manage_parsers": is_admin,
|
||||
"can_manage_database_connection": is_admin,
|
||||
"can_upload_registers": is_admin,
|
||||
"can_refresh_dashboard": is_admin,
|
||||
"settings_sections": (
|
||||
[
|
||||
cls.SETTINGS_SECTION_EXCHANGE,
|
||||
cls.SETTINGS_SECTION_PARSERS,
|
||||
cls.SETTINGS_SECTION_DATABASE_CONNECTION,
|
||||
cls.SETTINGS_SECTION_REGISTERS_UPLOAD,
|
||||
]
|
||||
if is_admin
|
||||
else []
|
||||
),
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def assign_role(cls, user: User, role: str) -> User:
|
||||
"""Назначает одну из системных ролей через auth.Group и is_staff."""
|
||||
if role not in cls.ROLE_LABELS:
|
||||
raise ValueError(f"Unsupported role: {role}")
|
||||
|
||||
groups = cls.ensure_role_groups()
|
||||
role_group_names = list(groups.keys())
|
||||
current_role_groups = list(user.groups.filter(name__in=role_group_names))
|
||||
if current_role_groups:
|
||||
user.groups.remove(*current_role_groups)
|
||||
user.groups.add(groups[role])
|
||||
|
||||
if role == cls.ROLE_ADMIN:
|
||||
user.is_staff = True
|
||||
else:
|
||||
user.is_staff = False
|
||||
user.is_superuser = False
|
||||
|
||||
user.save()
|
||||
return user
|
||||
|
||||
@classmethod
|
||||
def verify_email(cls, user_id: int) -> User:
|
||||
"""
|
||||
@@ -157,6 +321,22 @@ class UserService:
|
||||
user.save()
|
||||
return user
|
||||
|
||||
@classmethod
|
||||
def _update_or_create_profile(
|
||||
cls,
|
||||
*,
|
||||
user: User,
|
||||
first_name: str | None = None,
|
||||
last_name: str | None = None,
|
||||
) -> Profile:
|
||||
profile, _ = Profile.objects.get_or_create(user=user)
|
||||
if first_name is not None:
|
||||
profile.first_name = first_name
|
||||
if last_name is not None:
|
||||
profile.last_name = last_name
|
||||
profile.save()
|
||||
return profile
|
||||
|
||||
|
||||
class ProfileService:
|
||||
"""Сервисный слой для работы с профилями"""
|
||||
|
||||
@@ -16,6 +16,17 @@ urlpatterns = [
|
||||
path("me/update/", views.UserUpdateView.as_view(), name="user_update"),
|
||||
path("profile/", views.ProfileDetailView.as_view(), name="profile_detail"),
|
||||
path("profile/full/", views.user_profile_detail, name="profile_full"),
|
||||
path("admin/users/", views.AdminUserListCreateView.as_view(), name="admin-users"),
|
||||
path(
|
||||
"admin/users/<int:user_id>/",
|
||||
views.AdminUserDetailView.as_view(),
|
||||
name="admin-user-detail",
|
||||
),
|
||||
path(
|
||||
"admin/users/<int:user_id>/deactivate/",
|
||||
views.AdminUserDeactivateView.as_view(),
|
||||
name="admin-user-deactivate",
|
||||
),
|
||||
# Безопасность
|
||||
path(
|
||||
"password/change/", views.PasswordChangeView.as_view(), name="password_change"
|
||||
|
||||
@@ -1,17 +1,20 @@
|
||||
from apps.core.openapi import CommonResponses, ErrorResponses, swagger_tag
|
||||
from django.contrib.auth import authenticate
|
||||
from django.contrib.auth.hashers import check_password
|
||||
from django.shortcuts import get_object_or_404
|
||||
from drf_yasg import openapi
|
||||
from drf_yasg.utils import swagger_auto_schema
|
||||
from rest_framework import generics, status
|
||||
from rest_framework.decorators import api_view, permission_classes
|
||||
from rest_framework.permissions import AllowAny, IsAuthenticated
|
||||
from rest_framework.permissions import AllowAny, IsAdminUser, IsAuthenticated
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework_simplejwt.views import TokenRefreshView as SimpleJWTTokenRefreshView
|
||||
from rest_framework_simplejwt.views import TokenVerifyView as SimpleJWTTokenVerifyView
|
||||
|
||||
from .serializers import (
|
||||
AdminUserCreateSerializer,
|
||||
AdminUserUpdateSerializer,
|
||||
LoginSerializer,
|
||||
PasswordChangeSerializer,
|
||||
ProfileUpdateSerializer,
|
||||
@@ -25,6 +28,7 @@ from .services import ProfileService, UserService
|
||||
# Swagger теги для группировки
|
||||
AUTH_TAG = swagger_tag("Аутентификация", "authentication")
|
||||
USER_TAG = swagger_tag("Пользователь", "user")
|
||||
USER_ADMIN_TAG = swagger_tag("Управление пользователями", "user_management")
|
||||
|
||||
|
||||
class RegisterView(APIView):
|
||||
@@ -151,6 +155,129 @@ class CurrentUserView(APIView):
|
||||
return Response(serializer.data)
|
||||
|
||||
|
||||
class AdminUserListCreateView(APIView):
|
||||
"""Список пользователей и создание пользователя администратором."""
|
||||
|
||||
permission_classes = [IsAdminUser]
|
||||
|
||||
@swagger_auto_schema(
|
||||
tags=[USER_ADMIN_TAG],
|
||||
operation_summary="Список пользователей",
|
||||
operation_description="Возвращает список пользователей. Доступно только администраторам.",
|
||||
responses={
|
||||
200: UserSerializer(many=True),
|
||||
**ErrorResponses.ADMIN,
|
||||
},
|
||||
)
|
||||
def get(self, request):
|
||||
serializer = UserSerializer(UserService.get_users_queryset(), many=True)
|
||||
return Response(serializer.data)
|
||||
|
||||
@swagger_auto_schema(
|
||||
tags=[USER_ADMIN_TAG],
|
||||
operation_summary="Создать пользователя",
|
||||
operation_description=(
|
||||
"Создаёт пользователя и назначает ему одну из ролей: " "`user` или `admin`."
|
||||
),
|
||||
request_body=AdminUserCreateSerializer,
|
||||
responses={
|
||||
201: UserSerializer,
|
||||
400: CommonResponses.BAD_REQUEST,
|
||||
**ErrorResponses.ADMIN,
|
||||
},
|
||||
)
|
||||
def post(self, request):
|
||||
serializer = AdminUserCreateSerializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
user = UserService.create_managed_user(**serializer.validated_data)
|
||||
return Response(UserSerializer(user).data, status=status.HTTP_201_CREATED)
|
||||
|
||||
|
||||
class AdminUserDetailView(APIView):
|
||||
"""Просмотр и редактирование пользователя администратором."""
|
||||
|
||||
permission_classes = [IsAdminUser]
|
||||
|
||||
def _get_user(self, user_id):
|
||||
return get_object_or_404(UserService.get_users_queryset(), id=user_id)
|
||||
|
||||
@swagger_auto_schema(
|
||||
tags=[USER_ADMIN_TAG],
|
||||
operation_summary="Детали пользователя",
|
||||
operation_description="Возвращает данные конкретного пользователя.",
|
||||
responses={
|
||||
200: UserSerializer,
|
||||
**ErrorResponses.ADMIN_NOT_FOUND,
|
||||
},
|
||||
)
|
||||
def get(self, request, user_id: int):
|
||||
user = self._get_user(user_id)
|
||||
return Response(UserSerializer(user).data)
|
||||
|
||||
@swagger_auto_schema(
|
||||
tags=[USER_ADMIN_TAG],
|
||||
operation_summary="Обновить пользователя",
|
||||
operation_description=(
|
||||
"Частично обновляет пользователя. Администратор может изменить "
|
||||
"роль, активность и базовые учётные данные."
|
||||
),
|
||||
request_body=AdminUserUpdateSerializer,
|
||||
responses={
|
||||
200: UserSerializer,
|
||||
400: CommonResponses.BAD_REQUEST,
|
||||
**ErrorResponses.ADMIN_NOT_FOUND,
|
||||
},
|
||||
)
|
||||
def patch(self, request, user_id: int):
|
||||
user = self._get_user(user_id)
|
||||
serializer = AdminUserUpdateSerializer(user, data=request.data, partial=True)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
if request.user.id == user.id:
|
||||
if serializer.validated_data.get("is_active") is False:
|
||||
return Response(
|
||||
{"detail": "Нельзя деактивировать самого себя."},
|
||||
status=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
if serializer.validated_data.get("role") == UserService.ROLE_USER:
|
||||
return Response(
|
||||
{"detail": "Нельзя снять у себя роль администратора."},
|
||||
status=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
|
||||
updated_user = UserService.update_managed_user(
|
||||
user_id=user.id,
|
||||
**serializer.validated_data,
|
||||
)
|
||||
return Response(UserSerializer(updated_user).data)
|
||||
|
||||
|
||||
class AdminUserDeactivateView(APIView):
|
||||
"""Деактивация пользователя администратором."""
|
||||
|
||||
permission_classes = [IsAdminUser]
|
||||
|
||||
@swagger_auto_schema(
|
||||
tags=[USER_ADMIN_TAG],
|
||||
operation_summary="Деактивировать пользователя",
|
||||
operation_description="Помечает пользователя как неактивного без удаления записи.",
|
||||
responses={
|
||||
200: UserSerializer,
|
||||
400: CommonResponses.BAD_REQUEST,
|
||||
**ErrorResponses.ADMIN_NOT_FOUND,
|
||||
},
|
||||
)
|
||||
def post(self, request, user_id: int):
|
||||
if request.user.id == user_id:
|
||||
return Response(
|
||||
{"detail": "Нельзя деактивировать самого себя."},
|
||||
status=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
|
||||
user = UserService.deactivate_user(user_id)
|
||||
return Response(UserSerializer(user).data)
|
||||
|
||||
|
||||
class UserUpdateView(APIView):
|
||||
"""Обновление данных пользователя."""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user