diff --git a/passbook/api/v2/urls.py b/passbook/api/v2/urls.py index 9e518f6cc..2c898254b 100644 --- a/passbook/api/v2/urls.py +++ b/passbook/api/v2/urls.py @@ -9,12 +9,19 @@ from structlog import get_logger from passbook.api.permissions import CustomObjectPermissions from passbook.audit.api.events import EventViewSet from passbook.core.api.applications import ApplicationViewSet +from passbook.core.api.factors import FactorViewSet from passbook.core.api.groups import GroupViewSet from passbook.core.api.invitations import InvitationViewSet from passbook.core.api.policies import PolicyViewSet +from passbook.core.api.propertymappings import PropertyMappingViewSet from passbook.core.api.providers import ProviderViewSet from passbook.core.api.sources import SourceViewSet from passbook.core.api.users import UserViewSet +from passbook.factors.captcha.api import CaptchaFactorViewSet +from passbook.factors.dummy.api import DummyFactorViewSet +from passbook.factors.email.api import EmailFactorViewSet +from passbook.factors.otp.api import OTPFactorViewSet +from passbook.factors.password.api import PasswordFactorViewSet from passbook.lib.utils.reflection import get_apps from passbook.policies.expiry.api import PasswordExpiryPolicyViewSet from passbook.policies.group.api import GroupMembershipPolicyViewSet @@ -27,8 +34,10 @@ from passbook.policies.webhook.api import WebhookPolicyViewSet from passbook.providers.app_gw.api import ApplicationGatewayProviderViewSet from passbook.providers.oauth.api import OAuth2ProviderViewSet from passbook.providers.oidc.api import OpenIDProviderViewSet -from passbook.providers.saml.api import SAMLProviderViewSet -from passbook.sources.ldap.api import LDAPSourceViewSet +from passbook.providers.saml.api import (SAMLPropertyMappingViewSet, + SAMLProviderViewSet) +from passbook.sources.ldap.api import (LDAPPropertyMappingViewSet, + LDAPSourceViewSet) from passbook.sources.oauth.api import OAuthSourceViewSet LOGGER = get_logger() @@ -62,6 +71,15 @@ router.register('providers/applicationgateway', ApplicationGatewayProviderViewSe router.register('providers/oauth', OAuth2ProviderViewSet) router.register('providers/openid', OpenIDProviderViewSet) router.register('providers/saml', SAMLProviderViewSet) +router.register('propertymappings/all', PropertyMappingViewSet) +router.register('propertymappings/ldap', LDAPPropertyMappingViewSet) +router.register('propertymappings/saml', SAMLPropertyMappingViewSet) +router.register('factors/all', FactorViewSet) +router.register('factors/captcha', CaptchaFactorViewSet) +router.register('factors/dummy', DummyFactorViewSet) +router.register('factors/email', EmailFactorViewSet) +router.register('factors/otp', OTPFactorViewSet) +router.register('factors/password', PasswordFactorViewSet) info = openapi.Info( title="passbook API", diff --git a/passbook/core/api/factors.py b/passbook/core/api/factors.py new file mode 100644 index 000000000..3dd6029a7 --- /dev/null +++ b/passbook/core/api/factors.py @@ -0,0 +1,30 @@ +"""Factor API Views""" +from rest_framework.serializers import ModelSerializer, SerializerMethodField +from rest_framework.viewsets import ReadOnlyModelViewSet + +from passbook.core.models import Factor + + +class FactorSerializer(ModelSerializer): + """Factor Serializer""" + + __type__ = SerializerMethodField(method_name='get_type') + + def get_type(self, obj): + """Get object type so that we know which API Endpoint to use to get the full object""" + return obj._meta.object_name.lower().replace('factor', '') + + class Meta: + + model = Factor + fields = ['pk', 'name', 'slug', 'order', 'enabled', '__type__'] + + +class FactorViewSet(ReadOnlyModelViewSet): + """Factor Viewset""" + + queryset = Factor.objects.all() + serializer_class = FactorSerializer + + def get_queryset(self): + return Factor.objects.select_subclasses() diff --git a/passbook/core/api/propertymappings.py b/passbook/core/api/propertymappings.py new file mode 100644 index 000000000..f0d17c070 --- /dev/null +++ b/passbook/core/api/propertymappings.py @@ -0,0 +1,30 @@ +"""PropertyMapping API Views""" +from rest_framework.serializers import ModelSerializer, SerializerMethodField +from rest_framework.viewsets import ReadOnlyModelViewSet + +from passbook.core.models import PropertyMapping + + +class PropertyMappingSerializer(ModelSerializer): + """PropertyMapping Serializer""" + + __type__ = SerializerMethodField(method_name='get_type') + + def get_type(self, obj): + """Get object type so that we know which API Endpoint to use to get the full object""" + return obj._meta.object_name.lower().replace('propertymapping', '') + + class Meta: + + model = PropertyMapping + fields = ['pk', 'name', '__type__'] + + +class PropertyMappingViewSet(ReadOnlyModelViewSet): + """PropertyMapping Viewset""" + + queryset = PropertyMapping.objects.all() + serializer_class = PropertyMappingSerializer + + def get_queryset(self): + return PropertyMapping.objects.select_subclasses() diff --git a/passbook/factors/captcha/api.py b/passbook/factors/captcha/api.py new file mode 100644 index 000000000..ab8d5fb47 --- /dev/null +++ b/passbook/factors/captcha/api.py @@ -0,0 +1,21 @@ +"""CaptchaFactor API Views""" +from rest_framework.serializers import ModelSerializer +from rest_framework.viewsets import ModelViewSet + +from passbook.factors.captcha.models import CaptchaFactor + + +class CaptchaFactorSerializer(ModelSerializer): + """CaptchaFactor Serializer""" + + class Meta: + + model = CaptchaFactor + fields = ['pk', 'name', 'slug', 'order', 'enabled', 'public_key', 'private_key'] + + +class CaptchaFactorViewSet(ModelViewSet): + """CaptchaFactor Viewset""" + + queryset = CaptchaFactor.objects.all() + serializer_class = CaptchaFactorSerializer diff --git a/passbook/factors/dummy/api.py b/passbook/factors/dummy/api.py new file mode 100644 index 000000000..f34de9e93 --- /dev/null +++ b/passbook/factors/dummy/api.py @@ -0,0 +1,21 @@ +"""DummyFactor API Views""" +from rest_framework.serializers import ModelSerializer +from rest_framework.viewsets import ModelViewSet + +from passbook.factors.dummy.models import DummyFactor + + +class DummyFactorSerializer(ModelSerializer): + """DummyFactor Serializer""" + + class Meta: + + model = DummyFactor + fields = ['pk', 'name', 'slug', 'order', 'enabled', '__type__'] + + +class DummyFactorViewSet(ModelViewSet): + """DummyFactor Viewset""" + + queryset = DummyFactor.objects.all() + serializer_class = DummyFactorSerializer diff --git a/passbook/factors/email/api.py b/passbook/factors/email/api.py new file mode 100644 index 000000000..b2b3b8372 --- /dev/null +++ b/passbook/factors/email/api.py @@ -0,0 +1,33 @@ +"""EmailFactor API Views""" +from rest_framework.serializers import ModelSerializer +from rest_framework.viewsets import ModelViewSet + +from passbook.factors.email.models import EmailFactor + + +class EmailFactorSerializer(ModelSerializer): + """EmailFactor Serializer""" + + class Meta: + + model = EmailFactor + fields = ['pk', 'name', 'slug', 'order', 'enabled', 'host', + 'port', + 'username', + 'password', + 'use_tls', + 'use_ssl', + 'timeout', + 'from_address', + 'ssl_keyfile', + 'ssl_certfile', ] + extra_kwargs = { + 'password': {'write_only': True} + } + + +class EmailFactorViewSet(ModelViewSet): + """EmailFactor Viewset""" + + queryset = EmailFactor.objects.all() + serializer_class = EmailFactorSerializer diff --git a/passbook/factors/otp/api.py b/passbook/factors/otp/api.py new file mode 100644 index 000000000..437da1b91 --- /dev/null +++ b/passbook/factors/otp/api.py @@ -0,0 +1,21 @@ +"""OTPFactor API Views""" +from rest_framework.serializers import ModelSerializer +from rest_framework.viewsets import ModelViewSet + +from passbook.factors.otp.models import OTPFactor + + +class OTPFactorSerializer(ModelSerializer): + """OTPFactor Serializer""" + + class Meta: + + model = OTPFactor + fields = ['pk', 'name', 'slug', 'order', 'enabled', 'enforced'] + + +class OTPFactorViewSet(ModelViewSet): + """OTPFactor Viewset""" + + queryset = OTPFactor.objects.all() + serializer_class = OTPFactorSerializer diff --git a/passbook/factors/password/api.py b/passbook/factors/password/api.py new file mode 100644 index 000000000..4306f46a1 --- /dev/null +++ b/passbook/factors/password/api.py @@ -0,0 +1,22 @@ +"""PasswordFactor API Views""" +from rest_framework.serializers import ModelSerializer +from rest_framework.viewsets import ModelViewSet + +from passbook.factors.password.models import PasswordFactor + + +class PasswordFactorSerializer(ModelSerializer): + """PasswordFactor Serializer""" + + class Meta: + + model = PasswordFactor + fields = ['pk', 'name', 'slug', 'order', 'enabled', + 'backends', 'password_policies', 'reset_factors'] + + +class PasswordFactorViewSet(ModelViewSet): + """PasswordFactor Viewset""" + + queryset = PasswordFactor.objects.all() + serializer_class = PasswordFactorSerializer diff --git a/passbook/sources/ldap/api.py b/passbook/sources/ldap/api.py index 7de37343b..09470b48b 100644 --- a/passbook/sources/ldap/api.py +++ b/passbook/sources/ldap/api.py @@ -3,7 +3,7 @@ from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet from passbook.admin.forms.source import SOURCE_SERIALIZER_FIELDS -from passbook.sources.ldap.models import LDAPSource +from passbook.sources.ldap.models import LDAPPropertyMapping, LDAPSource class LDAPSourceSerializer(ModelSerializer): @@ -28,12 +28,27 @@ class LDAPSourceSerializer(ModelSerializer): 'property_mappings', ] extra_kwargs = { - 'password': {'bind_password': True} + 'bind_password': {'write_only': True} } +class LDAPPropertyMappingSerializer(ModelSerializer): + """LDAP PropertyMapping Serializer""" + + class Meta: + model = LDAPPropertyMapping + fields = SOURCE_SERIALIZER_FIELDS + ['name', 'ldap_property', 'object_field'] + + class LDAPSourceViewSet(ModelViewSet): - """Source Viewset""" + """LDAP Source Viewset""" queryset = LDAPSource.objects.all() serializer_class = LDAPSourceSerializer + + +class LDAPPropertyMappingViewSet(ModelViewSet): + """LDAP PropertyMapping Viewset""" + + queryset = LDAPPropertyMapping.objects.all() + serializer_class = LDAPPropertyMappingSerializer