Skip to content

Commit

Permalink
feat: migrate native APIs from forum V2
Browse files Browse the repository at this point in the history
- migrate following native APIs i.e. mark_thread_as_read, create_subscription,
delete_subscription, update_thread_votes, update_comment_votes, delete_thread_vote,
delete_comment_vote, get_user_threads, retire_user, update_username
- refactor some code
  • Loading branch information
Muhammad Faraz Maqsood committed Oct 2, 2024
1 parent 634af22 commit f6974be
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 106 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from opaque_keys.edx.keys import CourseKey

from .utils import CommentClientRequestError, extract, perform_request
from .utils import CommentClientRequestError, extract, perform_request, get_course_key
from forum import api as forum_api
from lms.djangoapps.discussion.toggles import is_forum_v2_enabled

Expand Down Expand Up @@ -74,10 +74,7 @@ def retrieve(self, *args, **kwargs):

def _retrieve(self, *args, **kwargs):
response = None
if course_id := self.attributes.get("course_id"):
if not isinstance(course_id, CourseKey):
course_id = CourseKey.from_string(course_id)
if is_forum_v2_enabled(course_id):
if is_forum_v2_enabled(get_course_key(self.attributes.get("course_id"))):
if self.type == "comment":
response = forum_api.get_parent_comment(self.attributes["id"])
if response is None:
Expand Down Expand Up @@ -173,10 +170,7 @@ def save(self, params=None):

def delete(self):
response = None
if course_id := self.attributes.get("course_id"):
if not isinstance(course_id, CourseKey):
course_id = CourseKey.from_string(course_id)
if is_forum_v2_enabled(course_id):
if is_forum_v2_enabled(get_course_key(self.attributes.get("course_id"))):
if self.type == "comment":
response = forum_api.delete_comment(self.attributes["id"])
if response is None:
Expand Down Expand Up @@ -218,10 +212,7 @@ def handle_update(self, params=None):
if params:
request_params.update(params)
response = None
if course_id := self.attributes.get("course_id"):
if not isinstance(course_id, CourseKey):
course_id = CourseKey.from_string(course_id)
if is_forum_v2_enabled(course_id):
if is_forum_v2_enabled(get_course_key(self.attributes.get("course_id"))):
if self.type == "comment":
response = self.handle_update_comment(request_params)
if response is None:
Expand Down Expand Up @@ -274,10 +265,7 @@ def perform_http_post_request(self):

def handle_create(self):
response = None
if course_id := self.attributes.get("course_id"):
if not isinstance(course_id, CourseKey):
course_id = CourseKey.from_string(course_id)
if is_forum_v2_enabled(course_id):
if is_forum_v2_enabled(get_course_key(self.attributes.get("course_id"))):
if self.type == "comment":
response = self.handle_create_comment()
if response is None:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,7 @@ def fetch(cls, thread_id, course_id, query_params):
utils.strip_blank(utils.strip_none(query_params))
)

