Merge pull request #23186 from edx/diana/replace-access-token-factory

Replace DOP library factories with the DOT equivalent.
This commit is contained in:
Diana Huang
2020-02-25 12:35:05 -05:00
committed by GitHub
12 changed files with 33 additions and 92 deletions

View File

@@ -23,7 +23,6 @@ from django.middleware.csrf import get_token
from django.test.client import RequestFactory
from django.test.utils import override_settings
from django.urls import reverse
from edx_oauth2_provider.tests.factories import AccessTokenFactory, ClientFactory
from edx_proctoring.api import create_exam, create_exam_attempt, update_attempt_status
from edx_proctoring.runtime import set_runtime_service
from edx_proctoring.tests.test_services import MockCertificateService, MockCreditService, MockGradesService
@@ -63,6 +62,7 @@ from lms.djangoapps.lms_xblock.field_data import LmsFieldData
from openedx.core.djangoapps.credit.api import set_credit_requirement_status, set_credit_requirements
from openedx.core.djangoapps.credit.models import CreditCourse
from openedx.core.djangoapps.oauth_dispatch.jwt import create_jwt_for_user
from openedx.core.djangoapps.oauth_dispatch.tests.factories import ApplicationFactory, AccessTokenFactory
from openedx.core.lib.courses import course_image_url
from openedx.core.lib.gating import api as gating_api
from openedx.core.lib.url_utils import quote_slashes
@@ -349,7 +349,7 @@ class ModuleRenderTestCase(SharedModuleStoreTestCase, LoginEnrollmentTestCase):
def test_oauth_authentication(self):
""" Test that the xblock endpoint supports OAuth authentication."""
dispatch_url = self._get_dispatch_url()
access_token = AccessTokenFactory(user=self.mock_user, client=ClientFactory()).token
access_token = AccessTokenFactory(user=self.mock_user, application=ApplicationFactory()).token
headers = {'HTTP_AUTHORIZATION': 'Bearer ' + access_token}
response = self.client.post(dispatch_url, {}, **headers)
self.assertEqual(200, response.status_code)

View File

