redo models again
This commit is contained in:
parent
de7a2fa034
commit
c1276e9695
|
@ -1,13 +1,12 @@
|
||||||
# Generated by Django 2.1.3 on 2018-11-11 14:06
|
# Generated by Django 2.1.3 on 2018-11-16 10:21
|
||||||
|
|
||||||
import uuid
|
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
import django.contrib.auth.models
|
import django.contrib.auth.models
|
||||||
import django.contrib.auth.validators
|
import django.contrib.auth.validators
|
||||||
|
from django.db import migrations, models
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
import django.utils.timezone
|
import django.utils.timezone
|
||||||
from django.conf import settings
|
import uuid
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
@ -33,7 +32,6 @@ class Migration(migrations.Migration):
|
||||||
('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
|
('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
|
||||||
('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
|
('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
|
||||||
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
|
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
|
||||||
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')),
|
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
'verbose_name': 'user',
|
'verbose_name': 'user',
|
||||||
|
@ -58,6 +56,12 @@ class Migration(migrations.Migration):
|
||||||
'abstract': False,
|
'abstract': False,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Provider',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
],
|
||||||
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='Rule',
|
name='Rule',
|
||||||
fields=[
|
fields=[
|
||||||
|
@ -114,6 +118,21 @@ class Migration(migrations.Migration):
|
||||||
name='application',
|
name='application',
|
||||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='passbook_core.Application'),
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='passbook_core.Application'),
|
||||||
),
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='application',
|
||||||
|
name='provider',
|
||||||
|
field=models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.SET_DEFAULT, to='passbook_core.Provider'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='user',
|
||||||
|
name='applications',
|
||||||
|
field=models.ManyToManyField(to='passbook_core.Application'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='user',
|
||||||
|
name='groups',
|
||||||
|
field=models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups'),
|
||||||
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='user',
|
model_name='user',
|
||||||
name='sources',
|
name='sources',
|
||||||
|
|
|
@ -16,6 +16,13 @@ class User(AbstractUser):
|
||||||
"""Custom User model to allow easier adding o f user-based settings"""
|
"""Custom User model to allow easier adding o f user-based settings"""
|
||||||
|
|
||||||
sources = models.ManyToManyField('Source', through='UserSourceConnection')
|
sources = models.ManyToManyField('Source', through='UserSourceConnection')
|
||||||
|
applications = models.ManyToManyField('Application')
|
||||||
|
|
||||||
|
@reversion.register()
|
||||||
|
class Provider(models.Model):
|
||||||
|
"""Application-independant Provider instance. For example SAML2 Remote, OAuth2 Application"""
|
||||||
|
|
||||||
|
# This class defines no field for easier inheritance
|
||||||
|
|
||||||
@reversion.register()
|
@reversion.register()
|
||||||
class Application(UUIDModel, CreatedUpdatedModel):
|
class Application(UUIDModel, CreatedUpdatedModel):
|
||||||
|
@ -26,6 +33,7 @@ class Application(UUIDModel, CreatedUpdatedModel):
|
||||||
name = models.TextField()
|
name = models.TextField()
|
||||||
launch_url = models.URLField(null=True, blank=True)
|
launch_url = models.URLField(null=True, blank=True)
|
||||||
icon_url = models.TextField(null=True, blank=True)
|
icon_url = models.TextField(null=True, blank=True)
|
||||||
|
provider = models.ForeignKey('Provider', null=True, default=None, on_delete=models.SET_DEFAULT)
|
||||||
|
|
||||||
objects = InheritanceManager()
|
objects = InheritanceManager()
|
||||||
|
|
||||||
|
|
|
@ -53,9 +53,9 @@ INSTALLED_APPS = [
|
||||||
'django.contrib.messages',
|
'django.contrib.messages',
|
||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
'reversion',
|
'reversion',
|
||||||
|
'rest_framework',
|
||||||
'passbook.core',
|
'passbook.core',
|
||||||
'passbook.admin',
|
'passbook.admin',
|
||||||
'rest_framework',
|
|
||||||
'passbook.lib',
|
'passbook.lib',
|
||||||
'passbook.ldap',
|
'passbook.ldap',
|
||||||
'passbook.oauth_client',
|
'passbook.oauth_client',
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
{% load static %}
|
{% load static %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
{% load utils %}
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>{% trans 'passbook' %}</title>
|
<title>
|
||||||
|
{% block title %}
|
||||||
|
{% title %}
|
||||||
|
{% endblock %}
|
||||||
|
</title>
|
||||||
<link rel="stylesheet" type="text/css" href="{% static 'css/patternfly.min.css' %}">
|
<link rel="stylesheet" type="text/css" href="{% static 'css/patternfly.min.css' %}">
|
||||||
<link rel="stylesheet" type="text/css" href="{% static 'css/patternfly-additions.min.css' %}">
|
<link rel="stylesheet" type="text/css" href="{% static 'css/patternfly-additions.min.css' %}">
|
||||||
</head>
|
</head>
|
||||||
|
|
|
@ -24,9 +24,12 @@ urlpatterns = [
|
||||||
include(('passbook.admin.urls', 'passbook_admin'), namespace='passbook_admin')),
|
include(('passbook.admin.urls', 'passbook_admin'), namespace='passbook_admin')),
|
||||||
path('source/oauth/', include(('passbook.oauth_client.urls',
|
path('source/oauth/', include(('passbook.oauth_client.urls',
|
||||||
'passbook_oauth_client'), namespace='passbook_oauth_client')),
|
'passbook_oauth_client'), namespace='passbook_oauth_client')),
|
||||||
path('application/oauth', include(('passbook.oauth_provider.urls',
|
path('application/oauth/', include(('passbook.oauth_provider.urls',
|
||||||
'passbook_oauth_provider'),
|
'passbook_oauth_provider'),
|
||||||
namespace='passbook_oauth_provider')),
|
namespace='passbook_oauth_provider')),
|
||||||
|
path('application/saml/', include(('passbook.saml_idp.urls',
|
||||||
|
'passbook_saml_idp'),
|
||||||
|
namespace='passbook_saml_idp')),
|
||||||
]
|
]
|
||||||
|
|
||||||
if settings.DEBUG:
|
if settings.DEBUG:
|
||||||
|
|
|
@ -75,7 +75,7 @@ class LoginView(UserPassesTestMixin, FormView):
|
||||||
login(request, user)
|
login(request, user)
|
||||||
|
|
||||||
if cleaned_data.get('remember') is True:
|
if cleaned_data.get('remember') is True:
|
||||||
request.session.set_expiry(CONFIG.get('passbook').get('session').get('remember_age'))
|
request.session.set_expiry(CONFIG.y('passbook.session.remember_age'))
|
||||||
else:
|
else:
|
||||||
request.session.set_expiry(0) # Expires when browser is closed
|
request.session.set_expiry(0) # Expires when browser is closed
|
||||||
messages.success(request, _("Successfully logged in!"))
|
messages.success(request, _("Successfully logged in!"))
|
||||||
|
@ -98,4 +98,5 @@ class LoginView(UserPassesTestMixin, FormView):
|
||||||
context = {
|
context = {
|
||||||
'reason': 'invalid',
|
'reason': 'invalid',
|
||||||
}
|
}
|
||||||
|
raise NotImplementedError()
|
||||||
return render(request, 'login/invalid.html', context)
|
return render(request, 'login/invalid.html', context)
|
||||||
|
|
|
@ -9,3 +9,7 @@ class OverviewView(LoginRequiredMixin, TemplateView):
|
||||||
and is not being forwarded"""
|
and is not being forwarded"""
|
||||||
|
|
||||||
template_name = 'overview/index.html'
|
template_name = 'overview/index.html'
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
kwargs['applications'] = self.request.user.applications.objects.all()
|
||||||
|
return super().get_context_data(**kwargs)
|
||||||
|
|
|
@ -76,7 +76,7 @@ def pick(cont, arg, fallback=''):
|
||||||
@register.simple_tag(takes_context=True)
|
@register.simple_tag(takes_context=True)
|
||||||
def title(context, *title):
|
def title(context, *title):
|
||||||
"""Return either just branding or title - branding"""
|
"""Return either just branding or title - branding"""
|
||||||
branding = Setting.get('branding', default='passbook')
|
branding = CONFIG.y('passbook.branding', 'passbook')
|
||||||
if not title:
|
if not title:
|
||||||
return branding
|
return branding
|
||||||
# Include App Title in title
|
# Include App Title in title
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# Generated by Django 2.1.3 on 2018-11-11 14:06
|
# Generated by Django 2.1.3 on 2018-11-16 10:21
|
||||||
|
|
||||||
import django.db.models.deletion
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
@ -9,7 +9,7 @@ class Migration(migrations.Migration):
|
||||||
initial = True
|
initial = True
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('passbook_core', '0001_initial'),
|
('passbook_core', '__first__'),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
# Generated by Django 2.1.3 on 2018-11-14 18:35
|
# Generated by Django 2.1.3 on 2018-11-16 10:21
|
||||||
|
|
||||||
import django.db.models.deletion
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
@ -11,19 +11,16 @@ class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
migrations.swappable_dependency(settings.OAUTH2_PROVIDER_APPLICATION_MODEL),
|
migrations.swappable_dependency(settings.OAUTH2_PROVIDER_APPLICATION_MODEL),
|
||||||
('passbook_core', '0001_initial'),
|
('passbook_core', '__first__'),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='OAuth2Application',
|
name='OAuth2Provider',
|
||||||
fields=[
|
fields=[
|
||||||
('application_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='passbook_core.Application')),
|
('provider_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='passbook_core.Provider')),
|
||||||
('oauth2', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.OAUTH2_PROVIDER_APPLICATION_MODEL)),
|
('oauth2_app', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.OAUTH2_PROVIDER_APPLICATION_MODEL)),
|
||||||
],
|
],
|
||||||
options={
|
bases=('passbook_core.provider',),
|
||||||
'abstract': False,
|
|
||||||
},
|
|
||||||
bases=('passbook_core.application',),
|
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
"""Oauth2 provider product extension"""
|
"""Oauth2 provider product extension"""
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from oauth2_provider.models import Application as _OAuth2Application
|
from oauth2_provider.models import Application
|
||||||
|
|
||||||
from passbook.core.models import Application
|
from passbook.core.models import Provider
|
||||||
|
|
||||||
|
|
||||||
class OAuth2Application(Application):
|
class OAuth2Provider(Provider):
|
||||||
"""Associate an OAuth2 Application with a Product"""
|
"""Associate an OAuth2 Application with a Product"""
|
||||||
|
|
||||||
oauth2 = models.ForeignKey(_OAuth2Application, on_delete=models.CASCADE)
|
oauth2_app = models.ForeignKey(Application, on_delete=models.CASCADE)
|
||||||
|
|
|
@ -8,5 +8,5 @@ urlpatterns = [
|
||||||
# Custom OAuth 2 Authorize View
|
# Custom OAuth 2 Authorize View
|
||||||
# path('authorize/', oauth2.PassbookAuthorizationView.as_view(), name="oauth2-authorize"),
|
# path('authorize/', oauth2.PassbookAuthorizationView.as_view(), name="oauth2-authorize"),
|
||||||
# OAuth API
|
# OAuth API
|
||||||
path('oauth2/', include('oauth2_provider.urls', namespace='oauth2_provider')),
|
path('', include('oauth2_provider.urls', namespace='oauth2_provider')),
|
||||||
]
|
]
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
# Generated by Django 2.1.3 on 2018-11-16 10:21
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('passbook_core', '__first__'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='SAMLApplication',
|
||||||
|
fields=[
|
||||||
|
('application_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='passbook_core.Application')),
|
||||||
|
('acs_url', models.URLField()),
|
||||||
|
('processor_path', models.CharField(max_length=255)),
|
||||||
|
('skip_authorization', models.BooleanField(default=False)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
|
bases=('passbook_core.application',),
|
||||||
|
),
|
||||||
|
]
|
|
@ -7,7 +7,7 @@ from passbook.lib.utils.reflection import class_to_path
|
||||||
from passbook.saml_idp.base import Processor
|
from passbook.saml_idp.base import Processor
|
||||||
|
|
||||||
|
|
||||||
class SAMLRemote(Application):
|
class SAMLApplication(Application):
|
||||||
"""Model to save information about a Remote SAML Endpoint"""
|
"""Model to save information about a Remote SAML Endpoint"""
|
||||||
|
|
||||||
acs_url = models.URLField()
|
acs_url = models.URLField()
|
||||||
|
@ -20,4 +20,4 @@ class SAMLRemote(Application):
|
||||||
self._meta.get_field('processor_path').choices = processors
|
self._meta.get_field('processor_path').choices = processors
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "SAMLRemote %s (processor=%s)" % (self.name, self.processor_path)
|
return "SAMLApplication %s (processor=%s)" % (self.name, self.processor_path)
|
||||||
|
|
|
@ -3,7 +3,7 @@ from logging import getLogger
|
||||||
|
|
||||||
from passbook.lib.utils.reflection import path_to_class
|
from passbook.lib.utils.reflection import path_to_class
|
||||||
from passbook.saml_idp.exceptions import CannotHandleAssertion
|
from passbook.saml_idp.exceptions import CannotHandleAssertion
|
||||||
from passbook.saml_idp.models import SAMLRemote
|
from passbook.saml_idp.models import SAMLApplication
|
||||||
|
|
||||||
LOGGER = getLogger(__name__)
|
LOGGER = getLogger(__name__)
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ def get_processor(remote):
|
||||||
|
|
||||||
def find_processor(request):
|
def find_processor(request):
|
||||||
"""Returns the Processor instance that is willing to handle this request."""
|
"""Returns the Processor instance that is willing to handle this request."""
|
||||||
for remote in SAMLRemote.objects.all():
|
for remote in SAMLApplication.objects.all():
|
||||||
proc = get_processor(remote)
|
proc = get_processor(remote)
|
||||||
try:
|
try:
|
||||||
if proc.can_handle(request):
|
if proc.can_handle(request):
|
||||||
|
|
|
@ -8,5 +8,5 @@ urlpatterns = [
|
||||||
url(r'^login/process/$', views.login_process, name='saml_login_process'),
|
url(r'^login/process/$', views.login_process, name='saml_login_process'),
|
||||||
url(r'^logout/$', views.logout, name="saml_logout"),
|
url(r'^logout/$', views.logout, name="saml_logout"),
|
||||||
url(r'^metadata/xml/$', views.descriptor, name='metadata_xml'),
|
url(r'^metadata/xml/$', views.descriptor, name='metadata_xml'),
|
||||||
url(r'^settings/$', views.IDPSettingsView.as_view(), name='admin_settings'),
|
# url(r'^settings/$', views.IDPSettingsView.as_view(), name='admin_settings'),
|
||||||
]
|
]
|
||||||
|
|
|
@ -17,22 +17,19 @@ from OpenSSL.crypto import FILETYPE_PEM
|
||||||
from OpenSSL.crypto import Error as CryptoError
|
from OpenSSL.crypto import Error as CryptoError
|
||||||
from OpenSSL.crypto import load_certificate
|
from OpenSSL.crypto import load_certificate
|
||||||
|
|
||||||
from passbook.core.models import Event, Setting, UserAcquirableRelationship
|
# from passbook.core.models import Event, Setting, UserAcquirableRelationship
|
||||||
from passbook.core.utils import render_to_string
|
from passbook.lib.utils.template import render_to_string
|
||||||
from passbook.core.views.common import ErrorResponseView
|
# from passbook.core.views.common import ErrorResponseView
|
||||||
from passbook.core.views.settings import GenericSettingView
|
# from passbook.core.views.settings import GenericSettingView
|
||||||
from passbook.mod.auth.saml.idp import exceptions, registry, xml_signing
|
from passbook.saml_idp import exceptions, registry, xml_signing
|
||||||
from passbook.mod.auth.saml.idp.forms.settings import IDPSettingsForm
|
|
||||||
|
|
||||||
LOGGER = getLogger(__name__)
|
LOGGER = getLogger(__name__)
|
||||||
URL_VALIDATOR = URLValidator(schemes=('http', 'https'))
|
URL_VALIDATOR = URLValidator(schemes=('http', 'https'))
|
||||||
|
|
||||||
|
|
||||||
def _generate_response(request, processor, remote):
|
def _generate_response(request, processor, remote):
|
||||||
"""
|
"""Generate a SAML response using processor and return it in the proper Django
|
||||||
Generate a SAML response using processor and return it in the proper Django
|
response."""
|
||||||
response.
|
|
||||||
"""
|
|
||||||
try:
|
try:
|
||||||
ctx = processor.generate_response()
|
ctx = processor.generate_response()
|
||||||
ctx['remote'] = remote
|
ctx['remote'] = remote
|
||||||
|
@ -49,10 +46,8 @@ def render_xml(request, template, ctx):
|
||||||
|
|
||||||
@csrf_exempt
|
@csrf_exempt
|
||||||
def login_begin(request):
|
def login_begin(request):
|
||||||
"""
|
"""Receives a SAML 2.0 AuthnRequest from a Service Provider and
|
||||||
Receives a SAML 2.0 AuthnRequest from a Service Provider and
|
stores it in the session prior to enforcing login."""
|
||||||
stores it in the session prior to enforcing login.
|
|
||||||
"""
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
source = request.POST
|
source = request.POST
|
||||||
else:
|
else:
|
||||||
|
@ -65,13 +60,11 @@ def login_begin(request):
|
||||||
return HttpResponseBadRequest('the SAML request payload is missing')
|
return HttpResponseBadRequest('the SAML request payload is missing')
|
||||||
|
|
||||||
request.session['RelayState'] = source.get('RelayState', '')
|
request.session['RelayState'] = source.get('RelayState', '')
|
||||||
return redirect(reverse('passbook_mod_auth_saml_idp:saml_login_process'))
|
return redirect(reverse('passbook_saml_idp:saml_login_process'))
|
||||||
|
|
||||||
|
|
||||||
def redirect_to_sp(request, acs_url, saml_response, relay_state):
|
def redirect_to_sp(request, acs_url, saml_response, relay_state):
|
||||||
"""
|
"""Return autosubmit form"""
|
||||||
Return autosubmit form
|
|
||||||
"""
|
|
||||||
return render(request, 'core/autosubmit_form.html', {
|
return render(request, 'core/autosubmit_form.html', {
|
||||||
'url': acs_url,
|
'url': acs_url,
|
||||||
'attrs': {
|
'attrs': {
|
||||||
|
@ -83,10 +76,8 @@ def redirect_to_sp(request, acs_url, saml_response, relay_state):
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def login_process(request):
|
def login_process(request):
|
||||||
"""
|
"""Processor-based login continuation.
|
||||||
Processor-based login continuation.
|
Presents a SAML 2.0 Assertion for POSTing back to the Service Provider."""
|
||||||
Presents a SAML 2.0 Assertion for POSTing back to the Service Provider.
|
|
||||||
"""
|
|
||||||
LOGGER.debug("Request: %s", request)
|
LOGGER.debug("Request: %s", request)
|
||||||
proc, remote = registry.find_processor(request)
|
proc, remote = registry.find_processor(request)
|
||||||
# Check if user has access
|
# Check if user has access
|
||||||
|
@ -141,11 +132,9 @@ def login_process(request):
|
||||||
|
|
||||||
@csrf_exempt
|
@csrf_exempt
|
||||||
def logout(request):
|
def logout(request):
|
||||||
"""
|
"""Allows a non-SAML 2.0 URL to log out the user and
|
||||||
Allows a non-SAML 2.0 URL to log out the user and
|
|
||||||
returns a standard logged-out page. (SalesForce and others use this method,
|
returns a standard logged-out page. (SalesForce and others use this method,
|
||||||
though it's technically not SAML 2.0).
|
though it's technically not SAML 2.0)."""
|
||||||
"""
|
|
||||||
auth.logout(request)
|
auth.logout(request)
|
||||||
|
|
||||||
redirect_url = request.GET.get('redirect_to', '')
|
redirect_url = request.GET.get('redirect_to', '')
|
||||||
|
@ -163,10 +152,8 @@ def logout(request):
|
||||||
@login_required
|
@login_required
|
||||||
@csrf_exempt
|
@csrf_exempt
|
||||||
def slo_logout(request):
|
def slo_logout(request):
|
||||||
"""
|
"""Receives a SAML 2.0 LogoutRequest from a Service Provider,
|
||||||
Receives a SAML 2.0 LogoutRequest from a Service Provider,
|
logs out the user and returns a standard logged-out page."""
|
||||||
logs out the user and returns a standard logged-out page.
|
|
||||||
"""
|
|
||||||
request.session['SAMLRequest'] = request.POST['SAMLRequest']
|
request.session['SAMLRequest'] = request.POST['SAMLRequest']
|
||||||
# TODO: Parse SAML LogoutRequest from POST data, similar to login_process().
|
# TODO: Parse SAML LogoutRequest from POST data, similar to login_process().
|
||||||
# TODO: Add a URL dispatch for this view.
|
# TODO: Add a URL dispatch for this view.
|
||||||
|
@ -179,12 +166,10 @@ def slo_logout(request):
|
||||||
|
|
||||||
|
|
||||||
def descriptor(request):
|
def descriptor(request):
|
||||||
"""
|
"""Replies with the XML Metadata IDSSODescriptor."""
|
||||||
Replies with the XML Metadata IDSSODescriptor.
|
entity_id = CONFIG.y('saml_idp.issuer')
|
||||||
"""
|
slo_url = request.build_absolute_uri(reverse('passbook_saml_idp:saml_logout'))
|
||||||
entity_id = Setting.get('issuer')
|
sso_url = request.build_absolute_uri(reverse('passbook_saml_idp:saml_login_begin'))
|
||||||
slo_url = request.build_absolute_uri(reverse('passbook_mod_auth_saml_idp:saml_logout'))
|
|
||||||
sso_url = request.build_absolute_uri(reverse('passbook_mod_auth_saml_idp:saml_login_begin'))
|
|
||||||
pubkey = xml_signing.load_certificate(strip=True)
|
pubkey = xml_signing.load_certificate(strip=True)
|
||||||
ctx = {
|
ctx = {
|
||||||
'entity_id': entity_id,
|
'entity_id': entity_id,
|
||||||
|
@ -194,25 +179,25 @@ def descriptor(request):
|
||||||
}
|
}
|
||||||
metadata = render_to_string('saml/xml/metadata.xml', ctx)
|
metadata = render_to_string('saml/xml/metadata.xml', ctx)
|
||||||
response = HttpResponse(metadata, content_type='application/xml')
|
response = HttpResponse(metadata, content_type='application/xml')
|
||||||
response['Content-Disposition'] = 'attachment; filename="sv_metadata.xml'
|
response['Content-Disposition'] = 'attachment; filename="passbook_metadata.xml'
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
class IDPSettingsView(GenericSettingView):
|
# class IDPSettingsView(GenericSettingView):
|
||||||
"""IDP Settings"""
|
# """IDP Settings"""
|
||||||
|
|
||||||
form = IDPSettingsForm
|
# form = IDPSettingsForm
|
||||||
template_name = 'saml/idp/settings.html'
|
# template_name = 'saml/idp/settings.html'
|
||||||
|
|
||||||
def dispatch(self, request, *args, **kwargs):
|
# def dispatch(self, request, *args, **kwargs):
|
||||||
self.extra_data['metadata'] = escape(descriptor(request).content.decode('utf-8'))
|
# self.extra_data['metadata'] = escape(descriptor(request).content.decode('utf-8'))
|
||||||
|
|
||||||
# Show the certificate fingerprint
|
# # Show the certificate fingerprint
|
||||||
sha1_fingerprint = _('<failed to parse certificate>')
|
# sha1_fingerprint = _('<failed to parse certificate>')
|
||||||
try:
|
# try:
|
||||||
cert = load_certificate(FILETYPE_PEM, Setting.get('certificate'))
|
# cert = load_certificate(FILETYPE_PEM, CONFIG.y('saml_idp.certificate'))
|
||||||
sha1_fingerprint = cert.digest("sha1")
|
# sha1_fingerprint = cert.digest("sha1")
|
||||||
except CryptoError:
|
# except CryptoError:
|
||||||
pass
|
# pass
|
||||||
self.extra_data['fingerprint'] = sha1_fingerprint
|
# self.extra_data['fingerprint'] = sha1_fingerprint
|
||||||
return super().dispatch(request, *args, **kwargs)
|
# return super().dispatch(request, *args, **kwargs)
|
||||||
|
|
Reference in New Issue