feat: Update forum role membership api to DRF ( 11th ) (#35343)

* feat: upgrading simple api to drf compatible.
This commit is contained in:
Awais Qureshi
2025-07-16 16:14:06 -04:00
committed by GitHub
parent be8a307a22
commit 8e94b2cba4
3 changed files with 85 additions and 69 deletions

View File

@@ -81,7 +81,6 @@ from lms.djangoapps.course_home_api.toggles import course_home_mfe_progress_tab_
from lms.djangoapps.courseware.access import has_access
from lms.djangoapps.courseware.courses import get_course_with_access
from lms.djangoapps.courseware.models import StudentModule
from lms.djangoapps.discussion.django_comment_client.utils import has_forum_access
from lms.djangoapps.instructor import enrollment
from lms.djangoapps.instructor.access import ROLES, allow_access, list_with_level, revoke_access, update_forum_role
from lms.djangoapps.instructor.constants import INVOICE_KEY
@@ -115,17 +114,14 @@ from lms.djangoapps.instructor.views.serializer import (
UserSerializer,
UniqueStudentIdentifierSerializer,
ProblemResetSerializer,
RescoreEntranceExamSerializer,
UpdateForumRoleMembershipSerializer,
RescoreEntranceExamSerializer
)
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
from openedx.core.djangoapps.course_groups.cohorts import add_user_to_cohort, is_course_cohorted
from openedx.core.djangoapps.course_groups.models import CourseUserGroup
from openedx.core.djangoapps.django_comment_common.models import (
CourseDiscussionSettings,
FORUM_ROLE_ADMINISTRATOR,
FORUM_ROLE_COMMUNITY_TA,
FORUM_ROLE_GROUP_MODERATOR,
FORUM_ROLE_MODERATOR,
Role,
)
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
@@ -3018,71 +3014,71 @@ class SendEmail(DeveloperErrorViewMixin, APIView):
return JsonResponse(response_payload)
@require_POST
@ensure_csrf_cookie
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
@require_course_permission(permissions.EDIT_FORUM_ROLES)
@require_post_params(
unique_student_identifier="email or username of user to change access",
rolename="the forum role",
action="'allow' or 'revoke'",
)
@common_exceptions_400
def update_forum_role_membership(request, course_id):
@method_decorator(cache_control(no_cache=True, no_store=True, must_revalidate=True), name='dispatch')
class UpdateForumRoleMembership(APIView):
"""
Modify user's forum role.
Modify a user's forum role in a course.
The requesting user must be at least staff.
Staff forum admins can access all roles EXCEPT for FORUM_ROLE_ADMINISTRATOR
which is limited to instructors.
No one can revoke an instructors FORUM_ROLE_ADMINISTRATOR status.
Permissions:
- Must be authenticated.
- Must be instructor or (staff + forum admin).
- Only instructors can grant FORUM_ROLE_ADMINISTRATOR.
Query parameters:
- `email` is the target users email
- `rolename` is one of [FORUM_ROLE_ADMINISTRATOR, FORUM_ROLE_GROUP_MODERATOR,
FORUM_ROLE_MODERATOR, FORUM_ROLE_COMMUNITY_TA]
- `action` is one of ['allow', 'revoke']
"""
course_id = CourseKey.from_string(course_id)
course = get_course_by_id(course_id)
has_instructor_access = has_access(request.user, 'instructor', course)
has_forum_admin = has_forum_access(
request.user, course_id, FORUM_ROLE_ADMINISTRATOR
)
unique_student_identifier = request.POST.get('unique_student_identifier')
rolename = request.POST.get('rolename')
action = request.POST.get('action')
# default roles require either (staff & forum admin) or (instructor)
if not (has_forum_admin or has_instructor_access):
return HttpResponseBadRequest(
"Operation requires staff & forum admin or instructor access"
)
# EXCEPT FORUM_ROLE_ADMINISTRATOR requires (instructor)
if rolename == FORUM_ROLE_ADMINISTRATOR and not has_instructor_access:
return HttpResponseBadRequest("Operation requires instructor access.")
if rolename not in [FORUM_ROLE_ADMINISTRATOR, FORUM_ROLE_MODERATOR, FORUM_ROLE_GROUP_MODERATOR,
FORUM_ROLE_COMMUNITY_TA]:
return HttpResponseBadRequest(strip_tags(
f"Unrecognized rolename '{rolename}'."
))
user = get_student_from_identifier(unique_student_identifier)
if action == 'allow' and not is_user_enrolled_in_course(user, course_id):
CourseEnrollment.enroll(user, course_id)
try:
update_forum_role(course_id, user, rolename, action)
except Role.DoesNotExist:
return HttpResponseBadRequest("Role does not exist.")
response_payload = {
'course_id': str(course_id),
'action': action,
Request (POST body):
{
"unique_student_identifier": "user@example.com",
"rolename": "FORUM_ROLE_MODERATOR",
"action": "allow" or "revoke"
}
return JsonResponse(response_payload)
"""
permission_classes = (
IsAuthenticated,
permissions.InstructorPermission,
permissions.ForumAdminRequiresInstructorAccess
)
permission_name = permissions.EDIT_FORUM_ROLES
serializer_class = UpdateForumRoleMembershipSerializer
@method_decorator(ensure_csrf_cookie)
def post(self, request, course_id):
"""
Handles role modification requests for a forum user.
Query parameters:
- `email` is the target users email
- `rolename` is one of [FORUM_ROLE_ADMINISTRATOR, FORUM_ROLE_GROUP_MODERATOR,
FORUM_ROLE_MODERATOR, FORUM_ROLE_COMMUNITY_TA]
- `action` is one of ['allow', 'revoke']
"""
course_id = CourseKey.from_string(course_id)
serializer_data = UpdateForumRoleMembershipSerializer(data=request.data)
if not serializer_data.is_valid():
return HttpResponseBadRequest(reason=serializer_data.errors)
user = serializer_data.validated_data.get('unique_student_identifier')
if not user:
return JsonResponse({'error': 'User does not exist.'}, status=400)
rolename = serializer_data.data['rolename']
action = serializer_data.data['action']
if action == 'allow' and not is_user_enrolled_in_course(user, course_id):
CourseEnrollment.enroll(user, course_id)
try:
update_forum_role(course_id, user, rolename, action)
except Role.DoesNotExist:
return HttpResponseBadRequest("Role does not exist.")
return Response(
{
"course_id": str(course_id),
"action": action,
},
status=status.HTTP_200_OK,
)
@require_POST

View File

@@ -49,7 +49,7 @@ urlpatterns = [
path('list_background_email_tasks', api.ListBackgroundEmailTasks.as_view(), name='list_background_email_tasks'),
path('list_email_content', api.ListEmailContent.as_view(), name='list_email_content'),
path('list_forum_members', api.ListForumMembers.as_view(), name='list_forum_members'),
path('update_forum_role_membership', api.update_forum_role_membership, name='update_forum_role_membership'),
path('update_forum_role_membership', api.UpdateForumRoleMembership.as_view(), name='update_forum_role_membership'),
path('change_due_date', api.ChangeDueDate.as_view(), name='change_due_date'),
path('send_email', api.SendEmail.as_view(), name='send_email'),
path('reset_due_date', api.ResetDueDate.as_view(), name='reset_due_date'),

View File

@@ -256,7 +256,27 @@ class StudentAttemptsSerializer(serializers.Serializer):
if value is not None:
return value in ['true', 'True', True]
return False
class UpdateForumRoleMembershipSerializer(AccessSerializer):
"""
Serializer for managing user's forum role.
This serializer extends the AccessSerializer to allow for different action
choices specific to this API. It validates and processes the data required
to modify user access within a system.
Attributes:
unique_student_identifier (str): The email or username of the user whose access is being modified.
rolename (str): The role name to assign to the user.
action (str): The specific action to perform on the user's access, with options 'activate' or 'deactivate'.
"""
rolename = serializers.ChoiceField(
choices=[
FORUM_ROLE_ADMINISTRATOR, FORUM_ROLE_MODERATOR,
FORUM_ROLE_GROUP_MODERATOR, FORUM_ROLE_COMMUNITY_TA
],
help_text="Rolename assign to given user."
)
class SendEmailSerializer(serializers.Serializer):