Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 2 additions & 22 deletions cms/djangoapps/contentstore/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
from common.djangoapps.course_modes.models import CourseMode
from common.djangoapps.edxmako.services import MakoService
from common.djangoapps.student import auth
from common.djangoapps.student.auth import STUDIO_EDIT_ROLES, has_studio_read_access, has_studio_write_access
from common.djangoapps.student.auth import STUDIO_EDIT_ROLES, has_studio_write_access
from common.djangoapps.student.models import CourseEnrollment
from common.djangoapps.student.roles import CourseInstructorRole, CourseStaffRole, GlobalStaff
from common.djangoapps.track import contexts
Expand All @@ -71,6 +71,7 @@
from common.djangoapps.xblock_django.user_service import DjangoXBlockUserService
from openedx.core import toggles as core_toggles
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
from openedx.core.djangoapps.content.services import StudioPermissionsService
from openedx.core.djangoapps.content_libraries.api import get_container
from openedx.core.djangoapps.content_tagging.toggles import is_tagging_feature_disabled
from openedx.core.djangoapps.credit.api import get_credit_requirements, is_credit_course
Expand Down Expand Up @@ -2243,27 +2244,6 @@ def get_group_configurations_context(course, store):
return context


class StudioPermissionsService:
"""
Service that can provide information about a user's permissions.

Deprecated. To be replaced by a more general authorization service.

Only used by LegacyLibraryContentBlock (and library_tools.py).
"""

def __init__(self, user):
self._user = user

def can_read(self, course_key):
""" Does the user have read access to the given course/library? """
return has_studio_read_access(self._user, course_key)

def can_write(self, course_key):
""" Does the user have read access to the given course/library? """
return has_studio_write_access(self._user, course_key)


def track_course_update_event(course_key, user, course_update_content=None):
"""
Track course update event
Expand Down
3 changes: 2 additions & 1 deletion cms/djangoapps/contentstore/views/preview.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
from common.djangoapps.student.models import anonymous_id_for_user
from common.djangoapps.xblock_django.user_service import DjangoXBlockUserService
from lms.djangoapps.lms_xblock.field_data import LmsFieldData
from openedx.core.djangoapps.content.services import StudioPermissionsService
from openedx.core.djangoapps.discussions.services import DiscussionConfigService
from openedx.core.djangoapps.video_config.services import VideoConfigService
from openedx.core.lib.cache_utils import CacheService
Expand All @@ -44,7 +45,7 @@
from xmodule.util.sandboxing import SandboxService
from xmodule.x_module import AUTHOR_VIEW, PREVIEW_VIEWS, STUDENT_VIEW, XModuleMixin

from ..utils import StudioPermissionsService, get_visibility_partition_info
from ..utils import get_visibility_partition_info
from .access import get_user_role
from .session_kv_store import SessionKeyValueStore

Expand Down
38 changes: 38 additions & 0 deletions openedx/core/djangoapps/content/services.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
"""
Services for learning content
"""
from __future__ import annotations

from content_libraries.api import has_permission_for_library_key, permissions
from opaque_keys.edx.locator import LibraryLocatorV2

from common.djangoapps.student.auth import has_studio_read_access, has_studio_write_access


class StudioPermissionsService:
"""
Service that can provide information about a user's permissions.
"""

def __init__(self, user):
self._user = user

def can_read(self, context_key):
""" Does the user have read access to the given course/library? """
if isinstance(context_key, LibraryLocatorV2):
return has_permission_for_library_key(
context_key,
self._user,
permissions.CAN_VIEW_THIS_CONTENT_LIBRARY,
)
return has_studio_read_access(self._user, context_key)

def can_write(self, context_key):
""" Does the user have read access to the given course/library? """
if isinstance(context_key, LibraryLocatorV2):
return has_permission_for_library_key(
context_key,
self._user,
permissions.CAN_EDIT_THIS_CONTENT_LIBRARY,
)
return has_studio_write_access(self._user, context_key)
25 changes: 25 additions & 0 deletions openedx/core/djangoapps/content_libraries/api/libraries.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@
"get_libraries_for_user",
"get_metadata",
"require_permission_for_library_key",
"has_permission_for_library_key",
"get_library",
"create_library",
"get_library_team",
Expand Down Expand Up @@ -363,6 +364,30 @@ def require_permission_for_library_key(
return library_obj


def has_permission_for_library_key(
library_key: LibraryLocatorV2, user: UserType, permission: str | authz_api.data.PermissionData
) -> bool:
"""
Like require_permission_for_library_key, checks if the user has the specified permission
for a library. Unlike require_permission_for_library_key, returns a boolean rather than the
library model or raising an exception.

Args:
library_key: The library key identifying the content library
user: The user whose permissions are being checked
permission: Either a permission string from content_libraries.permissions
or a PermissionData instance from the authz API

Returns:
bool: True if the user has the requested permission, False otherwise.
"""
try:
require_permission_for_library_key(library_key, user, permission)
return True
except (PermissionError, ContentLibrary.DoesNotExist):
return False


def get_library(library_key: LibraryLocatorV2) -> ContentLibraryMetadata:
"""
Get the library with the specified key. Does not check permissions.
Expand Down
3 changes: 3 additions & 0 deletions openedx/core/djangoapps/xblock/runtime/runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,9 @@ def service(self, block: XBlock, service_name: str):
return DiscussionConfigService()
elif service_name == 'xqueue':
return XQueueService(block)
elif service_name == 'studio_user_permissions':
from openedx.core.djangoapps.content.services import StudioPermissionsService
return StudioPermissionsService(self.user)

# Otherwise, fall back to the base implementation which loads services
# defined in the constructor:
Expand Down
Loading