Draft: Authens ! #767
18 changed files with 114 additions and 141 deletions
|
@ -11,26 +11,12 @@ from .common import INSTALLED_APPS
|
||||||
|
|
||||||
ALLOWED_HOSTS = ["bds.ens.fr", "www.bds.ens.fr", "dev.cof.ens.fr"]
|
ALLOWED_HOSTS = ["bds.ens.fr", "www.bds.ens.fr", "dev.cof.ens.fr"]
|
||||||
|
|
||||||
INSTALLED_APPS += ["bds", "events", "clubs", "authens"]
|
INSTALLED_APPS += ["bds", "events", "clubs"]
|
||||||
|
|
||||||
STATIC_ROOT = "/srv/bds.ens.fr/public/gestion2/static"
|
STATIC_ROOT = "/srv/bds.ens.fr/public/gestion2/static"
|
||||||
STATIC_URL = "/gestion2/static/"
|
STATIC_URL = "/gestion2/static/"
|
||||||
MEDIA_ROOT = "/srv/bds.ens.fr/gestion2/media"
|
MEDIA_ROOT = "/srv/bds.ens.fr/gestion2/media"
|
||||||
MEDIA_URL = "/gestion2/media/"
|
MEDIA_URL = "/gestion2/media/"
|
||||||
|
|
||||||
|
|
||||||
# ---
|
|
||||||
# Auth-related stuff
|
|
||||||
# ---
|
|
||||||
|
|
||||||
AUTHENTICATION_BACKENDS = [
|
|
||||||
"django.contrib.auth.backends.ModelBackend",
|
|
||||||
"authens.backends.ENSCASBackend",
|
|
||||||
"authens.backends.OldCASBackend",
|
|
||||||
]
|
|
||||||
|
|
||||||
AUTHENS_USE_OLDCAS = False
|
|
||||||
|
|
||||||
LOGIN_URL = "authens:login"
|
|
||||||
LOGIN_REDIRECT_URL = "bds:home"
|
LOGIN_REDIRECT_URL = "bds:home"
|
||||||
LOGOUT_REDIRECT_URL = "bds:home"
|
LOGOUT_REDIRECT_URL = "bds:home"
|
||||||
|
|
|
@ -4,7 +4,6 @@ The settings that are not listed here are imported from .common
|
||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from .common import * # NOQA
|
|
||||||
from .common import (
|
from .common import (
|
||||||
AUTHENTICATION_BACKENDS,
|
AUTHENTICATION_BACKENDS,
|
||||||
BASE_DIR,
|
BASE_DIR,
|
||||||
|
@ -14,6 +13,8 @@ from .common import (
|
||||||
import_secret,
|
import_secret,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from .common import * # NOQA
|
||||||
|
|
||||||
# ---
|
# ---
|
||||||
# COF-specific secrets
|
# COF-specific secrets
|
||||||
# ---
|
# ---
|
||||||
|
@ -108,13 +109,10 @@ CORS_ORIGIN_WHITELIST = ("bda.ens.fr", "www.bda.ens.fr" "cof.ens.fr", "www.cof.e
|
||||||
# Auth-related stuff
|
# Auth-related stuff
|
||||||
# ---
|
# ---
|
||||||
|
|
||||||
AUTHENTICATION_BACKENDS += [
|
AUTHENTICATION_BACKENDS.append("kfet.auth.backends.GenericBackend")
|
||||||
"gestioncof.shared.COFCASBackend",
|
|
||||||
"kfet.auth.backends.GenericBackend",
|
|
||||||
]
|
|
||||||
|
|
||||||
LOGIN_URL = "cof-login"
|
|
||||||
LOGIN_REDIRECT_URL = "home"
|
LOGIN_REDIRECT_URL = "home"
|
||||||
|
LOGOUT_REDIRECT_URL = "home"
|
||||||
|
|
||||||
# ---
|
# ---
|
||||||
# Cache settings
|
# Cache settings
|
||||||
|
|
|
@ -69,6 +69,7 @@ INSTALLED_APPS = [
|
||||||
"django_cas_ng",
|
"django_cas_ng",
|
||||||
"bootstrapform",
|
"bootstrapform",
|
||||||
"widget_tweaks",
|
"widget_tweaks",
|
||||||
|
"authens",
|
||||||
]
|
]
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
|
@ -133,11 +134,11 @@ FORMAT_MODULE_PATH = "cof.locale"
|
||||||
# Auth-related stuff
|
# Auth-related stuff
|
||||||
# ---
|
# ---
|
||||||
|
|
||||||
AUTHENTICATION_BACKENDS = ["django.contrib.auth.backends.ModelBackend"]
|
AUTHENTICATION_BACKENDS = [
|
||||||
|
"django.contrib.auth.backends.ModelBackend",
|
||||||
|
"authens.backends.ENSCASBackend",
|
||||||
|
]
|
||||||
|
|
||||||
CAS_SERVER_URL = "https://cas.eleves.ens.fr/"
|
AUTHENS_USE_OLDCAS = False
|
||||||
CAS_VERSION = "2"
|
|
||||||
CAS_LOGIN_MSG = None
|
LOGIN_URL = "authens:login"
|
||||||
CAS_IGNORE_REFERER = True
|
|
||||||
CAS_REDIRECT_URL = "/"
|
|
||||||
CAS_EMAIL_FORMAT = "%s@clipper.ens.fr"
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ app_dict = {
|
||||||
"bda": "gestion/bda/",
|
"bda": "gestion/bda/",
|
||||||
"petitscours": "gestion/petitcours/",
|
"petitscours": "gestion/petitcours/",
|
||||||
"events": "gestion/event_v2/", # the events module is still experimental !
|
"events": "gestion/event_v2/", # the events module is still experimental !
|
||||||
"authens": "gestion/authens/",
|
"authens": "gestion/auth/",
|
||||||
}
|
}
|
||||||
for (app_name, url_prefix) in app_dict.items():
|
for (app_name, url_prefix) in app_dict.items():
|
||||||
if app_name in settings.INSTALLED_APPS:
|
if app_name in settings.INSTALLED_APPS:
|
||||||
|
|
40
gestioncof/migrations/0018_django_cas_to_authens.py
Normal file
40
gestioncof/migrations/0018_django_cas_to_authens.py
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from authens.shortcuts import fetch_cas_account
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
def to_authens(apps, schema_editor):
|
||||||
|
User = apps.get_model("auth", "User")
|
||||||
|
CASAccount = apps.get_model("authens", "CASAccount")
|
||||||
|
|
||||||
|
failures = []
|
||||||
|
for user in User.objects.select_related("profile").all():
|
||||||
|
login_clipper = user.profile.login_clipper
|
||||||
|
if login_clipper:
|
||||||
|
ldap_info = fetch_cas_account(login_clipper)
|
||||||
|
if ldap_info is None:
|
||||||
|
failures.append(user)
|
||||||
|
else:
|
||||||
|
entrance_year = ldap_info["entrance_year"]
|
||||||
|
CASAccount.objects.create(
|
||||||
|
user=user, cas_login=login_clipper, entrance_year=entrance_year
|
||||||
|
)
|
||||||
|
|
||||||
|
if failures:
|
||||||
|
sys.stderr.write(" ---------- \n")
|
||||||
|
sys.stderr.write("Some accounts could not be linked to a CAS account:\n")
|
||||||
|
for user in failures:
|
||||||
|
sys.stderr.write(f"- {user.username}\n")
|
||||||
|
sys.stderr.write(" ---------- \n")
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("gestioncof", "0017_petitscours_uniqueness"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RunPython(to_authens, migrations.RunPython.noop),
|
||||||
|
]
|
15
gestioncof/static/gestioncof/css/authens_extra.css
Normal file
15
gestioncof/static/gestioncof/css/authens_extra.css
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
html, body {
|
||||||
|
background-color : #A7D4CD;
|
||||||
|
font-family: 'Roboto', sans-serif;
|
||||||
|
font-weight: 300;
|
||||||
|
}
|
||||||
|
|
||||||
|
#container-title, input[type="submit"] {
|
||||||
|
background: #4F504B;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cas { background: #49A5E3; }
|
||||||
|
.big-button.cas:hover { background: #71B5E3; }
|
||||||
|
|
||||||
|
.exte { background: #E36748; }
|
||||||
|
.big-button.exte:hover { background: #E38871; }
|
8
gestioncof/templates/authens/base.html
Normal file
8
gestioncof/templates/authens/base.html
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{% extends "authens/base.html" %}
|
||||||
|
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
|
{% block extra_css %}
|
||||||
|
<link type="text/css" rel="stylesheet" href="{% static "fonts/Roboto/roboto.css" %}" />
|
||||||
|
<link type="text/css" rel="stylesheet" href="{% static "gestioncof/css/authens_extra.css" %}" />
|
||||||
|
{% endblock %}
|
|
@ -11,7 +11,7 @@
|
||||||
</a>
|
</a>
|
||||||
<div class="secondary">
|
<div class="secondary">
|
||||||
<span class="hidden-xxs"> | </span>
|
<span class="hidden-xxs"> | </span>
|
||||||
<span><a href="{% url "cof-logout" %}">Se déconnecter <span class="glyphicon glyphicon-log-out"></span></a></span>
|
<span><a href="{% url "authens:logout" %}">Se déconnecter <span class="glyphicon glyphicon-log-out"></span></a></span>
|
||||||
</div>
|
</div>
|
||||||
<h2 class="member-status">{% if user.first_name %}{{ user.first_name }}{% else %}<tt>{{ user.username }}</tt>{% endif %}, {% if user.profile.is_cof %}<tt class="user-is-cof">au COF{% else %}<tt class="user-is-not-cof">non-COF{% endif %}</tt></h2>
|
<h2 class="member-status">{% if user.first_name %}{{ user.first_name }}{% else %}<tt>{{ user.username }}</tt>{% endif %}, {% if user.profile.is_cof %}<tt class="user-is-cof">au COF{% else %}<tt class="user-is-not-cof">non-COF{% endif %}</tt></h2>
|
||||||
</div><!-- /.container -->
|
</div><!-- /.container -->
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
|
from authens.views import LogoutView
|
||||||
from django.contrib.auth import views as django_auth_views
|
from django.contrib.auth import views as django_auth_views
|
||||||
from django.urls import include, path
|
from django.urls import include, path
|
||||||
from django.views.generic.base import TemplateView
|
from django.views.generic.base import TemplateView
|
||||||
from django_cas_ng import views as django_cas_views
|
|
||||||
|
|
||||||
from gestioncof import csv_views, views
|
from gestioncof import csv_views, views
|
||||||
|
|
||||||
|
@ -96,21 +96,7 @@ urlpatterns = [
|
||||||
TemplateView.as_view(template_name="cof-denied.html"),
|
TemplateView.as_view(template_name="cof-denied.html"),
|
||||||
name="cof-denied",
|
name="cof-denied",
|
||||||
),
|
),
|
||||||
path("cas/login", django_cas_views.LoginView.as_view(), name="cas_login_view"),
|
path("admin/logout/", LogoutView.as_view()),
|
||||||
path("cas/logout", django_cas_views.LogoutView.as_view()),
|
|
||||||
path(
|
|
||||||
"outsider/login",
|
|
||||||
views.LoginExtView.as_view(),
|
|
||||||
name="ext_login_view",
|
|
||||||
),
|
|
||||||
path(
|
|
||||||
"outsider/logout",
|
|
||||||
django_auth_views.LogoutView.as_view(),
|
|
||||||
{"next_page": "home"},
|
|
||||||
),
|
|
||||||
path("login", views.login, name="cof-login"),
|
|
||||||
path("logout", views.logout, name="cof-logout"),
|
|
||||||
path("admin/logout/", views.logout),
|
|
||||||
# -----
|
# -----
|
||||||
# Infos persos
|
# Infos persos
|
||||||
# -----
|
# -----
|
||||||
|
|
|
@ -2,17 +2,12 @@ import csv
|
||||||
import uuid
|
import uuid
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from smtplib import SMTPRecipientsRefused
|
from smtplib import SMTPRecipientsRefused
|
||||||
from urllib.parse import parse_qs, urlencode, urlparse, urlunparse
|
|
||||||
|
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.contrib.auth.views import (
|
from django.contrib.auth.views import redirect_to_login
|
||||||
LoginView as DjangoLoginView,
|
|
||||||
LogoutView as DjangoLogoutView,
|
|
||||||
redirect_to_login,
|
|
||||||
)
|
|
||||||
from django.contrib.sites.models import Site
|
from django.contrib.sites.models import Site
|
||||||
from django.core.mail import send_mail
|
from django.core.mail import send_mail
|
||||||
from django.http import Http404, HttpResponse, HttpResponseForbidden
|
from django.http import Http404, HttpResponse, HttpResponseForbidden
|
||||||
|
@ -22,7 +17,6 @@ from django.urls import reverse_lazy
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from django.views.generic import FormView, TemplateView
|
from django.views.generic import FormView, TemplateView
|
||||||
from django_cas_ng.views import LogoutView as CasLogoutView
|
|
||||||
from icalendar import Calendar, Event as Vevent
|
from icalendar import Calendar, Event as Vevent
|
||||||
|
|
||||||
from bda.models import Spectacle, Tirage
|
from bda.models import Spectacle, Tirage
|
||||||
|
@ -34,7 +28,6 @@ from gestioncof.forms import (
|
||||||
EventForm,
|
EventForm,
|
||||||
EventFormset,
|
EventFormset,
|
||||||
EventStatusFilterForm,
|
EventStatusFilterForm,
|
||||||
ExteAuthenticationForm,
|
|
||||||
GestioncofConfigForm,
|
GestioncofConfigForm,
|
||||||
PhoneForm,
|
PhoneForm,
|
||||||
ProfileForm,
|
ProfileForm,
|
||||||
|
@ -79,75 +72,6 @@ class HomeView(LoginRequiredMixin, TemplateView):
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
def login(request):
|
|
||||||
if request.user.is_authenticated:
|
|
||||||
return redirect("home")
|
|
||||||
context = {}
|
|
||||||
if request.method == "GET" and "next" in request.GET:
|
|
||||||
context["next"] = request.GET["next"]
|
|
||||||
return render(request, "login_switch.html", context)
|
|
||||||
|
|
||||||
|
|
||||||
class LoginExtView(DjangoLoginView):
|
|
||||||
template_name = "login.html"
|
|
||||||
form_class = ExteAuthenticationForm
|
|
||||||
|
|
||||||
def form_invalid(self, form):
|
|
||||||
for e in form.non_field_errors().as_data():
|
|
||||||
if e.code in ["has_clipper", "no_password"]:
|
|
||||||
return render(self.request, "login_error.html", {"error_code": e.code})
|
|
||||||
return super().form_invalid(form)
|
|
||||||
|
|
||||||
|
|
||||||
class CustomCasLogoutView(CasLogoutView):
|
|
||||||
"""
|
|
||||||
Actuellement, le CAS de l'ENS est pété et n'a pas le bon paramètre GET
|
|
||||||
pour rediriger après déconnexion. On change la redirection à la main
|
|
||||||
dans la vue de logout.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def get(self, request):
|
|
||||||
# CasLogoutView.get() retourne un HttpResponseRedirect
|
|
||||||
response = super().get(request)
|
|
||||||
parse_result = urlparse(response.url)
|
|
||||||
qd = parse_qs(parse_result.query)
|
|
||||||
|
|
||||||
if "url" in qd.keys():
|
|
||||||
# Le 2e pop est nécessaire car CAS n'aime pas
|
|
||||||
# les paramètres sous forme de liste
|
|
||||||
qd["service"] = qd.pop("url").pop()
|
|
||||||
|
|
||||||
# La méthode _replace est documentée !
|
|
||||||
new_url = parse_result._replace(query=urlencode(qd))
|
|
||||||
|
|
||||||
return redirect(urlunparse(new_url))
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
|
||||||
def logout(request, next_page=None):
|
|
||||||
if next_page is None:
|
|
||||||
next_page = request.GET.get("next", None)
|
|
||||||
|
|
||||||
profile = getattr(request.user, "profile", None)
|
|
||||||
|
|
||||||
if profile and profile.login_clipper:
|
|
||||||
if next_page is None:
|
|
||||||
# On ne voit pas les messages quand on se déconnecte de CAS
|
|
||||||
msg = None
|
|
||||||
else:
|
|
||||||
msg = _("Déconnexion de GestioCOF et CAS réussie. À bientôt {}.")
|
|
||||||
logout_view = CustomCasLogoutView.as_view()
|
|
||||||
else:
|
|
||||||
msg = _("Déconnexion de GestioCOF réussie. À bientôt {}.")
|
|
||||||
logout_view = DjangoLogoutView.as_view(
|
|
||||||
next_page=next_page, template_name="logout.html"
|
|
||||||
)
|
|
||||||
|
|
||||||
if msg is not None:
|
|
||||||
messages.success(request, msg.format(request.user.get_short_name()))
|
|
||||||
return logout_view(request)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def survey(request, survey_id):
|
def survey(request, survey_id):
|
||||||
survey = get_object_or_404(
|
survey = get_object_or_404(
|
||||||
|
|
|
@ -168,7 +168,9 @@ class GenericLoginViewTests(TestCase):
|
||||||
r = self.client.post(self.url)
|
r = self.client.post(self.url)
|
||||||
|
|
||||||
self.assertRedirects(
|
self.assertRedirects(
|
||||||
r, "/gestion/logout?next={}".format(self.url), fetch_redirect_response=False
|
r,
|
||||||
|
"/gestion/auth/logout?next={}".format(self.url),
|
||||||
|
fetch_redirect_response=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_notoken_not_team(self):
|
def test_notoken_not_team(self):
|
||||||
|
@ -180,13 +182,17 @@ class GenericLoginViewTests(TestCase):
|
||||||
# With GET.
|
# With GET.
|
||||||
r = self.client.get(self.url)
|
r = self.client.get(self.url)
|
||||||
self.assertRedirects(
|
self.assertRedirects(
|
||||||
r, "/gestion/login?next={}".format(self.url), fetch_redirect_response=False
|
r,
|
||||||
|
"/gestion/auth/login/choose?next={}".format(self.url),
|
||||||
|
fetch_redirect_response=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Also with POST.
|
# Also with POST.
|
||||||
r = self.client.post(self.url)
|
r = self.client.post(self.url)
|
||||||
self.assertRedirects(
|
self.assertRedirects(
|
||||||
r, "/gestion/login?next={}".format(self.url), fetch_redirect_response=False
|
r,
|
||||||
|
"/gestion/auth/login/choose?next={}".format(self.url),
|
||||||
|
fetch_redirect_response=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _set_signed_cookie(self, client, key, value):
|
def _set_signed_cookie(self, client, key, value):
|
||||||
|
|
|
@ -73,7 +73,7 @@ class GenericLoginView(View):
|
||||||
here_qd["next"] = self.request.GET["next"]
|
here_qd["next"] = self.request.GET["next"]
|
||||||
here_url += "?{}".format(here_qd.urlencode())
|
here_url += "?{}".format(here_qd.urlencode())
|
||||||
|
|
||||||
logout_url = reverse("cof-logout")
|
logout_url = reverse("authens:logout")
|
||||||
logout_qd = QueryDict(mutable=True)
|
logout_qd = QueryDict(mutable=True)
|
||||||
logout_qd["next"] = here_url
|
logout_qd["next"] = here_url
|
||||||
logout_url += "?{}".format(logout_qd.urlencode(safe="/"))
|
logout_url += "?{}".format(logout_qd.urlencode(safe="/"))
|
||||||
|
|
|
@ -1,8 +1,15 @@
|
||||||
from django.contrib.auth.decorators import user_passes_test
|
from django.contrib.auth.decorators import user_passes_test
|
||||||
|
from django.core.exceptions import PermissionDenied
|
||||||
|
|
||||||
|
|
||||||
def kfet_is_team(user):
|
def kfet_is_team(user):
|
||||||
return user.has_perm("kfet.is_team")
|
if user.is_authenticated:
|
||||||
|
if user.has_perm("kfet.is_team"):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
raise PermissionDenied
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
teamkfet_required = user_passes_test(kfet_is_team)
|
teamkfet_required = user_passes_test(kfet_is_team)
|
||||||
|
|
|
@ -101,7 +101,7 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<li class="divider"></li>
|
<li class="divider"></li>
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url "cof-logout" %}?next={{ kfet_home_url|urlencode }}">
|
<a href="{% url "authens:logout" %}?next={{ kfet_home_url|urlencode }}">
|
||||||
<span class="glyphicon glyphicon-log-out"></span><span>Déconnexion</span>
|
<span class="glyphicon glyphicon-log-out"></span><span>Déconnexion</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
@ -110,13 +110,13 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if user.is_authenticated and not perms.kfet.is_team %}
|
{% if user.is_authenticated and not perms.kfet.is_team %}
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url "cof-logout" %}?next={{ kfet_home_url|urlencode }}" title="Déconnexion">
|
<a href="{% url "authens:logout" %}?next={{ kfet_home_url|urlencode }}" title="Déconnexion">
|
||||||
<span class="glyphicon glyphicon-log-out"></span>
|
<span class="glyphicon glyphicon-log-out"></span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{% elif not user.is_authenticated %}
|
{% elif not user.is_authenticated %}
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url "cof-login" %}?next={{ request.path|urlencode }}" title="Connexion">
|
<a href="{% url "authens:login" %}?next={{ request.path|urlencode }}" title="Connexion">
|
||||||
<span>Connexion</span><!--
|
<span>Connexion</span><!--
|
||||||
--><span class="glyphicon glyphicon-log-in"></span>
|
--><span class="glyphicon glyphicon-log-in"></span>
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -61,7 +61,7 @@ class TestStats(TestCase):
|
||||||
self.assertEqual(404, resp2.status_code)
|
self.assertEqual(404, resp2.status_code)
|
||||||
|
|
||||||
# 2. FOO is a member of the team and can get these pages but BAR
|
# 2. FOO is a member of the team and can get these pages but BAR
|
||||||
# receives a Redirect response
|
# receives a 403 response
|
||||||
articles_urls = [
|
articles_urls = [
|
||||||
"/k-fet/articles/{}/stat/sales/list".format(article.pk),
|
"/k-fet/articles/{}/stat/sales/list".format(article.pk),
|
||||||
"/k-fet/articles/{}/stat/sales?{}".format(
|
"/k-fet/articles/{}/stat/sales?{}".format(
|
||||||
|
@ -80,4 +80,4 @@ class TestStats(TestCase):
|
||||||
resp = client.get(url)
|
resp = client.get(url)
|
||||||
self.assertEqual(200, resp.status_code)
|
self.assertEqual(200, resp.status_code)
|
||||||
resp2 = client2.get(url, follow=True)
|
resp2 = client2.get(url, follow=True)
|
||||||
self.assertRedirects(resp2, "/gestion/")
|
self.assertEqual(403, resp2.status_code)
|
||||||
|
|
|
@ -232,7 +232,7 @@ class AccountReadViewTests(ViewTestCaseMixin, TestCase):
|
||||||
response = client.get(url)
|
response = client.get(url)
|
||||||
self.assertRedirects(
|
self.assertRedirects(
|
||||||
response,
|
response,
|
||||||
"/gestion/login?next={}".format(url),
|
"/gestion/auth/login/choose?next={}".format(url),
|
||||||
fetch_redirect_response=False,
|
fetch_redirect_response=False,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
@ -344,7 +344,7 @@ class AccountUpdateViewTests(ViewTestCaseMixin, TestCase):
|
||||||
response = meth(url)
|
response = meth(url)
|
||||||
self.assertRedirects(
|
self.assertRedirects(
|
||||||
response,
|
response,
|
||||||
"/gestion/login?next={}".format(url),
|
"/gestion/auth/login/choose?next={}".format(url),
|
||||||
fetch_redirect_response=False,
|
fetch_redirect_response=False,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
@ -629,7 +629,7 @@ class AccountStatOperationListViewTests(ViewTestCaseMixin, TestCase):
|
||||||
response = client.get(url)
|
response = client.get(url)
|
||||||
self.assertRedirects(
|
self.assertRedirects(
|
||||||
response,
|
response,
|
||||||
"/gestion/login?next={}".format(url),
|
"/gestion/auth/login/choose?next={}".format(url),
|
||||||
fetch_redirect_response=False,
|
fetch_redirect_response=False,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
@ -723,7 +723,7 @@ class AccountStatOperationViewTests(ViewTestCaseMixin, TestCase):
|
||||||
response = client.get(url)
|
response = client.get(url)
|
||||||
self.assertRedirects(
|
self.assertRedirects(
|
||||||
response,
|
response,
|
||||||
"/gestion/login?next={}".format(url),
|
"/gestion/auth/login/choose?next={}".format(url),
|
||||||
fetch_redirect_response=False,
|
fetch_redirect_response=False,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
@ -764,7 +764,7 @@ class AccountStatBalanceListViewTests(ViewTestCaseMixin, TestCase):
|
||||||
response = client.get(url)
|
response = client.get(url)
|
||||||
self.assertRedirects(
|
self.assertRedirects(
|
||||||
response,
|
response,
|
||||||
"/gestion/login?next={}".format(url),
|
"/gestion/auth/login/choose?next={}".format(url),
|
||||||
fetch_redirect_response=False,
|
fetch_redirect_response=False,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
@ -830,7 +830,7 @@ class AccountStatBalanceViewTests(ViewTestCaseMixin, TestCase):
|
||||||
response = client.get(url)
|
response = client.get(url)
|
||||||
self.assertRedirects(
|
self.assertRedirects(
|
||||||
response,
|
response,
|
||||||
"/gestion/login?next={}".format(url),
|
"/gestion/auth/login/choose?next={}".format(url),
|
||||||
fetch_redirect_response=False,
|
fetch_redirect_response=False,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -39,7 +39,9 @@ class TestCaseMixin:
|
||||||
querystring = QueryDict(mutable=True)
|
querystring = QueryDict(mutable=True)
|
||||||
querystring["next"] = full_path
|
querystring["next"] = full_path
|
||||||
|
|
||||||
login_url = "/gestion/login?" + querystring.urlencode(safe="/")
|
login_url = "/gestion/auth/login/choose?{}".format(
|
||||||
|
querystring.urlencode(safe="/")
|
||||||
|
)
|
||||||
|
|
||||||
# We don't focus on what the login view does.
|
# We don't focus on what the login view does.
|
||||||
# So don't fetch the redirect.
|
# So don't fetch the redirect.
|
||||||
|
|
|
@ -173,7 +173,7 @@ class TestCaseMixin:
|
||||||
querystring["next"] = full_path
|
querystring["next"] = full_path
|
||||||
|
|
||||||
login_url = "{}?{}".format(
|
login_url = "{}?{}".format(
|
||||||
reverse("cof-login"), querystring.urlencode(safe="/")
|
reverse("authens:login"), querystring.urlencode(safe="/")
|
||||||
)
|
)
|
||||||
|
|
||||||
# We don't focus on what the login view does.
|
# We don't focus on what the login view does.
|
||||||
|
|
Loading…
Reference in a new issue