@@ -10,7 +10,6 @@ import ddt
import httpretty
import mock
from django.urls import reverse
from edx_oauth2_provider.tests.factories import AccessTokenFactory, ClientFactory
from opaque_keys.edx.keys import CourseKey
from pytz import UTC
from rest_framework.parsers import JSONParser
@@ -39,6 +38,7 @@ from openedx.core.djangoapps.course_groups.tests.helpers import config_course_co
from openedx.core.djangoapps.django_comment_common.models import CourseDiscussionSettings, Role
from openedx.core.djangoapps.django_comment_common.utils import seed_permissions_roles
from openedx.core.djangoapps.oauth_dispatch.jwt import create_jwt_for_user
from openedx.core.djangoapps.oauth_dispatch.tests.factories import ApplicationFactory, AccessTokenFactory
from openedx.core.djangoapps.user_api.accounts.image_helpers import get_profile_image_storage
from openedx.core.djangoapps.user_api.models import RetirementState, UserRetirementStatus
from student.models import get_retired_username_by_username
@@ -1906,7 +1906,7 @@ class CourseDiscussionSettingsAPIViewTest(APITestCase, UrlResetMixin, ModuleStor
def _get_oauth_headers(self, user):
"""Return the OAuth headers for testing OAuth authentication"""
access_token = AccessTokenFactory.create(user=user, client=ClientFactory()).token
access_token = AccessTokenFactory.create(user=user, application=ApplicationFactory()).token
headers = {
'HTTP_AUTHORIZATION': 'Bearer ' + access_token
}
@@ -2159,7 +2159,7 @@ class CourseDiscussionRolesAPIViewTest(APITestCase, UrlResetMixin, ModuleStoreTe
def _get_oauth_headers(self, user):
"""Return the OAuth headers for testing OAuth authentication."""
access_token = AccessTokenFactory.create(user=user, client=ClientFactory()).token
access_token = AccessTokenFactory.create(user=user, application=ApplicationFactory()).token
headers = {
'HTTP_AUTHORIZATION': 'Bearer ' + access_token
}

View File

@@ -8,9 +8,9 @@ from datetime import datetime
import ddt
import six
from django.urls import reverse
from edx_oauth2_provider.tests.factories import AccessTokenFactory, ClientFactory
from pytz import UTC
from openedx.core.djangoapps.oauth_dispatch.tests.factories import ApplicationFactory, AccessTokenFactory
from capa.tests.response_xml_factory import MultipleChoiceResponseXMLFactory
from lms.djangoapps.courseware.tests.factories import GlobalStaffFactory, StaffFactory
from student.tests.factories import UserFactory
@@ -32,8 +32,8 @@ class GradingPolicyTestMixin(object):
def create_user_and_access_token(self):
self.user = GlobalStaffFactory.create()
self.oauth_client = ClientFactory.create()
self.access_token = AccessTokenFactory.create(user=self.user, client=self.oauth_client).token
self.oauth_client = ApplicationFactory.create()
self.access_token = AccessTokenFactory.create(user=self.user, application=self.oauth_client).token
@classmethod
def create_course_data(cls):
@@ -103,7 +103,7 @@ class GradingPolicyTestMixin(object):
Returns Bearer auth header with a generated access token
for the given user.
"""
access_token = AccessTokenFactory.create(user=user, client=self.oauth_client).token
access_token = AccessTokenFactory.create(user=user, application=self.oauth_client).token
return 'Bearer ' + access_token
def test_get_invalid_course(self):

View File

@@ -10,8 +10,8 @@ import ddt
import six
from six.moves import range
from django.urls import reverse
from edx_oauth2_provider.tests.factories import AccessTokenFactory, ClientFactory
from openedx.core.djangoapps.oauth_dispatch.tests.factories import ApplicationFactory, AccessTokenFactory
from openedx.core.djangolib.testing.utils import skip_unless_lms
from student.tests.factories import UserFactory
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
@@ -54,8 +54,8 @@ class TestCohortOauth(SharedModuleStoreTestCase):
""" Verify the endpoints supports OAuth, and only allows authorization for staff users. """
path = reverse(path_name, kwargs={'course_key_string': self.course_str})
user = UserFactory(is_staff=False)
oauth_client = ClientFactory.create()
access_token = AccessTokenFactory.create(user=user, client=oauth_client).token
oauth_client = ApplicationFactory.create()
access_token = AccessTokenFactory.create(user=user, application=oauth_client).token
headers = {
'HTTP_AUTHORIZATION': 'Bearer ' + access_token
}
@@ -75,8 +75,8 @@ class TestCohortOauth(SharedModuleStoreTestCase):
cohorts.add_cohort(self.course_key, "DEFAULT", "random")
path = reverse('api_cohorts:cohort_users', kwargs={'course_key_string': self.course_str, 'cohort_id': 1})
user = UserFactory(is_staff=False)
oauth_client = ClientFactory.create()
access_token = AccessTokenFactory.create(user=user, client=oauth_client).token
oauth_client = ApplicationFactory.create()
access_token = AccessTokenFactory.create(user=user, application=oauth_client).token
headers = {
'HTTP_AUTHORIZATION': 'Bearer ' + access_token
}
@@ -99,8 +99,8 @@ class TestCohortOauth(SharedModuleStoreTestCase):
cohorts.add_cohort(self.course_key, "DEFAULT", "random")
path = reverse('api_cohorts:cohort_users_csv', kwargs={'course_key_string': self.course_str})
user = UserFactory(is_staff=False)
oauth_client = ClientFactory.create()
access_token = AccessTokenFactory.create(user=user, client=oauth_client).token
oauth_client = ApplicationFactory.create()
access_token = AccessTokenFactory.create(user=user, application=oauth_client).token
headers = {
'HTTP_AUTHORIZATION': 'Bearer ' + access_token
}

View File

@@ -4,13 +4,12 @@
import uuid
import mock
from edx_oauth2_provider.tests.factories import ClientFactory
from provider.constants import CONFIDENTIAL
from openedx.core.djangoapps.credentials.models import CredentialsApiConfig
from openedx.core.djangoapps.credentials.tests import factories
from openedx.core.djangoapps.credentials.tests.mixins import CredentialsApiConfigMixin
from openedx.core.djangoapps.credentials.utils import get_credentials
from openedx.core.djangoapps.oauth_dispatch.tests.factories import ApplicationFactory
from openedx.core.djangolib.testing.utils import CacheIsolationTestCase, skip_unless_lms
from student.tests.factories import UserFactory
@@ -27,7 +26,7 @@ class TestGetCredentials(CredentialsApiConfigMixin, CacheIsolationTestCase):
def setUp(self):
super(TestGetCredentials, self).setUp()
ClientFactory(name=CredentialsApiConfig.OAUTH2_CLIENT_NAME, client_type=CONFIDENTIAL)
ApplicationFactory(name=CredentialsApiConfig.OAUTH2_CLIENT_NAME)
self.credentials_config = self.create_credentials_config(cache_ttl=1)
self.user = UserFactory()

View File

@@ -13,7 +13,6 @@ from django.conf import settings
from django.test import Client, TestCase
from django.test.utils import override_settings
from django.urls import reverse
from edx_oauth2_provider.tests.factories import AccessTokenFactory, ClientFactory
from opaque_keys.edx.keys import CourseKey
from openedx.core.djangoapps.credit.models import (
@@ -32,6 +31,7 @@ from openedx.core.djangoapps.credit.tests.factories import (
CreditRequestFactory
)
from openedx.core.djangoapps.oauth_dispatch.jwt import create_jwt_for_user
from openedx.core.djangoapps.oauth_dispatch.tests.factories import ApplicationFactory, AccessTokenFactory
from openedx.core.djangolib.testing.utils import skip_unless_lms
from student.tests.factories import AdminFactory, UserFactory
from util.date_utils import to_timestamp
@@ -77,7 +77,7 @@ class AuthMixin(object):
def test_oauth(self):
""" Verify the endpoint supports authentication via OAuth 2.0. """
access_token = AccessTokenFactory(user=self.user, client=ClientFactory()).token
access_token = AccessTokenFactory(user=self.user, application=ApplicationFactory()).token
headers = {
'HTTP_AUTHORIZATION': 'Bearer ' + access_token
}
@@ -173,8 +173,8 @@ class CreditCourseViewSetTests(AuthMixin, UserMixin, TestCase):
def test_oauth(self):
""" Verify the endpoint supports OAuth, and only allows authorization for staff users. """
user = UserFactory(is_staff=False)
oauth_client = ClientFactory.create()
access_token = AccessTokenFactory.create(user=user, client=oauth_client).token
oauth_client = ApplicationFactory.create()
access_token = AccessTokenFactory.create(user=user, application=oauth_client).token
headers = {
'HTTP_AUTHORIZATION': 'Bearer ' + access_token
}

View File

@@ -22,7 +22,7 @@ class ApplicationFactory(DjangoModelFactory):
client_id = factory.Sequence(u'client_{0}'.format)
client_secret = 'some_secret'
client_type = 'confidential'
authorization_grant_type = 'Client credentials'
authorization_grant_type = Application.CLIENT_CONFIDENTIAL
name = FuzzyText(prefix='name', length=8)

View File

@@ -7,9 +7,7 @@ import unittest
from django.conf import settings
from django.test import TestCase
from django.urls import reverse
from edx_oauth2_provider.tests.factories import ClientFactory
from oauth2_provider.models import Application
from provider.oauth2.models import AccessToken
from student.tests.factories import UserFactory
@@ -26,29 +24,6 @@ class ClientCredentialsTest(mixins.AccessTokenMixin, TestCase):
super(ClientCredentialsTest, self).setUp()
self.user = UserFactory()
def test_access_token(self):
""" Verify the client credentials grant can be used to obtain an access token whose default scopes allow access
to the user info endpoint.
"""
oauth_client = ClientFactory(user=self.user)
data = {
'grant_type': 'client_credentials',
'client_id': oauth_client.client_id,
'client_secret': oauth_client.client_secret
}
response = self.client.post(reverse('oauth2:access_token'), data)
self.assertEqual(response.status_code, 200)
access_token = json.loads(response.content.decode('utf-8'))['access_token']
expected = AccessToken.objects.filter(client=oauth_client, user=self.user).first().token
self.assertEqual(access_token, expected)
headers = {
'HTTP_AUTHORIZATION': 'Bearer ' + access_token
}
response = self.client.get(reverse('oauth2:user_info'), **headers)
self.assertEqual(response.status_code, 200)
def test_jwt_access_token(self):
""" Verify the client credentials grant can be used to obtain a JWT access token. """
application = DOTAdapter().create_confidential_client(

View File

@@ -14,7 +14,6 @@ import pytz
from celery.exceptions import MaxRetriesExceededError
from django.conf import settings
from django.test import TestCase, override_settings
from edx_oauth2_provider.tests.factories import ClientFactory
from edx_rest_api_client import exceptions
from edx_rest_api_client.client import EdxRestApiClient
from waffle.testutils import override_switch
@@ -24,6 +23,7 @@ from openedx.core.djangoapps.catalog.tests.mixins import CatalogIntegrationMixin
from openedx.core.djangoapps.certificates.config import waffle
from openedx.core.djangoapps.content.course_overviews.tests.factories import CourseOverviewFactory
from openedx.core.djangoapps.credentials.tests.mixins import CredentialsApiConfigMixin
from openedx.core.djangoapps.oauth_dispatch.tests.factories import ApplicationFactory
from openedx.core.djangoapps.programs.tasks.v1 import tasks
from openedx.core.djangoapps.site_configuration.tests.factories import SiteConfigurationFactory, SiteFactory
from openedx.core.djangolib.testing.utils import skip_unless_lms
@@ -131,7 +131,7 @@ class AwardProgramCertificatesTestCase(CatalogIntegrationMixin, CredentialsApiCo
self.site = SiteFactory()
self.site_configuration = SiteConfigurationFactory(site=self.site)
self.catalog_integration = self.create_catalog_integration()
ClientFactory.create(name='credentials')
ApplicationFactory.create(name='credentials')
UserFactory.create(username=settings.CREDENTIALS_SERVICE_USERNAME)
def test_completion_check(
@@ -506,7 +506,7 @@ class AwardCourseCertificatesTestCase(CredentialsApiConfigMixin, TestCase):
self.create_credentials_config()
self.site = SiteFactory()
ClientFactory.create(name='credentials')
ApplicationFactory.create(name='credentials')
UserFactory.create(username=settings.CREDENTIALS_SERVICE_USERNAME)
@ddt.data(

View File

@@ -12,8 +12,7 @@ from django.conf import settings
from django.test import TestCase
from django.test.utils import override_settings
from django.urls import reverse
from edx_oauth2_provider.constants import AUTHORIZED_CLIENTS_SESSION_KEY
from edx_oauth2_provider.tests.factories import ClientFactory, TrustedClientFactory
from openedx.core.djangoapps.oauth_dispatch.tests.factories import ApplicationFactory
from student.tests.factories import UserFactory
@@ -31,9 +30,7 @@ class LogoutTests(TestCase):
def _create_oauth_client(self):
""" Creates a trusted OAuth client. """
client = ClientFactory(logout_uri='https://www.example.com/logout/')
TrustedClientFactory(client=client)
return client
return ApplicationFactory(redirect_uris='https://www.example.com/logout/', skip_authorization=True)
def _assert_session_logged_out(self, oauth_client, **logout_headers):
""" Authenticates a user via OAuth 2.0, logs out, and verifies the session is logged out. """
@@ -43,14 +40,11 @@ class LogoutTests(TestCase):
# The template will handle loading those URLs and redirecting the user. That functionality is not tested here.
response = self.client.get(reverse('logout'), **logout_headers)
self.assertEqual(response.status_code, 200)
self.assertNotIn(AUTHORIZED_CLIENTS_SESSION_KEY, self.client.session)
return response
def _authenticate_with_oauth(self, oauth_client):
""" Perform an OAuth authentication using the current web client.
This should add an AUTHORIZED_CLIENTS_SESSION_KEY entry to the current session.
"""
data = {
'client_id': oauth_client.client_id,
@@ -58,8 +52,8 @@ class LogoutTests(TestCase):
'response_type': 'code'
}
# Authenticate with OAuth to set the appropriate session values
self.client.post(reverse('oauth2:capture'), data, follow=True)
self.assertListEqual(self.client.session[AUTHORIZED_CLIENTS_SESSION_KEY], [oauth_client.client_id])
response = self.client.post(reverse('oauth2_provider:authorize'), data, follow=True)
self.assertEqual(response.status_code, 200)
@ddt.data(
('%2Fcourses', 'testserver'),
@@ -115,7 +109,7 @@ class LogoutTests(TestCase):
client = self._create_oauth_client()
response = self._assert_session_logged_out(client)
expected = {
'logout_uris': [client.logout_uri + '?no_redirect=1'],
'logout_uris': [],
'target': '/',
}
self.assertDictContainsSubset(expected, response.context_data)
@@ -134,10 +128,8 @@ class LogoutTests(TestCase):
"""
client = self._create_oauth_client()
response = self._assert_session_logged_out(client)
# Add the logout endpoints for the IDAs where auth was established via OIDC.
expected_logout_uris = [client.logout_uri + '?no_redirect=1']
# Add the logout endpoints for the IDAs where auth was established via DOT/OAuth2.
expected_logout_uris += [
expected_logout_uris = [
'http://fake.ida1/logout?no_redirect=1',
'http://fake.ida2/accounts/logout?no_redirect=1',
]
@@ -175,7 +167,7 @@ class LogoutTests(TestCase):
is not included in the context sent to the template.
"""
client = self._create_oauth_client()
response = self._assert_session_logged_out(client, HTTP_REFERER=client.logout_uri)
response = self._assert_session_logged_out(client, HTTP_REFERER=client.redirect_uris)
expected = {
'logout_uris': [],
'target': '/',

View File

@@ -16,7 +16,6 @@ from django.test.client import RequestFactory
from django.urls import reverse
from testfixtures import LogCapture
from edx_oauth2_provider.tests.factories import AccessTokenFactory, ClientFactory, RefreshTokenFactory
from openedx.core.djangoapps.site_configuration.tests.factories import SiteFactory
from openedx.core.djangoapps.oauth_dispatch.tests import factories as dot_factories
from openedx.core.djangoapps.user_api.accounts.tests.test_api import CreateAccountMixin
@@ -25,10 +24,6 @@ from openedx.core.djangoapps.user_authn.views.password_reset import request_pass
from openedx.core.djangolib.testing.utils import CacheIsolationTestCase, skip_unless_lms
from oauth2_provider.models import AccessToken as dot_access_token
from oauth2_provider.models import RefreshToken as dot_refresh_token
from provider.oauth2.models import AccessToken as dop_access_token
from provider.oauth2.models import RefreshToken as dop_refresh_token
from student.models import Registration
LOGGER_NAME = 'audit'
User = get_user_model() # pylint:disable=invalid-name
@@ -228,7 +223,6 @@ class TestPasswordChange(CreateAccountMixin, CacheIsolationTestCase):
def test_access_token_invalidation_logged_out(self):
self.client.logout()
user = User.objects.get(email=self.OLD_EMAIL)
self._create_dop_tokens(user)
self._create_dot_tokens(user)
response = self._change_password(email=self.OLD_EMAIL)
self.assertEqual(response.status_code, 200)
@@ -236,7 +230,6 @@ class TestPasswordChange(CreateAccountMixin, CacheIsolationTestCase):
def test_access_token_invalidation_logged_in(self):
user = User.objects.get(email=self.OLD_EMAIL)
self._create_dop_tokens(user)
self._create_dot_tokens(user)
response = self._change_password()
self.assertEqual(response.status_code, 200)
@@ -308,15 +301,6 @@ class TestPasswordChange(CreateAccountMixin, CacheIsolationTestCase):
return self.client.post(path=reverse('password_change_request'), data=data)
def _create_dop_tokens(self, user=None):
"""Create dop access token for given user if user provided else for default user."""
if not user:
user = User.objects.get(email=self.OLD_EMAIL)
client = ClientFactory()
access_token = AccessTokenFactory(user=user, client=client)
RefreshTokenFactory(user=user, client=client, access_token=access_token)
def _create_dot_tokens(self, user=None):
"""Create dot access token for given user if user provided else for default user."""
if not user:
@@ -330,5 +314,3 @@ class TestPasswordChange(CreateAccountMixin, CacheIsolationTestCase):
"""Assert all access tokens are destroyed."""
self.assertFalse(dot_access_token.objects.filter(user=user).exists())
self.assertFalse(dot_refresh_token.objects.filter(user=user).exists())
self.assertFalse(dop_access_token.objects.filter(user=user).exists())
self.assertFalse(dop_refresh_token.objects.filter(user=user).exists())

View File

@@ -22,10 +22,8 @@ from django.test.client import RequestFactory
from django.test.utils import override_settings
from django.urls import reverse
from django.utils.http import int_to_base36
from edx_oauth2_provider.tests.factories import AccessTokenFactory, ClientFactory, RefreshTokenFactory
from mock import Mock, patch
from oauth2_provider import models as dot_models
from provider.oauth2 import models as dop_models
from six.moves import range
from openedx.core.djangoapps.oauth_dispatch.tests import factories as dot_factories
@@ -154,16 +152,11 @@ class ResetPasswordTests(EventTestMixin, CacheIsolationTestCase):
good_req = self.request_factory.post('/password_reset/', {'email': self.user.email})
good_req.user = self.user
good_req.site = Mock(domain='example.com')
dop_client = ClientFactory()
dop_access_token = AccessTokenFactory(user=self.user, client=dop_client)
RefreshTokenFactory(user=self.user, client=dop_client, access_token=dop_access_token)
dot_application = dot_factories.ApplicationFactory(user=self.user)
dot_access_token = dot_factories.AccessTokenFactory(user=self.user, application=dot_application)
dot_factories.RefreshTokenFactory(user=self.user, application=dot_application, access_token=dot_access_token)
good_resp = password_reset(good_req)
self.assertEqual(good_resp.status_code, 200)
self.assertFalse(dop_models.AccessToken.objects.filter(user=self.user).exists())
self.assertFalse(dop_models.RefreshToken.objects.filter(user=self.user).exists())
self.assertFalse(dot_models.AccessToken.objects.filter(user=self.user).exists())
self.assertFalse(dot_models.RefreshToken.objects.filter(user=self.user).exists())
obj = json.loads(good_resp.content.decode('utf-8'))