from django.shortcuts import render, redirect, get_object_or_404 from django.contrib.auth import login, authenticate, logout, get_user_model from django.contrib import messages from django.core.mail import send_mail from django.conf import settings from django.urls import reverse from django.shortcuts import redirect from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode from django.utils.encoding import force_bytes, force_str from django.contrib.auth.tokens import default_token_generator from django.contrib.auth.decorators import login_required from django.contrib.auth import update_session_auth_hash from django.contrib.auth.forms import PasswordChangeForm from .forms import PasswordResetForm from .models import CustomUser import uuid def login_view(request): if request.method == 'POST': email = request.POST.get('email') password = request.POST.get('password') # Используем email как логин user = authenticate(request, username=email, password=password) if user is not None: if user.is_email_confirmed: # Проверяем, подтвержден ли email login(request, user) # Перенаправляем на главную страницу после успешного входа next_page = request.GET.get('next', 'index') # Если есть параметр next, переходим туда return redirect(next_page) else: messages.error(request, 'Пожалуйста, подтвердите ваш email для входа.') else: messages.error(request, 'Неверный email или пароль.') return render(request, 'login.html') def logout_view(request): logout(request) return redirect('index') @login_required def profile_view(request): return render(request, 'profile.html', {'user': request.user}) @login_required def change_password_view(request): if request.method == 'POST': form = PasswordChangeForm(request.user, request.POST) if form.is_valid(): user = form.save() update_session_auth_hash(request, user) # Important for keeping the user logged in messages.success(request, 'Ваш пароль был успешно изменен!') return redirect('profile') else: messages.error(request, 'Пожалуйста, исправьте ошибки в форме.') else: form = PasswordChangeForm(request.user) return render(request, 'change_password.html', {'form': form}) def confirm_email(request, token): user = get_object_or_404(CustomUser, email_confirmation_token=token) if user.is_email_confirmed: messages.info(request, 'Email уже был подтвержден.') else: user.confirm_email() user.is_active = True # Активируем пользователя user.save() messages.success(request, 'Email успешно подтвержден! Теперь вы можете войти.') return redirect('accounts:login') def password_reset_request(request): if request.method == 'POST': form = PasswordResetForm(request.POST) if form.is_valid(): email = form.cleaned_data['email'] try: user = CustomUser.objects.get(email=email) # Генерируем токен восстановления user.password_reset_token = uuid.uuid4() user.save() # Отправляем письмо с инструкциями по восстановлению reset_url = request.build_absolute_uri( reverse('accounts:password_reset_confirm', kwargs={'token': user.password_reset_token}) ) subject = 'Восстановление пароля' message = f'Привет {user.name}!\n\nДля восстановления пароля перейдите по следующей ссылке: {reset_url}\n\nЕсли вы не запрашивали восстановление пароля, проигнорируйте это письмо.' from_email = settings.DEFAULT_FROM_EMAIL recipient_list = [user.email] # Выводим письмо в консоль print(f"Письмо для восстановления пароля:\nТема: {subject}\nСообщение:\n{message}\nПолучатель: {recipient_list}") messages.success(request, f'Инструкции по восстановлению пароля отправлены на {email}') except CustomUser.DoesNotExist: # Для безопасности не сообщаем, что пользователя не существует messages.success(request, 'Если аккаунт с таким email существует, инструкции по восстановлению пароля были отправлены на него.') return redirect('accounts:login') else: form = PasswordResetForm() return render(request, 'login.html', {'form': form}) def password_reset_confirm(request, token): try: user = CustomUser.objects.get(password_reset_token=token) except CustomUser.DoesNotExist: messages.error(request, 'Ссылка для восстановления пароля недействительна.') return redirect('index') if request.method == 'POST': password1 = request.POST.get('password1') password2 = request.POST.get('password2') if password1 and password2 and password1 == password2: user.set_password(password1) user.password_reset_token = None # Обнуляем токен user.save() messages.success(request, 'Пароль успешно изменен. Теперь вы можете войти.') return redirect('accounts:login') else: messages.error(request, 'Пароли не совпадают.') # Отображаем форму смены пароля return render(request, 'accounts/password_reset_confirm.html', {'user': user}) def password_setup_confirm(request, token): """ Позволить владельцу тенанта установить начальный пароль после одобрения регистрации. Похоже на сброс пароля, но для новых аккаунтов. """ from tenants.models import TenantRegistration from datetime import timedelta from django.utils import timezone # Найти регистрацию по токену try: registration = TenantRegistration.objects.get( password_setup_token=token, status=TenantRegistration.STATUS_APPROVED ) except TenantRegistration.DoesNotExist: messages.error(request, 'Ссылка для настройки пароля недействительна.') return redirect('index') # Проверить истечение токена (7 дней) if registration.password_setup_token_created_at: expires_at = registration.password_setup_token_created_at + timedelta(days=7) if timezone.now() > expires_at: messages.error( request, 'Ссылка для настройки пароля истекла. Пожалуйста, свяжитесь с поддержкой.' ) return redirect('index') # Получить тенант и пользователя-владельца from django.db import connection tenant = registration.tenant if not tenant: messages.error(request, 'Тенант не найден.') return redirect('index') # Переключиться на схему тенанта чтобы найти владельца connection.set_tenant(tenant) User = get_user_model() try: owner = User.objects.get(email=registration.owner_email) except User.DoesNotExist: connection.set_schema_to_public() messages.error(request, 'Пользователь не найден.') return redirect('index') # Обработать POST - установить пароль if request.method == 'POST': password1 = request.POST.get('password1') password2 = request.POST.get('password2') if password1 and password2 and password1 == password2: # Установить пароль и активировать аккаунт owner.set_password(password1) owner.is_active = True owner.save() # Очистить токен connection.set_schema_to_public() registration.password_setup_token = None registration.password_setup_token_created_at = None registration.save() # Автоматический вход connection.set_tenant(tenant) login(request, owner, backend='django.contrib.auth.backends.ModelBackend') messages.success( request, f'Пароль успешно установлен! Добро пожаловать в {tenant.name}!' ) # Перенаправить на домен тенанта tenant_url = f'http://{tenant.schema_name}.localhost:8000/' return redirect(tenant_url) else: messages.error(request, 'Пароли не совпадают.') connection.set_schema_to_public() # Отрисовать форму установки пароля return render(request, 'accounts/password_setup_confirm.html', { 'registration': registration, 'tenant': tenant })