Login/Logout view are now class views
This commit is contained in:
parent
02872d218f
commit
a0b1a095e4
3 changed files with 204 additions and 144 deletions
|
@ -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'),
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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):
|
||||||
"""Clean sessions variables"""
|
"""destroy CAS session (logout) view"""
|
||||||
try:
|
request = None
|
||||||
del request.session["authenticated"]
|
service = None
|
||||||
except KeyError:
|
def clean_session_variables(self):
|
||||||
pass
|
"""Clean sessions variables"""
|
||||||
try:
|
try:
|
||||||
del request.session["username"]
|
del self.request.session["authenticated"]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
try:
|
try:
|
||||||
del request.session["warn"]
|
del self.request.session["username"]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
|
try:
|
||||||
|
del self.request.session["warn"]
|
||||||
|
except KeyError:
|
||||||
|
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):
|
def service_login(self):
|
||||||
|
"""Perform login agains a service"""
|
||||||
try:
|
try:
|
||||||
user = models.User.objects.get(username=request.session["username"])
|
# is the service allowed
|
||||||
|
service_pattern = models.ServicePattern.validate(self.service)
|
||||||
|
# is the current user allowed on this service
|
||||||
|
service_pattern.check_user(self.user)
|
||||||
|
# if the user has asked to be warned before any login to a service
|
||||||
|
if self.request.session.get("warn", True) and not self.warned:
|
||||||
|
messages.add_message(
|
||||||
|
self.request,
|
||||||
|
messages.WARNING,
|
||||||
|
_(u"Authentication has been required by service %(name)s (%(url)s)") % \
|
||||||
|
{'name':service_pattern.name, 'url':self.service}
|
||||||
|
)
|
||||||
|
return render(
|
||||||
|
self.request,
|
||||||
|
settings.CAS_WARN_TEMPLATE,
|
||||||
|
{'service_ticket_url':self.user.get_service_url(
|
||||||
|
self.service,
|
||||||
|
service_pattern,
|
||||||
|
renew=self.renew
|
||||||
|
)}
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# redirect, using method ?
|
||||||
|
return HttpResponseRedirect(
|
||||||
|
self.user.get_service_url(self.service, service_pattern, renew=self.renew)
|
||||||
|
)
|
||||||
|
except models.ServicePattern.DoesNotExist:
|
||||||
|
messages.add_message(
|
||||||
|
self.request,
|
||||||
|
messages.ERROR,
|
||||||
|
_(u'Service %(url)s non allowed.') % {'url' : self.service}
|
||||||
|
)
|
||||||
|
except models.BadUsername:
|
||||||
|
messages.add_message(
|
||||||
|
self.request,
|
||||||
|
messages.ERROR,
|
||||||
|
_(u"Username non allowed")
|
||||||
|
)
|
||||||
|
except models.BadFilter:
|
||||||
|
messages.add_message(
|
||||||
|
self.request,
|
||||||
|
messages.ERROR,
|
||||||
|
_(u"User charateristics non allowed")
|
||||||
|
)
|
||||||
|
except models.UserFieldNotDefined:
|
||||||
|
messages.add_message(
|
||||||
|
self.request,
|
||||||
|
messages.ERROR,
|
||||||
|
_(u"The attribut %(field)s is needed to use" \
|
||||||
|
" that service") % {'field':service_pattern.user_field}
|
||||||
|
)
|
||||||
|
|
||||||
|
# if gateway is set and auth failed redirect to the service without authentication
|
||||||
|
if self.gateway:
|
||||||
|
list(messages.get_messages(self.request)) # clean messages before leaving django
|
||||||
|
return HttpResponseRedirect(self.service)
|
||||||
|
|
||||||
|
return render(self.request, settings.CAS_LOGGED_TEMPLATE, {'session':self.request.session})
|
||||||
|
|
||||||
|
def authenticated(self):
|
||||||
|
"""Processing authenticated users"""
|
||||||
|
try:
|
||||||
|
self.user = models.User.objects.get(username=self.request.session.get("username"))
|
||||||
except models.User.DoesNotExist:
|
except models.User.DoesNotExist:
|
||||||
_logout(request)
|
self.logout()
|
||||||
return redirect_params("login", params=dict(request.GET))
|
return utils.redirect_params("cas_server:login", params=dict(self.request.GET))
|
||||||
|
|
||||||
# if login agains a service is requestest
|
# if login agains a service is self.requestest
|
||||||
if service:
|
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:
|
try:
|
||||||
# is the service allowed
|
service_pattern = models.ServicePattern.validate(self.service)
|
||||||
service_pattern = models.ServicePattern.validate(service)
|
if self.gateway:
|
||||||
# is the current user allowed on this service
|
list(messages.get_messages(self.request))# clean messages before leaving django
|
||||||
service_pattern.check_user(user)
|
return HttpResponseRedirect(self.service)
|
||||||
# if the user has asked to be warned before any login to a service
|
if self.request.session.get("authenticated") and self.renew:
|
||||||
if request.session.get("warn", True) and not 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 renewal required by service %(name)s (%(url)s).") %
|
||||||
{'name':service_pattern.name, 'url':service}
|
{'name':service_pattern.name, 'url':self.service}
|
||||||
)
|
|
||||||
return render(
|
|
||||||
request,
|
|
||||||
settings.CAS_WARN_TEMPLATE,
|
|
||||||
{'service_ticket_url':user.get_service_url(
|
|
||||||
service,
|
|
||||||
service_pattern,
|
|
||||||
renew=renew
|
|
||||||
)}
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
# redirect, using method ?
|
|
||||||
return redirect(user.get_service_url(service, service_pattern, renew=renew))
|
|
||||||
except models.ServicePattern.DoesNotExist:
|
|
||||||
messages.add_message(
|
|
||||||
request,
|
|
||||||
messages.ERROR,
|
|
||||||
_(u'Service %(url)s non allowed.') % {'url' : service}
|
|
||||||
)
|
|
||||||
except models.BadUsername:
|
|
||||||
messages.add_message(
|
|
||||||
request,
|
|
||||||
messages.ERROR,
|
|
||||||
_(u"Username non allowed")
|
|
||||||
)
|
|
||||||
except models.BadFilter:
|
|
||||||
messages.add_message(
|
|
||||||
request,
|
|
||||||
messages.ERROR,
|
|
||||||
_(u"User charateristics non allowed")
|
|
||||||
)
|
|
||||||
except models.UserFieldNotDefined:
|
|
||||||
messages.add_message(
|
|
||||||
request,
|
|
||||||
messages.ERROR,
|
|
||||||
_(u"The attribut %(field)s is needed to use" \
|
|
||||||
" that service") % {'field':service_pattern.user_field}
|
|
||||||
)
|
|
||||||
|
|
||||||
# if gateway is set and auth failed redirect to the service without authentication
|
|
||||||
if gateway:
|
|
||||||
list(messages.get_messages(request)) # clean messages before leaving the django app
|
|
||||||
return redirect(service)
|
|
||||||
|
|
||||||
return render(request, settings.CAS_LOGGED_TEMPLATE, {'session':request.session})
|
|
||||||
else:
|
|
||||||
if service:
|
|
||||||
try:
|
|
||||||
service_pattern = models.ServicePattern.validate(service)
|
|
||||||
if gateway:
|
|
||||||
list(messages.get_messages(request)) # clean messages before leaving django
|
|
||||||
return redirect(service)
|
|
||||||
if request.session.get("authenticated") and renew:
|
|
||||||
messages.add_message(
|
|
||||||
request,
|
|
||||||
messages.WARNING,
|
|
||||||
_(u"Authentication renewal required by service" \
|
|
||||||
" %(name)s (%(url)s).") % {'name':service_pattern.name, 'url':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)
|
else:
|
||||||
user.delete()
|
return self.not_authenticated()
|
||||||
_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:
|
|
||||||
messages.add_message(request, messages.SUCCESS, _(u'Successfully logout'))
|
|
||||||
return redirect("login")
|
|
||||||
|
|
||||||
def validate(request):
|
def validate(request):
|
||||||
"""service ticket validation"""
|
"""service ticket validation"""
|
||||||
|
|
Loading…
Reference in a new issue