"""passbook saml_idp Models""" from django.contrib.postgres.fields import ArrayField from django.db import models from django.shortcuts import reverse from django.utils.translation import gettext as _ from structlog import get_logger from passbook.core.models import PropertyMapping, Provider from passbook.lib.utils.reflection import class_to_path, path_to_class from passbook.providers.saml.base import Processor LOGGER = get_logger() class SAMLProvider(Provider): """Model to save information about a Remote SAML Endpoint""" name = models.TextField() acs_url = models.URLField() audience = models.TextField(default='') processor_path = models.CharField(max_length=255, choices=[]) issuer = models.TextField() assertion_valid_for = models.IntegerField(default=86400) signing = models.BooleanField(default=True) signing_cert = models.TextField() signing_key = models.TextField() form = 'passbook.providers.saml.forms.SAMLProviderForm' _processor = None def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._meta.get_field('processor_path').choices = get_provider_choices() @property def processor(self): """Return selected processor as instance""" if not self._processor: try: self._processor = path_to_class(self.processor_path)(self) except ImportError as exc: LOGGER.warning(exc) self._processor = None return self._processor def __str__(self): return "SAML Provider %s" % self.name def link_download_metadata(self): """Get link to download XML metadata for admin interface""" try: # pylint: disable=no-member return reverse('passbook_providers_saml:saml-metadata', kwargs={'application': self.application.slug}) except Provider.application.RelatedObjectDoesNotExist: return None class Meta: verbose_name = _('SAML Provider') verbose_name_plural = _('SAML Providers') class SAMLPropertyMapping(PropertyMapping): """SAML Property mapping, allowing Name/FriendlyName mapping to a list of strings""" saml_name = models.TextField() friendly_name = models.TextField(default=None, blank=True, null=True) values = ArrayField(models.TextField()) form = 'passbook.providers.saml.forms.SAMLPropertyMappingForm' def __str__(self): return "SAML Property Mapping %s" % self.saml_name class Meta: verbose_name = _('SAML Property Mapping') verbose_name_plural = _('SAML Property Mappings') def get_provider_choices(): """Return tuple of class_path, class name of all providers.""" return [(class_to_path(x), x.__name__) for x in Processor.__subclasses__()]