Replace the ApplicationOrganization in EdxOAuth2AuthorizationView

Move to using the filters list provided in the ApplicationAccess model
to genarically store scopes instead of the org specific ApplicationOrg
model mapping.
This commit is contained in:
Feanil Patel
2020-02-26 14:29:47 -05:00
parent 667df875bd
commit 4a54967cc5
4 changed files with 34 additions and 34 deletions

View File

@@ -10,7 +10,7 @@ from oauth2_provider.scopes import get_scopes_backend
from oauth2_provider.settings import oauth2_settings
from oauth2_provider.views import AuthorizationView
from openedx.core.djangoapps.oauth_dispatch.models import ApplicationOrganization
from openedx.core.djangoapps.oauth_dispatch.models import ApplicationAccess
class EdxOAuth2AuthorizationView(AuthorizationView):
@@ -43,16 +43,15 @@ class EdxOAuth2AuthorizationView(AuthorizationView):
kwargs["scopes_descriptions"] = [all_scopes[scope] for scope in scopes]
kwargs['scopes'] = scopes
# TODO: ROBERT:
# 1. Replace the below ApplicationOrganization code using filters instead!
# 2. Search for ApplicationOrganization and remove the rest.
# at this point we know an Application instance with such client_id exists in the database
application = get_application_model().objects.get(client_id=credentials['client_id'])
content_orgs = ApplicationOrganization.get_related_org_names(
application,
relation_type=ApplicationOrganization.RELATION_TYPE_CONTENT_ORG
)
try:
content_orgs = list(ApplicationAccess.get_filter_values(application, ApplicationAccess.CONTENT_ORG_FILTER_NAME))
except ApplicationAccess.DoesNotExist:
# No application access policy for this application exists.
# so we have no content orgs.
content_orgs = []
kwargs['application'] = application
kwargs['content_orgs'] = content_orgs
kwargs['client_id'] = credentials['client_id']

View File

@@ -70,6 +70,12 @@ class ApplicationAccess(models.Model):
.. no_pii:
"""
# Content org filters are of the form "content_org:<org_name>" eg. "content_org:SchoolX"
# and indicate that for anything that cares about the content_org filter, that the response
# should be filtered based on the filter value. ie. We should only get responses pertain
# to objects that are relevant to the SchoolX organization.
CONTENT_ORG_FILTER_NAME = 'content_org'
application = models.OneToOneField(oauth2_settings.APPLICATION_MODEL, related_name='access',
on_delete=models.CASCADE)
scopes = ListCharField(
@@ -99,6 +105,14 @@ class ApplicationAccess(models.Model):
def get_filters(cls, application):
return cls.objects.get(application=application).filters
@classmethod
def get_filter_values(cls, application, filter_name):
filters = cls.get_filters(application=application)
for filter_constraint in filters:
name, filter_value = filter_constraint.split(':', 1)
if name == filter_name:
yield filter_value
def __str__(self):
"""
Return a unicode representation of this object.

View File

@@ -8,9 +8,8 @@ import pytz
from factory.django import DjangoModelFactory
from factory.fuzzy import FuzzyText
from oauth2_provider.models import AccessToken, Application, RefreshToken
from organizations.tests.factories import OrganizationFactory
from openedx.core.djangoapps.oauth_dispatch.models import ApplicationAccess, ApplicationOrganization
from openedx.core.djangoapps.oauth_dispatch.models import ApplicationAccess
from student.tests.factories import UserFactory
@@ -34,15 +33,6 @@ class ApplicationAccessFactory(DjangoModelFactory):
scopes = ['grades:read']
class ApplicationOrganizationFactory(DjangoModelFactory):
class Meta(object):
model = ApplicationOrganization
application = factory.SubFactory(ApplicationFactory)
organization = factory.SubFactory(OrganizationFactory)
relation_type = ApplicationOrganization.RELATION_TYPE_CONTENT_ORG
class AccessTokenFactory(DjangoModelFactory):
class Meta(object):
model = AccessToken

View File

@@ -15,7 +15,6 @@ from django.urls import reverse
from jwkest import jwk
from mock import call, patch
from oauth2_provider import models as dot_models
from organizations.tests.factories import OrganizationFactory
from provider import constants
from openedx.core.djangoapps.oauth_dispatch.toggles import ENFORCE_JWT_SCOPES
@@ -107,10 +106,6 @@ class _DispatchingViewTestCase(TestCase):
application=self.dot_app,
scopes=['grades:read'],
)
self.dot_app_org = models.ApplicationOrganization.objects.create(
application=self.dot_app,
organization=OrganizationFactory()
)
# Create a "restricted" DOT Application which means any AccessToken/JWT
# generated for this application will be immediately expired
@@ -350,10 +345,6 @@ class TestAccessTokenView(AccessTokenLoginMixin, mixins.AccessTokenMixin, _Dispa
scopes=['grades:read'],
filters=['test:filter'],
)
models.ApplicationOrganization.objects.create(
application=dot_app,
organization=OrganizationFactory()
)
scopes = dot_app_access.scopes
filters = self.dot_adapter.get_authorization_filters(dot_app)
assert 'test:filter' in filters
@@ -416,10 +407,10 @@ class TestAuthorizationView(_DispatchingViewTestCase):
models.ApplicationAccess.objects.create(
application=self.dot_app,
scopes=['grades:read'],
)
self.dot_app_org = models.ApplicationOrganization.objects.create(
application=self.dot_app,
organization=OrganizationFactory()
filters=[
'content_org:test content org',
'other_filter:filter_val',
]
)
self.dop_app = self.dop_adapter.create_confidential_client(
name='test dop client',
@@ -497,7 +488,13 @@ class TestAuthorizationView(_DispatchingViewTestCase):
# Are the content provider organizations listed on the page?
self.assertContains(
response,
'<li>{org}</li>'.format(org=self.dot_app_org.organization.name)
'<li>{org}</li>'.format(org='test content org')
)
# Make sure other filters don't show up as orgs.
self.assertNotContains(
response,
'<li>{org}</li>'.format(org='filter_val')
)
def _check_dot_response(self, response):