Commit 87576950 authored by Nicolas Dandrimont's avatar Nicolas Dandrimont

[login.py] Nettoyage, Decorateur pour brancher plusieurs fonctions d'auth

parent bd98ccf8
......@@ -4,7 +4,9 @@
# LOGIN.PY -- Gère l'interface d'authentification.
#
# Copyright (C) 2009 Antoine Durand-Gasselin
# Author: Antoine Durand-Gasselin <adg@crans.org>
# Copyright (C) 2009-2010 Nicolas Dandrimont
# Authors: Antoine Durand-Gasselin <adg@crans.org>
# Nicolas Dandrimont <olasd@crans.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
......@@ -21,37 +23,95 @@
import django.contrib.auth, settings
from django.utils.http import urlquote
from django.http import HttpResponse, HttpResponseRedirect
from django.http import HttpResponse, HttpResponseRedirect, HttpResponseForbidden
from django.shortcuts import render_to_response
# Quelques fonction de login
def crans_ldap_login(request, login, password):
next = request.POST.get('next', '/')
from decorator import decorator
## Décorateur, liste des fonctions d'authentification
LOGIN_FUNS = []
def login_func(fun):
"""Décorateur pour chaque fonction de login. Les fonctions de
login sont appelées dans l'ordre de leur définition."""
LOGIN_FUNS.append(fun)
return fun
## Exceptions
class BaseLoginExc(Exception):
"""Exception de base pour le login"""
def __init__(self, message=""):
self.message = message
class UserNotFound(BaseLoginExc):
"""Utilisateur non trouvé. Passe à la méthode suivante."""
pass
class UserForbidden(BaseLoginExc):
"""Utilisateur non autorisé. Échoue directement."""
pass
## Fonctions d'authentification
# Les fonctions d'authentification prennent deux arguments (login, mot
# de passe).
#
# Elles doivent retourner un doublet ("Nom d'utilisateur", ["Droit A",
# "Droit B", ...]) si l'utilisateur est authentifié. Une exception
# doit être renvoyée sinon.
@login_func
def crans_ldap_login(login, password):
"""Login à l'aide de Cr@ns-LDAP"""
try:
adh = settings.db.search('uid=%s' % login)['adherent'][0]
except: adh = None
if adh and adh.checkPassword(password):
request.session['adherent'] = adh.Nom()
request.session['droits'] = adh.droits()
return HttpResponseRedirect(next)
except Exception:
adh = None
if adh:
if adh.checkPassword(password):
adh = adh.Nom()
droits = [droit.lower() for droit in adh.droits()]
else:
raise UserForbidden()
else:
request.session['message'] = u'Login ou mot de passe incorrect'
return HttpResponseRedirect('/login?next=%s' % next)
raise UserNotFound()
return adh, droits
def plain_login(request, login, password):
next = request.POST.get('next', '/')
@login_func
def plain_login(login, password):
"""Login en texte plein"""
if password == 'prout':
request.session['adherent'] = login
request.session['droits'] = ['nounou']
return HttpResponseRedirect(next)
adh = login
droits = ['nounou']
else:
request.session['message'] = u'Login ou mot de passe incorrect'
return HttpResponseRedirect('/login?next=%s' % next)
raise UserForbidden()
return adh, droits
# Fonction de login utilisée
login_function = plain_login # XXXX Authentication method here
## Fonction réelle d'authentification
def require_droits(droits=[]):
def login_function(request, login, password):
"""Fonction d'authentification"""
next = request.POST.get('next', '/')
print "prem's"
for function in LOGIN_FUNS:
print function
try:
adh, droits = function(login, password)
except (UserForbidden, UserNotFound):
print "not found..."
continue
else:
request.session["adherent"] = adh
request.session["droits"] = droits
return HttpResponseRedirect(next)
else:
request.session["message"] = u"Utilisateur inconnu !"
return HttpResponseRedirect('/login?next=%s' % next)
## Utilitaires sur les droits
def require_droits(droits=None):
"""Appliquée à une liste de droits, définit un décorateur qui
vérifie que l'adhérent est loggé et dispose des droits suffisants."""
def require_crans_login(view_func):
......@@ -59,26 +119,31 @@ def require_droits(droits=[]):
if request.session.get('adherent'):
if not droits or set(request.session.get('droits')).intersection(set(droits)):
return view_func(request, *args, **kwargs)
else: return HttpResponseRedirect('/static/403.html')
else: return HttpResponseForbidden()
else:
path = urlquote(request.get_full_path())
return HttpResponseRedirect('/login?next=%s' % path)
setattr (_wrapped_view, 'droits', droits)
_wrapped_view.droits = droits
return _wrapped_view
return require_crans_login
## Fonctions URL
def prompt_login(request):
"""Affiche la boite de login"""
message = request.session.get('message') # Un message à afficher ?
request.session['message'] = None # On l'afffiche donc on le supprime.
nextpage = request.GET.get('next', request.POST.get('next', '/'))
return render_to_response('login.html', {'message' : message, 'np': nextpage})
def do_login(request):
"""Effectue l'authentification et redirige sur la page demandée"""
login = request.POST.get('login')
password = request.POST.get('password')
return login_function(request, login, password)
def do_logout(request):
"""Désauthentifie la personne"""
django.contrib.auth.logout(request)
request.session['message'] = u'Votre session a été fermée'
return HttpResponseRedirect('/login')
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment