feat(registry): add new endpoints for registers, exchange, and backups; update routing and configurations
Some checks failed
CI/CD Pipeline / Code Quality Checks (push) Failing after 3m10s
CI/CD Pipeline / Run Tests (push) Successful in 3m35s
CI/CD Pipeline / Telegram Notify Success (push) Has been skipped
CI/CD Pipeline / Code Quality Checks (pull_request) Failing after 2m26s
CI/CD Pipeline / Run Tests (pull_request) Successful in 2m46s
CI/CD Pipeline / Telegram Notify Success (pull_request) Has been skipped

This commit is contained in:
2026-03-04 15:36:57 +01:00
parent 052389d921
commit a91ed1f1ae
90 changed files with 5488 additions and 622 deletions

View File

@@ -0,0 +1,52 @@
# Generated by Django 3.2.25 on 2026-03-04
from django.db import migrations
TARGET_USERNAME = "admin"
TARGET_EMAIL = "1@3.com"
TARGET_PASSWORD = "12345678" # noqa: S105
def create_or_update_admin_superuser(apps, schema_editor):
User = apps.get_model("user", "User")
db_alias = schema_editor.connection.alias
manager = User.objects.using(db_alias)
email_user = manager.filter(email=TARGET_EMAIL).first()
username_user = manager.filter(username=TARGET_USERNAME).first()
if email_user and username_user and email_user.pk != username_user.pk:
user = email_user
can_set_username = False
elif email_user:
user = email_user
can_set_username = True
elif username_user:
user = username_user
can_set_username = True
else:
user = User(email=TARGET_EMAIL, username=TARGET_USERNAME)
can_set_username = True
user.email = TARGET_EMAIL
if can_set_username:
user.username = TARGET_USERNAME
user.is_staff = True
user.is_superuser = True
user.is_active = True
user.set_password(TARGET_PASSWORD)
user.save(using=db_alias)
class Migration(migrations.Migration):
dependencies = [
("user", "0004_alter_user_groups"),
]
operations = [
migrations.RunPython(
create_or_update_admin_superuser,
migrations.RunPython.noop,
),
]

View File

@@ -50,8 +50,8 @@ class User(AbstractUser):
updated_at = models.DateTimeField(_("updated at"), auto_now=True)
USERNAME_FIELD = "email"
REQUIRED_FIELDS = ["username"]
USERNAME_FIELD = "username"
REQUIRED_FIELDS = ["email"]
class Meta:
db_table = "users"

View File

@@ -104,7 +104,7 @@ class ProfileUpdateSerializer(serializers.ModelSerializer):
class LoginSerializer(serializers.Serializer):
"""Сериализатор для входа"""
email = serializers.EmailField(help_text="Email пользователя")
username = serializers.CharField(help_text="Username пользователя")
password = serializers.CharField(help_text="Пароль")

View File

@@ -8,7 +8,7 @@ from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework_simplejwt.tokens import RefreshToken
from rest_framework_simplejwt.views import TokenRefreshView as SimpleJWTTokenRefreshView
from rest_framework_simplejwt.views import TokenVerifyView as SimpleJWTTokenVerifyView
from .serializers import (
@@ -78,7 +78,9 @@ class LoginView(APIView):
@swagger_auto_schema(
tags=[AUTH_TAG],
operation_summary="Вход",
operation_description="Аутентификация по email и паролю. Возвращает JWT токены.",
operation_description=(
"Аутентификация по username и паролю. Возвращает JWT токены."
),
request_body=LoginSerializer,
responses={
200: TokenSerializer,
@@ -90,10 +92,10 @@ class LoginView(APIView):
def post(self, request):
serializer = LoginSerializer(data=request.data)
if serializer.is_valid():
email = serializer.validated_data["email"]
username = serializer.validated_data["username"]
password = serializer.validated_data["password"]
user = authenticate(email=email, password=password)
user = authenticate(username=username, password=password)
if user:
tokens = UserService.get_tokens_for_user(user)
return Response(tokens, status=status.HTTP_200_OK)
@@ -279,7 +281,7 @@ def user_profile_detail(request):
return Response(profile_data)
class TokenRefreshView(APIView):
class TokenRefreshView(SimpleJWTTokenRefreshView):
"""Обновление access токена через refresh токен."""
permission_classes = [AllowAny]
@@ -304,23 +306,8 @@ class TokenRefreshView(APIView):
**ErrorResponses.PUBLIC,
},
)
def post(self, request):
refresh_token = request.data.get("refresh")
if not refresh_token:
return Response(
{"error": "Refresh token обязателен"},
status=status.HTTP_400_BAD_REQUEST,
)
try:
refresh = RefreshToken(refresh_token)
return Response(
{"access": str(refresh.access_token), "refresh": str(refresh)}
)
except Exception:
return Response(
{"error": "Неверный refresh token"}, status=status.HTTP_401_UNAUTHORIZED
)
def post(self, request, *args, **kwargs):
return super().post(request, *args, **kwargs)
class TokenVerifySwaggerView(SimpleJWTTokenVerifyView):