[FC-0099] feat: assign library roles after successful library creation (#37532)
This commit is contained in:
committed by
GitHub
parent
6b0af90664
commit
31b1e6ecc4
@@ -70,6 +70,7 @@ from openedx_learning.api.authoring_models import Component, LearningPackage
|
||||
from organizations.models import Organization
|
||||
from user_tasks.models import UserTaskArtifact, UserTaskStatus
|
||||
from xblock.core import XBlock
|
||||
from openedx_authz.api import assign_role_to_user_in_scope
|
||||
|
||||
from openedx.core.types import User as UserType
|
||||
|
||||
@@ -107,6 +108,7 @@ __all__ = [
|
||||
"publish_changes",
|
||||
"revert_changes",
|
||||
"get_backup_task_status",
|
||||
"assign_library_role_to_user",
|
||||
]
|
||||
|
||||
|
||||
@@ -155,6 +157,12 @@ class AccessLevel:
|
||||
NO_ACCESS = None
|
||||
|
||||
|
||||
ACCESS_LEVEL_TO_LIBRARY_ROLE = {
|
||||
AccessLevel.ADMIN_LEVEL: "library_admin",
|
||||
AccessLevel.AUTHOR_LEVEL: "library_author",
|
||||
}
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ContentLibraryPermissionEntry:
|
||||
"""
|
||||
@@ -518,6 +526,30 @@ def set_library_user_permissions(library_key: LibraryLocatorV2, user: UserType,
|
||||
)
|
||||
|
||||
|
||||
def assign_library_role_to_user(library_key: LibraryLocatorV2, user: UserType, access_level: str):
|
||||
"""Grant a role to the specified user for this library.
|
||||
|
||||
Args:
|
||||
library_key (LibraryLocatorV2): The key of the content library.
|
||||
user (UserType): The user to whom the role will be granted.
|
||||
access_level (str | None): The access level to be granted. This access level maps to a specific role.
|
||||
|
||||
Raises:
|
||||
TypeError: If the user is an instance of AnonymousUser.
|
||||
"""
|
||||
if isinstance(user, AnonymousUser):
|
||||
raise TypeError("Invalid user type")
|
||||
|
||||
role = ACCESS_LEVEL_TO_LIBRARY_ROLE.get(access_level)
|
||||
if role is None:
|
||||
raise ValueError(f"Invalid access level: {access_level}")
|
||||
|
||||
if assign_role_to_user_in_scope(user.username, role, str(library_key)):
|
||||
log.info(f"Assigned role '{role}' to user '{user.username}' for library '{library_key}'")
|
||||
else:
|
||||
log.warning(f"Failed to assign role '{role}' to user '{user.username}' for library '{library_key}'")
|
||||
|
||||
|
||||
def set_library_group_permissions(library_key: LibraryLocatorV2, group, access_level: str):
|
||||
"""
|
||||
Change the specified group's level of access to this library.
|
||||
|
||||
@@ -253,6 +253,12 @@ class LibraryRootView(GenericAPIView):
|
||||
result = api.create_library(org=org, **data)
|
||||
# Grant the current user admin permissions on the library:
|
||||
api.set_library_user_permissions(result.key, request.user, api.AccessLevel.ADMIN_LEVEL)
|
||||
|
||||
# Grant the current user the library admin role for this library.
|
||||
# Other role assignments are handled by openedx-authz and the Console MFE.
|
||||
# This ensures the creator has access to new libraries. From the library views,
|
||||
# users can then manage roles for others.
|
||||
api.assign_library_role_to_user(result.key, request.user, api.AccessLevel.ADMIN_LEVEL)
|
||||
except api.LibraryAlreadyExists:
|
||||
raise ValidationError(detail={"slug": "A library with that ID already exists."}) # lint-amnesty, pylint: disable=raise-missing-from
|
||||
|
||||
|
||||
@@ -28,8 +28,10 @@ from openedx_events.content_authoring.signals import (
|
||||
LIBRARY_COLLECTION_UPDATED,
|
||||
LIBRARY_CONTAINER_UPDATED,
|
||||
)
|
||||
from openedx_authz.api.users import get_user_role_assignments_in_scope
|
||||
from openedx_learning.api import authoring as authoring_api
|
||||
|
||||
from common.djangoapps.student.tests.factories import UserFactory
|
||||
from .. import api
|
||||
from ..models import ContentLibrary
|
||||
from .base import ContentLibrariesRestApiTest
|
||||
@@ -1479,3 +1481,126 @@ class ContentLibraryExportTest(ContentLibrariesRestApiTest):
|
||||
assert status is not None
|
||||
assert status['state'] == UserTaskStatus.FAILED
|
||||
assert status['file'] is None
|
||||
|
||||
|
||||
class ContentLibraryAuthZRoleAssignmentTest(ContentLibrariesRestApiTest):
|
||||
"""
|
||||
Tests for Content Library role assignment via the AuthZ Authorization Framework.
|
||||
|
||||
These tests verify that library roles are correctly assigned to users through
|
||||
the openedx-authz (AuthZ) Authorization Framework when libraries are created or when
|
||||
explicit role assignments are made.
|
||||
|
||||
See: https://github.com/openedx/openedx-authz/
|
||||
"""
|
||||
|
||||
def setUp(self) -> None:
|
||||
super().setUp()
|
||||
|
||||
# Create Content Libraries
|
||||
self._create_library("test-lib-role-1", "Test Library Role 1")
|
||||
|
||||
# Fetch the created ContentLibrary objects so we can access their learning_package.id
|
||||
self.lib1 = ContentLibrary.objects.get(slug="test-lib-role-1")
|
||||
|
||||
def test_assign_library_admin_role_to_user_via_authz(self) -> None:
|
||||
"""
|
||||
Test assigning a library admin role to a user via the AuthZ Authorization Framework.
|
||||
|
||||
This test verifies that the openedx-authz Authorization Framework correctly
|
||||
assigns the library_admin role to a user when explicitly called.
|
||||
"""
|
||||
api.assign_library_role_to_user(self.lib1.library_key, self.user, api.AccessLevel.ADMIN_LEVEL)
|
||||
|
||||
roles = get_user_role_assignments_in_scope(self.user.username, str(self.lib1.library_key))
|
||||
assert len(roles) == 1
|
||||
assert "library_admin" in repr(roles[0].roles[0])
|
||||
|
||||
def test_assign_library_author_role_to_user_via_authz(self) -> None:
|
||||
"""
|
||||
Test assigning a library author role to a user via the AuthZ Authorization Framework.
|
||||
|
||||
This test verifies that the openedx-authz Authorization Framework correctly
|
||||
assigns the library_author role to a user when explicitly called.
|
||||
"""
|
||||
# Create a new user to avoid conflicts with roles assigned during library creation
|
||||
author_user = UserFactory.create(username="Author", email="author@example.com")
|
||||
|
||||
api.assign_library_role_to_user(self.lib1.library_key, author_user, api.AccessLevel.AUTHOR_LEVEL)
|
||||
|
||||
roles = get_user_role_assignments_in_scope(author_user.username, str(self.lib1.library_key))
|
||||
assert len(roles) == 1
|
||||
assert "library_author" in repr(roles[0].roles[0])
|
||||
|
||||
@mock.patch("openedx.core.djangoapps.content_libraries.api.libraries.assign_role_to_user_in_scope")
|
||||
def test_library_creation_assigns_admin_role_via_authz(
|
||||
self,
|
||||
mock_assign_role
|
||||
) -> None:
|
||||
"""
|
||||
Test that creating a library via REST API assigns admin role via AuthZ.
|
||||
|
||||
This test verifies that when a library is created via the REST API,
|
||||
the creator is automatically assigned the library_admin role through
|
||||
the openedx-authz Authorization Framework.
|
||||
"""
|
||||
mock_assign_role.return_value = True
|
||||
|
||||
# Create a new library (this should trigger role assignment in the REST API)
|
||||
self._create_library("test-lib-role-2", "Test Library Role 2")
|
||||
|
||||
# Verify that assign_role_to_user_in_scope was called
|
||||
mock_assign_role.assert_called_once()
|
||||
call_args = mock_assign_role.call_args
|
||||
assert call_args[0][0] == self.user.username # username
|
||||
assert call_args[0][1] == "library_admin" # role
|
||||
assert "test-lib-role-2" in call_args[0][2] # library_key (contains slug)
|
||||
|
||||
@mock.patch("openedx.core.djangoapps.content_libraries.api.libraries.assign_role_to_user_in_scope")
|
||||
def test_library_creation_handles_authz_failure_gracefully(
|
||||
self,
|
||||
mock_assign_role
|
||||
) -> None:
|
||||
"""
|
||||
Test that library creation succeeds even if AuthZ role assignment fails.
|
||||
|
||||
This test verifies that if the openedx-authz Authorization Framework fails to assign
|
||||
a role (returns False), the library creation still succeeds. This ensures that
|
||||
the system degrades gracefully and doesn't break library creation if there are
|
||||
issues with the Authorization Framework.
|
||||
"""
|
||||
# Simulate openedx-authz failing to assign the role
|
||||
mock_assign_role.return_value = False
|
||||
|
||||
# Library creation should still succeed
|
||||
result = self._create_library("test-lib-role-3", "Test Library Role 3")
|
||||
assert result is not None
|
||||
assert result["slug"] == "test-lib-role-3"
|
||||
|
||||
# Verify that the library was created successfully
|
||||
lib3 = ContentLibrary.objects.get(slug="test-lib-role-3")
|
||||
assert lib3 is not None
|
||||
assert lib3.slug == "test-lib-role-3"
|
||||
|
||||
@mock.patch("openedx.core.djangoapps.content_libraries.api.libraries.assign_role_to_user_in_scope")
|
||||
def test_library_creation_handles_authz_exception(
|
||||
self,
|
||||
mock_assign_role
|
||||
) -> None:
|
||||
"""
|
||||
Test that library creation succeeds even if AuthZ raises an exception.
|
||||
|
||||
This test verifies that if the openedx-authz Authorization Framework raises an
|
||||
exception during role assignment, the library creation still succeeds. This ensures
|
||||
robust error handling when the Authorization Framework is unavailable or misconfigured.
|
||||
"""
|
||||
# Simulate openedx-authz raising an exception for unknown issues
|
||||
mock_assign_role.side_effect = Exception("AuthZ unavailable")
|
||||
|
||||
# Library creation should still succeed (the exception should be caught/handled)
|
||||
# Note: Currently, the code doesn't catch this exception, so we expect it to propagate.
|
||||
# This test documents the current behavior and can be updated if error handling is added.
|
||||
with self.assertRaises(Exception) as context:
|
||||
self._create_library("test-lib-role-4", "Test Library Role 4")
|
||||
|
||||
assert "AuthZ unavailable" in str(context.exception)
|
||||
|
||||
@@ -22,3 +22,10 @@
|
||||
# elastic search changelog: https://www.elastic.co/guide/en/enterprise-search/master/release-notes-7.14.0.html
|
||||
# See https://github.com/openedx/edx-platform/issues/35126 for more info
|
||||
elasticsearch<7.14.0
|
||||
|
||||
# pip 25.3 is incompatible with pip-tools hence causing failures during the build process
|
||||
# Make upgrade command and all requirements upgrade jobs are broken due to this.
|
||||
# See issue https://github.com/openedx/public-engineering/issues/440 for details regarding the ongoing fix.
|
||||
# The constraint can be removed once a release (pip-tools > 7.5.1) is available with support for pip 25.3
|
||||
# Issue to track this dependency and unpin later on: https://github.com/openedx/edx-lint/issues/503
|
||||
pip<25.3
|
||||
|
||||
@@ -40,6 +40,7 @@ attrs==25.4.0
|
||||
# edx-ace
|
||||
# jsonschema
|
||||
# lti-consumer-xblock
|
||||
# openedx-authz
|
||||
# openedx-events
|
||||
# openedx-learning
|
||||
# referencing
|
||||
@@ -81,6 +82,8 @@ botocore==1.40.57
|
||||
# boto3
|
||||
# s3transfer
|
||||
# snowflake-connector-python
|
||||
bracex==2.6
|
||||
# via wcmatch
|
||||
bridgekeeper==0.9
|
||||
# via -r requirements/edx/kernel.in
|
||||
cachecontrol==0.14.3
|
||||
@@ -91,6 +94,8 @@ cachetools==6.2.1
|
||||
# google-auth
|
||||
camel-converter[pydantic]==5.0.0
|
||||
# via meilisearch
|
||||
casbin-django-orm-adapter==1.7.0
|
||||
# via openedx-authz
|
||||
celery==5.5.3
|
||||
# via
|
||||
# -c requirements/constraints.txt
|
||||
@@ -169,6 +174,7 @@ django==5.2.7
|
||||
# via
|
||||
# -c requirements/constraints.txt
|
||||
# -r requirements/edx/kernel.in
|
||||
# casbin-django-orm-adapter
|
||||
# django-appconf
|
||||
# django-autocomplete-light
|
||||
# django-celery-results
|
||||
@@ -228,6 +234,7 @@ django==5.2.7
|
||||
# help-tokens
|
||||
# jsonfield
|
||||
# lti-consumer-xblock
|
||||
# openedx-authz
|
||||
# openedx-django-pyfs
|
||||
# openedx-django-wiki
|
||||
# openedx-events
|
||||
@@ -388,6 +395,7 @@ djangorestframework==3.16.1
|
||||
# edx-organizations
|
||||
# edx-proctoring
|
||||
# edx-submissions
|
||||
# openedx-authz
|
||||
# openedx-forum
|
||||
# openedx-learning
|
||||
# ora2
|
||||
@@ -412,6 +420,7 @@ edx-api-doc-tools==2.1.0
|
||||
# via
|
||||
# -r requirements/edx/kernel.in
|
||||
# edx-name-affirmation
|
||||
# openedx-authz
|
||||
edx-auth-backends==4.6.2
|
||||
# via -r requirements/edx/kernel.in
|
||||
edx-bulk-grades==1.2.0
|
||||
@@ -470,6 +479,7 @@ edx-drf-extensions==10.6.0
|
||||
# edx-when
|
||||
# edxval
|
||||
# enterprise-integrated-channels
|
||||
# openedx-authz
|
||||
# openedx-learning
|
||||
edx-enterprise==6.5.1
|
||||
# via
|
||||
@@ -502,6 +512,7 @@ edx-opaque-keys[django]==3.0.0
|
||||
# edx-when
|
||||
# enterprise-integrated-channels
|
||||
# lti-consumer-xblock
|
||||
# openedx-authz
|
||||
# openedx-events
|
||||
# openedx-filters
|
||||
# ora2
|
||||
@@ -812,7 +823,10 @@ openedx-atlas==0.7.0
|
||||
# via
|
||||
# -r requirements/edx/kernel.in
|
||||
# enterprise-integrated-channels
|
||||
# openedx-authz
|
||||
# openedx-forum
|
||||
openedx-authz==0.11.1
|
||||
# via -r requirements/edx/kernel.in
|
||||
openedx-calc==4.0.2
|
||||
# via -r requirements/edx/kernel.in
|
||||
openedx-django-pyfs==3.8.0
|
||||
@@ -909,6 +923,10 @@ pyasn1==0.6.1
|
||||
# rsa
|
||||
pyasn1-modules==0.4.2
|
||||
# via google-auth
|
||||
pycasbin==2.4.0
|
||||
# via
|
||||
# casbin-django-orm-adapter
|
||||
# openedx-authz
|
||||
pycountry==24.6.1
|
||||
# via -r requirements/edx/kernel.in
|
||||
pycparser==2.23
|
||||
@@ -1085,6 +1103,8 @@ semantic-version==2.10.0
|
||||
# via edx-drf-extensions
|
||||
shapely==2.1.2
|
||||
# via -r requirements/edx/kernel.in
|
||||
simpleeval==1.0.3
|
||||
# via pycasbin
|
||||
simplejson==3.20.2
|
||||
# via
|
||||
# -r requirements/edx/kernel.in
|
||||
@@ -1216,6 +1236,8 @@ voluptuous==0.15.2
|
||||
# via ora2
|
||||
walrus==0.9.5
|
||||
# via edx-event-bus-redis
|
||||
wcmatch==10.1
|
||||
# via pycasbin
|
||||
wcwidth==0.2.14
|
||||
# via prompt-toolkit
|
||||
web-fragments==3.1.0
|
||||
|
||||
@@ -89,6 +89,7 @@ attrs==25.4.0
|
||||
# edx-ace
|
||||
# jsonschema
|
||||
# lti-consumer-xblock
|
||||
# openedx-authz
|
||||
# openedx-events
|
||||
# openedx-learning
|
||||
# referencing
|
||||
@@ -151,6 +152,11 @@ botocore==1.40.57
|
||||
# boto3
|
||||
# s3transfer
|
||||
# snowflake-connector-python
|
||||
bracex==2.6
|
||||
# via
|
||||
# -r requirements/edx/doc.txt
|
||||
# -r requirements/edx/testing.txt
|
||||
# wcmatch
|
||||
bridgekeeper==0.9
|
||||
# via
|
||||
# -r requirements/edx/doc.txt
|
||||
@@ -176,6 +182,11 @@ camel-converter[pydantic]==5.0.0
|
||||
# -r requirements/edx/doc.txt
|
||||
# -r requirements/edx/testing.txt
|
||||
# meilisearch
|
||||
casbin-django-orm-adapter==1.7.0
|
||||
# via
|
||||
# -r requirements/edx/doc.txt
|
||||
# -r requirements/edx/testing.txt
|
||||
# openedx-authz
|
||||
celery==5.5.3
|
||||
# via
|
||||
# -c requirements/constraints.txt
|
||||
@@ -333,6 +344,7 @@ django==5.2.7
|
||||
# -c requirements/constraints.txt
|
||||
# -r requirements/edx/doc.txt
|
||||
# -r requirements/edx/testing.txt
|
||||
# casbin-django-orm-adapter
|
||||
# django-appconf
|
||||
# django-autocomplete-light
|
||||
# django-celery-results
|
||||
@@ -395,6 +407,7 @@ django==5.2.7
|
||||
# help-tokens
|
||||
# jsonfield
|
||||
# lti-consumer-xblock
|
||||
# openedx-authz
|
||||
# openedx-django-pyfs
|
||||
# openedx-django-wiki
|
||||
# openedx-events
|
||||
@@ -621,6 +634,7 @@ djangorestframework==3.16.1
|
||||
# edx-organizations
|
||||
# edx-proctoring
|
||||
# edx-submissions
|
||||
# openedx-authz
|
||||
# openedx-forum
|
||||
# openedx-learning
|
||||
# ora2
|
||||
@@ -671,6 +685,7 @@ edx-api-doc-tools==2.1.0
|
||||
# -r requirements/edx/doc.txt
|
||||
# -r requirements/edx/testing.txt
|
||||
# edx-name-affirmation
|
||||
# openedx-authz
|
||||
edx-auth-backends==4.6.2
|
||||
# via
|
||||
# -r requirements/edx/doc.txt
|
||||
@@ -743,6 +758,7 @@ edx-drf-extensions==10.6.0
|
||||
# edx-when
|
||||
# edxval
|
||||
# enterprise-integrated-channels
|
||||
# openedx-authz
|
||||
# openedx-learning
|
||||
edx-enterprise==6.5.1
|
||||
# via
|
||||
@@ -788,6 +804,7 @@ edx-opaque-keys[django]==3.0.0
|
||||
# edx-when
|
||||
# enterprise-integrated-channels
|
||||
# lti-consumer-xblock
|
||||
# openedx-authz
|
||||
# openedx-events
|
||||
# openedx-filters
|
||||
# ora2
|
||||
@@ -1352,7 +1369,12 @@ openedx-atlas==0.7.0
|
||||
# -r requirements/edx/doc.txt
|
||||
# -r requirements/edx/testing.txt
|
||||
# enterprise-integrated-channels
|
||||
# openedx-authz
|
||||
# openedx-forum
|
||||
openedx-authz==0.11.1
|
||||
# via
|
||||
# -r requirements/edx/doc.txt
|
||||
# -r requirements/edx/testing.txt
|
||||
openedx-calc==4.0.2
|
||||
# via
|
||||
# -r requirements/edx/doc.txt
|
||||
@@ -1534,6 +1556,12 @@ pyasn1-modules==0.4.2
|
||||
# -r requirements/edx/doc.txt
|
||||
# -r requirements/edx/testing.txt
|
||||
# google-auth
|
||||
pycasbin==2.4.0
|
||||
# via
|
||||
# -r requirements/edx/doc.txt
|
||||
# -r requirements/edx/testing.txt
|
||||
# casbin-django-orm-adapter
|
||||
# openedx-authz
|
||||
pycodestyle==2.8.0
|
||||
# via
|
||||
# -c requirements/constraints.txt
|
||||
@@ -1885,6 +1913,11 @@ shapely==2.1.2
|
||||
# via
|
||||
# -r requirements/edx/doc.txt
|
||||
# -r requirements/edx/testing.txt
|
||||
simpleeval==1.0.3
|
||||
# via
|
||||
# -r requirements/edx/doc.txt
|
||||
# -r requirements/edx/testing.txt
|
||||
# pycasbin
|
||||
simplejson==3.20.2
|
||||
# via
|
||||
# -r requirements/edx/doc.txt
|
||||
@@ -2190,6 +2223,11 @@ walrus==0.9.5
|
||||
# edx-event-bus-redis
|
||||
watchdog==6.0.0
|
||||
# via -r requirements/edx/development.in
|
||||
wcmatch==10.1
|
||||
# via
|
||||
# -r requirements/edx/doc.txt
|
||||
# -r requirements/edx/testing.txt
|
||||
# pycasbin
|
||||
wcwidth==0.2.14
|
||||
# via
|
||||
# -r requirements/edx/doc.txt
|
||||
|
||||
@@ -64,6 +64,7 @@ attrs==25.4.0
|
||||
# edx-ace
|
||||
# jsonschema
|
||||
# lti-consumer-xblock
|
||||
# openedx-authz
|
||||
# openedx-events
|
||||
# openedx-learning
|
||||
# referencing
|
||||
@@ -116,6 +117,10 @@ botocore==1.40.57
|
||||
# boto3
|
||||
# s3transfer
|
||||
# snowflake-connector-python
|
||||
bracex==2.6
|
||||
# via
|
||||
# -r requirements/edx/base.txt
|
||||
# wcmatch
|
||||
bridgekeeper==0.9
|
||||
# via -r requirements/edx/base.txt
|
||||
cachecontrol==0.14.3
|
||||
@@ -131,6 +136,10 @@ camel-converter[pydantic]==5.0.0
|
||||
# via
|
||||
# -r requirements/edx/base.txt
|
||||
# meilisearch
|
||||
casbin-django-orm-adapter==1.7.0
|
||||
# via
|
||||
# -r requirements/edx/base.txt
|
||||
# openedx-authz
|
||||
celery==5.5.3
|
||||
# via
|
||||
# -c requirements/constraints.txt
|
||||
@@ -227,6 +236,7 @@ django==5.2.7
|
||||
# via
|
||||
# -c requirements/constraints.txt
|
||||
# -r requirements/edx/base.txt
|
||||
# casbin-django-orm-adapter
|
||||
# django-appconf
|
||||
# django-autocomplete-light
|
||||
# django-celery-results
|
||||
@@ -286,6 +296,7 @@ django==5.2.7
|
||||
# help-tokens
|
||||
# jsonfield
|
||||
# lti-consumer-xblock
|
||||
# openedx-authz
|
||||
# openedx-django-pyfs
|
||||
# openedx-django-wiki
|
||||
# openedx-events
|
||||
@@ -460,6 +471,7 @@ djangorestframework==3.16.1
|
||||
# edx-organizations
|
||||
# edx-proctoring
|
||||
# edx-submissions
|
||||
# openedx-authz
|
||||
# openedx-forum
|
||||
# openedx-learning
|
||||
# ora2
|
||||
@@ -496,6 +508,7 @@ edx-api-doc-tools==2.1.0
|
||||
# via
|
||||
# -r requirements/edx/base.txt
|
||||
# edx-name-affirmation
|
||||
# openedx-authz
|
||||
edx-auth-backends==4.6.2
|
||||
# via -r requirements/edx/base.txt
|
||||
edx-bulk-grades==1.2.0
|
||||
@@ -554,6 +567,7 @@ edx-drf-extensions==10.6.0
|
||||
# edx-when
|
||||
# edxval
|
||||
# enterprise-integrated-channels
|
||||
# openedx-authz
|
||||
# openedx-learning
|
||||
edx-enterprise==6.5.1
|
||||
# via
|
||||
@@ -586,6 +600,7 @@ edx-opaque-keys[django]==3.0.0
|
||||
# edx-when
|
||||
# enterprise-integrated-channels
|
||||
# lti-consumer-xblock
|
||||
# openedx-authz
|
||||
# openedx-events
|
||||
# openedx-filters
|
||||
# ora2
|
||||
@@ -985,7 +1000,10 @@ openedx-atlas==0.7.0
|
||||
# via
|
||||
# -r requirements/edx/base.txt
|
||||
# enterprise-integrated-channels
|
||||
# openedx-authz
|
||||
# openedx-forum
|
||||
openedx-authz==0.11.1
|
||||
# via -r requirements/edx/base.txt
|
||||
openedx-calc==4.0.2
|
||||
# via -r requirements/edx/base.txt
|
||||
openedx-django-pyfs==3.8.0
|
||||
@@ -1105,6 +1123,11 @@ pyasn1-modules==0.4.2
|
||||
# via
|
||||
# -r requirements/edx/base.txt
|
||||
# google-auth
|
||||
pycasbin==2.4.0
|
||||
# via
|
||||
# -r requirements/edx/base.txt
|
||||
# casbin-django-orm-adapter
|
||||
# openedx-authz
|
||||
pycountry==24.6.1
|
||||
# via -r requirements/edx/base.txt
|
||||
pycparser==2.23
|
||||
@@ -1329,6 +1352,10 @@ semantic-version==2.10.0
|
||||
# edx-drf-extensions
|
||||
shapely==2.1.2
|
||||
# via -r requirements/edx/base.txt
|
||||
simpleeval==1.0.3
|
||||
# via
|
||||
# -r requirements/edx/base.txt
|
||||
# pycasbin
|
||||
simplejson==3.20.2
|
||||
# via
|
||||
# -r requirements/edx/base.txt
|
||||
@@ -1537,6 +1564,10 @@ walrus==0.9.5
|
||||
# via
|
||||
# -r requirements/edx/base.txt
|
||||
# edx-event-bus-redis
|
||||
wcmatch==10.1
|
||||
# via
|
||||
# -r requirements/edx/base.txt
|
||||
# pycasbin
|
||||
wcwidth==0.2.14
|
||||
# via
|
||||
# -r requirements/edx/base.txt
|
||||
|
||||
@@ -161,3 +161,4 @@ wrapt # Better functools.wrapped. TODO: functools
|
||||
XBlock[django] # Courseware component architecture
|
||||
xss-utils # https://github.com/openedx/edx-platform/pull/20633 Fix XSS via Translations
|
||||
unicodeit # Converts mathjax equation to plain text by using unicode symbols
|
||||
openedx-authz # Authorization Framework for the Open edX Ecosystem
|
||||
|
||||
@@ -63,6 +63,7 @@ attrs==25.4.0
|
||||
# edx-ace
|
||||
# jsonschema
|
||||
# lti-consumer-xblock
|
||||
# openedx-authz
|
||||
# openedx-events
|
||||
# openedx-learning
|
||||
# referencing
|
||||
@@ -113,6 +114,10 @@ botocore==1.40.57
|
||||
# boto3
|
||||
# s3transfer
|
||||
# snowflake-connector-python
|
||||
bracex==2.6
|
||||
# via
|
||||
# -r requirements/edx/base.txt
|
||||
# wcmatch
|
||||
bridgekeeper==0.9
|
||||
# via -r requirements/edx/base.txt
|
||||
cachecontrol==0.14.3
|
||||
@@ -129,6 +134,10 @@ camel-converter[pydantic]==5.0.0
|
||||
# via
|
||||
# -r requirements/edx/base.txt
|
||||
# meilisearch
|
||||
casbin-django-orm-adapter==1.7.0
|
||||
# via
|
||||
# -r requirements/edx/base.txt
|
||||
# openedx-authz
|
||||
celery==5.5.3
|
||||
# via
|
||||
# -c requirements/constraints.txt
|
||||
@@ -252,6 +261,7 @@ django==5.2.7
|
||||
# via
|
||||
# -c requirements/constraints.txt
|
||||
# -r requirements/edx/base.txt
|
||||
# casbin-django-orm-adapter
|
||||
# django-appconf
|
||||
# django-autocomplete-light
|
||||
# django-celery-results
|
||||
@@ -311,6 +321,7 @@ django==5.2.7
|
||||
# help-tokens
|
||||
# jsonfield
|
||||
# lti-consumer-xblock
|
||||
# openedx-authz
|
||||
# openedx-django-pyfs
|
||||
# openedx-django-wiki
|
||||
# openedx-events
|
||||
@@ -485,6 +496,7 @@ djangorestframework==3.16.1
|
||||
# edx-organizations
|
||||
# edx-proctoring
|
||||
# edx-submissions
|
||||
# openedx-authz
|
||||
# openedx-forum
|
||||
# openedx-learning
|
||||
# ora2
|
||||
@@ -516,6 +528,7 @@ edx-api-doc-tools==2.1.0
|
||||
# via
|
||||
# -r requirements/edx/base.txt
|
||||
# edx-name-affirmation
|
||||
# openedx-authz
|
||||
edx-auth-backends==4.6.2
|
||||
# via -r requirements/edx/base.txt
|
||||
edx-bulk-grades==1.2.0
|
||||
@@ -574,6 +587,7 @@ edx-drf-extensions==10.6.0
|
||||
# edx-when
|
||||
# edxval
|
||||
# enterprise-integrated-channels
|
||||
# openedx-authz
|
||||
# openedx-learning
|
||||
edx-enterprise==6.5.1
|
||||
# via
|
||||
@@ -608,6 +622,7 @@ edx-opaque-keys[django]==3.0.0
|
||||
# edx-when
|
||||
# enterprise-integrated-channels
|
||||
# lti-consumer-xblock
|
||||
# openedx-authz
|
||||
# openedx-events
|
||||
# openedx-filters
|
||||
# ora2
|
||||
@@ -1029,7 +1044,10 @@ openedx-atlas==0.7.0
|
||||
# via
|
||||
# -r requirements/edx/base.txt
|
||||
# enterprise-integrated-channels
|
||||
# openedx-authz
|
||||
# openedx-forum
|
||||
openedx-authz==0.11.1
|
||||
# via -r requirements/edx/base.txt
|
||||
openedx-calc==4.0.2
|
||||
# via -r requirements/edx/base.txt
|
||||
openedx-django-pyfs==3.8.0
|
||||
@@ -1167,6 +1185,11 @@ pyasn1-modules==0.4.2
|
||||
# via
|
||||
# -r requirements/edx/base.txt
|
||||
# google-auth
|
||||
pycasbin==2.4.0
|
||||
# via
|
||||
# -r requirements/edx/base.txt
|
||||
# casbin-django-orm-adapter
|
||||
# openedx-authz
|
||||
pycodestyle==2.8.0
|
||||
# via
|
||||
# -c requirements/constraints.txt
|
||||
@@ -1437,6 +1460,10 @@ semantic-version==2.10.0
|
||||
# edx-drf-extensions
|
||||
shapely==2.1.2
|
||||
# via -r requirements/edx/base.txt
|
||||
simpleeval==1.0.3
|
||||
# via
|
||||
# -r requirements/edx/base.txt
|
||||
# pycasbin
|
||||
simplejson==3.20.2
|
||||
# via
|
||||
# -r requirements/edx/base.txt
|
||||
@@ -1621,6 +1648,10 @@ walrus==0.9.5
|
||||
# via
|
||||
# -r requirements/edx/base.txt
|
||||
# edx-event-bus-redis
|
||||
wcmatch==10.1
|
||||
# via
|
||||
# -r requirements/edx/base.txt
|
||||
# pycasbin
|
||||
wcwidth==0.2.14
|
||||
# via
|
||||
# -r requirements/edx/base.txt
|
||||
|
||||
@@ -9,6 +9,8 @@ wheel==0.45.1
|
||||
|
||||
# The following packages are considered to be unsafe in a requirements file:
|
||||
pip==25.2
|
||||
# via -r requirements/pip.in
|
||||
# via
|
||||
# -c requirements/common_constraints.txt
|
||||
# -r requirements/pip.in
|
||||
setuptools==80.9.0
|
||||
# via -r requirements/pip.in
|
||||
|
||||
Reference in New Issue
Block a user