Files
edx-platform/common/djangoapps/third_party_auth/samlproviderdata/views.py
2021-03-19 15:39:48 +05:00

84 lines
3.6 KiB
Python

"""
Viewset for auth/saml/v0/samlproviderdata
"""
from django.shortcuts import get_object_or_404
from django.http import Http404
from edx_rbac.mixins import PermissionRequiredMixin
from edx_rest_framework_extensions.auth.jwt.authentication import JwtAuthentication
from rest_framework import permissions, viewsets
from rest_framework.authentication import SessionAuthentication
from rest_framework.exceptions import ParseError
from enterprise.models import EnterpriseCustomerIdentityProvider
from common.djangoapps.third_party_auth.utils import validate_uuid4_string, convert_saml_slug_provider_id
from ..models import SAMLProviderConfig, SAMLProviderData
from .serializers import SAMLProviderDataSerializer
class SAMLProviderDataMixin:
authentication_classes = [JwtAuthentication, SessionAuthentication]
permission_classes = [permissions.IsAuthenticated]
serializer_class = SAMLProviderDataSerializer
class SAMLProviderDataViewSet(PermissionRequiredMixin, SAMLProviderDataMixin, viewsets.ModelViewSet):
"""
A View to handle SAMLProviderData CRUD.
Uses the edx-rbac mixin PermissionRequiredMixin to apply enterprise authorization
Usage:
NOTE: Only the GET request requires a request parameter, otherwise pass the uuid as part
of the post body
GET /auth/saml/v0/provider_data/?enterprise-id=uuid
POST /auth/saml/v0/provider_data/ -d postData (must contain 'enterprise_customer_uuid')
DELETE /auth/saml/v0/provider_data/:pk -d postData (must contain 'enterprise_customer_uuid')
PATCH /auth/saml/v0/provider_data/:pk -d postData (must contain 'enterprise_customer_uuid')
"""
permission_required = 'enterprise.can_access_admin_dashboard'
def get_queryset(self):
"""
Find and return the matching providerid for the given enterprise uuid
Note: There is no direct association between samlproviderdata and enterprisecustomer.
So we make that association in code via samlproviderdata > samlproviderconfig ( via entity_id )
then, we fetch enterprisecustomer via samlproviderconfig > enterprisecustomer ( via association table )
"""
if self.requested_enterprise_uuid is None:
raise ParseError('Required enterprise_customer_uuid is missing')
enterprise_customer_idp = get_object_or_404(
EnterpriseCustomerIdentityProvider,
enterprise_customer__uuid=self.requested_enterprise_uuid
)
try:
saml_provider = SAMLProviderConfig.objects.current_set().get(
slug=convert_saml_slug_provider_id(enterprise_customer_idp.provider_id))
except SAMLProviderConfig.DoesNotExist:
raise Http404('No matching SAML provider found.') # lint-amnesty, pylint: disable=raise-missing-from
return SAMLProviderData.objects.filter(entity_id=saml_provider.entity_id)
@property
def requested_enterprise_uuid(self):
"""
The enterprise customer uuid from request params or post body
"""
if self.request.method in ('POST', 'PATCH'):
uuid_str = self.request.POST.get('enterprise_customer_uuid')
if uuid_str is None:
raise ParseError('Required enterprise_customer_uuid is missing')
return uuid_str
else:
uuid_str = self.request.query_params.get('enterprise_customer_uuid')
if validate_uuid4_string(uuid_str) is False:
raise ParseError('Invalid UUID enterprise_customer_id')
return uuid_str
def get_permission_object(self):
"""
Retrieve an EnterpriseCustomer to do auth against
"""
return self.requested_enterprise_uuid