|
11 | 11 | from django.contrib.auth import get_user_model |
12 | 12 | from django.test.utils import override_settings |
13 | 13 | from django.urls import reverse |
14 | | -from openedx_authz.constants.roles import COURSE_DATA_RESEARCHER, COURSE_STAFF |
| 14 | +from openedx_authz.constants.roles import COURSE_DATA_RESEARCHER, COURSE_EDITOR, COURSE_STAFF |
15 | 15 | from rest_framework import status |
16 | 16 | from rest_framework.test import APIClient, APITestCase |
17 | 17 |
|
18 | 18 | from cms.djangoapps.contentstore.api.tests.base import BaseCourseViewTest |
19 | 19 | from common.djangoapps.course_modes.models import CourseMode |
20 | 20 | from common.djangoapps.course_modes.tests.factories import CourseModeFactory |
21 | 21 | from common.djangoapps.student.tests.factories import StaffFactory, UserFactory |
22 | | -from openedx.core.djangoapps.authz.tests.mixins import CourseAuthzTestMixin |
| 22 | +from openedx.core.djangoapps.authz.tests.mixins import CourseAuthoringAuthzTestMixin, CourseAuthzTestMixin |
23 | 23 | from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase |
24 | 24 | from xmodule.modulestore.tests.factories import BlockFactory, CourseFactory |
25 | 25 |
|
@@ -247,7 +247,7 @@ def test_create_update_reference_success(self, mock_block, mock_user_task_status |
247 | 247 |
|
248 | 248 | mock_auth.assert_called_once() |
249 | 249 |
|
250 | | - @patch('cms.djangoapps.contentstore.api.views.utils.has_course_author_access') |
| 250 | + @patch('openedx.core.djangoapps.authz.decorators.user_has_course_permission') |
251 | 251 | @patch('xmodule.library_content_block.LegacyLibraryContentBlock.is_ready_to_migrate_to_v2') |
252 | 252 | def test_list_ready_to_update_reference_success(self, mock_block, mock_auth): |
253 | 253 | """ |
@@ -353,3 +353,83 @@ def test_non_staff_user_cannot_access(self): |
353 | 353 |
|
354 | 354 | resp = non_staff_client.get(self.get_url(self.course_key)) |
355 | 355 | self.assertEqual(resp.status_code, status.HTTP_403_FORBIDDEN) # noqa: PT009 |
| 356 | + |
| 357 | + |
| 358 | +class TestMigrationViewSetCreateAuthz( |
| 359 | + CourseAuthoringAuthzTestMixin, |
| 360 | + SharedModuleStoreTestCase, |
| 361 | + APITestCase, |
| 362 | +): |
| 363 | + """ |
| 364 | + AuthZ tests for: |
| 365 | + /api/courses/v1/migrate_legacy_content_blocks/<course_id>/ |
| 366 | + """ |
| 367 | + |
| 368 | + @classmethod |
| 369 | + def setUpClass(cls): |
| 370 | + super().setUpClass() |
| 371 | + |
| 372 | + cls.course = CourseFactory.create( |
| 373 | + display_name='test course', |
| 374 | + run="Testing_course", |
| 375 | + ) |
| 376 | + cls.course_key = cls.course.id |
| 377 | + |
| 378 | + cls.initialize_course(cls.course) |
| 379 | + |
| 380 | + @classmethod |
| 381 | + def initialize_course(cls, course): |
| 382 | + """Sets up test course structure.""" |
| 383 | + section = BlockFactory.create( |
| 384 | + parent_location=course.location, |
| 385 | + category="chapter", |
| 386 | + ) |
| 387 | + subsection = BlockFactory.create( |
| 388 | + parent_location=section.location, |
| 389 | + category="sequential", |
| 390 | + ) |
| 391 | + unit = BlockFactory.create( |
| 392 | + parent_location=subsection.location, |
| 393 | + category="vertical", |
| 394 | + ) |
| 395 | + BlockFactory.create( |
| 396 | + parent_location=unit.location, |
| 397 | + category="library_content", |
| 398 | + ) |
| 399 | + |
| 400 | + def url(self): |
| 401 | + return f"/api/courses/v1/migrate_legacy_content_blocks/{self.course_key}/" |
| 402 | + |
| 403 | + # ---- GET (list) ---- |
| 404 | + |
| 405 | + def test_authorized_user_can_list_blocks(self): |
| 406 | + """Authorized user can list migratable blocks.""" |
| 407 | + self.add_user_to_role_in_course( |
| 408 | + self.authorized_user, |
| 409 | + COURSE_EDITOR.external_key, |
| 410 | + self.course.id, |
| 411 | + ) |
| 412 | + |
| 413 | + response = self.authorized_client.get(self.url()) |
| 414 | + |
| 415 | + assert response.status_code == status.HTTP_200_OK |
| 416 | + |
| 417 | + def test_unauthorized_user_cannot_list_blocks(self): |
| 418 | + """Unauthorized user should receive 403.""" |
| 419 | + response = self.unauthorized_client.get(self.url()) |
| 420 | + |
| 421 | + assert response.status_code == status.HTTP_403_FORBIDDEN |
| 422 | + |
| 423 | + # ---- elevated users ---- |
| 424 | + |
| 425 | + def test_staff_user_can_access_without_authz_role(self): |
| 426 | + """Staff user bypasses AuthZ.""" |
| 427 | + response = self.staff_client.get(self.url()) |
| 428 | + |
| 429 | + assert response.status_code == status.HTTP_200_OK |
| 430 | + |
| 431 | + def test_superuser_can_access_without_authz_role(self): |
| 432 | + """Superuser bypasses AuthZ.""" |
| 433 | + response = self.super_client.get(self.url()) |
| 434 | + |
| 435 | + assert response.status_code in [status.HTTP_200_OK, status.HTTP_201_CREATED] |
0 commit comments