""" The common views of the different organisations. - Authentication - Profile edition """ from django.contrib import messages from django.contrib.auth.decorators import login_required from django.contrib.auth.models import User from django.contrib.auth.views import ( login as django_login, logout as django_logout ) from django.http import HttpResponseBadRequest from django.shortcuts import render, redirect, get_object_or_404 from django.utils.translation import ugettext_lazy as _ from django.views.generic import TemplateView from .forms import ( ProfileForm, UserForm, UserRegistrationForm, ProfileRegistrationForm ) from .shared import get_or_create_clipper # --- # Authentcation # --- def login(request): if request.user.is_authenticated(): return redirect("home") context = {} # Fetch the next page from the request data if request.method == "GET" and 'next' in request.GET: context['next'] = request.GET['next'] return render(request, "gestion/login_switch.html", context) def login_ext(request): if request.method == "POST" and "username" in request.POST: try: user = User.objects.get(username=request.POST["username"]) if user.profile.login_clipper: return render(request, "gestion/error.html", {"error_type": "use_clipper_login"}) if not user.has_usable_password() or user.password in ("", "!"): return render(request, "gestion/error.html", {"error_type": "no_password"}) except User.DoesNotExist: pass context = {} # Fetch the next page from the request data if request.method == "GET" and 'next' in request.GET: context['next'] = request.GET['next'] if request.method == "POST" and 'next' in request.POST: context['next'] = request.POST['next'] return django_login(request, template_name='gestion/login.html', extra_context=context) @login_required def logout(request): if request.user.profile.login_clipper: return redirect("gestion:cas_logout") else: return django_logout(request) # --- # User management # --- @login_required def profile(request): success = False user = request.user if request.method == "POST": user_form = UserForm(request.POST, instance=user) profile_form = ProfileForm(request.POST, instance=user.profile) if (user_form.is_valid() and profile_form.is_valid()): user_form.save() profile_form.save() success = True else: user_form = UserForm(instance=user) profile_form = ProfileForm(instance=user.profile) return render(request, "gestion/profile.html", {"user_form": user_form, "profile_form": profile_form, "success": success}) # TODO: send "Welcome" email class RegistrationView(TemplateView): user = None form_class = None form_only = False # TODO: explain this page_url = "" # TODO: explain this def get_form_kwargs(self, **kwargs): return kwargs # --- # Template related code # --- @property def template_name(self): if self.form_only: return "gestion/registration_form.html" else: return "gestion/registration.html" def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) post_data = kwargs.pop("post_data", None) user = self.user context["user"] = user context["page_url"] = self.page_url context["user_form"] = UserRegistrationForm( instance=user, prefix="user", data=post_data ) context["profile_form"] = ProfileRegistrationForm( instance=user.profile if user else None, prefix="profile", data=post_data ) context["extra_form"] = self.form_class(**self.get_form_kwargs( prefix="extra", data=post_data, )) return context # --- # Request processing # --- def get(self, request, username=""): """ The `user_type` GET parameter is used the following way: - If not set, return empty forms. - If set to "normal", assume the user exists. - If set to, "clipper" create a user linked to a clipper account if a user with the provided username doesn't exist. The `fullname` GET parameter is only used to create new clipper users """ user_type, fullname = self.clean_GET(request.GET) if user_type == "clipper": self.user, _ = get_or_create_clipper(username, fullname) elif user_type == "normal": self.user = get_object_or_404(User, username=username) context = self.get_context_data() return super().render_to_response(context) def post(self, request): # the `user_exists` POST parameter indicates that we should expect the # user to be in the database already. Otherwise we return a 404 page. # TODO: 404 is bad, prefer an "displayable" error if "user_exists" in request.POST: username = request.POST.get("user-username", "") self.user = get_object_or_404(User, username=username) context = self.get_context_data( post_data=request.POST, ) if all([context["user_form"].is_valid(), context["profile_form"].is_valid(), context["extra_form"].is_valid()]): self.user = context["user_form"].save() context["user"] = self.user context["profile_form"].save() context["extra_form"].save() messages.success( request, _("L'inscription de %(fullname)s (%(username)s)" " a été enregistrée avec succès") % {"fullname": self.user.get_full_name(), "username": self.user.username} ) return super().render_to_response(context) @staticmethod def clean_GET(get_params): allowed_user_types = {"normal", "clipper", None} user_type = get_params.get("user_type") if user_type not in allowed_user_types: return HttpResponseBadRequest( "Invalid value `{}` expected `({})`" .format(user_type, "|".join(allowed_user_types)) ) fullname = get_params.get("fullname") if fullname is not None: fullname = str(fullname) return user_type, fullname