Невозможно войти в поддомен арендатора django, основной домен и вход администратора работают

У меня есть приложение с несколькими арендаторами, использующее библиотеку django-tenants. При входе в основной URL с созданным суперпользователем страница входа работает совершенно нормально. При использовании адреса поддомена для входа в систему страница возвращает 500 error при использовании правильного имени пользователя и пароля, которые существуют, а консоль говорит Uncaught (in promise) SyntaxError: Unexpected token '<', " <!doctype "... is not valid JSON.

При использовании несуществующего имени пользователя вывод 400 Bad Request.

Странно, но я могу получить доступ к панели администратора поддомена, войти в систему совершенно нормально, изменить URL для перехода к части приложения - и пользователь теперь вошел в систему. После входа в систему я могу отправлять формы в полном порядке, и данные собираются, только на странице входа в систему на поддомене возникает ошибка отправки.

Я потерян, так как последующие формы данных отправляются и проходят правильно, и нет недействительных токенов (из того, что я вижу)

views.py


def dual_login_view(request):
    """Authenticate users with both Django Authentication System
    and Django Rest Framework"""
    if request.method == "POST":
        username = request.POST.get("login")
        password = request.POST.get("password")
        user = authenticate(request, username=username, password=password)
        if user is not None:
            # Login user and create session
            login(request, user)

            # Create or get API token
            token, created = Token.objects.get_or_create(user=user)

            response_data = {"status": "success", "token": token.key}
            return JsonResponse(response_data)
        else:
            return JsonResponse(
                {"status": "error", "message": "Username with the password doesn't exist!"}, status=400
            )

        
    return JsonResponse(
        {"status": "error", "message": "Invalid request method"}, status=405
    )


class CustomLoginView(LoginView):

    def form_invalid(self, form):
        for error in form.errors.values():
            for e in error:
                messages.error(self.request, e)
        return super().form_invalid(form)


class UserLoginAPIView(APIView):

    def post(self, request):
        if not (request.user and request.user.is_authenticated):
            return Response(
                {"error": "User not recognized"}, status=status.HTTP_401_UNAUTHORIZED
            )
        try:
            token, created = Token.objects.get_or_create(user=request.user)
            return Response({"token": f"Token {token.key}"}, status=status.HTTP_200_OK)
        except Exception as e:
            print(e)
            return Response(
                {"error": "Invalid credentials"}, status=status.HTTP_401_UNAUTHORIZED
            )


class UserLoginAPIView(APIView):
    def post(self, request):
        """Handle user login and return an authentication token."""
        username = request.data.get("username")
        password = request.data.get("password")

        try:
            user = MSPAuthUser.objects.get(username=username)

            # Verify password
            if not user.check_password(password):
                raise ValueError("Invalid credentials")

            token, created = Token.objects.get_or_create(user=user)
            return Response({"token": f"Token {token.key}"}, status=status.HTTP_200_OK)

        except ObjectDoesNotExist:
            return Response(
                {"error": "Invalid credentials"}, status=status.HTTP_401_UNAUTHORIZED
            )

        except ValueError as e:
            return Response({"error": str(e)}, status=status.HTTP_401_UNAUTHORIZED)

login.js

    <script>
        let form = document.querySelector('form');
        form.addEventListener('submit', function(event) {
            event.preventDefault();
            var formData = new FormData(this);

            form.classList.add('was-validated')
            if (!form.checkValidity()) {
                event.preventDefault()
                event.stopPropagation()
                return;
            }
            
            fetch("{% url 'dual_login' %}", {
                method: 'POST',
                body: formData,
                headers: {
                    'X-CSRFToken': formData.get('csrfmiddlewaretoken'),
                }
            }).then(response => response.json())
              .then(data => {
                  if (data.status === 'success') {
                      // Store the token (e.g., in local storage or a cookie)
                      localStorage.setItem('token', data.token);
                      // Redirect or update the UI
                       window.location.href = '/';
                  } else {
                    Swal.fire({
                        icon: 'error',
                        title: data.message,
                        showConfirmButton: false,
                        timer: 1500,
                    })
                  }
              });
        });

       
    </script> 

Проверьте на вкладке «Сеть» ответ API. Возможно, вы пытаетесь разобрать что-то, что не является JSON, как JSON.

Ошибка Uncaught (in promise) SyntaxError: Unexpected token '<', " <!doctype "... is not valid JSON возникает потому, что вызов Token, как вы заметили, поднимает не пойманное исключение. Что, в свою очередь, означает, что объект token не содержит токена, а содержит HTML-ответ, отображающий ответ на исключение.

И вы правильно поняли, что решение заключается в исправлении вызова Token.

Как я могу использовать модель rest_framework.authtoken.models для запроса из правильной схемы базы данных?

К моменту вызова Token вы уже аутентифицировали пользователя, поэтому следующим шагом будет поиск его ассоциации с арендатором. Затем вы можете использовать менеджер контекста schema_context(), чтобы направить запрос к нужной схеме.

from django_tenants.utils import schema_context
from .tenants import Tenant # Or whatever your tenant model is


def dual_login_view(request):
    """Authenticate users with both Django Authentication System
    and Django Rest Framework"""
    if request.method == "POST":
        username = request.POST.get("login")
        password = request.POST.get("password")
        user = authenticate(request, username=username, password=password)
        if user is not None:
            # Login user and create session
            login(request, user)

            # Retrieve tenant information
            tenant = user.tenant # Or whatever is appropriate for you to look up the relationship between the user and the tenant
            schema_name = tenant.schema_name

            # Create or get API token, schema-aware
            with schema_context(schema_name):
                token, created = Token.objects.get_or_create(user=user)

            response_data = {"status": "success", "token": token.key}
            return JsonResponse(response_data)
        else:
            return JsonResponse(
                {"status": "error", "message": "Username with the password doesn't exist!"}, status=400
            )

        
    return JsonResponse(
        {"status": "error", "message": "Invalid request method"}, status=405
    )
Вернуться на верх