Move the auth stuff to gestion/
- The login views are in `gestion/` - The templates are under `gestion/templates/gestion/` - `cof/shared.py` moves to `gestion/` and is splitted into 3 files: - The auth backends are in `backends.py`. - The context_processor is in `context_processor.py` - The LOCK/UNLOCK functions remain in `shared.py`
This commit is contained in:
parent
50b667993f
commit
a28c00e474
16 changed files with 156 additions and 147 deletions
|
@ -15,9 +15,9 @@ from django.core.validators import MinLengthValidator
|
|||
from .models import CofProfile, EventCommentValue, \
|
||||
CalendarSubscription, Club
|
||||
from .widgets import TriStateCheckbox
|
||||
from .shared import lock_table, unlock_table
|
||||
|
||||
from gestion.models import Profile
|
||||
from gestion.shared import lock_table, unlock_table
|
||||
|
||||
from bda.models import Spectacle
|
||||
|
||||
|
|
|
@ -18,9 +18,10 @@ from .petits_cours_models import (
|
|||
PetitCoursAbility, PetitCoursSubject
|
||||
)
|
||||
from .decorators import buro_required
|
||||
from .shared import lock_table, unlock_tables
|
||||
from .petits_cours_forms import DemandeForm, MatieresFormSet
|
||||
|
||||
from gestion.shared import lock_table, unlock_tables
|
||||
|
||||
|
||||
class DemandeListView(ListView):
|
||||
model = PetitCoursDemande
|
||||
|
|
|
@ -10,8 +10,10 @@
|
|||
{% endblock %}
|
||||
</a>
|
||||
<div class="secondary">
|
||||
<span class="hidden-xxs"> | </span>
|
||||
<span><a href="{% url "cof.views.logout" %}">Se déconnecter <span class="glyphicon glyphicon-log-out"></span></a></span>
|
||||
<span class="hidden-xxs"> | </span>
|
||||
<span><a href="{% url "gestion:logout" %}">
|
||||
Se déconnecter <span class="glyphicon glyphicon-log-out"></span>
|
||||
</a></span>
|
||||
</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>
|
||||
</div><!-- /.container -->
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
{% extends "base_title.html" %}
|
||||
|
||||
{% block realcontent %}
|
||||
{% if error_type == "use_clipper_login" %}
|
||||
<h2><strong>Votre identifiant est lié à un compte <tt>clipper</tt></strong></h2>
|
||||
<p>Veuillez vous connecter à l'aide de votre <a href="{% url 'cas_login_view' %}">compte <tt>clipper</tt></a></p>
|
||||
{% elif error_type == "no_password" %}
|
||||
<h2><strong>Votre compte n'a pas de mot de passe associé</strong></h2>
|
||||
<p>Veuillez <a href="mailto:cof@clipper.ens.fr">nous contacter</a> pour que nous en définissions un et que nous vous le transmettions !</p>
|
||||
{% else %}
|
||||
<h1><strong>{{ error_title }}</strong></h1>
|
||||
<p>{{ error_description }}</p>
|
||||
{% endif %}
|
||||
{% endblock %}
|
45
cof/views.py
45
cof/views.py
|
@ -9,7 +9,6 @@ from custommail.shortcuts import send_custom_mail
|
|||
from django.shortcuts import redirect, get_object_or_404, render
|
||||
from django.http import Http404, HttpResponse, HttpResponseForbidden
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth.views import login as django_login_view
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.sites.models import Site
|
||||
from django.utils import timezone
|
||||
|
@ -50,50 +49,6 @@ def home(request):
|
|||
return render(request, "home.html", data)
|
||||
|
||||
|
||||
def login(request):
|
||||
if request.user.is_authenticated():
|
||||
return redirect("cof.views.home")
|
||||
context = {}
|
||||
if request.method == "GET" and 'next' in request.GET:
|
||||
context['next'] = request.GET['next']
|
||||
return render(request, "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 not user.has_usable_password() or user.password in ("", "!"):
|
||||
profile, created = CofProfile.objects.get_or_create(user=user)
|
||||
if profile.login_clipper:
|
||||
return render(request, "error.html",
|
||||
{"error_type": "use_clipper_login"})
|
||||
else:
|
||||
return render(request, "error.html",
|
||||
{"error_type": "no_password"})
|
||||
except User.DoesNotExist:
|
||||
pass
|
||||
context = {}
|
||||
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_view(request, template_name='login.html',
|
||||
extra_context=context)
|
||||
|
||||
|
||||
@login_required
|
||||
def logout(request):
|
||||
try:
|
||||
profile = request.user.profile
|
||||
except CofProfile.DoesNotExist:
|
||||
profile, created = CofProfile.objects.get_or_create(user=request.user)
|
||||
if profile.login_clipper:
|
||||
return redirect("django_cas_ng.views.logout")
|
||||
else:
|
||||
return redirect("django.contrib.auth.views.logout")
|
||||
|
||||
|
||||
@login_required
|
||||
def survey(request, survey_id):
|
||||
survey = get_object_or_404(Survey, id=survey_id)
|
||||
|
|
|
@ -33,7 +33,6 @@ INSTALLED_APPS = (
|
|||
'django.contrib.sites',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'grappelli',
|
||||
'django.contrib.admin',
|
||||
'django.contrib.admindocs',
|
||||
'autocomplete_light',
|
||||
|
@ -80,7 +79,7 @@ TEMPLATES = [
|
|||
'django.core.context_processors.i18n',
|
||||
'django.core.context_processors.media',
|
||||
'django.core.context_processors.static',
|
||||
'cof.shared.context_processor',
|
||||
'gestion.context_processors.context_processor',
|
||||
'kfet.context_processors.auth',
|
||||
],
|
||||
},
|
||||
|
@ -130,9 +129,6 @@ MEDIA_URL = '/media/'
|
|||
# Various additional settings
|
||||
SITE_ID = 1
|
||||
|
||||
GRAPPELLI_ADMIN_HEADLINE = "GestioCOF"
|
||||
GRAPPELLI_ADMIN_TITLE = "<a href=\"/\">GestioCOF</a>"
|
||||
|
||||
MAIL_DATA = {
|
||||
'petits_cours': {
|
||||
'FROM': "Le COF <cof@ens.fr>",
|
||||
|
@ -146,7 +142,7 @@ MAIL_DATA = {
|
|||
'REPLYTO': 'BdA-Revente <bda-revente@ens.fr>'},
|
||||
}
|
||||
|
||||
LOGIN_URL = "cof-login"
|
||||
LOGIN_URL = "gestion:login"
|
||||
LOGIN_REDIRECT_URL = "home"
|
||||
|
||||
CAS_SERVER_URL = 'https://cas.eleves.ens.fr/'
|
||||
|
@ -155,7 +151,7 @@ CAS_REDIRECT_URL = '/'
|
|||
CAS_EMAIL_FORMAT = "%s@clipper.ens.fr"
|
||||
AUTHENTICATION_BACKENDS = (
|
||||
'django.contrib.auth.backends.ModelBackend',
|
||||
'cof.shared.COFCASBackend',
|
||||
'gestion.backends.COFCASBackend',
|
||||
'kfet.backends.GenericTeamBackend',
|
||||
)
|
||||
|
||||
|
|
|
@ -10,16 +10,16 @@ from django.conf import settings
|
|||
from django.conf.urls import include, url
|
||||
from django.conf.urls.static import static
|
||||
from django.contrib import admin
|
||||
from django.views.generic.base import TemplateView
|
||||
from django.contrib.auth import views as django_views
|
||||
from django_cas_ng import views as django_cas_views
|
||||
|
||||
from cof import views as cof_views, csv_views
|
||||
from cof import views as cof_views
|
||||
from cof.urls import export_patterns, petitcours_patterns, \
|
||||
surveys_patterns, events_patterns, calendar_patterns, \
|
||||
clubs_patterns
|
||||
from cof.autocomplete import autocomplete
|
||||
|
||||
from gestion import views as gestion_views
|
||||
|
||||
autocomplete_light.autodiscover()
|
||||
admin.autodiscover()
|
||||
|
||||
|
@ -28,6 +28,10 @@ urlpatterns = [
|
|||
url(r'^$', cof_views.home, name='home'),
|
||||
# The common views
|
||||
url(r"^", include("gestion.urls", namespace='gestion')),
|
||||
# Admin urls
|
||||
url(r'^admin/logout/', gestion_views.logout),
|
||||
url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
|
||||
url(r'^admin/', include(admin.site.urls)),
|
||||
# Le BdA
|
||||
url(r'^bda/', include('bda.urls')),
|
||||
# Les exports
|
||||
|
@ -42,15 +46,6 @@ urlpatterns = [
|
|||
url(r'^calendar/', include(calendar_patterns)),
|
||||
# Clubs
|
||||
url(r'^clubs/', include(clubs_patterns)),
|
||||
# Authentification
|
||||
url(r'^cof/denied$', TemplateView.as_view(template_name='cof-denied.html'),
|
||||
name="cof-denied"),
|
||||
url(r'^cas/login$', django_cas_views.login, name="cas_login_view"),
|
||||
url(r'^cas/logout$', django_cas_views.logout),
|
||||
url(r'^outsider/login$', cof_views.login_ext),
|
||||
url(r'^outsider/logout$', django_views.logout, {'next_page': 'home'}),
|
||||
url(r'^login$', cof_views.login, name="cof-login"),
|
||||
url(r'^logout$', cof_views.logout),
|
||||
# Infos persos
|
||||
url(r'^outsider/password-change$', django_views.password_change),
|
||||
url(r'^outsider/password-change-done$',
|
||||
|
@ -67,14 +62,6 @@ urlpatterns = [
|
|||
# Autocompletion
|
||||
url(r'^autocomplete/registration$', autocomplete),
|
||||
url(r'^autocomplete/', include('autocomplete_light.urls')),
|
||||
# Interface admin
|
||||
url(r'^admin/logout/', cof_views.logout),
|
||||
url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
|
||||
url(r'^admin/(?P<app_label>[\d\w]+)/(?P<model_name>[\d\w]+)/csv/',
|
||||
csv_views.admin_list_export,
|
||||
{'fields': ['username', ]}),
|
||||
url(r'^admin/', include(admin.site.urls)),
|
||||
url(r'^grappelli/', include('grappelli.urls')),
|
||||
# Liens utiles du COF et du BdA
|
||||
url(r'^utile_cof$', cof_views.utile_cof),
|
||||
url(r'^utile_bda$', cof_views.utile_bda),
|
||||
|
|
|
@ -1,17 +1,11 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.contrib.sites.models import Site
|
||||
from django.conf import settings
|
||||
from django_cas_ng.backends import CASBackend
|
||||
from django_cas_ng.utils import get_cas_client
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.db import connection
|
||||
|
||||
from .models import CofProfile
|
||||
from gestion.models import Profile
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
|
@ -32,9 +26,12 @@ class COFCASBackend(CASBackend):
|
|||
# éviter les doublons.
|
||||
username = username.strip().lower()
|
||||
|
||||
profiles = CofProfile.objects.filter(login_clipper=username)
|
||||
profiles = Profile.objects.filter(login_clipper=username)
|
||||
if len(profiles) > 0:
|
||||
profile = profiles.order_by('-is_cof')[0]
|
||||
# XXX. We have to deal with multiple profiles, this should not
|
||||
# happen
|
||||
# profile = profiles.order_by('-is_cof')[0]
|
||||
profile = profiles.first()
|
||||
user = profile.user
|
||||
return user
|
||||
try:
|
||||
|
@ -50,49 +47,11 @@ class COFCASBackend(CASBackend):
|
|||
user = self.authenticate_cas(ticket, service, request)
|
||||
if user is None:
|
||||
return user
|
||||
try:
|
||||
profile = user.profile
|
||||
except CofProfile.DoesNotExist:
|
||||
profile, created = CofProfile.objects.get_or_create(user=user)
|
||||
profile.save()
|
||||
profile = user.profile
|
||||
if not profile.login_clipper:
|
||||
profile.login_clipper = user.username
|
||||
profile.save()
|
||||
if not user.email:
|
||||
user.email = settings.CAS_EMAIL_FORMAT % profile.login_clipper
|
||||
user.save()
|
||||
if profile.is_buro and not user.is_staff:
|
||||
user.is_staff = True
|
||||
user.save()
|
||||
return user
|
||||
|
||||
|
||||
def context_processor(request):
|
||||
'''Append extra data to the context of the given request'''
|
||||
data = {
|
||||
"user": request.user,
|
||||
"site": Site.objects.get_current(),
|
||||
}
|
||||
return data
|
||||
|
||||
|
||||
def lock_table(*models):
|
||||
query = "LOCK TABLES "
|
||||
for i, model in enumerate(models):
|
||||
table = model._meta.db_table
|
||||
if i > 0:
|
||||
query += ", "
|
||||
query += "%s WRITE" % table
|
||||
cursor = connection.cursor()
|
||||
cursor.execute(query)
|
||||
row = cursor.fetchone()
|
||||
return row
|
||||
|
||||
|
||||
def unlock_tables(*models):
|
||||
cursor = connection.cursor()
|
||||
cursor.execute("UNLOCK TABLES")
|
||||
row = cursor.fetchone()
|
||||
return row
|
||||
|
||||
unlock_table = unlock_tables
|
10
gestion/context_processors.py
Normal file
10
gestion/context_processors.py
Normal file
|
@ -0,0 +1,10 @@
|
|||
from django.contrib.sites.models import Site
|
||||
|
||||
|
||||
def context_processor(request):
|
||||
'''Append extra data to the context of the given request'''
|
||||
data = {
|
||||
"user": request.user,
|
||||
"site": Site.objects.get_current(),
|
||||
}
|
||||
return data
|
27
gestion/shared.py
Normal file
27
gestion/shared.py
Normal file
|
@ -0,0 +1,27 @@
|
|||
"""
|
||||
Locking/unlocking tools to prevent tables to be corrupted
|
||||
"""
|
||||
|
||||
from django.db import connection
|
||||
|
||||
|
||||
def lock_table(*models):
|
||||
query = "LOCK TABLES "
|
||||
for i, model in enumerate(models):
|
||||
table = model._meta.db_table
|
||||
if i > 0:
|
||||
query += ", "
|
||||
query += "%s WRITE" % table
|
||||
cursor = connection.cursor()
|
||||
cursor.execute(query)
|
||||
row = cursor.fetchone()
|
||||
return row
|
||||
|
||||
|
||||
def unlock_tables(*models):
|
||||
cursor = connection.cursor()
|
||||
cursor.execute("UNLOCK TABLES")
|
||||
row = cursor.fetchone()
|
||||
return row
|
||||
|
||||
unlock_table = unlock_tables
|
20
gestion/templates/gestion/error.html
Normal file
20
gestion/templates/gestion/error.html
Normal file
|
@ -0,0 +1,20 @@
|
|||
{% extends "base_title.html" %}
|
||||
|
||||
{% block realcontent %}
|
||||
{% if error_type == "use_clipper_login" %}
|
||||
<h2><strong>Votre identifiant est lié à un compte <tt>clipper</tt></strong></h2>
|
||||
<p>
|
||||
Veuillez vous connecter à l'aide de votre
|
||||
<a href="{% url 'gestion:cas_login' %}">compte <tt>clipper</tt></a>
|
||||
</p>
|
||||
{% elif error_type == "no_password" %}
|
||||
<h2><strong>Votre compte n'a pas de mot de passe associé</strong></h2>
|
||||
<p>
|
||||
Veuillez <a href="mailto:cof@clipper.ens.fr">nous contacter</a> pour que
|
||||
nous en définissions un et que nous vous le transmettions !
|
||||
</p>
|
||||
{% else %}
|
||||
<h1><strong>{{ error_title }}</strong></h1>
|
||||
<p>{{ error_description }}</p>
|
||||
{% endif %}
|
||||
{% endblock %}
|
|
@ -15,7 +15,7 @@
|
|||
<p class="error">Identifiants incorrects.</p>
|
||||
{% endif %}
|
||||
<form class="form-horizontal" method="post"
|
||||
action="{% url 'cof.views.login_ext' %}?next={{ next|urlencode }}">
|
||||
action="{% url 'gestion:login_ext' %}?next={{ next|urlencode }}">
|
||||
{% csrf_token %}
|
||||
<div class="form-group">
|
||||
<input class="form-control" id="id_username" maxlength="254" name="username" type="text" placeholder="Nom d'utilisateur">
|
|
@ -12,13 +12,13 @@
|
|||
<div class="container-fluid">
|
||||
<div class="row" style="margin:0;">
|
||||
<a aria-label="Compte clipper"
|
||||
href="{% url 'django_cas_ng.views.login' %}?next={{ next|urlencode }}">
|
||||
<div class="col-xs-12 col-sm-6" id="login_clipper">
|
||||
Compte clipper
|
||||
</div>
|
||||
href="{% url 'gestion:cas_login' %}?next={{ next|urlencode }}">
|
||||
<div class="col-xs-12 col-sm-6" id="login_clipper">
|
||||
Compte clipper
|
||||
</div>
|
||||
</a>
|
||||
<a aria-label="Extérieur"
|
||||
href="{% url 'cof.views.login_ext' %}?next={{ next|urlencode }}">
|
||||
href="{% url 'gestion:login_ext' %}?next={{ next|urlencode }}">
|
||||
<div class="col-xs-12 col-sm-6" id="login_outsider">
|
||||
Extérieur
|
||||
</div>
|
|
@ -1,8 +1,24 @@
|
|||
from django.conf.urls import url
|
||||
from django.conf.urls import url, include
|
||||
from django.views.generic.base import TemplateView
|
||||
from django.contrib.auth import views as django_views
|
||||
from django.contrib import admin
|
||||
from django_cas_ng import views as django_cas_views
|
||||
|
||||
from . import views
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
# Profile edition
|
||||
url(r"^profile/?$", views.profile, name="profile"),
|
||||
|
||||
# Authentication
|
||||
url(r'^cof/denied$',
|
||||
TemplateView.as_view(template_name='cof-denied.html'),
|
||||
name="denied"),
|
||||
url(r'^cas/login$', django_cas_views.login, name="cas_login"),
|
||||
url(r'^cas/logout$', django_cas_views.logout, name="cas_logout"),
|
||||
url(r'^outsider/login$', views.login_ext, name="login_ext"),
|
||||
url(r'^outsider/logout$', django_views.logout, {'next_page': 'home'}),
|
||||
url(r'^login$', views.login, name="login"),
|
||||
url(r'^logout$', views.logout, name="logout"),
|
||||
]
|
||||
|
|
|
@ -1,9 +1,59 @@
|
|||
from django.shortcuts import render
|
||||
"""
|
||||
The common views of the different organisations.
|
||||
- Authentication
|
||||
- Profile edition
|
||||
"""
|
||||
|
||||
from django.shortcuts import render, redirect
|
||||
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 .forms import ProfileForm, UserForm
|
||||
|
||||
|
||||
def login(request):
|
||||
if request.user.is_authenticated():
|
||||
return redirect("cof.views.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)
|
||||
|
||||
|
||||
@login_required
|
||||
def profile(request):
|
||||
success = False
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
</li>
|
||||
{% endif %}
|
||||
{% if user.is_authenticated %}
|
||||
<li><a href="{% url 'cof.views.logout' %}?next=/k-fet/" title="Déconnexion"><span class="glyphicon glyphicon-log-out"></span></a></li>
|
||||
<li><a href="{% url 'gestion:logout' %}?next=/k-fet/" title="Déconnexion"><span class="glyphicon glyphicon-log-out"></span></a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue