from django.conf import settings from django.contrib.auth import get_user_model from django.contrib.auth import login as login_user from django.contrib.auth import logout as logout_user from django.contrib.auth.tokens import default_token_generator from django.core.exceptions import ValidationError from django.db import IntegrityError from django.shortcuts import redirect, render, reverse from django.utils.http import url_has_allowed_host_and_scheme, urlencode, urlsafe_base64_decode from django.utils.text import gettext_lazy as _ from django.views.generic import TemplateView, View from shop.models import CustomerAddress from users.forms import LoginForm, PasswordResetForm, RegisterForm, SetPasswordForm from web.models import WebSettings User = get_user_model() class RedirectionMixin: redirect_to = '' def get_redirection(self): return reverse(self.redirect_to) class LoginView(View, RedirectionMixin): template_name = 'users/login.html' redirect_to = 'web:index' login_form_class = LoginForm def get_redirection(self): next_page = self.request.GET.get('next', '') if next_page: return f'{reverse(self.redirect_to)}?next={next_page}' return reverse(self.redirect_to) def get_login_form(self, request): return self.login_form_class(data=request.POST) def get(self, request, *args, **kwargs): if request.user.is_authenticated: return redirect(self.get_redirection()) web_settings = WebSettings.load() login_form = self.login_form_class() return render( request, self.template_name, {'form': login_form, 'title': web_settings.web_title, 'description': _('inicio de sesión')}, ) def post(self, request, *args, **kwargs): login_form = self.get_login_form(request) if login_form.is_valid(): login_user(request, login_form.get_user()) if not login_form.cleaned_data.get('remember_me'): request.session.set_expiry(0) return redirect(self.get_redirection()) return render( request, self.template_name, {'form': login_form, 'errors': login_form.errors.get('__all__')}, status=400 ) class RegisterView(TemplateView, RedirectionMixin): template_name = 'users/register.html' redirect_to = 'web:login' form_class = RegisterForm def get_context_data(self, **kwargs): settings = WebSettings.load() return {'form': self.form_class(), 'title': settings.web_title, 'description': _('crear cuenta')} def post(self, request, *args, **kwargs): settings = WebSettings.load() form = self.form_class(request.POST) errors = [] try: if form.is_valid(): user = form.save() user.username = user.email user.first_name = form.cleaned_data.get('first_name') user.last_name = form.cleaned_data.get('last_name') user.save() login(request, user) return redirect(self.get_redirection()) else: errors = form.errors except IntegrityError: errors = [_('Ya existe un usuario con ese correo electrónico')] return render( request, self.template_name, {'form': form, 'title': settings.web_title, 'description': _('Crear cuenta'), 'errors': errors}, status=400, ) class LogoutView(View, RedirectionMixin): redirect_to = 'web:index' def get(self, request, *args, **kwargs): logout_user(request) return redirect(self.get_redirection()) def post(self, request, *args, **kwargs): logout_user(request) return redirect(self.get_redirection()) class ResetPasswordView(TemplateView): template_name = 'users/reset_password.html' form_class = PasswordResetForm redirect_to = 'web:reset_password_email_sent' html_reset_password_template_name = 'mails/reset_password.html' subject_template_name = 'mails/subject_reset_password.txt' def get_email_options(self): return { 'extra_email_context': {}, 'email_template_name': self.html_reset_password_template_name, 'html_email_template_name': self.html_reset_password_template_name, 'subject_template_name': self.subject_template_name, } def get_base_context(self): settings = WebSettings.load() return {'title': settings.web_title, 'description': _('Restablecer contraseña')} def get_context_data(self, **kwargs): context = self.get_base_context() context.update({'form': self.form_class()}) return context def post(self, request, *args, **kwargs): form = self.form_class(request.POST) if form.is_valid(): opts = { 'use_https': request.is_secure(), 'from_email': getattr(settings, 'DEFAULT_FROM_EMAIL'), 'request': request, } opts.update(self.get_email_options()) form.save(**opts) return redirect(self.redirect_to) context = self.get_base_context() context.update({'form': form}) return render(request, self.template_name, context) class ResetPasswordEmailSent(TemplateView): template_name = 'users/reset_password_email_sent.html' def get_context_data(self, **kwargs): settings = WebSettings.load() return {'title': settings.web_title, 'description': settings.web_description} class ResetPasswordConfirmView(TemplateView): template_name = 'users/reset_password_confirm.html' form_class = SetPasswordForm redirect_to = 'web:login' token_generator = default_token_generator def get_user(self): try: uidb64 = self.kwargs.get('uidb64') uid = urlsafe_base64_decode(uidb64).decode() user = User.objects.get(pk=uid) except (TypeError, ValueError, OverflowError, User.DoesNotExist, ValidationError): user = None return user def generate_new_token_for_user(self, user): return self.token_generator.make_token(user) def get_context_data(self, **kwargs): user = self.get_user() valid_token = self.check_token(user) new_token = self.generate_new_token_for_user(user) return { 'title': WebSettings.load().web_title, 'description': _('Establecer nueva contraseña'), 'form': self.form_class(user, {'token': new_token}), 'valid_token': valid_token, 'new_token': new_token, } def check_token(self, user): token = self.kwargs.get('token') valid_token = self.token_generator.check_token(user, token) return valid_token def post(self, request, *args, **kwargs): user = self.get_user() form = self.form_class(user, request.POST) if form.is_valid(): form.save() return redirect(self.redirect_to) return render(request, self.template_name, {}) class MyAccountView(TemplateView): template_name = 'users/user_details.html' def get_context_data(self, **kwargs): addresses = CustomerAddress.objects.filter(user=self.request.user) web_settings = WebSettings.load() return { 'title': f'{web_settings.web_title} - Mi cuenta', 'description': f'{web_settings.web_title} - Mi cuenta', 'customer_addresses': addresses, } login = LoginView.as_view() logout = LogoutView.as_view() register = RegisterView.as_view() reset_password = ResetPasswordView.as_view() reset_password_confirm = ResetPasswordConfirmView.as_view() reset_password_email_sent = ResetPasswordEmailSent.as_view() my_account = MyAccountView.as_view()