Skip to content

Commit

Permalink
test: add roles test
Browse files Browse the repository at this point in the history
  • Loading branch information
rpenido committed Apr 5, 2024
1 parent 6501b9b commit 8497e8c
Showing 1 changed file with 107 additions and 3 deletions.
110 changes: 107 additions & 3 deletions openedx/core/djangoapps/content/search/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,22 @@
"""
import functools
from django.test import override_settings
from rest_framework.test import APITestCase, APIClient
from rest_framework.test import APIClient
from unittest import mock

from organizations.models import Organization
from common.djangoapps.student.auth import add_users, update_org_role
from common.djangoapps.student.roles import (
CourseInstructorRole,
OrgStaffRole
)
from common.djangoapps.student.tests.factories import UserFactory
from openedx.core.djangoapps.content.course_overviews.tests.factories import CourseOverviewFactory
from openedx.core.djangoapps.content.search.models import SearchAccess
from openedx.core.djangolib.testing.utils import skip_unless_cms
from organizations.models import Organization
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory


STUDIO_SEARCH_ENDPOINT_URL = "/api/content_search/v2/studio/"
MOCK_API_KEY_UID = "3203d764-370f-4e99-a917-d47ab7f29739"
Expand Down Expand Up @@ -38,7 +48,7 @@ def wrapper(*args, **kwargs):


@skip_unless_cms
class StudioSearchViewTest(APITestCase):
class StudioSearchViewTest(SharedModuleStoreTestCase):
"""
General tests for the Studio search REST API.
"""
Expand All @@ -52,11 +62,41 @@ def setUpClass(cls):
cls.student = UserFactory.create(
username='student', email='[email protected]', is_staff=False, password='student_pass'
)
cls.staff_org = UserFactory.create(
username='staff_org', email='[email protected]', is_staff=False, password='staff_org_pass'
)
cls.instructor_course = UserFactory.create(
username='instructor_course',
email='[email protected]',
is_staff=False,
password='instructor_course_pass'
)
cls.org = Organization.objects.create(name="edX", short_name="edX")

def setUp(self):
super().setUp()
self.client = APIClient()

course_location = self.store.make_course_key('edX', 'CreatedCourse', 'Run')
self.course = self._create_course(course_location)
self.course_access_keys = SearchAccess.objects.get(context_key=self.course.id).id

update_org_role(self.staff, OrgStaffRole, self.staff_org, [self.course.id.org])

add_users(self.staff, CourseInstructorRole(self.course.id), self.instructor_course)

def _create_course(self, course_location):
"""
Create dummy course and overview.
"""
CourseFactory.create(
org=course_location.org,
number=course_location.course,
run=course_location.run
)
course = CourseOverviewFactory.create(id=course_location, org=course_location.org)
return course

@mock_meilisearch(enabled=False)
def test_studio_search_unathenticated_disabled(self):
"""
Expand Down Expand Up @@ -143,6 +183,70 @@ def test_studio_search_staff(self, mock_search_client):
expires_at=mock.ANY,
)

@mock_meilisearch(enabled=True)
@mock.patch('openedx.core.djangoapps.content.search.views.meilisearch.Client')
@mock.patch('openedx.core.djangoapps.content.search.views._get_meili_api_key_uid')
def test_studio_search_org_staff(self, mock_get_api_key_uid, mock_search_client):
"""
Org staff can access documents from its orgs
"""
self.client.login(username='staff_org', password='staff_org_pass')
mock_get_api_key_uid.return_value = MOCK_API_KEY_UID
mock_generate_tenant_token = mock.Mock(return_value='restricted_api_key')
mock_search_client.return_value = mock.Mock(
generate_tenant_token=mock_generate_tenant_token,
)
result = self.client.get(STUDIO_SEARCH_ENDPOINT_URL)
assert result.status_code == 200

### To help with debugging
assert mock_generate_tenant_token.call_args[1]["search_rules"]["studio_content"]["filter"] == (
"org IN ['edX'] OR access_id IN []"
)
###

mock_generate_tenant_token.assert_called_once_with(
api_key_uid=MOCK_API_KEY_UID,
search_rules={
"studio_content": {
"filter": "org IN ['edX'] OR access_id IN []",
}
},
expires_at=mock.ANY,
)

@mock_meilisearch(enabled=True)
@mock.patch('openedx.core.djangoapps.content.search.views.meilisearch.Client')
@mock.patch('openedx.core.djangoapps.content.search.views._get_meili_api_key_uid')
def test_studio_search_course_instructor(self, mock_get_api_key_uid, mock_search_client):
"""
Course instructor can access documents it has direct access to
"""
self.client.login(username='instructor_course', password='instructor_course_pass')
mock_get_api_key_uid.return_value = MOCK_API_KEY_UID
mock_generate_tenant_token = mock.Mock(return_value='restricted_api_key')
mock_search_client.return_value = mock.Mock(
generate_tenant_token=mock_generate_tenant_token,
)
result = self.client.get(STUDIO_SEARCH_ENDPOINT_URL)
assert result.status_code == 200

### To help with debugging
assert mock_generate_tenant_token.call_args[1]["search_rules"]["studio_content"]["filter"] == (
f"org IN [] OR access_id IN [{self.course_access_keys}]"
)
###

mock_generate_tenant_token.assert_called_once_with(
api_key_uid=MOCK_API_KEY_UID,
search_rules={
"studio_content": {
"filter": f"org IN [] OR access_id IN [{self.toy_course_access_id}]",
}
},
expires_at=mock.ANY,
)

@mock_meilisearch(enabled=True)
@mock.patch('openedx.core.djangoapps.content.search.views.get_access_ids_for_request')
@mock.patch('openedx.core.djangoapps.content.search.views.meilisearch.Client')
Expand Down

0 comments on commit 8497e8c

Please sign in to comment.