PEP8
This commit is contained in:
parent
ba4af1372c
commit
39557d1942
11 changed files with 161 additions and 115 deletions
|
@ -14,8 +14,12 @@ from .models import ServiceTicket, ProxyTicket, ProxyGrantingTicket, User, Servi
|
||||||
from .models import Username, ReplaceAttributName, ReplaceAttributValue, FilterAttributValue
|
from .models import Username, ReplaceAttributName, ReplaceAttributValue, FilterAttributValue
|
||||||
from .forms import TicketForm
|
from .forms import TicketForm
|
||||||
|
|
||||||
tickets_readonly_fields=('validate', 'service', 'service_pattern', 'creation', 'renew', 'single_log_out', 'value')
|
tickets_readonly_fields = ('validate', 'service', 'service_pattern',
|
||||||
tickets_fields = ('validate', 'service', 'service_pattern', 'creation', 'renew', 'single_log_out')
|
'creation', 'renew', 'single_log_out', 'value')
|
||||||
|
tickets_fields = ('validate', 'service', 'service_pattern',
|
||||||
|
'creation', 'renew', 'single_log_out')
|
||||||
|
|
||||||
|
|
||||||
class ServiceTicketInline(admin.TabularInline):
|
class ServiceTicketInline(admin.TabularInline):
|
||||||
"""`ServiceTicket` in admin interface"""
|
"""`ServiceTicket` in admin interface"""
|
||||||
model = ServiceTicket
|
model = ServiceTicket
|
||||||
|
@ -23,6 +27,8 @@ class ServiceTicketInline(admin.TabularInline):
|
||||||
form = TicketForm
|
form = TicketForm
|
||||||
readonly_fields = tickets_readonly_fields
|
readonly_fields = tickets_readonly_fields
|
||||||
fields = tickets_fields
|
fields = tickets_fields
|
||||||
|
|
||||||
|
|
||||||
class ProxyTicketInline(admin.TabularInline):
|
class ProxyTicketInline(admin.TabularInline):
|
||||||
"""`ProxyTicket` in admin interface"""
|
"""`ProxyTicket` in admin interface"""
|
||||||
model = ProxyTicket
|
model = ProxyTicket
|
||||||
|
@ -30,6 +36,8 @@ class ProxyTicketInline(admin.TabularInline):
|
||||||
form = TicketForm
|
form = TicketForm
|
||||||
readonly_fields = tickets_readonly_fields
|
readonly_fields = tickets_readonly_fields
|
||||||
fields = tickets_fields
|
fields = tickets_fields
|
||||||
|
|
||||||
|
|
||||||
class ProxyGrantingInline(admin.TabularInline):
|
class ProxyGrantingInline(admin.TabularInline):
|
||||||
"""`ProxyGrantingTicket` in admin interface"""
|
"""`ProxyGrantingTicket` in admin interface"""
|
||||||
model = ProxyGrantingTicket
|
model = ProxyGrantingTicket
|
||||||
|
@ -38,6 +46,7 @@ class ProxyGrantingInline(admin.TabularInline):
|
||||||
readonly_fields = tickets_readonly_fields
|
readonly_fields = tickets_readonly_fields
|
||||||
fields = tickets_fields[1:]
|
fields = tickets_fields[1:]
|
||||||
|
|
||||||
|
|
||||||
class UserAdmin(admin.ModelAdmin):
|
class UserAdmin(admin.ModelAdmin):
|
||||||
"""`User` in admin interface"""
|
"""`User` in admin interface"""
|
||||||
inlines = (ServiceTicketInline, ProxyTicketInline, ProxyGrantingInline)
|
inlines = (ServiceTicketInline, ProxyTicketInline, ProxyGrantingInline)
|
||||||
|
@ -45,23 +54,31 @@ class UserAdmin(admin.ModelAdmin):
|
||||||
fields = ('username', 'date', "session_key")
|
fields = ('username', 'date', "session_key")
|
||||||
list_display = ('username', 'date', "session_key")
|
list_display = ('username', 'date', "session_key")
|
||||||
|
|
||||||
|
|
||||||
class UsernamesInline(admin.TabularInline):
|
class UsernamesInline(admin.TabularInline):
|
||||||
"""`Username` in admin interface"""
|
"""`Username` in admin interface"""
|
||||||
model = Username
|
model = Username
|
||||||
extra = 0
|
extra = 0
|
||||||
|
|
||||||
|
|
||||||
class ReplaceAttributNameInline(admin.TabularInline):
|
class ReplaceAttributNameInline(admin.TabularInline):
|
||||||
"""`ReplaceAttributName` in admin interface"""
|
"""`ReplaceAttributName` in admin interface"""
|
||||||
model = ReplaceAttributName
|
model = ReplaceAttributName
|
||||||
extra = 0
|
extra = 0
|
||||||
|
|
||||||
|
|
||||||
class ReplaceAttributValueInline(admin.TabularInline):
|
class ReplaceAttributValueInline(admin.TabularInline):
|
||||||
"""`ReplaceAttributValue` in admin interface"""
|
"""`ReplaceAttributValue` in admin interface"""
|
||||||
model = ReplaceAttributValue
|
model = ReplaceAttributValue
|
||||||
extra = 0
|
extra = 0
|
||||||
|
|
||||||
|
|
||||||
class FilterAttributValueInline(admin.TabularInline):
|
class FilterAttributValueInline(admin.TabularInline):
|
||||||
"""`FilterAttributValue` in admin interface"""
|
"""`FilterAttributValue` in admin interface"""
|
||||||
model = FilterAttributValue
|
model = FilterAttributValue
|
||||||
extra = 0
|
extra = 0
|
||||||
|
|
||||||
|
|
||||||
class ServicePatternAdmin(admin.ModelAdmin):
|
class ServicePatternAdmin(admin.ModelAdmin):
|
||||||
"""`ServicePattern` in admin interface"""
|
"""`ServicePattern` in admin interface"""
|
||||||
inlines = (
|
inlines = (
|
||||||
|
@ -70,7 +87,8 @@ class ServicePatternAdmin(admin.ModelAdmin):
|
||||||
ReplaceAttributValueInline,
|
ReplaceAttributValueInline,
|
||||||
FilterAttributValueInline
|
FilterAttributValueInline
|
||||||
)
|
)
|
||||||
list_display = ('pos', 'name', 'pattern', 'proxy', 'single_log_out', 'proxy_callback', 'restrict_users')
|
list_display = ('pos', 'name', 'pattern', 'proxy',
|
||||||
|
'single_log_out', 'proxy_callback', 'restrict_users')
|
||||||
|
|
||||||
|
|
||||||
admin.site.register(User, UserAdmin)
|
admin.site.register(User, UserAdmin)
|
||||||
|
|
|
@ -19,8 +19,10 @@ try:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
MySQLdb = None
|
MySQLdb = None
|
||||||
|
|
||||||
|
|
||||||
class DummyAuthUser(object):
|
class DummyAuthUser(object):
|
||||||
"""A Dummy authentication class"""
|
"""A Dummy authentication class"""
|
||||||
|
|
||||||
def __init__(self, username):
|
def __init__(self, username):
|
||||||
self.username = username
|
self.username = username
|
||||||
|
|
||||||
|
@ -36,6 +38,7 @@ class DummyAuthUser(object):
|
||||||
class TestAuthUser(DummyAuthUser):
|
class TestAuthUser(DummyAuthUser):
|
||||||
"""A test authentication class with one user test having
|
"""A test authentication class with one user test having
|
||||||
alose test as password and some attributes"""
|
alose test as password and some attributes"""
|
||||||
|
|
||||||
def __init__(self, username):
|
def __init__(self, username):
|
||||||
super(TestAuthUser, self).__init__(username)
|
super(TestAuthUser, self).__init__(username)
|
||||||
|
|
||||||
|
@ -51,6 +54,7 @@ class TestAuthUser(DummyAuthUser):
|
||||||
class MysqlAuthUser(DummyAuthUser):
|
class MysqlAuthUser(DummyAuthUser):
|
||||||
"""A mysql auth class: authentication user agains a mysql database"""
|
"""A mysql auth class: authentication user agains a mysql database"""
|
||||||
user = None
|
user = None
|
||||||
|
|
||||||
def __init__(self, username):
|
def __init__(self, username):
|
||||||
mysql_config = {
|
mysql_config = {
|
||||||
"user": settings.CAS_SQL_USERNAME,
|
"user": settings.CAS_SQL_USERNAME,
|
||||||
|
@ -92,9 +96,11 @@ class MysqlAuthUser(DummyAuthUser):
|
||||||
else:
|
else:
|
||||||
return self.user
|
return self.user
|
||||||
|
|
||||||
|
|
||||||
class DjangoAuthUser(DummyAuthUser):
|
class DjangoAuthUser(DummyAuthUser):
|
||||||
"""A django auth class: authenticate user agains django internal users"""
|
"""A django auth class: authenticate user agains django internal users"""
|
||||||
user = None
|
user = None
|
||||||
|
|
||||||
def __init__(self, username):
|
def __init__(self, username):
|
||||||
try:
|
try:
|
||||||
self.user = User.objects.get(username=username)
|
self.user = User.objects.get(username=username)
|
||||||
|
@ -102,7 +108,6 @@ class DjangoAuthUser(DummyAuthUser):
|
||||||
pass
|
pass
|
||||||
super(DjangoAuthUser, self).__init__(username)
|
super(DjangoAuthUser, self).__init__(username)
|
||||||
|
|
||||||
|
|
||||||
def test_password(self, password):
|
def test_password(self, password):
|
||||||
"""test `password` agains the user"""
|
"""test `password` agains the user"""
|
||||||
if not self.user:
|
if not self.user:
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
"""Default values for the app's settings"""
|
"""Default values for the app's settings"""
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
|
|
||||||
def setting_default(name, default_value):
|
def setting_default(name, default_value):
|
||||||
"""if the config `name` is not set, set it the `default_value`"""
|
"""if the config `name` is not set, set it the `default_value`"""
|
||||||
value = getattr(settings, name, default_value)
|
value = getattr(settings, name, default_value)
|
||||||
|
@ -60,7 +61,6 @@ setting_default('CAS_SQL_USERNAME', '')
|
||||||
setting_default('CAS_SQL_PASSWORD', '')
|
setting_default('CAS_SQL_PASSWORD', '')
|
||||||
setting_default('CAS_SQL_DBNAME', '')
|
setting_default('CAS_SQL_DBNAME', '')
|
||||||
setting_default('CAS_SQL_DBCHARSET', 'utf8')
|
setting_default('CAS_SQL_DBCHARSET', 'utf8')
|
||||||
setting_default('CAS_SQL_USER_QUERY', 'SELECT user AS usersame, pass AS ' \
|
setting_default('CAS_SQL_USER_QUERY', 'SELECT user AS usersame, pass AS '
|
||||||
'password, users.* FROM users WHERE user = %s')
|
'password, users.* FROM users WHERE user = %s')
|
||||||
setting_default('CAS_SQL_PASSWORD_CHECK', 'crypt') # crypt or plain
|
setting_default('CAS_SQL_PASSWORD_CHECK', 'crypt') # crypt or plain
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ from django.utils.translation import ugettext_lazy as _
|
||||||
import utils
|
import utils
|
||||||
import models
|
import models
|
||||||
|
|
||||||
|
|
||||||
class UserCredential(forms.Form):
|
class UserCredential(forms.Form):
|
||||||
"""Form used on the login page to retrive user credentials"""
|
"""Form used on the login page to retrive user credentials"""
|
||||||
username = forms.CharField(label=_('login'))
|
username = forms.CharField(label=_('login'))
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
from django.core.management.base import BaseCommand, CommandError
|
from django.core.management.base import BaseCommand
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from ... import models
|
from ... import models
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
args = ''
|
args = ''
|
||||||
help = _(u"Clean deleted sessions")
|
help = _(u"Clean deleted sessions")
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
from django.core.management.base import BaseCommand, CommandError
|
from django.core.management.base import BaseCommand
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from ... import models
|
from ... import models
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
args = ''
|
args = ''
|
||||||
help = _(u"Clean old trickets")
|
help = _(u"Clean old trickets")
|
||||||
|
|
|
@ -31,6 +31,7 @@ import utils
|
||||||
|
|
||||||
SessionStore = import_module(settings.SESSION_ENGINE).SessionStore
|
SessionStore = import_module(settings.SESSION_ENGINE).SessionStore
|
||||||
|
|
||||||
|
|
||||||
class User(models.Model):
|
class User(models.Model):
|
||||||
"""A user logged into the CAS"""
|
"""A user logged into the CAS"""
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -126,21 +127,29 @@ class User(models.Model):
|
||||||
url = utils.update_url(service, {'ticket': ticket.value})
|
url = utils.update_url(service, {'ticket': ticket.value})
|
||||||
return url
|
return url
|
||||||
|
|
||||||
|
|
||||||
class ServicePatternException(Exception):
|
class ServicePatternException(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class BadUsername(ServicePatternException):
|
class BadUsername(ServicePatternException):
|
||||||
"""Exception raised then an non allowed username
|
"""Exception raised then an non allowed username
|
||||||
try to get a ticket for a service"""
|
try to get a ticket for a service"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class BadFilter(ServicePatternException):
|
class BadFilter(ServicePatternException):
|
||||||
""""Exception raised then a user try
|
""""Exception raised then a user try
|
||||||
to get a ticket for a service and do not reach a condition"""
|
to get a ticket for a service and do not reach a condition"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class UserFieldNotDefined(ServicePatternException):
|
class UserFieldNotDefined(ServicePatternException):
|
||||||
"""Exception raised then a user try to get a ticket for a service
|
"""Exception raised then a user try to get a ticket for a service
|
||||||
using as username an attribut not present on this user"""
|
using as username an attribut not present on this user"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class ServicePattern(models.Model):
|
class ServicePattern(models.Model):
|
||||||
"""Allowed services pattern agains services are tested to"""
|
"""Allowed services pattern agains services are tested to"""
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -196,11 +205,10 @@ class ServicePattern(models.Model):
|
||||||
default="",
|
default="",
|
||||||
blank=True,
|
blank=True,
|
||||||
verbose_name=_(u"single log out callback"),
|
verbose_name=_(u"single log out callback"),
|
||||||
help_text=_(u"URL where the SLO request will be POST. empty = service url\n" \
|
help_text=_(u"URL where the SLO request will be POST. empty = service url\n"
|
||||||
u"This is usefull for non HTTP proxied services.")
|
u"This is usefull for non HTTP proxied services.")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return u"%s: %s" % (self.pos, self.pattern)
|
return u"%s: %s" % (self.pos, self.pattern)
|
||||||
|
|
||||||
|
@ -226,7 +234,6 @@ class ServicePattern(models.Model):
|
||||||
raise UserFieldNotDefined()
|
raise UserFieldNotDefined()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def validate(cls, service):
|
def validate(cls, service):
|
||||||
"""Check if a Service Patern match `service` and
|
"""Check if a Service Patern match `service` and
|
||||||
|
@ -236,6 +243,7 @@ class ServicePattern(models.Model):
|
||||||
return service_pattern
|
return service_pattern
|
||||||
raise cls.DoesNotExist()
|
raise cls.DoesNotExist()
|
||||||
|
|
||||||
|
|
||||||
class Username(models.Model):
|
class Username(models.Model):
|
||||||
"""A list of allowed usernames on a service pattern"""
|
"""A list of allowed usernames on a service pattern"""
|
||||||
value = models.CharField(
|
value = models.CharField(
|
||||||
|
@ -248,6 +256,7 @@ class Username(models.Model):
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return self.value
|
return self.value
|
||||||
|
|
||||||
|
|
||||||
class ReplaceAttributName(models.Model):
|
class ReplaceAttributName(models.Model):
|
||||||
"""A list of replacement of attributs name for a service pattern"""
|
"""A list of replacement of attributs name for a service pattern"""
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -261,7 +270,7 @@ class ReplaceAttributName(models.Model):
|
||||||
max_length=255,
|
max_length=255,
|
||||||
blank=True,
|
blank=True,
|
||||||
verbose_name=_(u"replace"),
|
verbose_name=_(u"replace"),
|
||||||
help_text=_(u"name under which the attribut will be show" \
|
help_text=_(u"name under which the attribut will be show"
|
||||||
u"to the service. empty = default name of the attribut")
|
u"to the service. empty = default name of the attribut")
|
||||||
)
|
)
|
||||||
service_pattern = models.ForeignKey(ServicePattern, related_name="attributs")
|
service_pattern = models.ForeignKey(ServicePattern, related_name="attributs")
|
||||||
|
@ -272,6 +281,7 @@ class ReplaceAttributName(models.Model):
|
||||||
else:
|
else:
|
||||||
return u"%s → %s" % (self.name, self.replace)
|
return u"%s → %s" % (self.name, self.replace)
|
||||||
|
|
||||||
|
|
||||||
class FilterAttributValue(models.Model):
|
class FilterAttributValue(models.Model):
|
||||||
"""A list of filter on attributs for a service pattern"""
|
"""A list of filter on attributs for a service pattern"""
|
||||||
attribut = models.CharField(
|
attribut = models.CharField(
|
||||||
|
@ -289,6 +299,7 @@ class FilterAttributValue(models.Model):
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return u"%s %s" % (self.attribut, self.pattern)
|
return u"%s %s" % (self.attribut, self.pattern)
|
||||||
|
|
||||||
|
|
||||||
class ReplaceAttributValue(models.Model):
|
class ReplaceAttributValue(models.Model):
|
||||||
"""Replacement to apply on attributs values for a service pattern"""
|
"""Replacement to apply on attributs values for a service pattern"""
|
||||||
attribut = models.CharField(
|
attribut = models.CharField(
|
||||||
|
@ -340,8 +351,8 @@ class Ticket(models.Model):
|
||||||
(
|
(
|
||||||
Q(single_log_out=False) & Q(validate=True)
|
Q(single_log_out=False) & Q(validate=True)
|
||||||
) | (
|
) | (
|
||||||
Q(validate=False)&\
|
Q(validate=False)
|
||||||
Q(creation__lt=(timezone.now() - timedelta(seconds=cls.VALIDITY)))
|
& Q(creation__lt=(timezone.now() - timedelta(seconds=cls.VALIDITY)))
|
||||||
)
|
)
|
||||||
).delete()
|
).delete()
|
||||||
|
|
||||||
|
@ -398,28 +409,35 @@ class Ticket(models.Model):
|
||||||
else:
|
else:
|
||||||
sys.stderr.write("%r\n" % error)
|
sys.stderr.write("%r\n" % error)
|
||||||
|
|
||||||
|
|
||||||
class ServiceTicket(Ticket):
|
class ServiceTicket(Ticket):
|
||||||
"""A Service Ticket"""
|
"""A Service Ticket"""
|
||||||
PREFIX = settings.CAS_SERVICE_TICKET_PREFIX
|
PREFIX = settings.CAS_SERVICE_TICKET_PREFIX
|
||||||
value = models.CharField(max_length=255, default=utils.gen_st, unique=True)
|
value = models.CharField(max_length=255, default=utils.gen_st, unique=True)
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return u"ServiceTicket-%s" % self.pk
|
return u"ServiceTicket-%s" % self.pk
|
||||||
|
|
||||||
|
|
||||||
class ProxyTicket(Ticket):
|
class ProxyTicket(Ticket):
|
||||||
"""A Proxy Ticket"""
|
"""A Proxy Ticket"""
|
||||||
PREFIX = settings.CAS_PROXY_TICKET_PREFIX
|
PREFIX = settings.CAS_PROXY_TICKET_PREFIX
|
||||||
value = models.CharField(max_length=255, default=utils.gen_pt, unique=True)
|
value = models.CharField(max_length=255, default=utils.gen_pt, unique=True)
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return u"ProxyTicket-%s" % self.pk
|
return u"ProxyTicket-%s" % self.pk
|
||||||
|
|
||||||
|
|
||||||
class ProxyGrantingTicket(Ticket):
|
class ProxyGrantingTicket(Ticket):
|
||||||
"""A Proxy Granting Ticket"""
|
"""A Proxy Granting Ticket"""
|
||||||
PREFIX = settings.CAS_PROXY_GRANTING_TICKET_PREFIX
|
PREFIX = settings.CAS_PROXY_GRANTING_TICKET_PREFIX
|
||||||
VALIDITY = settings.CAS_PGT_VALIDITY
|
VALIDITY = settings.CAS_PGT_VALIDITY
|
||||||
value = models.CharField(max_length=255, default=utils.gen_pgt, unique=True)
|
value = models.CharField(max_length=255, default=utils.gen_pgt, unique=True)
|
||||||
|
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return u"ProxyGrantingTicket-%s" % self.pk
|
return u"ProxyGrantingTicket-%s" % self.pk
|
||||||
|
|
||||||
|
|
||||||
class Proxy(models.Model):
|
class Proxy(models.Model):
|
||||||
"""A list of proxies on `ProxyTicket`"""
|
"""A list of proxies on `ProxyTicket`"""
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -429,4 +447,3 @@ class Proxy(models.Model):
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return self.url
|
return self.url
|
||||||
|
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License version 3 for
|
|
||||||
# more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License version 3
|
|
||||||
# along with this program; if not, write to the Free Software Foundation, Inc., 51
|
|
||||||
# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
#
|
|
||||||
# (c) 2015 Valentin Samir
|
|
||||||
from django.test import TestCase
|
|
||||||
|
|
|
@ -21,12 +21,27 @@ urlpatterns = patterns(
|
||||||
url('^login$', views.LoginView.as_view(), name='login'),
|
url('^login$', views.LoginView.as_view(), name='login'),
|
||||||
url('^logout$', views.LogoutView.as_view(), name='logout'),
|
url('^logout$', views.LogoutView.as_view(), name='logout'),
|
||||||
url('^validate$', views.Validate.as_view(), name='validate'),
|
url('^validate$', views.Validate.as_view(), name='validate'),
|
||||||
url('^serviceValidate$', views.ValidateService.as_view(allow_proxy_ticket=False), name='serviceValidate'),
|
url(
|
||||||
url('^proxyValidate$', views.ValidateService.as_view(allow_proxy_ticket=True), name='proxyValidate'),
|
'^serviceValidate$',
|
||||||
|
views.ValidateService.as_view(allow_proxy_ticket=False),
|
||||||
|
name='serviceValidate'
|
||||||
|
),
|
||||||
|
url(
|
||||||
|
'^proxyValidate$',
|
||||||
|
views.ValidateService.as_view(allow_proxy_ticket=True),
|
||||||
|
name='proxyValidate'
|
||||||
|
),
|
||||||
url('^proxy$', views.Proxy.as_view(), name='proxy'),
|
url('^proxy$', views.Proxy.as_view(), name='proxy'),
|
||||||
url('^p3/serviceValidate$', views.ValidateService.as_view(allow_proxy_ticket=False), name='p3_serviceValidate'),
|
url(
|
||||||
url('^p3/proxyValidate$', views.ValidateService.as_view(allow_proxy_ticket=True), name='p3_proxyValidate'),
|
'^p3/serviceValidate$',
|
||||||
|
views.ValidateService.as_view(allow_proxy_ticket=False),
|
||||||
|
name='p3_serviceValidate'
|
||||||
|
),
|
||||||
|
url(
|
||||||
|
'^p3/proxyValidate$',
|
||||||
|
views.ValidateService.as_view(allow_proxy_ticket=True),
|
||||||
|
name='p3_proxyValidate'
|
||||||
|
),
|
||||||
url('^samlValidate$', views.SamlValidate.as_view(), name='samlValidate'),
|
url('^samlValidate$', views.SamlValidate.as_view(), name='samlValidate'),
|
||||||
url('^auth$', views.Auth.as_view(), name='auth'),
|
url('^auth$', views.Auth.as_view(), name='auth'),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ import urllib
|
||||||
import random
|
import random
|
||||||
import string
|
import string
|
||||||
|
|
||||||
|
|
||||||
def import_attr(path):
|
def import_attr(path):
|
||||||
"""transform a python module.attr path to the attr"""
|
"""transform a python module.attr path to the attr"""
|
||||||
if not isinstance(path, str):
|
if not isinstance(path, str):
|
||||||
|
@ -28,12 +29,14 @@ def import_attr(path):
|
||||||
module, attr = path.rsplit('.', 1)
|
module, attr = path.rsplit('.', 1)
|
||||||
return getattr(import_module(module), attr)
|
return getattr(import_module(module), attr)
|
||||||
|
|
||||||
|
|
||||||
def redirect_params(url_name, params=None):
|
def redirect_params(url_name, params=None):
|
||||||
"""Redirect to `url_name` with `params` as querystring"""
|
"""Redirect to `url_name` with `params` as querystring"""
|
||||||
url = reverse(url_name)
|
url = reverse(url_name)
|
||||||
params = urllib.urlencode(params if params else {})
|
params = urllib.urlencode(params if params else {})
|
||||||
return HttpResponseRedirect(url + "?%s" % params)
|
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"""
|
||||||
if isinstance(url, unicode):
|
if isinstance(url, unicode):
|
||||||
|
@ -51,6 +54,7 @@ def update_url(url, params):
|
||||||
url_parts[4] = urllib.urlencode(query)
|
url_parts[4] = urllib.urlencode(query)
|
||||||
return urlparse.urlunparse(url_parts).decode('utf-8')
|
return urlparse.urlunparse(url_parts).decode('utf-8')
|
||||||
|
|
||||||
|
|
||||||
def unpack_nested_exception(error):
|
def unpack_nested_exception(error):
|
||||||
"""If exception are stacked, return the first one"""
|
"""If exception are stacked, return the first one"""
|
||||||
i = 0
|
i = 0
|
||||||
|
@ -77,22 +81,27 @@ def _gen_ticket(prefix, lg=settings.CAS_TICKET_LEN):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def gen_lt():
|
def gen_lt():
|
||||||
"""Generate a Service Ticket"""
|
"""Generate a Service Ticket"""
|
||||||
return _gen_ticket(settings.CAS_LOGIN_TICKET_PREFIX, settings.CAS_LT_LEN)
|
return _gen_ticket(settings.CAS_LOGIN_TICKET_PREFIX, settings.CAS_LT_LEN)
|
||||||
|
|
||||||
|
|
||||||
def gen_st():
|
def gen_st():
|
||||||
"""Generate a Service Ticket"""
|
"""Generate a Service Ticket"""
|
||||||
return _gen_ticket(settings.CAS_SERVICE_TICKET_PREFIX, settings.CAS_ST_LEN)
|
return _gen_ticket(settings.CAS_SERVICE_TICKET_PREFIX, settings.CAS_ST_LEN)
|
||||||
|
|
||||||
|
|
||||||
def gen_pt():
|
def gen_pt():
|
||||||
"""Generate a Proxy Ticket"""
|
"""Generate a Proxy Ticket"""
|
||||||
return _gen_ticket(settings.CAS_PROXY_TICKET_PREFIX, settings.CAS_PT_LEN)
|
return _gen_ticket(settings.CAS_PROXY_TICKET_PREFIX, settings.CAS_PT_LEN)
|
||||||
|
|
||||||
|
|
||||||
def gen_pgt():
|
def gen_pgt():
|
||||||
"""Generate a Proxy Granting Ticket"""
|
"""Generate a Proxy Granting Ticket"""
|
||||||
return _gen_ticket(settings.CAS_PROXY_GRANTING_TICKET_PREFIX, settings.CAS_PGT_LEN)
|
return _gen_ticket(settings.CAS_PROXY_GRANTING_TICKET_PREFIX, settings.CAS_PGT_LEN)
|
||||||
|
|
||||||
|
|
||||||
def gen_pgtiou():
|
def gen_pgtiou():
|
||||||
"""Generate a Proxy Granting Ticket IOU"""
|
"""Generate a Proxy Granting Ticket IOU"""
|
||||||
return _gen_ticket(settings.CAS_PROXY_GRANTING_TICKET_IOU_PREFIX, settings.CAS_PGTIOU_LEN)
|
return _gen_ticket(settings.CAS_PROXY_GRANTING_TICKET_IOU_PREFIX, settings.CAS_PGTIOU_LEN)
|
||||||
|
|
|
@ -33,6 +33,7 @@ import models
|
||||||
from .models import ServiceTicket, ProxyTicket, ProxyGrantingTicket
|
from .models import ServiceTicket, ProxyTicket, ProxyGrantingTicket
|
||||||
from .models import ServicePattern
|
from .models import ServicePattern
|
||||||
|
|
||||||
|
|
||||||
class AttributesMixin(object):
|
class AttributesMixin(object):
|
||||||
"""mixin for the attributs methode"""
|
"""mixin for the attributs methode"""
|
||||||
|
|
||||||
|
@ -49,6 +50,7 @@ class AttributesMixin(object):
|
||||||
attributes.append((key, value))
|
attributes.append((key, value))
|
||||||
return attributes
|
return attributes
|
||||||
|
|
||||||
|
|
||||||
class LogoutMixin(object):
|
class LogoutMixin(object):
|
||||||
"""destroy CAS session utils"""
|
"""destroy CAS session utils"""
|
||||||
def clean_session_variables(self):
|
def clean_session_variables(self):
|
||||||
|
@ -80,6 +82,7 @@ class LogoutMixin(object):
|
||||||
finally:
|
finally:
|
||||||
self.clean_session_variables()
|
self.clean_session_variables()
|
||||||
|
|
||||||
|
|
||||||
class LogoutView(View, LogoutMixin):
|
class LogoutView(View, LogoutMixin):
|
||||||
"""destroy CAS session (logout) view"""
|
"""destroy CAS session (logout) view"""
|
||||||
|
|
||||||
|
@ -107,6 +110,7 @@ class LogoutView(View, LogoutMixin):
|
||||||
else:
|
else:
|
||||||
return render(request, settings.CAS_LOGOUT_TEMPLATE)
|
return render(request, settings.CAS_LOGOUT_TEMPLATE)
|
||||||
|
|
||||||
|
|
||||||
class LoginView(View, LogoutMixin):
|
class LoginView(View, LogoutMixin):
|
||||||
"""credential requestor / acceptor"""
|
"""credential requestor / acceptor"""
|
||||||
|
|
||||||
|
@ -207,7 +211,7 @@ class LoginView(View, LogoutMixin):
|
||||||
messages.add_message(
|
messages.add_message(
|
||||||
self.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': self.service}
|
{'name': service_pattern.name, 'url': self.service}
|
||||||
)
|
)
|
||||||
return render(
|
return render(
|
||||||
|
@ -247,8 +251,8 @@ class LoginView(View, LogoutMixin):
|
||||||
messages.add_message(
|
messages.add_message(
|
||||||
self.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}
|
u" 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
|
||||||
|
@ -285,7 +289,8 @@ class LoginView(View, LogoutMixin):
|
||||||
try:
|
try:
|
||||||
service_pattern = ServicePattern.validate(self.service)
|
service_pattern = ServicePattern.validate(self.service)
|
||||||
if self.gateway:
|
if self.gateway:
|
||||||
list(messages.get_messages(self.request))# clean messages before leaving django
|
# clean messages before leaving django
|
||||||
|
list(messages.get_messages(self.request))
|
||||||
return HttpResponseRedirect(self.service)
|
return HttpResponseRedirect(self.service)
|
||||||
if self.request.session.get("authenticated") and self.renew:
|
if self.request.session.get("authenticated") and self.renew:
|
||||||
messages.add_message(
|
messages.add_message(
|
||||||
|
@ -317,6 +322,7 @@ class LoginView(View, LogoutMixin):
|
||||||
else:
|
else:
|
||||||
return self.not_authenticated()
|
return self.not_authenticated()
|
||||||
|
|
||||||
|
|
||||||
class Auth(View):
|
class Auth(View):
|
||||||
"""A simple view to validate username/password/service tuple"""
|
"""A simple view to validate username/password/service tuple"""
|
||||||
@method_decorator(csrf_exempt)
|
@method_decorator(csrf_exempt)
|
||||||
|
@ -351,7 +357,7 @@ class Auth(View):
|
||||||
try:
|
try:
|
||||||
user = models.User.objects.get(
|
user = models.User.objects.get(
|
||||||
username=form.cleaned_data['username'],
|
username=form.cleaned_data['username'],
|
||||||
session_key=self.request.session.session_key
|
session_key=request.session.session_key
|
||||||
)
|
)
|
||||||
# is the service allowed
|
# is the service allowed
|
||||||
service_pattern = ServicePattern.validate(service)
|
service_pattern = ServicePattern.validate(service)
|
||||||
|
@ -360,11 +366,12 @@ class Auth(View):
|
||||||
if not request.session.get("authenticated"):
|
if not request.session.get("authenticated"):
|
||||||
user.delete()
|
user.delete()
|
||||||
return HttpResponse("yes\n", content_type="text/plain")
|
return HttpResponse("yes\n", content_type="text/plain")
|
||||||
except (ServicePattern.DoesNotExist, ServicePatternException) as error:
|
except (ServicePattern.DoesNotExist, models.ServicePatternException):
|
||||||
return HttpResponse("no\n", content_type="text/plain")
|
return HttpResponse("no\n", content_type="text/plain")
|
||||||
else:
|
else:
|
||||||
return HttpResponse("no\n", content_type="text/plain")
|
return HttpResponse("no\n", content_type="text/plain")
|
||||||
|
|
||||||
|
|
||||||
class Validate(View):
|
class Validate(View):
|
||||||
"""service ticket validation"""
|
"""service ticket validation"""
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -441,8 +448,8 @@ class ValidateService(View, AttributesMixin):
|
||||||
'attributes': self.attributes(),
|
'attributes': self.attributes(),
|
||||||
'proxies': proxies
|
'proxies': proxies
|
||||||
}
|
}
|
||||||
if self.ticket.service_pattern.user_field and \
|
if (self.ticket.service_pattern.user_field and
|
||||||
self.ticket.user.attributs.get(self.ticket.service_pattern.user_field):
|
self.ticket.user.attributs.get(self.ticket.service_pattern.user_field)):
|
||||||
params['username'] = self.ticket.user.attributs.get(
|
params['username'] = self.ticket.user.attributs.get(
|
||||||
self.ticket.service_pattern.user_field
|
self.ticket.service_pattern.user_field
|
||||||
)
|
)
|
||||||
|
@ -458,7 +465,6 @@ class ValidateService(View, AttributesMixin):
|
||||||
except ValidateError as error:
|
except ValidateError as error:
|
||||||
return error.render(request)
|
return error.render(request)
|
||||||
|
|
||||||
|
|
||||||
def process_ticket(self):
|
def process_ticket(self):
|
||||||
"""fetch the ticket angains the database and check its validity"""
|
"""fetch the ticket angains the database and check its validity"""
|
||||||
try:
|
try:
|
||||||
|
@ -489,7 +495,6 @@ class ValidateService(View, AttributesMixin):
|
||||||
except (ServiceTicket.DoesNotExist, ProxyTicket.DoesNotExist):
|
except (ServiceTicket.DoesNotExist, ProxyTicket.DoesNotExist):
|
||||||
raise ValidateError('INVALID_TICKET', 'ticket not found')
|
raise ValidateError('INVALID_TICKET', 'ticket not found')
|
||||||
|
|
||||||
|
|
||||||
def process_pgturl(self, params):
|
def process_pgturl(self, params):
|
||||||
"""Handle PGT request"""
|
"""Handle PGT request"""
|
||||||
try:
|
try:
|
||||||
|
@ -529,6 +534,7 @@ class ValidateService(View, AttributesMixin):
|
||||||
'callback url not allowed by configuration'
|
'callback url not allowed by configuration'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class Proxy(View):
|
class Proxy(View):
|
||||||
"""proxy ticket service"""
|
"""proxy ticket service"""
|
||||||
|
|
||||||
|
@ -552,7 +558,6 @@ class Proxy(View):
|
||||||
except ValidateError as error:
|
except ValidateError as error:
|
||||||
return error.render(request)
|
return error.render(request)
|
||||||
|
|
||||||
|
|
||||||
def process_proxy(self):
|
def process_proxy(self):
|
||||||
"""handle PT request"""
|
"""handle PT request"""
|
||||||
try:
|
try:
|
||||||
|
@ -593,7 +598,6 @@ class Proxy(View):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class SamlValidateError(Exception):
|
class SamlValidateError(Exception):
|
||||||
"""handle saml validation error"""
|
"""handle saml validation error"""
|
||||||
def __init__(self, code, msg=""):
|
def __init__(self, code, msg=""):
|
||||||
|
@ -618,19 +622,6 @@ class SamlValidateError(Exception):
|
||||||
content_type="text/xml; charset=utf-8"
|
content_type="text/xml; charset=utf-8"
|
||||||
)
|
)
|
||||||
|
|
||||||
def _saml_validate_error(request, code, msg=""):
|
|
||||||
"""render the samlValidateError.xml templace using `code` and `msg`"""
|
|
||||||
return render(
|
|
||||||
request,
|
|
||||||
"cas_server/samlValidateError.xml",
|
|
||||||
{
|
|
||||||
'code':code,
|
|
||||||
'msg':msg,
|
|
||||||
'IssueInstant':timezone.now().isoformat(),
|
|
||||||
'ResponseID':utils.gen_saml_id()
|
|
||||||
},
|
|
||||||
content_type="text/xml; charset=utf-8"
|
|
||||||
)
|
|
||||||
|
|
||||||
class SamlValidate(View, AttributesMixin):
|
class SamlValidate(View, AttributesMixin):
|
||||||
"""SAML ticket validation"""
|
"""SAML ticket validation"""
|
||||||
|
@ -651,7 +642,7 @@ class SamlValidate(View, AttributesMixin):
|
||||||
self.root = etree.fromstring(request.body)
|
self.root = etree.fromstring(request.body)
|
||||||
try:
|
try:
|
||||||
self.ticket = self.process_ticket()
|
self.ticket = self.process_ticket()
|
||||||
expire_instant = (self.ticket.creation + \
|
expire_instant = (self.ticket.creation +
|
||||||
timedelta(seconds=self.ticket.VALIDITY)).isoformat()
|
timedelta(seconds=self.ticket.VALIDITY)).isoformat()
|
||||||
attributes = self.attributes()
|
attributes = self.attributes()
|
||||||
params = {
|
params = {
|
||||||
|
|
Loading…
Reference in a new issue