Рефакторинг инфраструктуры и конфигурации проекта
Some checks failed
CI/CD Pipeline / Code Quality Checks (push) Successful in 1m52s
CI/CD Pipeline / Run Tests (push) Failing after 2m2s
CI/CD Pipeline / Build & Push Images (push) Has been skipped

- Перенесена структура Django-конфига в src/core и src/settings

- Унифицирована Docker-сборка и docker-compose для dev/prod

- Добавлены startup-checks (DB/Redis) и обновлены env-шаблоны

- Расширена OpenAPI-документация и ответы API

- Удалены устаревшие deploy/requirements/служебные скрипты

- Обновлены CI/CD, README и тесты
This commit is contained in:
2026-02-18 13:25:01 +01:00
parent 0f4af561de
commit d5d184537f
71 changed files with 1253 additions and 2318 deletions

View File

@@ -1,6 +1,7 @@
"""Tests for core admin configurations."""
from datetime import timedelta
from unittest.mock import patch
from django.contrib.admin.sites import AdminSite
from django.contrib.messages.storage.fallback import FallbackStorage
@@ -88,6 +89,8 @@ class CoreAdminTest(TestCase):
)
request = self._request()
qs = BackgroundJob.objects.all()
self.admin.revoke_jobs(request, qs)
with patch("celery.current_app.control.revoke") as revoke_mock:
self.admin.revoke_jobs(request, qs)
revoke_mock.assert_called_once_with(job.task_id, terminate=True)
job.refresh_from_db()
self.assertEqual(job.status, "revoked")

View File

@@ -2,11 +2,11 @@
from __future__ import annotations
from django.test import SimpleTestCase
from django.test import SimpleTestCase, override_settings
from drf_yasg import openapi
from rest_framework import serializers
from apps.core.openapi import _get_status_description, api_docs
from apps.core.openapi import _get_status_description, api_docs, swagger_tag
class DummySerializer(serializers.Serializer):
@@ -34,3 +34,10 @@ class OpenAPIDocsTest(SimpleTestCase):
decorated = decorator(view)
self.assertTrue(callable(decorated))
def test_swagger_tag_default_russian(self):
self.assertEqual(swagger_tag("Пользователь", "User"), "Пользователь")
@override_settings(OPENAPI_USE_ENGLISH_TAGS=True)
def test_swagger_tag_english_in_dev_mode(self):
self.assertEqual(swagger_tag("Пользователь", "User"), "User")

View File

@@ -11,7 +11,7 @@ from apps.core.tasks import (
TransactionalTask,
)
from celery import Task
from config.celery import app as celery_app
from core.celery import app as celery_app
from django.test import TestCase

View File

@@ -6,7 +6,7 @@ from django.contrib.auth import get_user_model
from django.urls import reverse
from faker import Faker
from rest_framework import status
from rest_framework.test import APITestCase
from rest_framework.test import APIClient, APITestCase
from .factories import ProfileFactory, UserFactory
@@ -310,3 +310,33 @@ class TokenRefreshViewTest(APITestCase):
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertIn("error", response.data)
class ApiJwtOnlyAuthenticationTest(APITestCase):
"""Tests that API auth flow is JWT-only and not session-cookie based."""
def setUp(self):
self.user = UserFactory.create_user()
self.tokens = UserService.get_tokens_for_user(self.user)
self.update_url = reverse("api_v1:user:user_update")
self.patch_data = {"username": fake.unique.user_name()}
# Explicitly enable CSRF checks to catch accidental SessionAuthentication usage.
self.client = APIClient(enforce_csrf_checks=True)
self.client.cookies["sessionid"] = "fake-admin-session"
self.client.cookies["csrftoken"] = "fake-csrf-token"
def test_patch_with_bearer_and_session_cookies_returns_200(self):
"""Bearer JWT should authenticate even if session cookies are present."""
self.client.credentials(HTTP_AUTHORIZATION=f"Bearer {self.tokens['access']}")
response = self.client.patch(self.update_url, self.patch_data, format="json")
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data["id"], self.user.id)
def test_patch_with_only_session_cookies_returns_401_not_403(self):
"""Session cookies without JWT should not trigger CSRF 403 for API auth."""
response = self.client.patch(self.update_url, self.patch_data, format="json")
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)