Files
octopus/myproject/activate_tenant.py
Andrey Smakotin 4b44624f86 feat: Добавить автоматическое создание суперпользователей для тенантов
Реализована система автоматического создания суперпользователей при активации
новых тенантов (магазинов). Credentials читаются из .env файла.

Изменения:
- Подключен django-environ для управления переменными окружения
- Обновлен settings.py: SECRET_KEY, DEBUG, DATABASE теперь из .env
- Добавлены настройки TENANT_ADMIN_EMAIL, TENANT_ADMIN_PASSWORD, TENANT_ADMIN_NAME
- Обновлен tenants/admin.py: автоматическое создание superuser при активации
- Создан activate_tenant.py: универсальный скрипт активации заявок
- Обновлен activate_mixflowers.py: добавлено создание superuser
- Создан .gitignore для защиты секретов
- Добавлена документация TENANT_ADMIN_GUIDE.md

Использование:
1. Через админку: Заявки → Активировать (автоматически создаст superuser)
2. Через скрипт: python activate_tenant.py <schema_name>

Доступ к админке тенанта:
- URL: http://{schema_name}.localhost:8000/admin/
- Email: admin@localhost (из .env)
- Password: 1234 (из .env)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-27 18:20:26 +03:00

177 lines
7.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
"""
Универсальный скрипт для активации заявки на создание тенанта.
Использование:
python activate_tenant.py <schema_name>
Примеры:
python activate_tenant.py grach
python activate_tenant.py myshop
Скрипт выполняет:
1. Находит заявку по schema_name
2. Создает тенант (Client)
3. Создает домен ({schema_name}.localhost)
4. Создает триальную подписку (90 дней)
5. Создает суперпользователя (credentials из .env)
6. Обновляет статус заявки на "Одобрено"
"""
import os
import sys
import django
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
django.setup()
from django.db import transaction, connection
from django.utils import timezone
from django.contrib.auth import get_user_model
from django.conf import settings
from tenants.models import TenantRegistration, Client, Domain, Subscription
def print_usage():
"""Вывод справки по использованию"""
print("Использование: python activate_tenant.py <schema_name>")
print("")
print("Примеры:")
print(" python activate_tenant.py grach")
print(" python activate_tenant.py myshop")
print("")
print("Доступные заявки (со статусом 'pending'):")
pending_regs = TenantRegistration.objects.filter(status=TenantRegistration.STATUS_PENDING)
if pending_regs.exists():
for reg in pending_regs:
print(f" - {reg.schema_name}: {reg.shop_name} ({reg.owner_email})")
else:
print(" Нет заявок, ожидающих активации")
def activate_tenant(schema_name):
"""Активация тенанта по schema_name"""
# Ищем заявку
try:
registration = TenantRegistration.objects.get(schema_name=schema_name)
except TenantRegistration.DoesNotExist:
print(f"Ошибка: Заявка с schema_name '{schema_name}' не найдена")
print("")
print_usage()
return False
print(f'Найдена заявка: {registration.shop_name} ({registration.schema_name})')
print(f'Статус: {registration.get_status_display()}')
print(f'Email: {registration.owner_email}')
print('')
# Проверяем статус
if registration.status == TenantRegistration.STATUS_APPROVED:
print(f'Внимание: Эта заявка уже была активирована!')
if registration.tenant:
print(f'Тенант: {registration.tenant.name} (ID: {registration.tenant.id})')
print(f'Домен: http://{registration.schema_name}.localhost:8000/')
return False
# Проверяем, не существует ли уже тенант
if Client.objects.filter(schema_name=schema_name).exists():
print(f'Ошибка: Тенант с schema_name "{schema_name}" уже существует!')
return False
print('Начинаю активацию...')
print('')
try:
with transaction.atomic():
# Создаем тенант
print(f'1. Создание тенанта: {registration.schema_name}')
client = Client.objects.create(
schema_name=registration.schema_name,
name=registration.shop_name,
owner_email=registration.owner_email,
owner_name=registration.owner_name,
phone=registration.phone,
is_active=True
)
print(f' [OK] Тенант создан (ID: {client.id})')
# Создаем домен
domain_name = f"{registration.schema_name}.localhost"
print(f'2. Создание домена: {domain_name}')
domain = Domain.objects.create(
domain=domain_name,
tenant=client,
is_primary=True
)
print(f' [OK] Домен создан (ID: {domain.id})')
# Создаем триальную подписку
print('3. Создание триальной подписки на 90 дней')
subscription = Subscription.create_trial(client)
print(f' [OK] Подписка создана (ID: {subscription.id})')
print(f' Истекает: {subscription.expires_at.strftime("%Y-%m-%d")} ({subscription.days_left()} дней)')
# Создаем суперпользователя для тенанта
print('4. Создание суперпользователя для тенанта')
# Переключаемся на схему тенанта
connection.set_tenant(client)
User = get_user_model()
if not User.objects.filter(email=settings.TENANT_ADMIN_EMAIL).exists():
superuser = User.objects.create_superuser(
email=settings.TENANT_ADMIN_EMAIL,
name=settings.TENANT_ADMIN_NAME,
password=settings.TENANT_ADMIN_PASSWORD
)
print(f' [OK] Суперпользователь создан (ID: {superuser.id})')
else:
print(f' [SKIP] Пользователь с email {settings.TENANT_ADMIN_EMAIL} уже существует')
# Возвращаемся в public схему
public_tenant = Client.objects.get(schema_name='public')
connection.set_tenant(public_tenant)
# Обновляем заявку
print('5. Обновление статуса заявки')
registration.status = TenantRegistration.STATUS_APPROVED
registration.processed_at = timezone.now()
registration.processed_by = None # Активировано через скрипт
registration.tenant = client
registration.save()
print(' [OK] Заявка помечена как "Одобрено"')
print('')
print('=' * 70)
print('АКТИВАЦИЯ ЗАВЕРШЕНА УСПЕШНО!')
print('=' * 70)
print(f'Магазин: {client.name}')
print(f'Schema: {client.schema_name}')
print(f'Домен: http://{domain_name}:8000/')
print(f'Подписка до: {subscription.expires_at.strftime("%Y-%m-%d")} ({subscription.days_left()} дней)')
print('')
print('Доступ к админке тенанта:')
print(f' URL: http://{domain_name}:8000/admin/')
print(f' Email: {settings.TENANT_ADMIN_EMAIL}')
print(f' Password: {settings.TENANT_ADMIN_PASSWORD}')
print('=' * 70)
return True
except Exception as e:
print('')
print(f'Ошибка при активации: {str(e)}')
import traceback
traceback.print_exc()
return False
if __name__ == '__main__':
if len(sys.argv) < 2:
print("Ошибка: Не указан schema_name")
print("")
print_usage()
sys.exit(1)
schema_name = sys.argv[1]
success = activate_tenant(schema_name)
sys.exit(0 if success else 1)