-
Notifications
You must be signed in to change notification settings - Fork 3.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adding oauth test #35417
Adding oauth test #35417
Changes from 13 commits
f8897bc
a51005a
c62bc4a
86257a5
effcc39
7751d00
c32d150
f11eb1a
981dcc4
ee61c4f
b73fb3e
61bc5a8
36a231d
9f60b3a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -47,6 +47,7 @@ | |
UNENROLLED_TO_ALLOWEDTOENROLL, | ||
UNENROLLED_TO_ENROLLED, | ||
UNENROLLED_TO_UNENROLLED, | ||
CourseAccessRole, | ||
CourseEnrollment, | ||
CourseEnrollmentAllowed, | ||
ManualEnrollmentAudit, | ||
|
@@ -60,12 +61,14 @@ | |
CourseFinanceAdminRole, | ||
CourseInstructorRole, | ||
) | ||
from common.djangoapps.student.tests.factories import BetaTesterFactory | ||
from common.djangoapps.student.tests.factories import CourseEnrollmentFactory | ||
from common.djangoapps.student.tests.factories import GlobalStaffFactory | ||
from common.djangoapps.student.tests.factories import InstructorFactory | ||
from common.djangoapps.student.tests.factories import StaffFactory | ||
from common.djangoapps.student.tests.factories import UserFactory | ||
from common.djangoapps.student.tests.factories import ( | ||
BetaTesterFactory, | ||
CourseEnrollmentFactory, | ||
GlobalStaffFactory, | ||
InstructorFactory, | ||
StaffFactory, | ||
UserFactory | ||
) | ||
from lms.djangoapps.bulk_email.models import BulkEmailFlag, CourseEmail, CourseEmailTemplate | ||
from lms.djangoapps.certificates.data import CertificateStatuses | ||
from lms.djangoapps.certificates.tests.factories import ( | ||
|
@@ -94,6 +97,9 @@ | |
from openedx.core.djangoapps.course_groups.cohorts import set_course_cohorted | ||
from openedx.core.djangoapps.django_comment_common.models import FORUM_ROLE_COMMUNITY_TA | ||
from openedx.core.djangoapps.django_comment_common.utils import seed_permissions_roles | ||
from openedx.core.djangoapps.oauth_dispatch import jwt as jwt_api | ||
from openedx.core.djangoapps.oauth_dispatch.adapters import DOTAdapter | ||
from openedx.core.djangoapps.oauth_dispatch.tests.factories import AccessTokenFactory, ApplicationFactory | ||
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers | ||
from openedx.core.djangoapps.site_configuration.tests.mixins import SiteMixin | ||
from openedx.core.djangoapps.user_api.preferences.api import delete_user_preference | ||
|
@@ -4675,3 +4681,117 @@ def test_get_certificate_for_user_no_certificate(self): | |
f"The student {self.user} does not have certificate for the course {self.course.id.course}. Kindly " | ||
"verify student username/email and the selected course are correct and try again." | ||
) | ||
|
||
|
||
@patch.dict(settings.FEATURES, {'ALLOW_AUTOMATED_SIGNUPS': True}) | ||
class TestOauthInstructorAPILevelsAccess(SharedModuleStoreTestCase, LoginEnrollmentTestCase): | ||
""" | ||
Test endpoints using Oauth2 authentication. | ||
""" | ||
|
||
@classmethod | ||
def setUpClass(cls): | ||
super().setUpClass() | ||
cls.course = CourseFactory.create( | ||
entrance_exam_id='i4x://{}/{}/chapter/Entrance_exam'.format('test_org', 'test_course') | ||
) | ||
|
||
def setUp(self): | ||
super().setUp() | ||
|
||
self.other_user = UserFactory() | ||
dot_application = ApplicationFactory(user=self.other_user, authorization_grant_type='password') | ||
access_token = AccessTokenFactory(user=self.other_user, application=dot_application) | ||
oauth_adapter = DOTAdapter() | ||
token_dict = { | ||
'access_token': access_token, | ||
'scope': 'email profile', | ||
} | ||
jwt_token = jwt_api.create_jwt_from_token(token_dict, oauth_adapter, use_asymmetric_key=True) | ||
|
||
self.headers = { | ||
'HTTP_AUTHORIZATION': 'JWT ' + jwt_token | ||
} | ||
|
||
# endpoints contains all urls with body and role. | ||
self.endpoints = [ | ||
('list_course_role_members', {'rolename': 'staff'}, 'instructor'), | ||
('register_and_enroll_students', {}, 'staff'), | ||
('get_student_progress_url', {'course_id': str(self.course.id), | ||
'unique_student_identifier': self.other_user.email | ||
}, 'staff' | ||
), | ||
('list_entrance_exam_instructor_tasks', {'unique_student_identifier': self.other_user.email}, 'staff'), | ||
('list_email_content', {}, 'staff'), | ||
('show_student_extensions', {'student': self.other_user.email}, 'staff'), | ||
('list_email_content', {}, 'staff'), | ||
('list_report_downloads', { | ||
"send-to": ["myself"], | ||
"subject": "This is subject", | ||
"message": "message" | ||
}, 'data_researcher') | ||
] | ||
|
||
self.fake_jwt = ('wyJUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJjaGFuZ2UtbWUiLCJleHAiOjE3MjU4OTA2NzIsImdyY' | ||
'W50X3R5cGUiOiJwYXNzd29yZCIsImlhdCI6MTcyNTg4NzA3MiwiaXNzIjoiaHR0cDovLzEyNy4wLjAuMTo4MDAwL29h' | ||
'XNlcl9pZCI6MX0' | ||
'.ec8neWp1YAuF40ye4oeK40obaapUvjfNPUQCycrsajwvcu58KcuLc96sf0JKmMMMn7DH9N98hg8W38iwbhKif1kLsCKr' | ||
'tStl1u2XGvFkyMov8TtespbHit5LYRZpJwrhC1h50ru2buYj3isWrAElGPIDyAj0FAvSJnvJhWSMDtIwB2gxZI1DqOm' | ||
'M6mzT7JbOU4QH2PNZrb2EZ11F6k9I-HrHnLQymr4s0vyjMlcBWllW3y19futNCgsFFRMXI4Z9zIbspsy5bq_Skub' | ||
'dBpnl0P9x8vUJCAbFnJABAVPtF7F7nNsROQMKsZtQxaUUwdcYZi5qKL2GcgGfO0eTL4IbJA') | ||
|
||
def assert_all_end_points(self, endpoint, body, role, add_role, use_jwt=True): | ||
""" | ||
Util method for verifying different end-points. | ||
""" | ||
if add_role: | ||
role, _ = CourseAccessRole.objects.get_or_create( | ||
course_id=self.course.id, | ||
user=self.other_user, | ||
role=role, | ||
org=self.course.id.org | ||
) | ||
|
||
if use_jwt: | ||
headers = self.headers | ||
else: | ||
headers = { | ||
'HTTP_AUTHORIZATION': 'JWT ' + self.fake_jwt # this is fake jwt. | ||
} | ||
|
||
url = reverse(endpoint, kwargs={'course_id': str(self.course.id)}) | ||
response = self.client.post( | ||
url, | ||
data=body, | ||
**headers | ||
) | ||
return response | ||
|
||
def test_end_points_with_oauth_without_jwt(self): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should create a common function to avoid duplicating the code in all test cases.
containing all the duplicate code so the actual tests can be changed to something like following:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @UsamaSadiq good suggestion, I have implemented. |
||
""" | ||
Verify the endpoint using invalid JWT returns 401. | ||
""" | ||
for endpoint, body, role in self.endpoints: | ||
with self.subTest(endpoint=endpoint, role=role, body=body): | ||
response = self.assert_all_end_points(endpoint, body, role, False, False) | ||
# JWT authentication works but it has no permissions. | ||
assert response.status_code == 401, f"Failed for endpoint: {endpoint}" | ||
|
||
def test_end_points_with_oauth_without_permissions(self): | ||
""" | ||
Verify the endpoint using JWT authentication. But has no permissions. | ||
""" | ||
for endpoint, body, role in self.endpoints: | ||
with self.subTest(endpoint=endpoint, role=role, body=body): | ||
response = self.assert_all_end_points(endpoint, body, role, False, True) | ||
# JWT authentication works but it has no permissions. | ||
assert response.status_code == 403, f"Failed for endpoint: {endpoint}" | ||
|
||
def test_end_points_with_oauth_with_permissions(self): | ||
""" | ||
Verify the endpoint using JWT authentication with permissions. | ||
""" | ||
for endpoint, body, role in self.endpoints: | ||
with self.subTest(endpoint=endpoint, role=role, body=body): | ||
response = self.assert_all_end_points(endpoint, body, role, True, True) | ||
assert response.status_code == 200, f"Failed for endpoint: {endpoint}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we only testing these specific endpoints?
Do they belong to a particular feature?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am converting these endpoints to DRF. So now they all are oauth2 compatible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps we can organize this endpoints list in a maintainable way, for example define the endpoints in the constants in next PRs