Skip to content

Commit d1aa766

Browse files
authored
Merge branch 'master' into marslan/10083-export-content-libraries-git
2 parents 137e035 + 1ffedf4 commit d1aa766

27 files changed

Lines changed: 874 additions & 1103 deletions

File tree

cms/djangoapps/contentstore/rest_api/v1/views/certificates.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,14 @@
66
from rest_framework.response import Response
77
from rest_framework.views import APIView
88

9+
from openedx_authz.constants.permissions import COURSES_MANAGE_CERTIFICATES
10+
911
from cms.djangoapps.contentstore.utils import get_certificates_context
1012
from cms.djangoapps.contentstore.rest_api.v1.serializers import (
1113
CourseCertificatesSerializer,
1214
)
13-
from common.djangoapps.student.auth import has_studio_write_access
15+
from openedx.core.djangoapps.authz.constants import LegacyAuthoringPermission
16+
from openedx.core.djangoapps.authz.decorators import user_has_course_permission
1417
from openedx.core.lib.api.view_utils import (
1518
DeveloperErrorViewMixin,
1619
verify_course_exists,
@@ -96,7 +99,12 @@ def get(self, request: Request, course_id: str):
9699
course_key = CourseKey.from_string(course_id)
97100
store = modulestore()
98101

99-
if not has_studio_write_access(request.user, course_key):
102+
if not user_has_course_permission(
103+
request.user,
104+
COURSES_MANAGE_CERTIFICATES.identifier,
105+
course_key,
106+
LegacyAuthoringPermission.WRITE
107+
):
100108
self.permission_denied(request)
101109

102110
with store.bulk_operations(course_key):

cms/djangoapps/contentstore/rest_api/v1/views/tests/test_certificates.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@
44
from django.urls import reverse
55
from rest_framework import status
66

7+
from openedx_authz.constants.roles import COURSE_STAFF, COURSE_EDITOR
8+
79
from cms.djangoapps.contentstore.tests.utils import CourseTestCase
810
from cms.djangoapps.contentstore.views.tests.test_certificates import HelperMethods
11+
from openedx.core.djangoapps.authz.tests.mixins import CourseAuthoringAuthzTestMixin
912

1013
from ...mixins import PermissionAccessMixin
1114

@@ -36,3 +39,35 @@ def test_success_response(self):
3639
self.assertEqual(response_data["course_number_override"], self.course.display_coursenumber)
3740
self.assertEqual(response_data["course_title"], self.course.display_name_with_default)
3841
self.assertEqual(response_data["course_number"], self.course.number)
42+
43+
44+
class CourseCertificatesAuthzViewTest(
45+
CourseAuthoringAuthzTestMixin, CourseTestCase, PermissionAccessMixin, HelperMethods
46+
):
47+
"""
48+
Tests for CourseCertificatesView with AuthZ enabled.
49+
"""
50+
51+
def setUp(self):
52+
super().setUp()
53+
self.url = reverse(
54+
"cms.djangoapps.contentstore:v1:certificates",
55+
kwargs={"course_id": self.course.id},
56+
)
57+
58+
def test_authorized_user_can_access(self):
59+
"""User with COURSE_STAFF role can access."""
60+
self._add_course_certificates(count=2, signatory_count=2)
61+
self.add_user_to_role_in_course(self.authorized_user, COURSE_STAFF.external_key, self.course.id)
62+
resp = self.authorized_client.get(self.url)
63+
self.assertEqual(resp.status_code, status.HTTP_200_OK)
64+
65+
def test_non_staff_user_cannot_access(self):
66+
"""
67+
User without permissions should be denied.
68+
This case validates that a non-staff user cannot access.
69+
"""
70+
self._add_course_certificates(count=2, signatory_count=2)
71+
self.add_user_to_role_in_course(self.authorized_user, COURSE_EDITOR.external_key, self.course.id)
72+
resp = self.authorized_client.get(self.url)
73+
self.assertEqual(resp.status_code, status.HTTP_403_FORBIDDEN)

cms/djangoapps/contentstore/tests/test_utils.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
from django.conf import settings
1010
from django.test import TestCase
1111
from django.test.utils import override_settings
12-
from edx_toggles.toggles.testutils import override_waffle_flag
1312
from opaque_keys.edx.keys import CourseKey
1413
from opaque_keys.edx.locator import CourseLocator, LibraryLocator
1514
from openedx_events.tests.utils import OpenEdxEventsTestMixin
@@ -24,7 +23,6 @@
2423
from cms.djangoapps.contentstore.utils import send_course_update_notification
2524
from common.djangoapps.student.models import CourseEnrollment
2625
from common.djangoapps.student.tests.factories import GlobalStaffFactory, InstructorFactory, UserFactory
27-
from openedx.core.djangoapps.notifications.config.waffle import ENABLE_NOTIFICATIONS
2826
from openedx.core.djangoapps.notifications.models import Notification
2927
from openedx.core.djangoapps.site_configuration.tests.test_util import with_site_configuration_context
3028
from xmodule.modulestore import ModuleStoreEnum # lint-amnesty, pylint: disable=wrong-import-order
@@ -938,7 +936,6 @@ def test_update_course_details_instructor_paced(self, mock_update):
938936
mock_update.assert_called_once_with(self.course.id, payload, mock_request.user)
939937

940938

941-
@override_waffle_flag(ENABLE_NOTIFICATIONS, active=True)
942939
class CourseUpdateNotificationTests(OpenEdxEventsTestMixin, ModuleStoreTestCase):
943940
"""
944941
Unit tests for the course_update notification.

0 commit comments

Comments
 (0)