if course_id and not isinstance(course_id, CourseKey):
course_id = CourseKey.from_string(course_id)
if is_forum_v2_enabled(course_id):
if is_forum_v2_enabled(utils.get_course_key(course_id)):
response = forum_api.get_thread_subscriptions(thread_id, params['page'], params['per_page'])
else:
response = utils.perform_request(
Expand Down
204 changes: 118 additions & 86 deletions openedx/core/djangoapps/django_comment_common/comment_client/user.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
# pylint: disable=missing-docstring,protected-access
""" User model wrapper for comment service"""

from opaque_keys.edx.keys import CourseKey

from . import models, settings, utils
from forum import api as forum_api
from forum.utils import str_to_bool
Expand Down Expand Up @@ -38,34 +36,44 @@ def read(self, source):
"""
Calls cs_comments_service to mark thread as read for the user
"""
params = {'source_type': source.type, 'source_id': source.id}
utils.perform_request(
'post',
_url_for_read(self.id),
params,
metric_action='user.read',
metric_tags=self._metric_tags + [f'target.type:{source.type}'],
)
course_key = utils.get_course_key(self.course_id)
if is_forum_v2_enabled(course_key):
forum_api.mark_thread_as_read(self.id, source.id, course_id=str(self.course_id))
else:
params = {'source_type': source.type, 'source_id': source.id}
utils.perform_request(
'post',
_url_for_read(self.id),
params,
metric_action='user.read',
metric_tags=self._metric_tags + [f'target.type:{source.type}'],
)

def follow(self, source):
params = {'source_type': source.type, 'source_id': source.id}
utils.perform_request(
'post',
_url_for_subscription(self.id),
params,
metric_action='user.follow',
metric_tags=self._metric_tags + [f'target.type:{source.type}'],
)
if is_forum_v2_enabled(utils.get_course_key(self.course_id)):
forum_api.create_subscription(self.id, source.id)
else:
params = {'source_type': source.type, 'source_id': source.id}
utils.perform_request(
'post',
_url_for_subscription(self.id),
params,
metric_action='user.follow',
metric_tags=self._metric_tags + [f'target.type:{source.type}'],
)

def unfollow(self, source):
params = {'source_type': source.type, 'source_id': source.id}
utils.perform_request(
'delete',
_url_for_subscription(self.id),
params,
metric_action='user.unfollow',
metric_tags=self._metric_tags + [f'target.type:{source.type}'],
)
if is_forum_v2_enabled(utils.get_course_key(self.course_id)):
forum_api.delete_subscription(self.id, source.id)
else:
params = {'source_type': source.type, 'source_id': source.id}
utils.perform_request(
'delete',
_url_for_subscription(self.id),
params,
metric_action='user.unfollow',
metric_tags=self._metric_tags + [f'target.type:{source.type}'],
)

def vote(self, voteable, value):
if voteable.type == 'thread':
Expand All @@ -74,14 +82,20 @@ def vote(self, voteable, value):
url = _url_for_vote_comment(voteable.id)
else:
raise utils.CommentClientRequestError("Can only vote / unvote for threads or comments")
params = {'user_id': self.id, 'value': value}
response = utils.perform_request(
'put',
url,
params,
metric_action='user.vote',
metric_tags=self._metric_tags + [f'target.type:{voteable.type}'],
)
if is_forum_v2_enabled(utils.get_course_key(self.course_id)):
if voteable.type == 'thread':
response = forum_api.update_thread_votes(voteable.id, self.id, value)
else:
response = forum_api.update_comment_votes(voteable.id, self.id, value)
else:
params = {'user_id': self.id, 'value': value}
response = utils.perform_request(
'put',
url,
params,
metric_action='user.vote',
metric_tags=self._metric_tags + [f'target.type:{voteable.type}'],
)
voteable._update_from_response(response)

def unvote(self, voteable):
Expand All @@ -91,14 +105,20 @@ def unvote(self, voteable):
url = _url_for_vote_comment(voteable.id)
else:
raise utils.CommentClientRequestError("Can only vote / unvote for threads or comments")
params = {'user_id': self.id}
response = utils.perform_request(
'delete',
url,
params,
metric_action='user.unvote',
metric_tags=self._metric_tags + [f'target.type:{voteable.type}'],
)
if is_forum_v2_enabled(utils.get_course_key(self.course_id)):
if voteable.type == 'thread':
response = forum_api.delete_thread_vote(voteable.id, self.id)
else:
response = forum_api.delete_comment_vote(voteable.id, self.id)
else:
params = {'user_id': self.id}
response = utils.perform_request(
'delete',
url,
params,
metric_action='user.unvote',
metric_tags=self._metric_tags + [f'target.type:{voteable.type}'],
)
voteable._update_from_response(response)

def active_threads(self, query_params=None):
Expand All @@ -109,19 +129,15 @@ def active_threads(self, query_params=None):
url = _url_for_user_active_threads(self.id)
params = {'course_id': str(self.course_id)}
params.update(query_params)
if user_id := params.get("user_id"):
params["user_id"] = str(user_id)
if page := params.get("page"):
params["page"] = int(page)
if per_page := params.get("per_page"):
params["per_page"] = int(per_page)
if count_flagged := params.get("count_flagged", False):
params["count_flagged"] = str_to_bool(count_flagged)

if course_id := self.attributes.get("course_id"):
if not isinstance(course_id, CourseKey):
course_id = CourseKey.from_string(course_id)
if is_forum_v2_enabled(course_id):
if is_forum_v2_enabled(utils.get_course_key(self.course_id)):
if user_id := params.get("user_id"):
params["user_id"] = str(user_id)
if page := params.get("page"):
params["page"] = int(page)
if per_page := params.get("per_page"):
params["per_page"] = int(per_page)
if count_flagged := params.get("count_flagged", False):
params["count_flagged"] = str_to_bool(count_flagged)
response = forum_api.get_user_active_threads(**params)
else:
response = utils.perform_request(
Expand All @@ -144,14 +160,25 @@ def subscribed_threads(self, query_params=None):
url = _url_for_user_subscribed_threads(self.id)
params = {'course_id': str(self.course_id)}
params.update(query_params)
response = utils.perform_request(
'get',
url,
params,
metric_action='user.subscribed_threads',
metric_tags=self._metric_tags,
paged_results=True
)
if is_forum_v2_enabled(utils.get_course_key(self.course_id)):
if user_id := params.get("user_id"):
params["user_id"] = str(user_id)
if page := params.get("page"):
params["page"] = int(page)
if per_page := params.get("per_page"):
params["per_page"] = int(per_page)
if count_flagged := params.get("count_flagged", False):
params["count_flagged"] = str_to_bool(count_flagged)
response = forum_api.get_user_threads(**params)
else:
response = utils.perform_request(
'get',
url,
params,
metric_action='user.subscribed_threads',
metric_tags=self._metric_tags,
paged_results=True
)
return utils.CommentClientPaginatedResult(
collection=response.get('collection', []),
page=response.get('page', 1),
Expand All @@ -160,16 +187,16 @@ def subscribed_threads(self, query_params=None):
)

def _retrieve(self, *args, **kwargs):
url = self.url(action='get', params=self.attributes)
retrieve_params = self.default_retrieve_params.copy()
retrieve_params.update(kwargs)
if self.attributes.get('course_id'):
retrieve_params['course_id'] = str(self.attributes["course_id"])
retrieve_params['course_id'] = str(self.course_id)
if self.attributes.get('group_id'):
retrieve_params['group_id'] = self.attributes["group_id"]
if is_forum_v2_enabled(self.attributes.get("course_id")):
if is_forum_v2_enabled(utils.get_course_key(self.course_id)):
response = forum_api.get_user(self.attributes["id"], retrieve_params)
else:
url = self.url(action='get', params=self.attributes)
try:
response = utils.perform_request(
'get',
Expand All @@ -195,28 +222,33 @@ def _retrieve(self, *args, **kwargs):
self._update_from_response(response)

def retire(self, retired_username):
url = _url_for_retire(self.id)
params = {'retired_username': retired_username}

utils.perform_request(
'post',
url,
params,
raw=True,
metric_action='user.retire',
metric_tags=self._metric_tags
)
if is_forum_v2_enabled(utils.get_course_key(self.course_id)):
forum_api.retire_user(self.id, retired_username)
else:
url = _url_for_retire(self.id)
params = {'retired_username': retired_username}
utils.perform_request(
'post',
url,
params,
raw=True,
metric_action='user.retire',
metric_tags=self._metric_tags
)

def replace_username(self, new_username):
url = _url_for_username_replacement(self.id)
params = {"new_username": new_username}

utils.perform_request(
'post',
url,
params,
raw=True,
)
if is_forum_v2_enabled(utils.get_course_key(self.course_id)):
forum_api.update_username(self.id, new_username)
else:
url = _url_for_username_replacement(self.id)
params = {"new_username": new_username}

utils.perform_request(
'post',
url,
params,
raw=True,
)


def _url_for_vote_comment(comment_id):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import requests
from django.utils.translation import get_language
from opaque_keys.edx.keys import CourseKey

from .settings import SERVICE_HOST as COMMENTS_SERVICE

Expand Down Expand Up @@ -167,3 +168,9 @@ def check_forum_heartbeat():
return 'forum', False, res.get('check', 'Forum heartbeat failed')
except Exception as fail:
return 'forum', False, str(fail)


def get_course_key(course_id):
if course_id and isinstance(course_id, str):
course_id = CourseKey.from_string(course_id)
return course_id

0 comments on commit f6974be

Please sign in to comment.