providers/saml: fix 500 when SAML Provider not assigned to application

This commit is contained in:
Jens Langhammer 2020-02-21 20:54:00 +01:00
parent 1147c4901b
commit 88c1ad4c1c
6 changed files with 38 additions and 16 deletions

View File

@ -3,10 +3,9 @@ import inspect
from django import template from django import template
from django.db.models import Model from django.db.models import Model
from django.utils.html import mark_safe
from structlog import get_logger from structlog import get_logger
from passbook.lib.utils.template import render_to_string
register = template.Library() register = template.Library()
LOGGER = get_logger() LOGGER = get_logger()
@ -51,8 +50,9 @@ def get_htmls(context, model_instance):
model_instance, predicate=inspect.ismethod model_instance, predicate=inspect.ismethod
): ):
if name.startswith(prefix): if name.startswith(prefix):
template, _context = method(context.get("request")) html = method(context.get("request"))
htmls.append(render_to_string(template, _context)) if html:
htmls.append(mark_safe(html))
except NotImplementedError: except NotImplementedError:
pass pass

View File

@ -1,13 +1,16 @@
"""passbook app_gw models""" """passbook app_gw models"""
import string import string
from random import SystemRandom from random import SystemRandom
from typing import Optional
from django.db import models from django.db import models
from django.http import HttpRequest
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from oidc_provider.models import Client from oidc_provider.models import Client
from passbook import __version__ from passbook import __version__
from passbook.core.models import Provider from passbook.core.models import Provider
from passbook.lib.utils.template import render_to_string
class ApplicationGatewayProvider(Provider): class ApplicationGatewayProvider(Provider):
@ -21,13 +24,13 @@ class ApplicationGatewayProvider(Provider):
form = "passbook.providers.app_gw.forms.ApplicationGatewayProviderForm" form = "passbook.providers.app_gw.forms.ApplicationGatewayProviderForm"
def html_setup_urls(self, request): def html_setup_urls(self, request: HttpRequest) -> Optional[str]:
"""return template and context modal with URLs for authorize, token, openid-config, etc""" """return template and context modal with URLs for authorize, token, openid-config, etc"""
cookie_secret = "".join( cookie_secret = "".join(
SystemRandom().choice(string.ascii_uppercase + string.digits) SystemRandom().choice(string.ascii_uppercase + string.digits)
for _ in range(50) for _ in range(50)
) )
return ( return render_to_string(
"app_gw/setup_modal.html", "app_gw/setup_modal.html",
{"provider": self, "cookie_secret": cookie_secret, "version": __version__}, {"provider": self, "cookie_secret": cookie_secret, "version": __version__},
) )

View File

@ -1,10 +1,14 @@
"""Oauth2 provider product extension""" """Oauth2 provider product extension"""
from typing import Optional
from django.http import HttpRequest
from django.shortcuts import reverse from django.shortcuts import reverse
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from oauth2_provider.models import AbstractApplication from oauth2_provider.models import AbstractApplication
from passbook.core.models import Provider from passbook.core.models import Provider
from passbook.lib.utils.template import render_to_string
class OAuth2Provider(Provider, AbstractApplication): class OAuth2Provider(Provider, AbstractApplication):
@ -15,9 +19,9 @@ class OAuth2Provider(Provider, AbstractApplication):
def __str__(self): def __str__(self):
return f"OAuth2 Provider {self.name}" return f"OAuth2 Provider {self.name}"
def html_setup_urls(self, request): def html_setup_urls(self, request: HttpRequest) -> Optional[str]:
"""return template and context modal with URLs for authorize, token, openid-config, etc""" """return template and context modal with URLs for authorize, token, openid-config, etc"""
return ( return render_to_string(
"oauth2_provider/setup_url_modal.html", "oauth2_provider/setup_url_modal.html",
{ {
"provider": self, "provider": self,

View File

@ -1,10 +1,14 @@
"""oidc models""" """oidc models"""
from typing import Optional
from django.db import models from django.db import models
from django.http import HttpRequest
from django.shortcuts import reverse from django.shortcuts import reverse
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from oidc_provider.models import Client from oidc_provider.models import Client
from passbook.core.models import Provider from passbook.core.models import Provider
from passbook.lib.utils.template import render_to_string
class OpenIDProvider(Provider): class OpenIDProvider(Provider):
@ -26,9 +30,9 @@ class OpenIDProvider(Provider):
def __str__(self): def __str__(self):
return "OpenID Connect Provider %s" % self.oidc_client.__str__() return "OpenID Connect Provider %s" % self.oidc_client.__str__()
def html_setup_urls(self, request): def html_setup_urls(self, request: HttpRequest) -> Optional[str]:
"""return template and context modal with URLs for authorize, token, openid-config, etc""" """return template and context modal with URLs for authorize, token, openid-config, etc"""
return ( return render_to_string(
"oidc_provider/setup_url_modal.html", "oidc_provider/setup_url_modal.html",
{ {
"provider": self, "provider": self,

View File

@ -1,11 +1,15 @@
"""passbook saml_idp Models""" """passbook saml_idp Models"""
from typing import Optional
from django.db import models from django.db import models
from django.http import HttpRequest
from django.shortcuts import reverse from django.shortcuts import reverse
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from structlog import get_logger from structlog import get_logger
from passbook.core.models import PropertyMapping, Provider from passbook.core.models import PropertyMapping, Provider
from passbook.lib.utils.reflection import class_to_path, path_to_class from passbook.lib.utils.reflection import class_to_path, path_to_class
from passbook.lib.utils.template import render_to_string
from passbook.providers.saml.processors.base import Processor from passbook.providers.saml.processors.base import Processor
from passbook.providers.saml.utils.time import timedelta_string_validator from passbook.providers.saml.utils.time import timedelta_string_validator
@ -106,15 +110,19 @@ class SAMLProvider(Provider):
except Provider.application.RelatedObjectDoesNotExist: except Provider.application.RelatedObjectDoesNotExist:
return None return None
def html_metadata_view(self, request): def html_metadata_view(self, request: HttpRequest) -> Optional[str]:
"""return template and context modal with to view Metadata without downloading it""" """return template and context modal with to view Metadata without downloading it"""
from passbook.providers.saml.views import DescriptorDownloadView from passbook.providers.saml.views import DescriptorDownloadView
try:
# pylint: disable=no-member
metadata = DescriptorDownloadView.get_metadata(request, self) metadata = DescriptorDownloadView.get_metadata(request, self)
return ( return render_to_string(
"saml/idp/admin_metadata_modal.html", "saml/idp/admin_metadata_modal.html",
{"provider": self, "metadata": metadata,}, {"provider": self, "metadata": metadata,},
) )
except Provider.application.RelatedObjectDoesNotExist:
return None
class Meta: class Meta:

View File

@ -43,6 +43,9 @@ class SAMLSource(Source):
) )
return f'<a href="{metadata_url}" class="btn btn-default btn-sm">Metadata Download</a>' return f'<a href="{metadata_url}" class="btn btn-default btn-sm">Metadata Download</a>'
def __str__(self):
return f"SAML Source {self.name}"
class Meta: class Meta:
verbose_name = _("SAML Source") verbose_name = _("SAML Source")