chore: Реорганизация проекта - очистка и структурирование файлов

- Добавлена папка ДОКУМЕНТАЦИЯ с централизованным хранением всех руководств
- Перенесены утилитарные скрипты в myproject/scripts/
- Удалены временные файлы (current_settings.txt, old_settings.txt, nul)
- Добавлены celerybeat-schedule файлы в .gitignore
- Обновлен .env.example (удалены устаревшие настройки PLATFORM_SUPPORT)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-09 05:50:42 +03:00
parent 0bddbc08c4
commit 256606f2a0
12 changed files with 208 additions and 2534 deletions

View File

@@ -5,7 +5,6 @@
Единственный источник истины для создания тенанта и всех связанных сущностей.
"""
import logging
import secrets
from django.db import connection, transaction
from django.utils import timezone
from django.conf import settings
@@ -229,8 +228,11 @@ class TenantOnboardingService:
else:
logger.warning(f"Пользователь {registration.owner_email} уже существует")
# 2. Техподдержка платформы (скрытый аккаунт)
cls._create_platform_support_user(registration)
# 2. Техподдержка платформы
# SECURITY: НЕ создаём отдельную учетку CustomUser для саппорта
# PlatformAdmin с is_superuser=True уже имеет полный доступ к tenant
# через PlatformAdminBackend и TenantAdminAccessMiddleware
logger.info("Техподдержка: используется PlatformAdmin (отдельный CustomUser НЕ создаётся)")
@classmethod
def _assign_owner_role(cls, owner):
@@ -245,83 +247,6 @@ class TenantOnboardingService:
except Exception as e:
logger.error(f"Ошибка при назначении роли: {e}", exc_info=True)
@classmethod
def _create_platform_support_user(cls, registration: TenantRegistration):
"""
Создание скрытого аккаунта техподдержки платформы.
- Email берётся из настроек PLATFORM_SUPPORT_EMAIL
- Пароль генерируется уникальный для каждого тенанта
- Пароль выводится в лог (для владельца платформы)
- Пользователь не виден владельцу тенанта
"""
from accounts.models import CustomUser
from user_roles.services import RoleService
from user_roles.models import Role
support_email = getattr(settings, 'PLATFORM_SUPPORT_EMAIL', None)
if not support_email:
logger.info("PLATFORM_SUPPORT_EMAIL не задан - пропускаем создание техподдержки")
return
if CustomUser.objects.filter(email=support_email).exists():
logger.info(f"Техподдержка {support_email} уже существует в этом тенанте")
return
# Генерируем уникальный пароль для этого тенанта
password = secrets.token_urlsafe(16)
support_user = CustomUser.objects.create_user(
email=support_email,
name='Техподдержка',
password=password,
)
support_user.is_email_confirmed = True
support_user.email_confirmed_at = timezone.now()
support_user.is_active = True
support_user.is_superuser = True
support_user.save()
# Назначаем роль platform_support
RoleService.assign_role_to_user(support_user, Role.PLATFORM_SUPPORT, created_by=None)
# Выводим пароль в лог (безопасно, т.к. логи доступны только владельцу платформы)
logger.info(
f"[PLATFORM_SUPPORT] Тенант: {registration.schema_name} | "
f"Email: {support_email} | Пароль: {password}"
)
# Сохраняем credentials в файл
cls._save_support_credentials(registration, support_email, password)
@classmethod
def _save_support_credentials(cls, registration: TenantRegistration, email: str, password: str):
"""
Сохраняет credentials техподдержки в файл.
Формат: домен:логин:пароль
Файл: support_credentials.txt в корне проекта
"""
import os
from pathlib import Path
# Корень проекта (где manage.py)
project_root = Path(settings.BASE_DIR)
credentials_file = project_root / 'support_credentials.txt'
# Формируем домен тенанта
domain_base = settings.TENANT_DOMAIN_BASE
if ':' in domain_base:
domain_base = domain_base.split(':')[0]
tenant_domain = f"{registration.schema_name}.{domain_base}"
# Добавляем строку в файл
try:
with open(credentials_file, 'a', encoding='utf-8') as f:
f.write(f"{tenant_domain}:{email}:{password}\n")
logger.info(f"Credentials сохранены в {credentials_file}")
except Exception as e:
logger.error(f"Ошибка сохранения credentials: {e}")
@classmethod
def _init_tenant_data(cls):