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>
This commit is contained in:
176
myproject/activate_tenant.py
Normal file
176
myproject/activate_tenant.py
Normal file
@@ -0,0 +1,176 @@
|
||||
# -*- 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)
|
||||
Reference in New Issue
Block a user