Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add content tagging application #19

Merged
merged 10 commits into from
May 9, 2024
2 changes: 1 addition & 1 deletion .github/workflows/pylint-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
- module-name: openedx-1
path: "--django-settings-module=lms.envs.test openedx/core/types/ openedx/core/djangoapps/ace_common/ openedx/core/djangoapps/agreements/ openedx/core/djangoapps/api_admin/ openedx/core/djangoapps/auth_exchange/ openedx/core/djangoapps/bookmarks/ openedx/core/djangoapps/cache_toolbox/ openedx/core/djangoapps/catalog/ openedx/core/djangoapps/ccxcon/ openedx/core/djangoapps/commerce/ openedx/core/djangoapps/common_initialization/ openedx/core/djangoapps/common_views/ openedx/core/djangoapps/config_model_utils/ openedx/core/djangoapps/content/ openedx/core/djangoapps/content_libraries/ openedx/core/djangoapps/contentserver/ openedx/core/djangoapps/cookie_metadata/ openedx/core/djangoapps/cors_csrf/ openedx/core/djangoapps/course_apps/ openedx/core/djangoapps/course_date_signals/ openedx/core/djangoapps/course_groups/ openedx/core/djangoapps/courseware_api/ openedx/core/djangoapps/crawlers/ openedx/core/djangoapps/credentials/ openedx/core/djangoapps/credit/ openedx/core/djangoapps/dark_lang/ openedx/core/djangoapps/debug/ openedx/core/djangoapps/demographics/ openedx/core/djangoapps/discussions/ openedx/core/djangoapps/django_comment_common/ openedx/core/djangoapps/embargo/ openedx/core/djangoapps/enrollments/ openedx/core/djangoapps/external_user_ids/ openedx/core/djangoapps/zendesk_proxy/ openedx/core/djangolib/ openedx/core/lib/ openedx/core/tests/ openedx/core/djangoapps/course_live/"
- module-name: openedx-2
path: "--django-settings-module=lms.envs.test openedx/core/djangoapps/geoinfo/ openedx/core/djangoapps/header_control/ openedx/core/djangoapps/heartbeat/ openedx/core/djangoapps/lang_pref/ openedx/core/djangoapps/models/ openedx/core/djangoapps/monkey_patch/ openedx/core/djangoapps/oauth_dispatch/ openedx/core/djangoapps/olx_rest_api/ openedx/core/djangoapps/password_policy/ openedx/core/djangoapps/plugin_api/ openedx/core/djangoapps/plugins/ openedx/core/djangoapps/profile_images/ openedx/core/djangoapps/programs/ openedx/core/djangoapps/safe_sessions/ openedx/core/djangoapps/schedules/ openedx/core/djangoapps/service_status/ openedx/core/djangoapps/session_inactivity_timeout/ openedx/core/djangoapps/signals/ openedx/core/djangoapps/site_configuration/ openedx/core/djangoapps/system_wide_roles/ openedx/core/djangoapps/theming/ openedx/core/djangoapps/user_api/ openedx/core/djangoapps/user_authn/ openedx/core/djangoapps/util/ openedx/core/djangoapps/verified_track_content/ openedx/core/djangoapps/video_config/ openedx/core/djangoapps/video_pipeline/ openedx/core/djangoapps/waffle_utils/ openedx/core/djangoapps/xblock/ openedx/core/djangoapps/xmodule_django/ openedx/core/tests/ openedx/features/ openedx/testing/ openedx/tests/ openedx/core/djangoapps/learner_pathway/"
path: "--django-settings-module=lms.envs.test openedx/core/djangoapps/geoinfo/ openedx/core/djangoapps/header_control/ openedx/core/djangoapps/heartbeat/ openedx/core/djangoapps/lang_pref/ openedx/core/djangoapps/models/ openedx/core/djangoapps/monkey_patch/ openedx/core/djangoapps/oauth_dispatch/ openedx/core/djangoapps/olx_rest_api/ openedx/core/djangoapps/password_policy/ openedx/core/djangoapps/plugin_api/ openedx/core/djangoapps/plugins/ openedx/core/djangoapps/profile_images/ openedx/core/djangoapps/programs/ openedx/core/djangoapps/safe_sessions/ openedx/core/djangoapps/schedules/ openedx/core/djangoapps/service_status/ openedx/core/djangoapps/session_inactivity_timeout/ openedx/core/djangoapps/signals/ openedx/core/djangoapps/site_configuration/ openedx/core/djangoapps/system_wide_roles/ openedx/core/djangoapps/theming/ openedx/core/djangoapps/user_api/ openedx/core/djangoapps/user_authn/ openedx/core/djangoapps/util/ openedx/core/djangoapps/verified_track_content/ openedx/core/djangoapps/video_config/ openedx/core/djangoapps/video_pipeline/ openedx/core/djangoapps/waffle_utils/ openedx/core/djangoapps/xblock/ openedx/core/djangoapps/xmodule_django/ openedx/core/tests/ openedx/features/ openedx/testing/ openedx/tests/ openedx/core/djangoapps/learner_pathway/ openedx/core/djangoapps/content_tagging/"
- module-name: common
path: "--django-settings-module=lms.envs.test common"
- module-name: cms
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/unit-test-shards.json
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@
"openedx-4": {
"settings": "cms.envs.test",
"paths": [
"openedx/core/djangoapps/content_tagging/",
"openedx/core/djangoapps/geoinfo/",
"openedx/core/djangoapps/header_control/",
"openedx/core/djangoapps/heartbeat/",
Expand Down
4 changes: 4 additions & 0 deletions cms/envs/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -1748,6 +1748,10 @@
# API Documentation
'drf_yasg',

# Tagging
'openedx_tagging.core.tagging.apps.TaggingConfig',
'openedx.core.djangoapps.content_tagging',

'openedx.features.course_duration_limits',
'openedx.features.content_type_gating',
'openedx.features.discounts',
Expand Down
5 changes: 5 additions & 0 deletions cms/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -336,3 +336,8 @@
urlpatterns += [
path('api/contentstore/', include('cms.djangoapps.contentstore.rest_api.urls'))
]

# Content tagging
urlpatterns += [
path('api/content_tagging/', include(('openedx.core.djangoapps.content_tagging.urls', 'content_tagging'))),
]
38 changes: 37 additions & 1 deletion common/djangoapps/student/role_helpers.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
"""
Helpers for student roles
"""
from typing import List

from django.contrib.auth import get_user_model

from openedx.core.djangoapps.django_comment_common.models import (
FORUM_ROLE_ADMINISTRATOR,
Expand All @@ -12,15 +14,20 @@
)
from openedx.core.lib.cache_utils import request_cached
from common.djangoapps.student.roles import (
CourseAccessRole,
CourseBetaTesterRole,
CourseInstructorRole,
CourseStaffRole,
GlobalStaff,
OrgInstructorRole,
OrgStaffRole
OrgStaffRole,
RoleCache,
)


User = get_user_model()


@request_cached()
def has_staff_roles(user, course_key):
"""
Expand All @@ -40,3 +47,32 @@ def has_staff_roles(user, course_key):
is_org_instructor, is_global_staff, has_forum_role]):
return True
return False


@request_cached()
def get_role_cache(user: User) -> RoleCache:
"""
Returns a populated RoleCache for the given user.

The returned RoleCache is also cached on the provided `user` to improve performance on future roles checks.

:param user: User
:return: All roles for all courses that this user has access to.
"""
# pylint: disable=protected-access
if not hasattr(user, '_roles'):
user._roles = RoleCache(user)
return user._roles


@request_cached()
def get_course_roles(user: User) -> List[CourseAccessRole]:
"""
Returns a list of all course-level roles that this user has.

:param user: User
:return: All roles for all courses that this user has access to.
"""
# pylint: disable=protected-access
role_cache = get_role_cache(user)
return list(role_cache._roles)
16 changes: 15 additions & 1 deletion common/djangoapps/student/roles.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
# A list of registered access roles.
REGISTERED_ACCESS_ROLES = {}

# A mapping of roles to the roles that they inherit permissions from.
ACCESS_ROLES_INHERITANCE = {}


def register_access_role(cls):
"""
Expand All @@ -33,6 +36,10 @@ def register_access_role(cls):
REGISTERED_ACCESS_ROLES[role_name] = cls
except AttributeError:
log.exception("Unable to register Access Role with attribute 'ROLE'.")

if base_role := getattr(cls, "BASE_ROLE", None):
ACCESS_ROLES_INHERITANCE.setdefault(base_role, set()).add(cls.ROLE)

return cls


Expand Down Expand Up @@ -69,12 +76,19 @@ def __init__(self, user):
CourseAccessRole.objects.filter(user=user).all()
)

@staticmethod
def get_roles(role):
"""
Return the roles that should have the same permissions as the specified role.
"""
return ACCESS_ROLES_INHERITANCE.get(role, set()) | {role}

def has_role(self, role, course_id, org):
"""
Return whether this RoleCache contains a role with the specified role, course_id, and org
"""
return any(
access_role.role == role and
access_role.role in self.get_roles(role) and
access_role.course_id == course_id and
access_role.org == org
for access_role in self._roles
Expand Down
4 changes: 4 additions & 0 deletions lms/envs/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -3193,6 +3193,10 @@ def _make_locale_paths(settings): # pylint: disable=missing-function-docstring
# Course Goals
'lms.djangoapps.course_goals.apps.CourseGoalsConfig',

# Tagging
'openedx_tagging.core.tagging.apps.TaggingConfig',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didnt now where is tagging, now I now is part of openedx-learning wtf

'openedx.core.djangoapps.content_tagging',

# Features
'openedx.features.calendar_sync',
'openedx.features.course_bookmarks',
Expand Down
23 changes: 20 additions & 3 deletions openedx/core/djangoapps/content_libraries/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,15 @@
from xblock.exceptions import XBlockNotFoundError
from edx_rest_api_client.client import OAuthAPIClient
from openedx.core.djangoapps.content_libraries import permissions
from openedx.core.djangoapps.content_libraries.constants import DRAFT_NAME, COMPLEX
# pylint: disable=unused-import
from openedx.core.djangoapps.content_libraries.constants import (
ALL_RIGHTS_RESERVED,
CC_4_BY,
COMPLEX,
DRAFT_NAME,
PROBLEM,
VIDEO,
)
from openedx.core.djangoapps.content_libraries.library_bundle import LibraryBundle
from openedx.core.djangoapps.content_libraries.libraries_index import ContentLibraryIndexer, LibraryBlockIndexer
from openedx.core.djangoapps.content_libraries.models import (
Expand Down Expand Up @@ -406,8 +414,15 @@ def get_library(library_key):


def create_library(
collection_uuid, library_type, org, slug, title, description, allow_public_learning, allow_public_read,
library_license,
collection_uuid,
org,
slug,
title,
description="",
allow_public_learning=False,
allow_public_read=False,
library_license=ALL_RIGHTS_RESERVED,
library_type=COMPLEX,
):
"""
Create a new content library.
Expand All @@ -424,6 +439,8 @@ def create_library(

allow_public_read: Allow anyone to view blocks (including source) in Studio?

library_type: Deprecated parameter, not really used. Set to COMPLEX.

Returns a ContentLibraryMetadata instance.
"""
assert isinstance(collection_uuid, UUID)
Expand Down
Empty file.
6 changes: 6 additions & 0 deletions openedx/core/djangoapps/content_tagging/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
""" Tagging app admin """
from django.contrib import admin

from .models import TaxonomyOrg

admin.site.register(TaxonomyOrg)
Loading
Loading