forked from DGNum/gestioCOF
Refer to allauth doc for an accurate features list: http://django-allauth.readthedocs.io/en/latest/ Users can now change their password, ask for a password reset, or set one if they don't have one. In particular, it allows users whose account has been created via a clipper authentication to configure a password before losing their clipper. Even if they have already lost it, they are able to get one using the "Reset password" functionality. Allauth multiple emails management is deactivated. Requests to the related url redirect to the home page. All the login and logout views are replaced by the allauth' ones. It also concerns the Django and Wagtail admin sites. Note that users are no longer logged out of the clipper CAS server when they authenticated via this server. Instead a message suggests the user to disconnect. Clipper connections and `login_clipper` --------------------------------------- - Non-empty `login_clipper` are now unique among `CofProfile` instances. - They are created once for users with a non-empty 'login_clipper' (with the data migration 0014_create_clipper_connections). - The `login_clipper` of CofProfile instances are sync with their clipper connections: * `CofProfile.sync_clipper_connections` method updates the connections based on `login_clipper`. * Signals receivers `sync_clipper…` update `login_clipper` based on connections creations/updates/deletions. Misc ---- - Add NullCharField (model field) which allows to use `unique=True` on CharField (even with empty strings). - Parts of kfet mixins for TestCase are now in shared.tests.testcase, as they are used elsewhere than in the kfet app.
136 lines
4.9 KiB
Python
136 lines
4.9 KiB
Python
from django.contrib import messages
|
|
from django.contrib.auth import authenticate, login
|
|
from django.contrib.auth.decorators import permission_required
|
|
from django.contrib.auth.models import Group, User
|
|
from django.contrib.auth.views import redirect_to_login
|
|
from django.contrib.messages.views import SuccessMessageMixin
|
|
from django.core.urlresolvers import reverse, reverse_lazy
|
|
from django.db.models import Prefetch
|
|
from django.http import QueryDict
|
|
from django.shortcuts import redirect, render
|
|
from django.utils.decorators import method_decorator
|
|
from django.utils.translation import ugettext_lazy as _
|
|
from django.views.decorators.http import require_http_methods
|
|
from django.views.generic import View
|
|
from django.views.generic.edit import CreateView, UpdateView
|
|
|
|
from .forms import GroupForm
|
|
from .models import GenericTeamToken
|
|
|
|
|
|
class GenericLoginView(View):
|
|
"""
|
|
View to authenticate as kfet generic user.
|
|
|
|
It is a 2-step view. First, issue a token if user is a team member and send
|
|
him to the logout view (for proper disconnect) with callback url to here.
|
|
Then authenticate the token to log in as the kfet generic user.
|
|
|
|
Token is stored in COOKIES to avoid share it with the authentication
|
|
provider, which can be external. Session is unusable as it will be cleared
|
|
on logout.
|
|
"""
|
|
|
|
TOKEN_COOKIE_NAME = "kfettoken"
|
|
|
|
@method_decorator(require_http_methods(["GET", "POST"]))
|
|
def dispatch(self, request, *args, **kwargs):
|
|
token = request.get_signed_cookie(self.TOKEN_COOKIE_NAME, None)
|
|
if not token:
|
|
if not request.user.has_perm("kfet.is_team"):
|
|
return redirect_to_login(request.get_full_path())
|
|
|
|
if request.method == "POST":
|
|
# Step 1: set token and logout user.
|
|
return self.prepare_auth()
|
|
else:
|
|
# GET request should not change server/client states. Send a
|
|
# confirmation template to emit a POST request.
|
|
return render(
|
|
request,
|
|
"kfet/confirm_form.html",
|
|
{
|
|
"title": _("Ouvrir une session partagée"),
|
|
"text": _(
|
|
"Êtes-vous sûr·e de vouloir ouvrir une session "
|
|
"partagée ?"
|
|
),
|
|
},
|
|
)
|
|
else:
|
|
# Step 2: validate token.
|
|
return self.validate_auth(token)
|
|
|
|
def prepare_auth(self):
|
|
# Issue token.
|
|
token = GenericTeamToken.objects.create_token()
|
|
|
|
# Prepare callback of logout.
|
|
here_url = reverse(login_generic)
|
|
if "next" in self.request.GET:
|
|
# Keep given next page.
|
|
here_qd = QueryDict(mutable=True)
|
|
here_qd["next"] = self.request.GET["next"]
|
|
here_url += "?{}".format(here_qd.urlencode())
|
|
|
|
logout_url = reverse("account_logout")
|
|
logout_qd = QueryDict(mutable=True)
|
|
logout_qd["next"] = here_url
|
|
logout_url += "?{}".format(logout_qd.urlencode(safe="/"))
|
|
|
|
resp = redirect(logout_url)
|
|
resp.set_signed_cookie(self.TOKEN_COOKIE_NAME, token.token, httponly=True)
|
|
return resp
|
|
|
|
def validate_auth(self, token):
|
|
# Authenticate with GenericBackend.
|
|
user = authenticate(request=self.request, kfet_token=token)
|
|
|
|
if user:
|
|
# Log in generic user.
|
|
login(self.request, user)
|
|
messages.success(
|
|
self.request, _("K-Fêt — Ouverture d'une session partagée.")
|
|
)
|
|
resp = redirect(self.get_next_url())
|
|
else:
|
|
# Try again.
|
|
resp = redirect(self.request.get_full_path())
|
|
|
|
# Prevents blocking due to an invalid COOKIE.
|
|
resp.delete_cookie(self.TOKEN_COOKIE_NAME)
|
|
return resp
|
|
|
|
def get_next_url(self):
|
|
return self.request.GET.get("next", reverse("kfet.kpsul"))
|
|
|
|
|
|
login_generic = GenericLoginView.as_view()
|
|
|
|
|
|
@permission_required("kfet.manage_perms")
|
|
def account_group(request):
|
|
user_pre = Prefetch(
|
|
"user_set", queryset=User.objects.select_related("profile__account_kfet")
|
|
)
|
|
groups = Group.objects.filter(name__icontains="K-Fêt").prefetch_related(
|
|
"permissions", user_pre
|
|
)
|
|
return render(request, "kfet/account_group.html", {"groups": groups})
|
|
|
|
|
|
class AccountGroupCreate(SuccessMessageMixin, CreateView):
|
|
model = Group
|
|
template_name = "kfet/account_group_form.html"
|
|
form_class = GroupForm
|
|
success_message = "Nouveau groupe : %(name)s"
|
|
success_url = reverse_lazy("kfet.account.group")
|
|
|
|
|
|
class AccountGroupUpdate(SuccessMessageMixin, UpdateView):
|
|
queryset = Group.objects.filter(name__icontains="K-Fêt")
|
|
template_name = "kfet/account_group_form.html"
|
|
form_class = GroupForm
|
|
success_message = "Groupe modifié : %(name)s"
|
|
success_url = reverse_lazy("kfet.account.group")
|