Login/Logout view are now class views

This commit is contained in:
Valentin Samir 2015-05-29 16:11:10 +02:00
parent 02872d218f
commit a0b1a095e4
3 changed files with 204 additions and 144 deletions

View File

@ -18,8 +18,8 @@ from . import views
urlpatterns = patterns( urlpatterns = patterns(
'', '',
url(r'^$', RedirectView.as_view(pattern_name="login")), url(r'^$', RedirectView.as_view(pattern_name="login")),
url('^login$', views.login, name='login'), url('^login$', views.LoginView.as_view(), name='login'),
url('^logout$', views.logout, name='logout'), url('^logout$', views.LogoutView.as_view(), name='logout'),
url('^validate$', views.validate, name='validate'), url('^validate$', views.validate, name='validate'),
url('^serviceValidate$', views.service_validate, name='serviceValidate'), url('^serviceValidate$', views.service_validate, name='serviceValidate'),
url('^proxyValidate$', views.proxy_validate, name='proxyValidate'), url('^proxyValidate$', views.proxy_validate, name='proxyValidate'),

View File

@ -12,12 +12,20 @@
from . import default_settings from . import default_settings
from django.conf import settings from django.conf import settings
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
import urlparse import urlparse
import urllib import urllib
import random import random
import string import string
def redirect_params(url_name, params=None):
"""Redirect to `url_name` with `params` as querystring"""
url = reverse(url_name)
params = urllib.urlencode(params if params else {})
return HttpResponseRedirect(url + "?%s" % params)
def update_url(url, params): def update_url(url, params):
"""update params in the `url` query string""" """update params in the `url` query string"""
url_parts = list(urlparse.urlparse(url)) url_parts = list(urlparse.urlparse(url))

View File

@ -20,6 +20,7 @@ from django.views.decorators.csrf import csrf_exempt
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.utils import timezone from django.utils import timezone
from django.views.generic import View
import requests import requests
import urllib import urllib
@ -30,181 +31,232 @@ from . import utils
from . import forms from . import forms
from . import models from . import models
def _logout(request): class LogoutView(View):
"""destroy CAS session (logout) view"""
request = None
service = None
def clean_session_variables(self):
"""Clean sessions variables""" """Clean sessions variables"""
try: try:
del request.session["authenticated"] del self.request.session["authenticated"]
except KeyError: except KeyError:
pass pass
try: try:
del request.session["username"] del self.request.session["username"]
except KeyError: except KeyError:
pass pass
try: try:
del request.session["warn"] del self.request.session["warn"]
except KeyError: except KeyError:
pass pass
def logout(self):
"""effectively destroy CAS session"""
try:
user = models.User.objects.get(username=self.request.session.get("username"))
user.logout(self.request)
user.delete()
except models.User.DoesNotExist:
pass
finally:
self.clean_session_variables()
def redirect_params(url_name, params=None): def get(self, request, *args, **kwargs):
"""Redirect to `url_name` with `params` as querystring""" """methode called on GET request on this view"""
url = reverse(url_name) self.request = request
params = urllib.urlencode(params if params else {}) self.service = request.GET.get('service')
return HttpResponseRedirect(url + "?%s" % params) self.logout()
# if service is set, redirect to service after logout
if self.service:
list(messages.get_messages(request)) # clean messages before leaving the django app
return HttpResponseRedirect(self.service)
# else redirect to login page
else:
messages.add_message(request, messages.SUCCESS, _(u'Successfully logout'))
return redirect("cas_server:login")
class LoginView(View, LogoutView):
def login(request):
"""credential requestor / acceptor""" """credential requestor / acceptor"""
# pylint: disable=too-many-instance-attributes
# Nine is reasonable in this case.
user = None user = None
form = None form = None
service_pattern = None
request = None
service = None
renew = None
gateway = None
method = None
renewed = False renewed = False
warned = False warned = False
if request.method == 'POST':
service = request.POST.get('service')
renew = True if request.POST.get('renew') else False
gateway = request.POST.get('gateway')
method = request.POST.get('method')
if not request.session.get("authenticated") or renew: def post(self, request, *args, **kwargs):
form = forms.UserCredential( """methode called on POST request on this view"""
self.request = request
self.service = request.POST.get('service')
self.renew = True if request.POST.get('renew') else False
self.gateway = request.POST.get('gateway')
self.method = request.POST.get('method')
if not request.session.get("authenticated") or self.renew:
self.form = forms.UserCredential(
request.POST, request.POST,
initial={'service':service, 'method':method, 'warn':request.session.get("warn")} initial={
'service':self.service,
'method':self.method,
'warn':request.session.get("warn")
}
) )
if form.is_valid(): if self.form.is_valid():
user = models.User.objects.get(username=form.cleaned_data['username']) self.user = models.User.objects.get(username=self.form.cleaned_data['username'])
request.session.set_expiry(0) request.session.set_expiry(0)
request.session["username"] = form.cleaned_data['username'] request.session["username"] = self.form.cleaned_data['username']
request.session["warn"] = True if form.cleaned_data.get("warn") else False request.session["warn"] = True if self.form.cleaned_data.get("warn") else False
request.session["authenticated"] = True request.session["authenticated"] = True
renewed = True self.renewed = True
warned = True self.warned = True
else: else:
_logout(request) self.logout()
else: return self.common()
service = request.GET.get('service')
renew = True if request.GET.get('renew') else False
gateway = request.GET.get('gateway')
method = request.GET.get('method')
if not request.session.get("authenticated") or renew: def get(self, request, *args, **kwargs):
form = forms.UserCredential( self.request = request
initial={'service':service, 'method':method, 'warn':request.session.get("warn")} self.service = request.GET.get('service')
self.renew = True if request.GET.get('renew') else False
self.gateway = request.GET.get('gateway')
self.method = request.GET.get('method')
if not request.session.get("authenticated") or self.renew:
self.form = forms.UserCredential(
initial={
'service':self.service,
'method':self.method,
'warn':request.session.get("warn")
}
) )
# if authenticated and successfully renewed authentication if needed return self.common()
if request.session.get("authenticated") and \
request.session.get("username") and (not renew or renewed):
try:
user = models.User.objects.get(username=request.session["username"])
except models.User.DoesNotExist:
_logout(request)
return redirect_params("login", params=dict(request.GET))
# if login agains a service is requestest def service_login(self):
if service: """Perform login agains a service"""
try: try:
# is the service allowed # is the service allowed
service_pattern = models.ServicePattern.validate(service) service_pattern = models.ServicePattern.validate(self.service)
# is the current user allowed on this service # is the current user allowed on this service
service_pattern.check_user(user) service_pattern.check_user(self.user)
# if the user has asked to be warned before any login to a service # if the user has asked to be warned before any login to a service
if request.session.get("warn", True) and not warned: if self.request.session.get("warn", True) and not self.warned:
messages.add_message( messages.add_message(
request, self.request,
messages.WARNING, messages.WARNING,
_(u"Authentication has been required by service %(name)s (%(url)s)") % \ _(u"Authentication has been required by service %(name)s (%(url)s)") % \
{'name':service_pattern.name, 'url':service} {'name':service_pattern.name, 'url':self.service}
) )
return render( return render(
request, self.request,
settings.CAS_WARN_TEMPLATE, settings.CAS_WARN_TEMPLATE,
{'service_ticket_url':user.get_service_url( {'service_ticket_url':self.user.get_service_url(
service, self.service,
service_pattern, service_pattern,
renew=renew renew=self.renew
)} )}
) )
else: else:
# redirect, using method ? # redirect, using method ?
return redirect(user.get_service_url(service, service_pattern, renew=renew)) return HttpResponseRedirect(
self.user.get_service_url(self.service, service_pattern, renew=self.renew)
)
except models.ServicePattern.DoesNotExist: except models.ServicePattern.DoesNotExist:
messages.add_message( messages.add_message(
request, self.request,
messages.ERROR, messages.ERROR,
_(u'Service %(url)s non allowed.') % {'url' : service} _(u'Service %(url)s non allowed.') % {'url' : self.service}
) )
except models.BadUsername: except models.BadUsername:
messages.add_message( messages.add_message(
request, self.request,
messages.ERROR, messages.ERROR,
_(u"Username non allowed") _(u"Username non allowed")
) )
except models.BadFilter: except models.BadFilter:
messages.add_message( messages.add_message(
request, self.request,
messages.ERROR, messages.ERROR,
_(u"User charateristics non allowed") _(u"User charateristics non allowed")
) )
except models.UserFieldNotDefined: except models.UserFieldNotDefined:
messages.add_message( messages.add_message(
request, self.request,
messages.ERROR, messages.ERROR,
_(u"The attribut %(field)s is needed to use" \ _(u"The attribut %(field)s is needed to use" \
" that service") % {'field':service_pattern.user_field} " that service") % {'field':service_pattern.user_field}
) )
# if gateway is set and auth failed redirect to the service without authentication # if gateway is set and auth failed redirect to the service without authentication
if gateway: if self.gateway:
list(messages.get_messages(request)) # clean messages before leaving the django app list(messages.get_messages(self.request)) # clean messages before leaving django
return redirect(service) return HttpResponseRedirect(self.service)
return render(request, settings.CAS_LOGGED_TEMPLATE, {'session':request.session}) return render(self.request, settings.CAS_LOGGED_TEMPLATE, {'session':self.request.session})
else:
if service: def authenticated(self):
"""Processing authenticated users"""
try: try:
service_pattern = models.ServicePattern.validate(service) self.user = models.User.objects.get(username=self.request.session.get("username"))
if gateway: except models.User.DoesNotExist:
list(messages.get_messages(request)) # clean messages before leaving django self.logout()
return redirect(service) return utils.redirect_params("cas_server:login", params=dict(self.request.GET))
if request.session.get("authenticated") and renew:
# if login agains a service is self.requestest
if self.service:
return self.service_login()
else:
return render(
self.request,
settings.CAS_LOGGED_TEMPLATE,
{'session':self.request.session}
)
def not_authenticated(self):
"""Processing non authenticated users"""
if self.service:
try:
service_pattern = models.ServicePattern.validate(self.service)
if self.gateway:
list(messages.get_messages(self.request))# clean messages before leaving django
return HttpResponseRedirect(self.service)
if self.request.session.get("authenticated") and self.renew:
messages.add_message( messages.add_message(
request, self.request,
messages.WARNING, messages.WARNING,
_(u"Authentication renewal required by service" \ _(u"Authentication renewal required by service %(name)s (%(url)s).") %
" %(name)s (%(url)s).") % {'name':service_pattern.name, 'url':service} {'name':service_pattern.name, 'url':self.service}
) )
else: else:
messages.add_message( messages.add_message(
request, self.request,
messages.WARNING, messages.WARNING,
_(u"Authentication required by service" \ _(u"Authentication required by service %(name)s (%(url)s).") %
" %(name)s (%(url)s).") % {'name':service_pattern.name, 'url':service} {'name':service_pattern.name, 'url':self.service}
) )
except models.ServicePattern.DoesNotExist: except models.ServicePattern.DoesNotExist:
messages.add_message( messages.add_message(
request, self.request,
messages.ERROR, messages.ERROR,
_(u'Service %s non allowed') % service _(u'Service %s non allowed') % self.service
) )
return render(request, settings.CAS_LOGIN_TEMPLATE, {'form':form}) return render(self.request, settings.CAS_LOGIN_TEMPLATE, {'form':self.form})
def logout(request): def common(self):
"""destroy CAS session (logout)""" """Part execute uppon GET and POST request"""
service = request.GET.get('service') # if authenticated and successfully renewed authentication if needed
if request.session.get("authenticated"): if self.request.session.get("authenticated") and (not self.renew or self.renewed):
user = models.User.objects.get(username=request.session["username"]) return self.authenticated()
user.logout(request)
user.delete()
_logout(request)
# if service is set, redirect to service after logout
if service:
list(messages.get_messages(request)) # clean messages before leaving the django app
return redirect(service)
# else redirect to login page
else: else:
messages.add_message(request, messages.SUCCESS, _(u'Successfully logout')) return self.not_authenticated()
return redirect("login")
def validate(request): def validate(request):
"""service ticket validation""" """service ticket validation"""