kpsul/gestion/views.py
Martin Pépin ac4dc0c192 tmp
2017-07-23 19:57:18 +01:00

197 lines
6.5 KiB
Python

"""
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 (<tt>%(username)s</tt>)"
" 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