"""Definición de las vistas de la aplicación""" from django.http import HttpResponseRedirect, HttpResponseNotAllowed from django.shortcuts import render from django.utils.http import url_has_allowed_host_and_scheme from django.contrib.auth import login as auth_login, logout as auth_logout from django.contrib.auth import authenticate, get_user_model from django.views.decorators.csrf import csrf_protect def get_next_url(request): """Obtiene el parametro next, el cual puede estar en POST o GET Este parametro es una url por lo que debe validarse que sea seguro, en caso que no lo sea se retornara '/' para evitar problemas de seguridad """ next_url = request.POST.get('next', request.GET.get('next', '')) url_is_safe = url_has_allowed_host_and_scheme( url=next_url, allowed_hosts=request.get_host(), require_https=request.is_secure(), ) print(next_url if url_is_safe else '/') return next_url if url_is_safe else '/' @csrf_protect def login(request): """Entrada de la ruta de login Solo se permiten request que sean GET o POST """ if request.method == 'GET': return _login_get(request) if request.method == 'POST': return _login_post(request) return HttpResponseNotAllowed(permitted_methods=['GET', 'POST']) def _login_get(request): """Retorna la vista de login y le entrega el parametro next a la vista""" return render(request, template_name='users/login.html', context={'next': get_next_url(request)}) def _login_post(request): """El POST de login que corresponde a la autenticación de un usuario Si es que es correcta continuara el usuario sera autenticado en el sistema y se le redirigirá a la direccion del parametro next Si es que no se volverá a la misma vista de login con un error """ username = request.POST.get('username', '') password = request.POST.get('password', '') user = authenticate(request, username=username, password=password) if user is not None: auth_login(request, user) return HttpResponseRedirect(get_next_url(request)) return render( request, template_name='users/login.html', context={'next': get_next_url(request), 'error': 'Usuario o contraseña son incorrectos'} ) def logout(request): """Realiza el logout de un usuario y lo redirige a la url del parametro next""" auth_logout(request) return HttpResponseRedirect(get_next_url(request)) @csrf_protect def register(request): """Entrada de la ruta de register, solo acepta GET y POST""" if request.method == 'GET': return _register_get(request) if request.method == 'POST': return _register_post(request) return HttpResponseNotAllowed(permitted_methods=['GET', 'POST']) def _register_get(request): """Retorna la vista de registro con el parametro de next""" return render(request, template_name='users/register.html', context={'next': get_next_url(request)}) def _register_post(request): """Registra un usuario, si es que es correcto sera logeado y se redireccionara a la url en next, en otro caso, se devolverá a la vista de registro con errores """ username = request.POST.get('username', '') password = request.POST.get('password', '') password_confirm = request.POST.get('password_confirm', '') email = request.POST.get('email', '') old = { 'username': username, 'email': email } if not username: return render( request, template_name='users/register.html', context={'next': get_next_url(request), 'error': 'Debe ingresar un nombre de usuario', 'old': old} ) if get_user_model().objects.filter(username=username).count() > 0: return render( request, template_name='users/register.html', context={'next': get_next_url(request), 'error': 'El nombre de usuario esta en uso', 'old': old} ) if password and password != password_confirm: return render( request, template_name='users/register.html', context={'next': get_next_url(request), 'error': 'Las contraseñas no coinciden', 'old': old} ) user = get_user_model().objects.create_user(username, email, password) auth_login(request, user) return HttpResponseRedirect(get_next_url(request))