* ENT-3007 auth/saml/v0/saml/providerdata and auth/saml/v0/saml/providerconfig endpoints Move code to subfolder for samlproviderconfig extra comma undo accidental remove of import GET works for a single config now Use ModelViewSet to get all CRUD method. Test still fails Add auth/saml/v0/providerdata endpoints fixup reverse and test issue, remove leading caret just triggering run, why is it failing in CI? pycodelint fixes Skip auth tests unless feature is on Tests for post/put for samlproviderdata move urls to their own folders api tests for post samlprovierconfig create 1 providerconfig test case lint fixes lint lint cleanup code local urls /samlproviderconfig works note needed right now Fix import errors lint unused import wip: first attempt at rbac auth and jwt cookie in test round 2 with enterprise uuid as url param for samlproviderconfig improve tests, still dont pass fix test by using system role, wip other test fix create test add get/post tests for providerdata isort fixes string lint fix Cleanup based on feedback round1 move utils to tests package Move util fn to openedx.feature area lint ENT-3007 : Round 2 of work on auth/saml/v0/providerconfig and auth/saml/v0/providerdata endpoints * Fix test issue use string uuid for permission obj * snake case changes provider_config * snake case * provider_data, tests and lint * patch and delete tests for providerdata * snake_case * snake_case * snake_case * make patch test stronger * 404 if invalid uuid for get param * common util for validate uuid4 * unused import * lint fixes for pycodestyle * 400 when uuid is missing * 400 instead of 404 for missing uuid * spell fix * update docstring for api usage * docstring clarify
79 lines
3.4 KiB
Python
79 lines
3.4 KiB
Python
"""
|
|
Viewset for auth/saml/v0/samlproviderdata
|
|
"""
|
|
|
|
from django.shortcuts import get_object_or_404
|
|
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 third_party_auth.utils import validate_uuid4_string
|
|
|
|
from ..models import SAMLProviderConfig, SAMLProviderData
|
|
from .serializers import SAMLProviderDataSerializer
|
|
|
|
|
|
class SAMLProviderDataMixin(object):
|
|
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
|
|
)
|
|
saml_provider = SAMLProviderConfig.objects.get(pk=enterprise_customer_idp.provider_id)
|
|
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', 'DELETE'):
|
|
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
|