Revert "feat: Integrate Forum V2 into edx-platform"

This reverts commit 70b60ff256.
This commit is contained in:
Diana Huang
2024-12-05 11:09:11 -05:00
committed by Diana Huang
parent 8d4909a999
commit 818aa343a2
26 changed files with 420 additions and 1822 deletions

View File

@@ -82,7 +82,6 @@ class MockRequestSetupMixin:
@patch('openedx.core.djangoapps.django_comment_common.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled', autospec=True)
class CreateThreadGroupIdTestCase(
MockRequestSetupMixin,
CohortedTestCase,
@@ -91,21 +90,7 @@ class CreateThreadGroupIdTestCase(
):
cs_endpoint = "/threads"
def setUp(self):
super().setUp()
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread"
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.models.forum_api.get_course_id_by_comment"
)
self.mock_get_course_id_by_comment = patcher.start()
self.addCleanup(patcher.stop)
def call_view(self, mock_is_forum_v2_enabled, mock_request, commentable_id, user, group_id, pass_group_id=True):
mock_is_forum_v2_enabled.return_value = False
def call_view(self, mock_request, commentable_id, user, group_id, pass_group_id=True):
self._set_mock_request_data(mock_request, {})
request_data = {"body": "body", "title": "title", "thread_type": "discussion"}
if pass_group_id:
@@ -120,9 +105,8 @@ class CreateThreadGroupIdTestCase(
commentable_id=commentable_id
)
def test_group_info_in_response(self, mock_is_forum_v2_enabled, mock_request):
def test_group_info_in_response(self, mock_request):
response = self.call_view(
mock_is_forum_v2_enabled,
mock_request,
"cohorted_topic",
self.student,
@@ -132,7 +116,6 @@ class CreateThreadGroupIdTestCase(
@patch('openedx.core.djangoapps.django_comment_common.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled', autospec=True)
@disable_signal(views, 'thread_edited')
@disable_signal(views, 'thread_voted')
@disable_signal(views, 'thread_deleted')
@@ -144,18 +127,11 @@ class ThreadActionGroupIdTestCase(
def call_view(
self,
view_name,
mock_is_forum_v2_enabled,
mock_request,
user=None,
post_params=None,
view_args=None
):
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread"
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
mock_is_forum_v2_enabled.return_value = False
self._set_mock_request_data(
mock_request,
{
@@ -178,58 +154,53 @@ class ThreadActionGroupIdTestCase(
**(view_args or {})
)
def test_update(self, mock_is_forum_v2_enabled, mock_request):
def test_update(self, mock_request):
response = self.call_view(
"update_thread",
mock_is_forum_v2_enabled,
mock_request,
post_params={"body": "body", "title": "title"}
)
self._assert_json_response_contains_group_info(response)
def test_delete(self, mock_is_forum_v2_enabled, mock_request):
response = self.call_view("delete_thread", mock_is_forum_v2_enabled, mock_request)
def test_delete(self, mock_request):
response = self.call_view("delete_thread", mock_request)
self._assert_json_response_contains_group_info(response)
def test_vote(self, mock_is_forum_v2_enabled, mock_request):
def test_vote(self, mock_request):
response = self.call_view(
"vote_for_thread",
mock_is_forum_v2_enabled,
mock_request,
view_args={"value": "up"}
)
self._assert_json_response_contains_group_info(response)
response = self.call_view("undo_vote_for_thread", mock_is_forum_v2_enabled, mock_request)
response = self.call_view("undo_vote_for_thread", mock_request)
self._assert_json_response_contains_group_info(response)
def test_flag(self, mock_is_forum_v2_enabled, mock_request):
def test_flag(self, mock_request):
with mock.patch('openedx.core.djangoapps.django_comment_common.signals.thread_flagged.send') as signal_mock:
response = self.call_view("flag_abuse_for_thread", mock_is_forum_v2_enabled, mock_request)
response = self.call_view("flag_abuse_for_thread", mock_request)
self._assert_json_response_contains_group_info(response)
self.assertEqual(signal_mock.call_count, 1)
response = self.call_view("un_flag_abuse_for_thread", mock_is_forum_v2_enabled, mock_request)
response = self.call_view("un_flag_abuse_for_thread", mock_request)
self._assert_json_response_contains_group_info(response)
def test_pin(self, mock_is_forum_v2_enabled, mock_request):
def test_pin(self, mock_request):
response = self.call_view(
"pin_thread",
mock_is_forum_v2_enabled,
mock_request,
user=self.moderator
)
self._assert_json_response_contains_group_info(response)
response = self.call_view(
"un_pin_thread",
mock_is_forum_v2_enabled,
mock_request,
user=self.moderator
)
self._assert_json_response_contains_group_info(response)
def test_openclose(self, mock_is_forum_v2_enabled, mock_request):
def test_openclose(self, mock_request):
response = self.call_view(
"openclose_thread",
mock_is_forum_v2_enabled,
mock_request,
user=self.moderator
)
@@ -309,11 +280,10 @@ class ViewsTestCaseMixin:
data["depth"] = 0
self._set_mock_request_data(mock_request, data)
def create_thread_helper(self, mock_is_forum_v2_enabled, mock_request, extra_request_data=None, extra_response_data=None):
def create_thread_helper(self, mock_request, extra_request_data=None, extra_response_data=None):
"""
Issues a request to create a thread and verifies the result.
"""
mock_is_forum_v2_enabled.return_value = False
self._set_mock_request_data(mock_request, {
"thread_type": "discussion",
"title": "Hello",
@@ -380,11 +350,10 @@ class ViewsTestCaseMixin:
)
assert response.status_code == 200
def update_thread_helper(self, mock_is_forum_v2_enabled, mock_request):
def update_thread_helper(self, mock_request):
"""
Issues a request to update a thread and verifies the result.
"""
mock_is_forum_v2_enabled.return_value = False
self._setup_mock_request(mock_request)
# Mock out saving in order to test that content is correctly
# updated. Otherwise, the call to thread.save() receives the
@@ -407,7 +376,6 @@ class ViewsTestCaseMixin:
@ddt.ddt
@patch('openedx.core.djangoapps.django_comment_common.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled', autospec=True)
@disable_signal(views, 'thread_created')
@disable_signal(views, 'thread_edited')
class ViewsQueryCountTestCase(
@@ -425,11 +393,6 @@ class ViewsQueryCountTestCase(
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
def setUp(self):
super().setUp()
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread"
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
def count_queries(func): # pylint: disable=no-self-argument
"""
@@ -451,23 +414,22 @@ class ViewsQueryCountTestCase(
)
@ddt.unpack
@count_queries
def test_create_thread(self, mock_is_forum_v2_enabled, mock_request):
self.create_thread_helper(mock_is_forum_v2_enabled, mock_request)
def test_create_thread(self, mock_request):
self.create_thread_helper(mock_request)
@ddt.data(
(ModuleStoreEnum.Type.split, 3, 6, 41),
)
@ddt.unpack
@count_queries
def test_update_thread(self, mock_is_forum_v2_enabled, mock_request):
self.update_thread_helper(mock_is_forum_v2_enabled, mock_request)
def test_update_thread(self, mock_request):
self.update_thread_helper(mock_request)
@ddt.ddt
@disable_signal(views, 'comment_flagged')
@disable_signal(views, 'thread_flagged')
@patch('openedx.core.djangoapps.django_comment_common.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled', autospec=True)
class ViewsTestCase(
ForumsEnableMixin,
UrlResetMixin,
@@ -502,16 +464,7 @@ class ViewsTestCase(
# so we need to call super.setUp() which reloads urls.py (because
# of the UrlResetMixin)
super().setUp()
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.models.forum_api.get_course_id_by_comment"
)
self.mock_get_course_id_by_comment = patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread"
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
# Patch the comment client user save method so it does not try
# to create a new cc user when creating a django user
with patch('common.djangoapps.student.models.user.cc.User.save'):
@@ -544,11 +497,11 @@ class ViewsTestCase(
with self.assert_signal_sent(views, signal, sender=None, user=user, exclude_args=('post',)):
yield
def test_create_thread(self, mock_is_forum_v2_enabled, mock_request):
def test_create_thread(self, mock_request):
with self.assert_discussion_signals('thread_created'):
self.create_thread_helper(mock_is_forum_v2_enabled, mock_request)
self.create_thread_helper(mock_request)
def test_create_thread_standalone(self, mock_is_forum_v2_enabled, mock_request):
def test_create_thread_standalone(self, mock_request):
team = CourseTeamFactory.create(
name="A Team",
course_id=self.course_id,
@@ -560,15 +513,15 @@ class ViewsTestCase(
team.add_user(self.student)
# create_thread_helper verifies that extra data are passed through to the comments service
self.create_thread_helper(mock_is_forum_v2_enabled, mock_request, extra_response_data={'context': ThreadContext.STANDALONE})
self.create_thread_helper(mock_request, extra_response_data={'context': ThreadContext.STANDALONE})
@ddt.data(
('follow_thread', 'thread_followed'),
('unfollow_thread', 'thread_unfollowed'),
)
@ddt.unpack
def test_follow_unfollow_thread_signals(self, view_name, signal, mock_is_forum_v2_enabled, mock_request):
self.create_thread_helper(mock_is_forum_v2_enabled, mock_request)
def test_follow_unfollow_thread_signals(self, view_name, signal, mock_request):
self.create_thread_helper(mock_request)
with self.assert_discussion_signals(signal):
response = self.client.post(
@@ -579,8 +532,7 @@ class ViewsTestCase(
)
assert response.status_code == 200
def test_delete_thread(self, mock_is_forum_v2_enabled, mock_request):
mock_is_forum_v2_enabled.return_value = False
def test_delete_thread(self, mock_request):
self._set_mock_request_data(mock_request, {
"user_id": str(self.student.id),
"closed": False,
@@ -599,8 +551,7 @@ class ViewsTestCase(
assert response.status_code == 200
assert mock_request.called
def test_delete_comment(self, mock_is_forum_v2_enabled, mock_request):
mock_is_forum_v2_enabled.return_value = False
def test_delete_comment(self, mock_request):
self._set_mock_request_data(mock_request, {
"user_id": str(self.student.id),
"closed": False,
@@ -622,13 +573,12 @@ class ViewsTestCase(
assert args[0] == 'delete'
assert args[1].endswith(f"/{test_comment_id}")
def _test_request_error(self, view_name, view_kwargs, data, mock_is_forum_v2_enabled, mock_request):
def _test_request_error(self, view_name, view_kwargs, data, mock_request):
"""
Submit a request against the given view with the given data and ensure
that the result is a 400 error and that no data was posted using
mock_request
"""
mock_is_forum_v2_enabled.return_value = False
self._setup_mock_request(mock_request, include_depth=(view_name == "create_sub_comment"))
response = self.client.post(reverse(view_name, kwargs=view_kwargs), data=data)
@@ -636,97 +586,87 @@ class ViewsTestCase(
for call in mock_request.call_args_list:
assert call[0][0].lower() == 'get'
def test_create_thread_no_title(self, mock_is_forum_v2_enabled, mock_request):
def test_create_thread_no_title(self, mock_request):
self._test_request_error(
"create_thread",
{"commentable_id": "dummy", "course_id": str(self.course_id)},
{"body": "foo"},
mock_is_forum_v2_enabled,
mock_request
)
def test_create_thread_empty_title(self, mock_is_forum_v2_enabled, mock_request):
def test_create_thread_empty_title(self, mock_request):
self._test_request_error(
"create_thread",
{"commentable_id": "dummy", "course_id": str(self.course_id)},
{"body": "foo", "title": " "},
mock_is_forum_v2_enabled,
mock_request
)
def test_create_thread_no_body(self, mock_is_forum_v2_enabled, mock_request):
def test_create_thread_no_body(self, mock_request):
self._test_request_error(
"create_thread",
{"commentable_id": "dummy", "course_id": str(self.course_id)},
{"title": "foo"},
mock_is_forum_v2_enabled,
mock_request
)
def test_create_thread_empty_body(self, mock_is_forum_v2_enabled, mock_request):
def test_create_thread_empty_body(self, mock_request):
self._test_request_error(
"create_thread",
{"commentable_id": "dummy", "course_id": str(self.course_id)},
{"body": " ", "title": "foo"},
mock_is_forum_v2_enabled,
mock_request
)
def test_update_thread_no_title(self, mock_is_forum_v2_enabled, mock_request):
def test_update_thread_no_title(self, mock_request):
self._test_request_error(
"update_thread",
{"thread_id": "dummy", "course_id": str(self.course_id)},
{"body": "foo"},
mock_is_forum_v2_enabled,
mock_request
)
def test_update_thread_empty_title(self, mock_is_forum_v2_enabled, mock_request):
def test_update_thread_empty_title(self, mock_request):
self._test_request_error(
"update_thread",
{"thread_id": "dummy", "course_id": str(self.course_id)},
{"body": "foo", "title": " "},
mock_is_forum_v2_enabled,
mock_request
)
def test_update_thread_no_body(self, mock_is_forum_v2_enabled, mock_request):
def test_update_thread_no_body(self, mock_request):
self._test_request_error(
"update_thread",
{"thread_id": "dummy", "course_id": str(self.course_id)},
{"title": "foo"},
mock_is_forum_v2_enabled,
mock_request
)
def test_update_thread_empty_body(self, mock_is_forum_v2_enabled, mock_request):
def test_update_thread_empty_body(self, mock_request):
self._test_request_error(
"update_thread",
{"thread_id": "dummy", "course_id": str(self.course_id)},
{"body": " ", "title": "foo"},
mock_is_forum_v2_enabled,
mock_request
)
def test_update_thread_course_topic(self, mock_is_forum_v2_enabled, mock_request):
def test_update_thread_course_topic(self, mock_request):
with self.assert_discussion_signals('thread_edited'):
self.update_thread_helper(mock_is_forum_v2_enabled, mock_request)
self.update_thread_helper(mock_request)
@patch(
'lms.djangoapps.discussion.django_comment_client.utils.get_discussion_categories_ids',
return_value=["test_commentable"],
)
def test_update_thread_wrong_commentable_id(self, mock_get_discussion_id_map, mock_is_forum_v2_enabled, mock_request):
def test_update_thread_wrong_commentable_id(self, mock_get_discussion_id_map, mock_request):
self._test_request_error(
"update_thread",
{"thread_id": "dummy", "course_id": str(self.course_id)},
{"body": "foo", "title": "foo", "commentable_id": "wrong_commentable"},
mock_is_forum_v2_enabled,
mock_request
)
def test_create_comment(self, mock_is_forum_v2_enabled, mock_request):
mock_is_forum_v2_enabled.return_value = False
def test_create_comment(self, mock_request):
self._setup_mock_request(mock_request)
with self.assert_discussion_signals('comment_created'):
response = self.client.post(
@@ -738,62 +678,55 @@ class ViewsTestCase(
)
assert response.status_code == 200
def test_create_comment_no_body(self, mock_is_forum_v2_enabled, mock_request):
def test_create_comment_no_body(self, mock_request):
self._test_request_error(
"create_comment",
{"thread_id": "dummy", "course_id": str(self.course_id)},
{},
mock_is_forum_v2_enabled,
mock_request
)
def test_create_comment_empty_body(self, mock_is_forum_v2_enabled, mock_request):
def test_create_comment_empty_body(self, mock_request):
self._test_request_error(
"create_comment",
{"thread_id": "dummy", "course_id": str(self.course_id)},
{"body": " "},
mock_is_forum_v2_enabled,
mock_request
)
def test_create_sub_comment_no_body(self, mock_is_forum_v2_enabled, mock_request):
def test_create_sub_comment_no_body(self, mock_request):
self._test_request_error(
"create_sub_comment",
{"comment_id": "dummy", "course_id": str(self.course_id)},
{},
mock_is_forum_v2_enabled,
mock_request
)
def test_create_sub_comment_empty_body(self, mock_is_forum_v2_enabled, mock_request):
def test_create_sub_comment_empty_body(self, mock_request):
self._test_request_error(
"create_sub_comment",
{"comment_id": "dummy", "course_id": str(self.course_id)},
{"body": " "},
mock_is_forum_v2_enabled,
mock_request
)
def test_update_comment_no_body(self, mock_is_forum_v2_enabled, mock_request):
def test_update_comment_no_body(self, mock_request):
self._test_request_error(
"update_comment",
{"comment_id": "dummy", "course_id": str(self.course_id)},
{},
mock_is_forum_v2_enabled,
mock_request
)
def test_update_comment_empty_body(self, mock_is_forum_v2_enabled, mock_request):
def test_update_comment_empty_body(self, mock_request):
self._test_request_error(
"update_comment",
{"comment_id": "dummy", "course_id": str(self.course_id)},
{"body": " "},
mock_is_forum_v2_enabled,
mock_request
)
def test_update_comment_basic(self, mock_is_forum_v2_enabled, mock_request):
mock_is_forum_v2_enabled.return_value = False
def test_update_comment_basic(self, mock_request):
self._setup_mock_request(mock_request)
comment_id = "test_comment_id"
updated_body = "updated body"
@@ -815,14 +748,13 @@ class ViewsTestCase(
data={"body": updated_body}
)
def test_flag_thread_open(self, mock_is_forum_v2_enabled, mock_request):
self.flag_thread(mock_is_forum_v2_enabled, mock_request, False)
def test_flag_thread_open(self, mock_request):
self.flag_thread(mock_request, False)
def test_flag_thread_close(self, mock_is_forum_v2_enabled, mock_request):
self.flag_thread(mock_is_forum_v2_enabled, mock_request, True)
def test_flag_thread_close(self, mock_request):
self.flag_thread(mock_request, True)
def flag_thread(self, mock_is_forum_v2_enabled, mock_request, is_closed):
mock_is_forum_v2_enabled.return_value = False
def flag_thread(self, mock_request, is_closed):
self._set_mock_request_data(mock_request, {
"title": "Hello",
"body": "this is a post",
@@ -894,14 +826,13 @@ class ViewsTestCase(
assert response.status_code == 200
def test_un_flag_thread_open(self, mock_is_forum_v2_enabled, mock_request):
self.un_flag_thread(mock_is_forum_v2_enabled, mock_request, False)
def test_un_flag_thread_open(self, mock_request):
self.un_flag_thread(mock_request, False)
def test_un_flag_thread_close(self, mock_is_forum_v2_enabled, mock_request):
self.un_flag_thread(mock_is_forum_v2_enabled, mock_request, True)
def test_un_flag_thread_close(self, mock_request):
self.un_flag_thread(mock_request, True)
def un_flag_thread(self, mock_is_forum_v2_enabled, mock_request, is_closed):
mock_is_forum_v2_enabled.return_value = False
def un_flag_thread(self, mock_request, is_closed):
self._set_mock_request_data(mock_request, {
"title": "Hello",
"body": "this is a post",
@@ -974,14 +905,13 @@ class ViewsTestCase(
assert response.status_code == 200
def test_flag_comment_open(self, mock_is_forum_v2_enabled, mock_request):
self.flag_comment(mock_is_forum_v2_enabled, mock_request, False)
def test_flag_comment_open(self, mock_request):
self.flag_comment(mock_request, False)
def test_flag_comment_close(self, mock_is_forum_v2_enabled, mock_request):
self.flag_comment(mock_is_forum_v2_enabled, mock_request, True)
def test_flag_comment_close(self, mock_request):
self.flag_comment(mock_request, True)
def flag_comment(self, mock_is_forum_v2_enabled, mock_request, is_closed):
mock_is_forum_v2_enabled.return_value = False
def flag_comment(self, mock_request, is_closed):
self._set_mock_request_data(mock_request, {
"body": "this is a comment",
"course_id": "MITx/999/Robot_Super_Course",
@@ -1046,14 +976,13 @@ class ViewsTestCase(
assert response.status_code == 200
def test_un_flag_comment_open(self, mock_is_forum_v2_enabled, mock_request):
self.un_flag_comment(mock_is_forum_v2_enabled, mock_request, False)
def test_un_flag_comment_open(self, mock_request):
self.un_flag_comment(mock_request, False)
def test_un_flag_comment_close(self, mock_is_forum_v2_enabled, mock_request):
self.un_flag_comment(mock_is_forum_v2_enabled, mock_request, True)
def test_un_flag_comment_close(self, mock_request):
self.un_flag_comment(mock_request, True)
def un_flag_comment(self, mock_is_forum_v2_enabled, mock_request, is_closed):
mock_is_forum_v2_enabled.return_value = False
def un_flag_comment(self, mock_request, is_closed):
self._set_mock_request_data(mock_request, {
"body": "this is a comment",
"course_id": "MITx/999/Robot_Super_Course",
@@ -1125,8 +1054,7 @@ class ViewsTestCase(
('downvote_comment', 'comment_id', 'comment_voted')
)
@ddt.unpack
def test_voting(self, view_name, item_id, signal, mock_is_forum_v2_enabled, mock_request):
mock_is_forum_v2_enabled.return_value = False
def test_voting(self, view_name, item_id, signal, mock_request):
self._setup_mock_request(mock_request)
with self.assert_discussion_signals(signal):
response = self.client.post(
@@ -1137,8 +1065,7 @@ class ViewsTestCase(
)
assert response.status_code == 200
def test_endorse_comment(self, mock_is_forum_v2_enabled, mock_request):
mock_is_forum_v2_enabled.return_value = False
def test_endorse_comment(self, mock_request):
self._setup_mock_request(mock_request)
self.client.login(username=self.moderator.username, password=self.password)
with self.assert_discussion_signals('comment_endorsed', user=self.moderator):
@@ -1152,7 +1079,6 @@ class ViewsTestCase(
@patch("openedx.core.djangoapps.django_comment_common.comment_client.utils.requests.request", autospec=True)
@patch('openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled', autospec=True)
@disable_signal(views, 'comment_endorsed')
class ViewPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleStoreTestCase, MockRequestSetupMixin):
@@ -1180,19 +1106,8 @@ class ViewPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleStor
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
def setUp(self):
super().setUp()
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.models.forum_api.get_course_id_by_comment"
)
self.mock_get_course_id_by_comment = patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread"
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
def test_pin_thread_as_student(self, mock_is_forum_v2_enabled, mock_request):
mock_is_forum_v2_enabled.return_value = False
def test_pin_thread_as_student(self, mock_request):
self._set_mock_request_data(mock_request, {})
self.client.login(username=self.student.username, password=self.password)
response = self.client.post(
@@ -1200,8 +1115,7 @@ class ViewPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleStor
)
assert response.status_code == 401
def test_pin_thread_as_moderator(self, mock_is_forum_v2_enabled, mock_request):
mock_is_forum_v2_enabled.return_value = False
def test_pin_thread_as_moderator(self, mock_request):
self._set_mock_request_data(mock_request, {})
self.client.login(username=self.moderator.username, password=self.password)
response = self.client.post(
@@ -1209,8 +1123,7 @@ class ViewPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleStor
)
assert response.status_code == 200
def test_un_pin_thread_as_student(self, mock_is_forum_v2_enabled, mock_request):
mock_is_forum_v2_enabled.return_value = False
def test_un_pin_thread_as_student(self, mock_request):
self._set_mock_request_data(mock_request, {})
self.client.login(username=self.student.username, password=self.password)
response = self.client.post(
@@ -1218,8 +1131,7 @@ class ViewPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleStor
)
assert response.status_code == 401
def test_un_pin_thread_as_moderator(self, mock_is_forum_v2_enabled, mock_request):
mock_is_forum_v2_enabled.return_value = False
def test_un_pin_thread_as_moderator(self, mock_request):
self._set_mock_request_data(mock_request, {})
self.client.login(username=self.moderator.username, password=self.password)
response = self.client.post(
@@ -1227,7 +1139,7 @@ class ViewPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleStor
)
assert response.status_code == 200
def _set_mock_request_thread_and_comment(self, mock_is_forum_v2_enabled, mock_request, thread_data, comment_data):
def _set_mock_request_thread_and_comment(self, mock_request, thread_data, comment_data):
def handle_request(*args, **kwargs):
url = args[1]
if "/threads/" in url:
@@ -1236,12 +1148,10 @@ class ViewPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleStor
return self._create_response_mock(comment_data)
else:
raise ArgumentError("Bad url to mock request")
mock_is_forum_v2_enabled.return_value = False
mock_request.side_effect = handle_request
def test_endorse_response_as_staff(self, mock_is_forum_v2_enabled, mock_request):
def test_endorse_response_as_staff(self, mock_request):
self._set_mock_request_thread_and_comment(
mock_is_forum_v2_enabled,
mock_request,
{"type": "thread", "thread_type": "question", "user_id": str(self.student.id), "commentable_id": "course"},
{"type": "comment", "thread_id": "dummy"}
@@ -1252,9 +1162,8 @@ class ViewPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleStor
)
assert response.status_code == 200
def test_endorse_response_as_student(self, mock_is_forum_v2_enabled, mock_request):
def test_endorse_response_as_student(self, mock_request):
self._set_mock_request_thread_and_comment(
mock_is_forum_v2_enabled,
mock_request,
{"type": "thread", "thread_type": "question",
"user_id": str(self.moderator.id), "commentable_id": "course"},
@@ -1266,9 +1175,8 @@ class ViewPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleStor
)
assert response.status_code == 401
def test_endorse_response_as_student_question_author(self, mock_is_forum_v2_enabled, mock_request):
def test_endorse_response_as_student_question_author(self, mock_request):
self._set_mock_request_thread_and_comment(
mock_is_forum_v2_enabled,
mock_request,
{"type": "thread", "thread_type": "question", "user_id": str(self.student.id), "commentable_id": "course"},
{"type": "comment", "thread_id": "dummy"}
@@ -1301,12 +1209,10 @@ class CreateThreadUnicodeTestCase(
CourseEnrollmentFactory(user=cls.student, course_id=cls.course.id)
@patch('openedx.core.djangoapps.django_comment_common.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled', autospec=True)
def _test_unicode_data(self, text, mock_is_forum_v2_enabled, mock_request,):
def _test_unicode_data(self, text, mock_request,):
"""
Test to make sure unicode data in a thread doesn't break it.
"""
mock_is_forum_v2_enabled.return_value = False
self._set_mock_request_data(mock_request, {})
request = RequestFactory().post("dummy_url", {"thread_type": "discussion", "body": text, "title": text})
request.user = self.student
@@ -1329,13 +1235,6 @@ class UpdateThreadUnicodeTestCase(
UnicodeTestMixin,
MockRequestSetupMixin
):
def setUp(self):
super().setUp()
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread"
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
@classmethod
def setUpClass(cls):
@@ -1356,9 +1255,7 @@ class UpdateThreadUnicodeTestCase(
return_value=["test_commentable"],
)
@patch('openedx.core.djangoapps.django_comment_common.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled', autospec=True)
def _test_unicode_data(self, text, mock_is_forum_v2_enabled, mock_request, mock_get_discussion_id_map):
mock_is_forum_v2_enabled.return_value = False
def _test_unicode_data(self, text, mock_request, mock_get_discussion_id_map):
self._set_mock_request_data(mock_request, {
"user_id": str(self.student.id),
"closed": False,
@@ -1383,13 +1280,6 @@ class CreateCommentUnicodeTestCase(
UnicodeTestMixin,
MockRequestSetupMixin
):
def setUp(self):
super().setUp()
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread"
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
@classmethod
def setUpClass(cls):
@@ -1406,9 +1296,7 @@ class CreateCommentUnicodeTestCase(
CourseEnrollmentFactory(user=cls.student, course_id=cls.course.id)
@patch('openedx.core.djangoapps.django_comment_common.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled', autospec=True)
def _test_unicode_data(self, text, mock_is_forum_v2_enabled, mock_request):
mock_is_forum_v2_enabled.return_value = False
def _test_unicode_data(self, text, mock_request):
commentable_id = "non_team_dummy_id"
self._set_mock_request_data(mock_request, {
"closed": False,
@@ -1439,13 +1327,6 @@ class UpdateCommentUnicodeTestCase(
UnicodeTestMixin,
MockRequestSetupMixin
):
def setUp(self):
super().setUp()
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.models.forum_api.get_course_id_by_comment"
)
self.mock_get_course_id_by_comment = patcher.start()
self.addCleanup(patcher.stop)
@classmethod
def setUpClass(cls):
@@ -1462,9 +1343,7 @@ class UpdateCommentUnicodeTestCase(
CourseEnrollmentFactory(user=cls.student, course_id=cls.course.id)
@patch('openedx.core.djangoapps.django_comment_common.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled', autospec=True)
def _test_unicode_data(self, text, mock_is_forum_v2_enabled, mock_request):
mock_is_forum_v2_enabled.return_value = False
def _test_unicode_data(self, text, mock_request):
self._set_mock_request_data(mock_request, {
"user_id": str(self.student.id),
"closed": False,
@@ -1480,7 +1359,6 @@ class UpdateCommentUnicodeTestCase(
@patch('openedx.core.djangoapps.django_comment_common.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled', autospec=True)
class CommentActionTestCase(
MockRequestSetupMixin,
CohortedTestCase,
@@ -1489,18 +1367,11 @@ class CommentActionTestCase(
def call_view(
self,
view_name,
mock_is_forum_v2_enabled,
mock_request,
user=None,
post_params=None,
view_args=None
):
mock_is_forum_v2_enabled.return_value = False
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.models.forum_api.get_course_id_by_comment"
)
self.mock_get_course_id_by_comment = patcher.start()
self.addCleanup(patcher.stop)
self._set_mock_request_data(
mock_request,
{
@@ -1523,9 +1394,9 @@ class CommentActionTestCase(
**(view_args or {})
)
def test_flag(self, mock_is_forum_v2_enabled, mock_request):
def test_flag(self, mock_request):
with mock.patch('openedx.core.djangoapps.django_comment_common.signals.comment_flagged.send') as signal_mock:
self.call_view("flag_abuse_for_comment", mock_is_forum_v2_enabled, mock_request)
self.call_view("flag_abuse_for_comment", mock_request)
self.assertEqual(signal_mock.call_count, 1)
@@ -1539,14 +1410,6 @@ class CreateSubCommentUnicodeTestCase(
"""
Make sure comments under a response can handle unicode.
"""
def setUp(self):
super().setUp()
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.models.forum_api.get_course_id_by_comment"
)
self.mock_get_course_id_by_comment = patcher.start()
self.addCleanup(patcher.stop)
@classmethod
def setUpClass(cls):
# pylint: disable=super-method-not-called
@@ -1562,12 +1425,10 @@ class CreateSubCommentUnicodeTestCase(
CourseEnrollmentFactory(user=cls.student, course_id=cls.course.id)
@patch('openedx.core.djangoapps.django_comment_common.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled', autospec=True)
def _test_unicode_data(self, text, mock_is_forum_v2_enabled, mock_request):
def _test_unicode_data(self, text, mock_request):
"""
Create a comment with unicode in it.
"""
mock_is_forum_v2_enabled.return_value = False
self._set_mock_request_data(mock_request, {
"closed": False,
"depth": 1,
@@ -1592,7 +1453,6 @@ class CreateSubCommentUnicodeTestCase(
@ddt.ddt
@patch("openedx.core.djangoapps.django_comment_common.comment_client.utils.requests.request", autospec=True)
@patch('openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled', autospec=True)
@disable_signal(views, 'thread_voted')
@disable_signal(views, 'thread_edited')
@disable_signal(views, 'comment_created')
@@ -1702,24 +1562,13 @@ class TeamsPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleSto
users=[cls.group_moderator, cls.cohorted]
)
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
def setUp(self):
super().setUp()
def _setup_mock(self, user, mock_is_forum_v2_enabled, mock_request, data):
def _setup_mock(self, user, mock_request, data):
user = getattr(self, user)
mock_is_forum_v2_enabled.return_value = False
self._set_mock_request_data(mock_request, data)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.models.forum_api.get_course_id_by_comment"
)
self.mock_get_course_id_by_comment = patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread"
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
self.client.login(username=user.username, password=self.password)
@ddt.data(
@@ -1744,7 +1593,7 @@ class TeamsPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleSto
('group_moderator', 'cohorted', 'course_commentable_id', 401, CourseDiscussionSettings.NONE)
)
@ddt.unpack
def test_update_thread(self, user, thread_author, commentable_id, status_code, division_scheme, mock_is_forum_v2_enabled, mock_request):
def test_update_thread(self, user, thread_author, commentable_id, status_code, division_scheme, mock_request):
"""
Verify that update_thread is limited to thread authors and privileged users (team membership does not matter).
"""
@@ -1754,7 +1603,7 @@ class TeamsPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleSto
thread_author = getattr(self, thread_author)
self._setup_mock(
user, mock_is_forum_v2_enabled, mock_request, # user is the person making the request.
user, mock_request, # user is the person making the request.
{
"user_id": str(thread_author.id),
"closed": False, "commentable_id": commentable_id,
@@ -1794,12 +1643,12 @@ class TeamsPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleSto
('group_moderator', 'cohorted', 'team_commentable_id', 401, CourseDiscussionSettings.NONE)
)
@ddt.unpack
def test_delete_comment(self, user, comment_author, commentable_id, status_code, division_scheme, mock_is_forum_v2_enabled, mock_request):
def test_delete_comment(self, user, comment_author, commentable_id, status_code, division_scheme, mock_request):
commentable_id = getattr(self, commentable_id)
comment_author = getattr(self, comment_author)
self.change_divided_discussion_settings(division_scheme)
self._setup_mock(user, mock_is_forum_v2_enabled, mock_request, {
self._setup_mock(user, mock_request, {
"closed": False,
"commentable_id": commentable_id,
"user_id": str(comment_author.id),
@@ -1822,12 +1671,12 @@ class TeamsPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleSto
@ddt.data(*ddt_permissions_args)
@ddt.unpack
def test_create_comment(self, user, commentable_id, status_code, mock_is_forum_v2_enabled, mock_request):
def test_create_comment(self, user, commentable_id, status_code, mock_request):
"""
Verify that create_comment is limited to members of the team or users with 'edit_content' permission.
"""
commentable_id = getattr(self, commentable_id)
self._setup_mock(user, mock_is_forum_v2_enabled, mock_request, {"closed": False, "commentable_id": commentable_id})
self._setup_mock(user, mock_request, {"closed": False, "commentable_id": commentable_id})
response = self.client.post(
reverse(
@@ -1843,13 +1692,13 @@ class TeamsPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleSto
@ddt.data(*ddt_permissions_args)
@ddt.unpack
def test_create_sub_comment(self, user, commentable_id, status_code, mock_is_forum_v2_enabled, mock_request):
def test_create_sub_comment(self, user, commentable_id, status_code, mock_request):
"""
Verify that create_subcomment is limited to members of the team or users with 'edit_content' permission.
"""
commentable_id = getattr(self, commentable_id)
self._setup_mock(
user, mock_is_forum_v2_enabled, mock_request,
user, mock_request,
{"closed": False, "commentable_id": commentable_id, "thread_id": "dummy_thread"},
)
response = self.client.post(
@@ -1866,14 +1715,14 @@ class TeamsPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleSto
@ddt.data(*ddt_permissions_args)
@ddt.unpack
def test_comment_actions(self, user, commentable_id, status_code, mock_is_forum_v2_enabled, mock_request):
def test_comment_actions(self, user, commentable_id, status_code, mock_request):
"""
Verify that voting and flagging of comments is limited to members of the team or users with
'edit_content' permission.
"""
commentable_id = getattr(self, commentable_id)
self._setup_mock(
user, mock_is_forum_v2_enabled, mock_request,
user, mock_request,
{
"closed": False,
"commentable_id": commentable_id,
@@ -1893,14 +1742,14 @@ class TeamsPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleSto
@ddt.data(*ddt_permissions_args)
@ddt.unpack
def test_threads_actions(self, user, commentable_id, status_code, mock_is_forum_v2_enabled, mock_request):
def test_threads_actions(self, user, commentable_id, status_code, mock_request):
"""
Verify that voting, flagging, and following of threads is limited to members of the team or users with
'edit_content' permission.
"""
commentable_id = getattr(self, commentable_id)
self._setup_mock(
user, mock_is_forum_v2_enabled, mock_request,
user, mock_request,
{"closed": False, "commentable_id": commentable_id, "body": "dummy body", "course_id": str(self.course.id)}
)
for action in ["upvote_thread", "downvote_thread", "un_flag_abuse_for_thread", "flag_abuse_for_thread",
@@ -1923,19 +1772,6 @@ class ForumEventTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockReque
"""
Forum actions are expected to launch analytics events. Test these here.
"""
def setUp(self):
super().setUp()
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.models.forum_api.get_course_id_by_comment"
)
self.mock_get_course_id_by_comment = patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread"
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
@classmethod
def setUpClass(cls):
# pylint: disable=super-method-not-called
@@ -1955,14 +1791,12 @@ class ForumEventTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockReque
@patch('eventtracking.tracker.emit')
@patch('openedx.core.djangoapps.django_comment_common.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled', autospec=True)
def test_response_event(self, mock_is_forum_v2_enabled, mock_request, mock_emit):
def test_response_event(self, mock_request, mock_emit):
"""
Check to make sure an event is fired when a user responds to a thread.
"""
event_receiver = Mock()
FORUM_THREAD_RESPONSE_CREATED.connect(event_receiver)
mock_is_forum_v2_enabled.return_value = False
self._set_mock_request_data(mock_request, {
"closed": False,
"commentable_id": 'test_commentable_id',
@@ -1999,14 +1833,12 @@ class ForumEventTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockReque
@patch('eventtracking.tracker.emit')
@patch('openedx.core.djangoapps.django_comment_common.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled', autospec=True)
def test_comment_event(self, mock_is_forum_v2_enabled, mock_request, mock_emit):
def test_comment_event(self, mock_request, mock_emit):
"""
Ensure an event is fired when someone comments on a response.
"""
event_receiver = Mock()
FORUM_RESPONSE_COMMENT_CREATED.connect(event_receiver)
mock_is_forum_v2_enabled.return_value = False
self._set_mock_request_data(mock_request, {
"closed": False,
"depth": 1,
@@ -2043,7 +1875,6 @@ class ForumEventTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockReque
@patch('eventtracking.tracker.emit')
@patch('openedx.core.djangoapps.django_comment_common.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled', autospec=True)
@ddt.data((
'create_thread',
'edx.forum.thread.created', {
@@ -2065,7 +1896,7 @@ class ForumEventTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockReque
{'comment_id': 'dummy_comment_id'}
))
@ddt.unpack
def test_team_events(self, view_name, event_name, view_data, view_kwargs, mock_is_forum_v2_enabled, mock_request, mock_emit):
def test_team_events(self, view_name, event_name, view_data, view_kwargs, mock_request, mock_emit):
user = self.student
team = CourseTeamFactory.create(discussion_topic_id=TEAM_COMMENTABLE_ID)
CourseTeamMembershipFactory.create(team=team, user=user)
@@ -2074,7 +1905,6 @@ class ForumEventTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockReque
forum_event = views.TRACKING_LOG_TO_EVENT_MAPS.get(event_name)
forum_event.connect(event_receiver)
mock_is_forum_v2_enabled.return_value = False
self._set_mock_request_data(mock_request, {
'closed': False,
'commentable_id': TEAM_COMMENTABLE_ID,
@@ -2113,11 +1943,9 @@ class ForumEventTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockReque
@ddt.unpack
@patch('eventtracking.tracker.emit')
@patch('openedx.core.djangoapps.django_comment_common.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled', autospec=True)
def test_thread_voted_event(self, view_name, obj_id_name, obj_type, mock_is_forum_v2_enabled, mock_request, mock_emit):
def test_thread_voted_event(self, view_name, obj_id_name, obj_type, mock_request, mock_emit):
undo = view_name.startswith('undo')
mock_is_forum_v2_enabled.return_value = False
self._set_mock_request_data(mock_request, {
'closed': False,
'commentable_id': 'test_commentable_id',
@@ -2143,13 +1971,11 @@ class ForumEventTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockReque
@ddt.data('follow_thread', 'unfollow_thread',)
@patch('eventtracking.tracker.emit')
@patch('openedx.core.djangoapps.django_comment_common.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled', autospec=True)
def test_thread_followed_event(self, view_name, mock_is_forum_v2_enabled, mock_request, mock_emit):
def test_thread_followed_event(self, view_name, mock_request, mock_emit):
event_receiver = Mock()
for signal in views.TRACKING_LOG_TO_EVENT_MAPS.values():
signal.connect(event_receiver)
mock_is_forum_v2_enabled.return_value = False
self._set_mock_request_data(mock_request, {
'closed': False,
'commentable_id': 'test_commentable_id',
@@ -2199,11 +2025,10 @@ class UsersEndpointTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockRe
cls.other_user = UserFactory.create(username="other")
CourseEnrollmentFactory(user=cls.other_user, course_id=cls.course.id)
def set_post_counts(self, mock_is_forum_v2_enabled, mock_request, threads_count=1, comments_count=1):
def set_post_counts(self, mock_request, threads_count=1, comments_count=1):
"""
sets up a mock response from the comments service for getting post counts for our other_user
"""
mock_is_forum_v2_enabled.return_value = False
self._set_mock_request_data(mock_request, {
"threads_count": threads_count,
"comments_count": comments_count,
@@ -2217,17 +2042,15 @@ class UsersEndpointTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockRe
return views.users(request, course_id=str(course_id))
@patch('openedx.core.djangoapps.django_comment_common.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled', autospec=True)
def test_finds_exact_match(self, mock_is_forum_v2_enabled, mock_request):
self.set_post_counts(mock_is_forum_v2_enabled, mock_request)
def test_finds_exact_match(self, mock_request):
self.set_post_counts(mock_request)
response = self.make_request(username="other")
assert response.status_code == 200
assert json.loads(response.content.decode('utf-8'))['users'] == [{'id': self.other_user.id, 'username': self.other_user.username}]
@patch('openedx.core.djangoapps.django_comment_common.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled', autospec=True)
def test_finds_no_match(self, mock_is_forum_v2_enabled, mock_request):
self.set_post_counts(mock_is_forum_v2_enabled, mock_request)
def test_finds_no_match(self, mock_request):
self.set_post_counts(mock_request)
response = self.make_request(username="othor")
assert response.status_code == 200
assert json.loads(response.content.decode('utf-8'))['users'] == []
@@ -2263,9 +2086,8 @@ class UsersEndpointTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockRe
assert 'users' not in content
@patch('openedx.core.djangoapps.django_comment_common.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled', autospec=True)
def test_requires_matched_user_has_forum_content(self, mock_is_forum_v2_enabled, mock_request):
self.set_post_counts(mock_is_forum_v2_enabled, mock_request, 0, 0)
def test_requires_matched_user_has_forum_content(self, mock_request):
self.set_post_counts(mock_request, 0, 0)
response = self.make_request(username="other")
assert response.status_code == 200
assert json.loads(response.content.decode('utf-8'))['users'] == []

View File

@@ -562,6 +562,7 @@ def create_thread(request, course_id, commentable_id):
params['context'] = ThreadContext.STANDALONE
else:
params['context'] = ThreadContext.COURSE
thread = cc.Thread(**params)
# Divide the thread if required

View File

@@ -60,76 +60,51 @@ class CohortedTopicGroupIdTestMixin(GroupIdAssertionMixin):
Provides test cases to verify that views pass the correct `group_id` to
the comments service when requesting content in cohorted discussions.
"""
def call_view(self, mock_is_forum_v2_enabled, mock_request, commentable_id, user, group_id, pass_group_id=True):
def call_view(self, mock_request, commentable_id, user, group_id, pass_group_id=True):
"""
Call the view for the implementing test class, constructing a request
from the parameters.
"""
pass # lint-amnesty, pylint: disable=unnecessary-pass
def test_cohorted_topic_student_without_group_id(self, mock_is_forum_v2_enabled, mock_request):
self.call_view(mock_is_forum_v2_enabled, mock_request, "cohorted_topic", self.student, '', pass_group_id=False)
def test_cohorted_topic_student_without_group_id(self, mock_request):
self.call_view(mock_request, "cohorted_topic", self.student, '', pass_group_id=False)
self._assert_comments_service_called_with_group_id(mock_request, self.student_cohort.id)
def test_cohorted_topic_student_none_group_id(self, mock_is_forum_v2_enabled, mock_request):
self.call_view(mock_is_forum_v2_enabled, mock_request, "cohorted_topic", self.student, "")
def test_cohorted_topic_student_none_group_id(self, mock_request):
self.call_view(mock_request, "cohorted_topic", self.student, "")
self._assert_comments_service_called_with_group_id(mock_request, self.student_cohort.id)
def test_cohorted_topic_student_with_own_group_id(self, mock_is_forum_v2_enabled, mock_request):
self.call_view(mock_is_forum_v2_enabled, mock_request, "cohorted_topic", self.student, self.student_cohort.id)
def test_cohorted_topic_student_with_own_group_id(self, mock_request):
self.call_view(mock_request, "cohorted_topic", self.student, self.student_cohort.id)
self._assert_comments_service_called_with_group_id(mock_request, self.student_cohort.id)
def test_cohorted_topic_student_with_other_group_id(self, mock_is_forum_v2_enabled, mock_request):
self.call_view(
mock_is_forum_v2_enabled,
mock_request,
"cohorted_topic",
self.student,
self.moderator_cohort.id
)
def test_cohorted_topic_student_with_other_group_id(self, mock_request):
self.call_view(mock_request, "cohorted_topic", self.student, self.moderator_cohort.id)
self._assert_comments_service_called_with_group_id(mock_request, self.student_cohort.id)
def test_cohorted_topic_moderator_without_group_id(self, mock_is_forum_v2_enabled, mock_request):
self.call_view(
mock_is_forum_v2_enabled,
mock_request,
"cohorted_topic",
self.moderator,
'',
pass_group_id=False
)
def test_cohorted_topic_moderator_without_group_id(self, mock_request):
self.call_view(mock_request, "cohorted_topic", self.moderator, '', pass_group_id=False)
self._assert_comments_service_called_without_group_id(mock_request)
def test_cohorted_topic_moderator_none_group_id(self, mock_is_forum_v2_enabled, mock_request):
self.call_view(mock_is_forum_v2_enabled, mock_request, "cohorted_topic", self.moderator, "")
def test_cohorted_topic_moderator_none_group_id(self, mock_request):
self.call_view(mock_request, "cohorted_topic", self.moderator, "")
self._assert_comments_service_called_without_group_id(mock_request)
def test_cohorted_topic_moderator_with_own_group_id(self, mock_is_forum_v2_enabled, mock_request):
self.call_view(
mock_is_forum_v2_enabled,
mock_request,
"cohorted_topic",
self.moderator,
self.moderator_cohort.id
)
def test_cohorted_topic_moderator_with_own_group_id(self, mock_request):
self.call_view(mock_request, "cohorted_topic", self.moderator, self.moderator_cohort.id)
self._assert_comments_service_called_with_group_id(mock_request, self.moderator_cohort.id)
def test_cohorted_topic_moderator_with_other_group_id(self, mock_is_forum_v2_enabled, mock_request):
self.call_view(
mock_is_forum_v2_enabled,
mock_request,
"cohorted_topic",
self.moderator,
self.student_cohort.id
)
def test_cohorted_topic_moderator_with_other_group_id(self, mock_request):
self.call_view(mock_request, "cohorted_topic", self.moderator, self.student_cohort.id)
self._assert_comments_service_called_with_group_id(mock_request, self.student_cohort.id)
def test_cohorted_topic_moderator_with_invalid_group_id(self, mock_is_forum_v2_enabled, mock_request):
def test_cohorted_topic_moderator_with_invalid_group_id(self, mock_request):
invalid_id = self.student_cohort.id + self.moderator_cohort.id
response = self.call_view(mock_is_forum_v2_enabled, mock_request, "cohorted_topic", self.moderator, invalid_id) # lint-amnesty, pylint: disable=assignment-from-no-return
response = self.call_view(mock_request, "cohorted_topic", self.moderator, invalid_id) # lint-amnesty, pylint: disable=assignment-from-no-return
assert response.status_code == 500
def test_cohorted_topic_enrollment_track_invalid_group_id(self, mock_is_forum_v2_enabled, mock_request):
def test_cohorted_topic_enrollment_track_invalid_group_id(self, mock_request):
CourseModeFactory.create(course_id=self.course.id, mode_slug=CourseMode.AUDIT)
CourseModeFactory.create(course_id=self.course.id, mode_slug=CourseMode.VERIFIED)
discussion_settings = CourseDiscussionSettings.get(self.course.id)
@@ -140,7 +115,7 @@ class CohortedTopicGroupIdTestMixin(GroupIdAssertionMixin):
})
invalid_id = -1000
response = self.call_view(mock_is_forum_v2_enabled, mock_request, "cohorted_topic", self.moderator, invalid_id) # lint-amnesty, pylint: disable=assignment-from-no-return
response = self.call_view(mock_request, "cohorted_topic", self.moderator, invalid_id) # lint-amnesty, pylint: disable=assignment-from-no-return
assert response.status_code == 500
@@ -149,95 +124,57 @@ class NonCohortedTopicGroupIdTestMixin(GroupIdAssertionMixin):
Provides test cases to verify that views pass the correct `group_id` to
the comments service when requesting content in non-cohorted discussions.
"""
def call_view(self, mock_is_forum_v2_enabled, mock_request, commentable_id, user, group_id, pass_group_id=True):
def call_view(self, mock_request, commentable_id, user, group_id, pass_group_id=True):
"""
Call the view for the implementing test class, constructing a request
from the parameters.
"""
pass # lint-amnesty, pylint: disable=unnecessary-pass
def test_non_cohorted_topic_student_without_group_id(self, mock_is_forum_v2_enabled, mock_request):
self.call_view(
mock_is_forum_v2_enabled,
mock_request,
"non_cohorted_topic",
self.student,
'',
pass_group_id=False
)
def test_non_cohorted_topic_student_without_group_id(self, mock_request):
self.call_view(mock_request, "non_cohorted_topic", self.student, '', pass_group_id=False)
self._assert_comments_service_called_without_group_id(mock_request)
def test_non_cohorted_topic_student_none_group_id(self, mock_is_forum_v2_enabled, mock_request):
self.call_view(mock_is_forum_v2_enabled, mock_request, "non_cohorted_topic", self.student, '')
def test_non_cohorted_topic_student_none_group_id(self, mock_request):
self.call_view(mock_request, "non_cohorted_topic", self.student, '')
self._assert_comments_service_called_without_group_id(mock_request)
def test_non_cohorted_topic_student_with_own_group_id(self, mock_is_forum_v2_enabled, mock_request):
self.call_view(
mock_is_forum_v2_enabled,
mock_request,
"non_cohorted_topic",
self.student,
self.student_cohort.id
)
def test_non_cohorted_topic_student_with_own_group_id(self, mock_request):
self.call_view(mock_request, "non_cohorted_topic", self.student, self.student_cohort.id)
self._assert_comments_service_called_without_group_id(mock_request)
def test_non_cohorted_topic_student_with_other_group_id(self, mock_is_forum_v2_enabled, mock_request):
self.call_view(
mock_is_forum_v2_enabled,
mock_request,
"non_cohorted_topic",
self.student,
self.moderator_cohort.id
)
def test_non_cohorted_topic_student_with_other_group_id(self, mock_request):
self.call_view(mock_request, "non_cohorted_topic", self.student, self.moderator_cohort.id)
self._assert_comments_service_called_without_group_id(mock_request)
def test_non_cohorted_topic_moderator_without_group_id(self, mock_is_forum_v2_enabled, mock_request):
self.call_view(
mock_is_forum_v2_enabled,
mock_request,
"non_cohorted_topic",
self.moderator,
"",
pass_group_id=False,
)
def test_non_cohorted_topic_moderator_without_group_id(self, mock_request):
self.call_view(mock_request, "non_cohorted_topic", self.moderator, '', pass_group_id=False)
self._assert_comments_service_called_without_group_id(mock_request)
def test_non_cohorted_topic_moderator_none_group_id(self, mock_is_forum_v2_enabled, mock_request):
self.call_view(mock_is_forum_v2_enabled, mock_request, "non_cohorted_topic", self.moderator, '')
def test_non_cohorted_topic_moderator_none_group_id(self, mock_request):
self.call_view(mock_request, "non_cohorted_topic", self.moderator, '')
self._assert_comments_service_called_without_group_id(mock_request)
def test_non_cohorted_topic_moderator_with_own_group_id(self, mock_is_forum_v2_enabled, mock_request):
self.call_view(
mock_is_forum_v2_enabled,
mock_request,
"non_cohorted_topic",
self.moderator,
self.moderator_cohort.id,
)
def test_non_cohorted_topic_moderator_with_own_group_id(self, mock_request):
self.call_view(mock_request, "non_cohorted_topic", self.moderator, self.moderator_cohort.id)
self._assert_comments_service_called_without_group_id(mock_request)
def test_non_cohorted_topic_moderator_with_other_group_id(self, mock_is_forum_v2_enabled, mock_request):
self.call_view(
mock_is_forum_v2_enabled,
mock_request,
"non_cohorted_topic",
self.moderator,
self.student_cohort.id,
)
def test_non_cohorted_topic_moderator_with_other_group_id(self, mock_request):
self.call_view(mock_request, "non_cohorted_topic", self.moderator, self.student_cohort.id)
self._assert_comments_service_called_without_group_id(mock_request)
def test_non_cohorted_topic_moderator_with_invalid_group_id(self, mock_is_forum_v2_enabled, mock_request):
def test_non_cohorted_topic_moderator_with_invalid_group_id(self, mock_request):
invalid_id = self.student_cohort.id + self.moderator_cohort.id
self.call_view(mock_is_forum_v2_enabled, mock_request, "non_cohorted_topic", self.moderator, invalid_id)
self.call_view(mock_request, "non_cohorted_topic", self.moderator, invalid_id)
self._assert_comments_service_called_without_group_id(mock_request)
def test_team_discussion_id_not_cohorted(self, mock_is_forum_v2_enabled, mock_request):
def test_team_discussion_id_not_cohorted(self, mock_request):
team = CourseTeamFactory(
course_id=self.course.id,
topic_id='topic-id'
)
team.add_user(self.student)
self.call_view(mock_is_forum_v2_enabled, mock_request, team.discussion_topic_id, self.student, '')
self.call_view(mock_request, team.discussion_topic_id, self.student, '')
self._assert_comments_service_called_without_group_id(mock_request)

View File

@@ -199,7 +199,7 @@ def _get_course(course_key: CourseKey, user: User, check_tab: bool = True) -> Co
return course
def _get_thread_and_context(request, thread_id, retrieve_kwargs=None, course_id=None):
def _get_thread_and_context(request, thread_id, retrieve_kwargs=None):
"""
Retrieve the given thread and build a serializer context for it, returning
both. This function also enforces access control for the thread (checking
@@ -213,7 +213,7 @@ def _get_thread_and_context(request, thread_id, retrieve_kwargs=None, course_id=
retrieve_kwargs["with_responses"] = False
if "mark_as_read" not in retrieve_kwargs:
retrieve_kwargs["mark_as_read"] = False
cc_thread = Thread(id=thread_id).retrieve(course_id=course_id, **retrieve_kwargs)
cc_thread = Thread(id=thread_id).retrieve(**retrieve_kwargs)
course_key = CourseKey.from_string(cc_thread["course_id"])
course = _get_course(course_key, request.user)
context = get_context(course, request, cc_thread)
@@ -1645,8 +1645,7 @@ def get_thread(request, thread_id, requested_fields=None, course_id=None):
retrieve_kwargs={
"with_responses": True,
"user_id": str(request.user.id),
},
course_id=course_id,
}
)
if course_id and course_id != cc_thread.course_id:
raise ThreadNotFoundError("Thread not found.")

View File

@@ -202,7 +202,7 @@ class DiscussionNotificationSender:
while has_more_subscribers:
subscribers = Subscription.fetch(self.thread.id, self.course.id, query_params={'page': page})
subscribers = Subscription.fetch(self.thread.id, query_params={'page': page})
if page <= subscribers.num_pages:
for subscriber in subscribers.collection:
# Check if the subscriber is not the thread creator or response creator

View File

@@ -68,7 +68,7 @@ def get_context(course, request, thread=None):
moderator_user_ids = get_moderator_users_list(course.id)
ta_user_ids = get_course_ta_users_list(course.id)
requester = request.user
cc_requester = CommentClientUser.from_django_user(requester).retrieve(course_id=course.id)
cc_requester = CommentClientUser.from_django_user(requester).retrieve()
cc_requester["course_id"] = course.id
course_discussion_settings = CourseDiscussionSettings.get(course.id)
is_global_staff = GlobalStaff().has_user(requester)

View File

@@ -1248,22 +1248,6 @@ class GetCommentListTest(ForumsEnableMixin, CommentsServiceMockMixin, SharedModu
httpretty.enable()
self.addCleanup(httpretty.reset)
self.addCleanup(httpretty.disable)
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.models.forum_api.get_course_id_by_comment"
)
self.mock_get_course_id_by_comment = patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread"
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
self.maxDiff = None # pylint: disable=invalid-name
self.user = UserFactory.create()
self.register_get_user_response(self.user)
@@ -1888,12 +1872,6 @@ class CreateThreadTest(
httpretty.enable()
self.addCleanup(httpretty.reset)
self.addCleanup(httpretty.disable)
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
self.user = UserFactory.create()
self.register_get_user_response(self.user)
self.request = RequestFactory().get("/test_path")
@@ -2220,22 +2198,6 @@ class CreateCommentTest(
self.course = CourseFactory.create()
self.addCleanup(httpretty.reset)
self.addCleanup(httpretty.disable)
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.models.forum_api.get_course_id_by_comment"
)
self.mock_get_course_id_by_comment = patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread"
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
self.user = UserFactory.create()
self.register_get_user_response(self.user)
self.request = RequestFactory().get("/test_path")
@@ -2627,17 +2589,6 @@ class UpdateThreadTest(
httpretty.enable()
self.addCleanup(httpretty.reset)
self.addCleanup(httpretty.disable)
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread"
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
self.user = UserFactory.create()
self.register_get_user_response(self.user)
@@ -3202,22 +3153,6 @@ class UpdateCommentTest(
self.addCleanup(httpretty.reset)
self.addCleanup(httpretty.disable)
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.models.forum_api.get_course_id_by_comment"
)
self.mock_get_course_id_by_comment = patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread"
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
self.user = UserFactory.create()
self.register_get_user_response(self.user)
self.request = RequestFactory().get("/test_path")
@@ -3735,22 +3670,6 @@ class DeleteThreadTest(
httpretty.enable()
self.addCleanup(httpretty.reset)
self.addCleanup(httpretty.disable)
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.models.forum_api.get_course_id_by_comment"
)
self.mock_get_course_id_by_comment = patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread"
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
self.user = UserFactory.create()
self.register_get_user_response(self.user)
self.request = RequestFactory().get("/test_path")
@@ -3904,22 +3823,6 @@ class DeleteCommentTest(
httpretty.enable()
self.addCleanup(httpretty.reset)
self.addCleanup(httpretty.disable)
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.models.forum_api.get_course_id_by_comment"
)
self.mock_get_course_id_by_comment = patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread"
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
self.user = UserFactory.create()
self.register_get_user_response(self.user)
self.request = RequestFactory().get("/test_path")
@@ -4088,17 +3991,6 @@ class RetrieveThreadTest(
httpretty.enable()
self.addCleanup(httpretty.reset)
self.addCleanup(httpretty.disable)
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread"
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
self.user = UserFactory.create()
self.register_get_user_response(self.user)
self.request = RequestFactory().get("/test_path")

View File

@@ -54,12 +54,6 @@ class SerializerTestMixin(ForumsEnableMixin, CommentsServiceMockMixin, UrlResetM
httpretty.enable()
self.addCleanup(httpretty.reset)
self.addCleanup(httpretty.disable)
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
self.maxDiff = None # pylint: disable=invalid-name
self.user = UserFactory.create()
self.register_get_user_response(self.user)
@@ -577,12 +571,6 @@ class ThreadSerializerDeserializationTest(
httpretty.enable()
self.addCleanup(httpretty.reset)
self.addCleanup(httpretty.disable)
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
self.user = UserFactory.create()
self.register_get_user_response(self.user)
self.request = RequestFactory().get("/dummy")
@@ -814,22 +802,6 @@ class CommentSerializerDeserializationTest(ForumsEnableMixin, CommentsServiceMoc
httpretty.enable()
self.addCleanup(httpretty.reset)
self.addCleanup(httpretty.disable)
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.models.forum_api.get_course_id_by_comment"
)
self.mock_get_course_id_by_comment = patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread"
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
self.user = UserFactory.create()
self.register_get_user_response(self.user)
self.request = RequestFactory().get("/dummy")

View File

@@ -58,27 +58,10 @@ class TestNewThreadCreatedNotification(DiscussionAPIViewTestMixin, ModuleStoreTe
Setup test case
"""
super().setUp()
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
# Creating a course
self.course = CourseFactory.create()
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread",
return_value=self.course.id
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.models.forum_api.get_course_id_by_comment",
return_value=self.course.id
)
self.mock_get_course_id_by_comment = patcher.start()
self.addCleanup(patcher.stop)
# Creating relative discussion and cohort settings
CourseCohortsSettings.objects.create(course_id=str(self.course.id))
CourseDiscussionSettings.objects.create(course_id=str(self.course.id), _divided_discussions='[]')
@@ -267,26 +250,8 @@ class TestSendResponseNotifications(DiscussionAPIViewTestMixin, ModuleStoreTestC
super().setUp()
httpretty.reset()
httpretty.enable()
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
self.course = CourseFactory.create()
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread",
return_value=self.course.id
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.models.forum_api.get_course_id_by_comment",
return_value=self.course.id
)
self.mock_get_course_id_by_comment = patcher.start()
self.addCleanup(patcher.stop)
self.user_1 = UserFactory.create()
CourseEnrollment.enroll(self.user_1, self.course.id)
self.user_2 = UserFactory.create()
@@ -571,26 +536,8 @@ class TestSendCommentNotification(DiscussionAPIViewTestMixin, ModuleStoreTestCas
super().setUp()
httpretty.reset()
httpretty.enable()
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
self.course = CourseFactory.create()
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread",
return_value=self.course.id
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.models.forum_api.get_course_id_by_comment",
return_value=self.course.id
)
self.mock_get_course_id_by_comment = patcher.start()
self.addCleanup(patcher.stop)
self.user_1 = UserFactory.create()
CourseEnrollment.enroll(self.user_1, self.course.id)
self.user_2 = UserFactory.create()
@@ -656,26 +603,8 @@ class TestResponseEndorsedNotifications(DiscussionAPIViewTestMixin, ModuleStoreT
super().setUp()
httpretty.reset()
httpretty.enable()
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
self.course = CourseFactory.create()
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread",
return_value=self.course.id
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.models.forum_api.get_course_id_by_comment",
return_value=self.course.id
)
self.mock_get_course_id_by_comment = patcher.start()
self.addCleanup(patcher.stop)
self.user_1 = UserFactory.create()
CourseEnrollment.enroll(self.user_1, self.course.id)
self.user_2 = UserFactory.create()

View File

@@ -171,12 +171,6 @@ class UploadFileViewTest(ForumsEnableMixin, CommentsServiceMockMixin, UrlResetMi
self.user = UserFactory.create(password=self.TEST_PASSWORD)
self.course = CourseFactory.create(org='a', course='b', run='c', start=datetime.now(UTC))
self.url = reverse("upload_file", kwargs={"course_id": str(self.course.id)})
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
def user_login(self):
"""
@@ -307,7 +301,6 @@ class UploadFileViewTest(ForumsEnableMixin, CommentsServiceMockMixin, UrlResetMi
@ddt.ddt
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_FORUM_V2": False})
class CommentViewSetListByUserTest(
ForumsEnableMixin,
CommentsServiceMockMixin,
@@ -326,12 +319,6 @@ class CommentViewSetListByUserTest(
httpretty.enable()
self.addCleanup(httpretty.reset)
self.addCleanup(httpretty.disable)
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
self.user = UserFactory.create(password=self.TEST_PASSWORD)
self.register_get_user_response(self.user)
@@ -513,12 +500,6 @@ class CourseViewTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
def setUp(self):
super().setUp()
self.url = reverse("discussion_course", kwargs={"course_id": str(self.course.id)})
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
def test_404(self):
response = self.client.get(
@@ -580,12 +561,6 @@ class RetireViewTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
self.superuser_client = APIClient()
self.retired_username = get_retired_username_by_username(self.user.username)
self.url = reverse("retire_discussion_user")
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
def assert_response_correct(self, response, expected_status, expected_content):
"""
@@ -656,12 +631,6 @@ class ReplaceUsernamesViewTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
self.worker_client = APIClient()
self.new_username = "test_username_replacement"
self.url = reverse("replace_discussion_username")
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
def assert_response_correct(self, response, expected_status, expected_content):
"""
@@ -764,12 +733,6 @@ class CourseTopicsViewTest(DiscussionAPIViewTestMixin, CommentsServiceMockMixin,
"courseware-3": {"discussion": 7, "question": 2},
}
self.register_get_course_commentable_counts_response(self.course.id, self.thread_counts_map)
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
def create_course(self, blocks_count, module_store, topics):
"""
@@ -1025,12 +988,6 @@ class CourseTopicsViewV3Test(DiscussionAPIViewTestMixin, CommentsServiceMockMixi
patcher.start()
self.addCleanup(patcher.stop)
self.url = reverse("course_topics_v3", kwargs={"course_id": str(self.course.id)})
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
def test_basic(self):
response = self.client.get(self.url)
@@ -1067,12 +1024,6 @@ class ThreadViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase, Pro
super().setUp()
self.author = UserFactory.create()
self.url = reverse("thread-list")
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
def create_source_thread(self, overrides=None):
"""
@@ -1414,12 +1365,6 @@ class ThreadViewSetCreateTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
def setUp(self):
super().setUp()
self.url = reverse("thread-list")
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
def test_basic(self):
self.register_get_user_response(self.user)
@@ -1492,17 +1437,6 @@ class ThreadViewSetPartialUpdateTest(DiscussionAPIViewTestMixin, ModuleStoreTest
self.unsupported_media_type = JSONParser.media_type
super().setUp()
self.url = reverse("thread-detail", kwargs={"thread_id": "test_thread"})
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread"
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
def test_basic(self):
self.register_get_user_response(self.user)
@@ -1647,17 +1581,6 @@ class ThreadViewSetDeleteTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
super().setUp()
self.url = reverse("thread-detail", kwargs={"thread_id": "test_thread"})
self.thread_id = "test_thread"
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread"
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
def test_basic(self):
self.register_get_user_response(self.user)
@@ -1758,12 +1681,6 @@ class LearnerThreadViewAPITest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
]
self.url = reverse("discussion_learner_threads", kwargs={'course_id': str(self.course.id)})
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
def update_thread(self, thread):
"""
@@ -2006,17 +1923,6 @@ class CommentViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase, Pr
self.url = reverse("comment-list")
self.thread_id = "test_thread"
self.storage = get_profile_image_storage()
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread"
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
def create_source_comment(self, overrides=None):
"""
@@ -2471,22 +2377,6 @@ class CommentViewSetDeleteTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
super().setUp()
self.url = reverse("comment-detail", kwargs={"comment_id": "test_comment"})
self.comment_id = "test_comment"
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.models.forum_api.get_course_id_by_comment"
)
self.mock_get_course_id_by_comment = patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread"
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
def test_basic(self):
self.register_get_user_response(self.user)
@@ -2526,23 +2416,6 @@ class CommentViewSetCreateTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
def setUp(self):
super().setUp()
self.url = reverse("comment-list")
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.models.forum_api.get_course_id_by_comment"
)
self.mock_get_course_id_by_comment = patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread"
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
def test_basic(self):
self.register_get_user_response(self.user)
@@ -2645,22 +2518,6 @@ class CommentViewSetPartialUpdateTest(DiscussionAPIViewTestMixin, ModuleStoreTes
httpretty.enable()
self.addCleanup(httpretty.reset)
self.addCleanup(httpretty.disable)
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.models.forum_api.get_course_id_by_comment"
)
self.mock_get_course_id_by_comment = patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread"
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
self.register_get_user_response(self.user)
self.url = reverse("comment-detail", kwargs={"comment_id": "test_comment"})
@@ -2783,22 +2640,6 @@ class ThreadViewSetRetrieveTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase,
super().setUp()
self.url = reverse("thread-detail", kwargs={"thread_id": "test_thread"})
self.thread_id = "test_thread"
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.models.forum_api.get_course_id_by_comment"
)
self.mock_get_course_id_by_comment = patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread"
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
def test_basic(self):
self.register_get_user_response(self.user)
@@ -2852,22 +2693,6 @@ class CommentViewSetRetrieveTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase
self.url = reverse("comment-detail", kwargs={"comment_id": "test_comment"})
self.thread_id = "test_thread"
self.comment_id = "test_comment"
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.models.forum_api.get_course_id_by_comment"
)
self.mock_get_course_id_by_comment = patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread"
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
def make_comment_data(self, comment_id, parent_id=None, children=[]): # pylint: disable=W0102
"""
@@ -3013,12 +2838,6 @@ class CourseDiscussionSettingsAPIViewTest(APITestCase, UrlResetMixin, ModuleStor
self.path = reverse('discussion_course_settings', kwargs={'course_id': str(self.course.id)})
self.password = self.TEST_PASSWORD
self.user = UserFactory(username='staff', password=self.password, is_staff=True)
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
def _get_oauth_headers(self, user):
"""Return the OAuth headers for testing OAuth authentication"""
@@ -3308,12 +3127,6 @@ class CourseDiscussionRolesAPIViewTest(APITestCase, UrlResetMixin, ModuleStoreTe
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
def setUp(self):
super().setUp()
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
self.course = CourseFactory.create(
org="x",
course="y",
@@ -3505,12 +3318,6 @@ class CourseActivityStatsTest(ForumsEnableMixin, UrlResetMixin, CommentsServiceM
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
def setUp(self) -> None:
super().setUp()
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
self.course = CourseFactory.create()
self.course_key = str(self.course.id)
seed_permissions_roles(self.course.id)

View File

@@ -232,22 +232,6 @@ class TaskTestCase(ModuleStoreTestCase): # lint-amnesty, pylint: disable=missin
thread_permalink = '/courses/discussion/dummy_discussion_id'
self.permalink_patcher = mock.patch('lms.djangoapps.discussion.tasks.permalink', return_value=thread_permalink)
self.mock_permalink = self.permalink_patcher.start()
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.models.forum_api.get_course_id_by_comment"
)
self.mock_get_course_id_by_comment = patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread"
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
def tearDown(self):
super().tearDown()

View File

@@ -4,7 +4,6 @@ Tests the forum notification views.
import json
import logging
from datetime import datetime
from unittest import mock
from unittest.mock import ANY, Mock, call, patch
import ddt
@@ -110,20 +109,9 @@ class ViewsExceptionTestCase(UrlResetMixin, ModuleStoreTestCase): # lint-amnest
config = ForumsConfig.current()
config.enabled = True
config.save()
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread"
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
@patch('common.djangoapps.student.models.user.cc.User.from_django_user')
@patch('openedx.core.djangoapps.django_comment_common.comment_client.user.User.active_threads')
@patch('common.djangoapps.student.models.user.cc.User.active_threads')
def test_user_profile_exception(self, mock_threads, mock_from_django_user):
# Mock the code that makes the HTTP requests to the cs_comment_service app
@@ -335,17 +323,6 @@ class SingleThreadTestCase(ForumsEnableMixin, ModuleStoreTestCase): # lint-amne
def setUp(self):
super().setUp()
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread"
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
self.course = CourseFactory.create(discussion_topics={'dummy discussion': {'id': 'dummy_discussion_id'}})
self.student = UserFactory.create()
@@ -536,20 +513,6 @@ class SingleThreadQueryCountTestCase(ForumsEnableMixin, ModuleStoreTestCase):
Ensures the number of modulestore queries and number of sql queries are
independent of the number of responses retrieved for a given discussion thread.
"""
def setUp(self):
super().setUp()
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread"
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
@ddt.data(
# split mongo: 3 queries, regardless of thread response size.
(False, 1, 2, 2, 21, 8),
@@ -619,20 +582,6 @@ class SingleThreadQueryCountTestCase(ForumsEnableMixin, ModuleStoreTestCase):
@patch('requests.request', autospec=True)
class SingleCohortedThreadTestCase(CohortedTestCase): # lint-amnesty, pylint: disable=missing-class-docstring
def setUp(self):
super().setUp()
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread"
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
def _create_mock_cohorted_thread(self, mock_request): # lint-amnesty, pylint: disable=missing-function-docstring
mock_text = "dummy content"
mock_thread_id = "test_thread_id"
@@ -695,20 +644,6 @@ class SingleCohortedThreadTestCase(CohortedTestCase): # lint-amnesty, pylint: d
@patch('openedx.core.djangoapps.django_comment_common.comment_client.utils.requests.request', autospec=True)
class SingleThreadAccessTestCase(CohortedTestCase): # lint-amnesty, pylint: disable=missing-class-docstring
def setUp(self):
super().setUp()
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread"
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
def call_view(self, mock_request, commentable_id, user, group_id, thread_group_id=None, pass_group_id=True): # lint-amnesty, pylint: disable=missing-function-docstring
thread_id = "test_thread_id"
mock_request.side_effect = make_mock_request_impl(
@@ -811,20 +746,6 @@ class SingleThreadAccessTestCase(CohortedTestCase): # lint-amnesty, pylint: dis
class SingleThreadGroupIdTestCase(CohortedTestCase, GroupIdAssertionMixin): # lint-amnesty, pylint: disable=missing-class-docstring
cs_endpoint = "/threads/dummy_thread_id"
def setUp(self):
super().setUp()
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread"
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
def call_view(self, mock_request, commentable_id, user, group_id, pass_group_id=True, is_ajax=False): # lint-amnesty, pylint: disable=missing-function-docstring
mock_request.side_effect = make_mock_request_impl(
course=self.course, text="dummy context", group_id=self.student_cohort.id
@@ -960,22 +881,6 @@ class SingleThreadContentGroupTestCase(ForumsEnableMixin, UrlResetMixin, Content
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
def setUp(self):
super().setUp()
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.models.forum_api.get_course_id_by_comment"
)
self.mock_get_course_id_by_comment = patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread"
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
def assert_can_access(self, user, discussion_id, thread_id, should_have_access):
"""
@@ -1141,7 +1046,6 @@ class InlineDiscussionContextTestCase(ForumsEnableMixin, ModuleStoreTestCase):
@patch('openedx.core.djangoapps.django_comment_common.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled', autospec=True)
class InlineDiscussionGroupIdTestCase( # lint-amnesty, pylint: disable=missing-class-docstring
CohortedTestCase,
CohortedTopicGroupIdTestMixin,
@@ -1152,22 +1056,8 @@ class InlineDiscussionGroupIdTestCase( # lint-amnesty, pylint: disable=missing-
def setUp(self):
super().setUp()
self.cohorted_commentable_id = 'cohorted_topic'
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread"
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
def call_view(
self,
mock_is_forum_v2_enabled,
mock_request,
commentable_id,
user,
group_id,
pass_group_id=True
): # pylint: disable=arguments-differ
mock_is_forum_v2_enabled.return_value = False
def call_view(self, mock_request, commentable_id, user, group_id, pass_group_id=True):
kwargs = {'commentable_id': self.cohorted_commentable_id}
if group_id:
# avoid causing a server error when the LMS chokes attempting
@@ -1194,9 +1084,8 @@ class InlineDiscussionGroupIdTestCase( # lint-amnesty, pylint: disable=missing-
commentable_id
)
def test_group_info_in_ajax_response(self, mock_is_forum_v2_enabled, mock_request):
def test_group_info_in_ajax_response(self, mock_request):
response = self.call_view(
mock_is_forum_v2_enabled,
mock_request,
self.cohorted_commentable_id,
self.student,
@@ -1208,29 +1097,10 @@ class InlineDiscussionGroupIdTestCase( # lint-amnesty, pylint: disable=missing-
@patch('openedx.core.djangoapps.django_comment_common.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled', autospec=True)
class ForumFormDiscussionGroupIdTestCase(CohortedTestCase, CohortedTopicGroupIdTestMixin): # lint-amnesty, pylint: disable=missing-class-docstring
cs_endpoint = "/threads"
def setUp(self):
super().setUp()
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread"
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
def call_view(
self,
mock_is_forum_v2_enabled,
mock_request,
commentable_id,
user,
group_id,
pass_group_id=True,
is_ajax=False
): # pylint: disable=arguments-differ
mock_is_forum_v2_enabled.return_value = False
def call_view(self, mock_request, commentable_id, user, group_id, pass_group_id=True, is_ajax=False): # pylint: disable=arguments-differ
kwargs = {}
if group_id:
kwargs['group_id'] = group_id
@@ -1250,9 +1120,8 @@ class ForumFormDiscussionGroupIdTestCase(CohortedTestCase, CohortedTopicGroupIdT
**headers
)
def test_group_info_in_html_response(self, mock_is_forum_v2_enabled, mock_request):
def test_group_info_in_html_response(self, mock_request):
response = self.call_view(
mock_is_forum_v2_enabled,
mock_request,
"cohorted_topic",
self.student,
@@ -1260,9 +1129,8 @@ class ForumFormDiscussionGroupIdTestCase(CohortedTestCase, CohortedTopicGroupIdT
)
self._assert_html_response_contains_group_info(response)
def test_group_info_in_ajax_response(self, mock_is_forum_v2_enabled, mock_request):
def test_group_info_in_ajax_response(self, mock_request):
response = self.call_view(
mock_is_forum_v2_enabled,
mock_request,
"cohorted_topic",
self.student,
@@ -1275,38 +1143,16 @@ class ForumFormDiscussionGroupIdTestCase(CohortedTestCase, CohortedTopicGroupIdT
@patch('openedx.core.djangoapps.django_comment_common.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled', autospec=True)
class UserProfileDiscussionGroupIdTestCase(CohortedTestCase, CohortedTopicGroupIdTestMixin): # lint-amnesty, pylint: disable=missing-class-docstring
cs_endpoint = "/active_threads"
def setUp(self):
super().setUp()
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.models.forum_api.get_course_id_by_comment"
)
self.mock_get_course_id_by_comment = patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread"
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
def call_view_for_profiled_user(
self,
mock_is_forum_v2_enabled,
mock_request,
requesting_user,
profiled_user,
group_id,
pass_group_id,
is_ajax=False
self, mock_request, requesting_user, profiled_user, group_id, pass_group_id, is_ajax=False
):
"""
Calls "user_profile" view method on behalf of "requesting_user" to get information about
the user "profiled_user".
"""
mock_is_forum_v2_enabled.return_value = False
kwargs = {}
if group_id:
kwargs['group_id'] = group_id
@@ -1326,23 +1172,13 @@ class UserProfileDiscussionGroupIdTestCase(CohortedTestCase, CohortedTopicGroupI
**headers
)
def call_view(
self,
mock_is_forum_v2_enabled,
mock_request,
_commentable_id,
user,
group_id,
pass_group_id=True,
is_ajax=False
): # pylint: disable=arguments-differ
def call_view(self, mock_request, _commentable_id, user, group_id, pass_group_id=True, is_ajax=False): # pylint: disable=arguments-differ
return self.call_view_for_profiled_user(
mock_is_forum_v2_enabled, mock_request, user, user, group_id, pass_group_id=pass_group_id, is_ajax=is_ajax
mock_request, user, user, group_id, pass_group_id=pass_group_id, is_ajax=is_ajax
)
def test_group_info_in_html_response(self, mock_is_forum_v2_enabled, mock_request):
def test_group_info_in_html_response(self, mock_request):
response = self.call_view(
mock_is_forum_v2_enabled,
mock_request,
"cohorted_topic",
self.student,
@@ -1351,9 +1187,8 @@ class UserProfileDiscussionGroupIdTestCase(CohortedTestCase, CohortedTopicGroupI
)
self._assert_html_response_contains_group_info(response)
def test_group_info_in_ajax_response(self, mock_is_forum_v2_enabled, mock_request):
def test_group_info_in_ajax_response(self, mock_request):
response = self.call_view(
mock_is_forum_v2_enabled,
mock_request,
"cohorted_topic",
self.student,
@@ -1365,14 +1200,7 @@ class UserProfileDiscussionGroupIdTestCase(CohortedTestCase, CohortedTopicGroupI
)
def _test_group_id_passed_to_user_profile(
self,
mock_is_forum_v2_enabled,
mock_request,
expect_group_id_in_request,
requesting_user,
profiled_user,
group_id,
pass_group_id
self, mock_request, expect_group_id_in_request, requesting_user, profiled_user, group_id, pass_group_id
):
"""
Helper method for testing whether or not group_id was passed to the user_profile request.
@@ -1393,11 +1221,10 @@ class UserProfileDiscussionGroupIdTestCase(CohortedTestCase, CohortedTopicGroupI
has_course_id = "course_id" in params
if (for_specific_course and has_course_id) or (not for_specific_course and not has_course_id):
return params
pytest.fail(f"Did not find appropriate user_profile call for 'for_specific_course'={for_specific_course}")
pytest.fail("Did not find appropriate user_profile call for 'for_specific_course'=" + for_specific_course)
mock_request.reset_mock()
self.call_view_for_profiled_user(
mock_is_forum_v2_enabled,
mock_request,
requesting_user,
profiled_user,
@@ -1416,7 +1243,7 @@ class UserProfileDiscussionGroupIdTestCase(CohortedTestCase, CohortedTopicGroupI
else:
assert 'group_id' not in params_with_course_id
def test_group_id_passed_to_user_profile_student(self, mock_is_forum_v2_enabled, mock_request):
def test_group_id_passed_to_user_profile_student(self, mock_request):
"""
Test that the group id is always included when requesting user profile information for a particular
course if the requester does not have discussion moderation privileges.
@@ -1427,13 +1254,7 @@ class UserProfileDiscussionGroupIdTestCase(CohortedTestCase, CohortedTopicGroupI
(non-privileged user).
"""
self._test_group_id_passed_to_user_profile(
mock_is_forum_v2_enabled,
mock_request,
True,
self.student,
profiled_user,
self.student_cohort.id,
pass_group_id
mock_request, True, self.student, profiled_user, self.student_cohort.id, pass_group_id
)
# In all these test cases, the requesting_user is the student (non-privileged user).
@@ -1443,7 +1264,7 @@ class UserProfileDiscussionGroupIdTestCase(CohortedTestCase, CohortedTopicGroupI
verify_group_id_always_present(profiled_user=self.moderator, pass_group_id=True)
verify_group_id_always_present(profiled_user=self.moderator, pass_group_id=False)
def test_group_id_user_profile_moderator(self, mock_is_forum_v2_enabled, mock_request):
def test_group_id_user_profile_moderator(self, mock_request):
"""
Test that the group id is only included when a privileged user requests user profile information for a
particular course and user if the group_id is explicitly passed in.
@@ -1453,13 +1274,7 @@ class UserProfileDiscussionGroupIdTestCase(CohortedTestCase, CohortedTopicGroupI
Helper method to verify that group_id is present.
"""
self._test_group_id_passed_to_user_profile(
mock_is_forum_v2_enabled,
mock_request,
True,
self.moderator,
profiled_user,
requested_cohort.id,
pass_group_id
mock_request, True, self.moderator, profiled_user, requested_cohort.id, pass_group_id
)
def verify_group_id_not_present(profiled_user, pass_group_id, requested_cohort=self.moderator_cohort):
@@ -1467,13 +1282,7 @@ class UserProfileDiscussionGroupIdTestCase(CohortedTestCase, CohortedTopicGroupI
Helper method to verify that group_id is not present.
"""
self._test_group_id_passed_to_user_profile(
mock_is_forum_v2_enabled,
mock_request,
False,
self.moderator,
profiled_user,
requested_cohort.id,
pass_group_id
mock_request, False, self.moderator, profiled_user, requested_cohort.id, pass_group_id
)
# In all these test cases, the requesting_user is the moderator (privileged user).
@@ -1492,28 +1301,10 @@ class UserProfileDiscussionGroupIdTestCase(CohortedTestCase, CohortedTopicGroupI
@patch('openedx.core.djangoapps.django_comment_common.comment_client.utils.requests.request', autospec=True)
@patch('openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled', autospec=True)
class FollowedThreadsDiscussionGroupIdTestCase(CohortedTestCase, CohortedTopicGroupIdTestMixin): # lint-amnesty, pylint: disable=missing-class-docstring
cs_endpoint = "/subscribed_threads"
def setUp(self):
super().setUp()
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread"
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
def call_view(
self,
mock_is_forum_v2_enabled,
mock_request,
commentable_id,
user,
group_id,
pass_group_id=True
): # pylint: disable=arguments-differ
mock_is_forum_v2_enabled.return_value = False
def call_view(self, mock_request, commentable_id, user, group_id, pass_group_id=True):
kwargs = {}
if group_id:
kwargs['group_id'] = group_id
@@ -1534,9 +1325,8 @@ class FollowedThreadsDiscussionGroupIdTestCase(CohortedTestCase, CohortedTopicGr
user.id
)
def test_group_info_in_ajax_response(self, mock_is_forum_v2_enabled, mock_request):
def test_group_info_in_ajax_response(self, mock_request):
response = self.call_view(
mock_is_forum_v2_enabled,
mock_request,
"cohorted_topic",
self.student,
@@ -1738,22 +1528,6 @@ class CommentsServiceRequestHeadersTestCase(ForumsEnableMixin, UrlResetMixin, Mo
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
def setUp(self):
super().setUp()
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.models.forum_api.get_course_id_by_comment"
)
self.mock_get_course_id_by_comment = patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread"
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
username = "foo"
password = "bar"
@@ -1968,20 +1742,6 @@ class SingleThreadUnicodeTestCase(ForumsEnableMixin, SharedModuleStoreTestCase,
with super().setUpClassAndTestData():
cls.course = CourseFactory.create(discussion_topics={'dummy_discussion_id': {'id': 'dummy_discussion_id'}})
def setUp(self):
super().setUp()
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread"
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
@classmethod
def setUpTestData(cls):
super().setUpTestData()
@@ -2098,17 +1858,7 @@ class EnterpriseConsentTestCase(EnterpriseTestConsentRequired, ForumsEnableMixin
def setUp(self):
# Invoke UrlResetMixin setUp
super().setUp()
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread"
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
username = "foo"
password = "bar"
@@ -2445,17 +2195,6 @@ class ThreadViewedEventTestCase(EventTestMixin, ForumsEnableMixin, UrlResetMixin
def setUp(self): # pylint: disable=arguments-differ
super().setUp('lms.djangoapps.discussion.django_comment_client.base.views.tracker')
patcher = mock.patch(
'openedx.core.djangoapps.discussions.config.waffle.ENABLE_FORUM_V2.is_enabled',
return_value=False
)
patcher.start()
self.addCleanup(patcher.stop)
patcher = mock.patch(
"openedx.core.djangoapps.django_comment_common.comment_client.thread.forum_api.get_course_id_by_thread"
)
self.mock_get_course_id_by_thread = patcher.start()
self.addCleanup(patcher.stop)
self.course = CourseFactory.create(
teams_configuration=TeamsConfig({
'topics': [{

View File

@@ -1,7 +1,6 @@
"""
Discussions feature toggles
"""
from openedx.core.djangoapps.discussions.config.waffle import WAFFLE_FLAG_NAMESPACE
from openedx.core.djangoapps.waffle_utils import CourseWaffleFlag
@@ -12,6 +11,4 @@ from openedx.core.djangoapps.waffle_utils import CourseWaffleFlag
# .. toggle_use_cases: temporary, open_edx
# .. toggle_creation_date: 2021-11-05
# .. toggle_target_removal_date: 2022-12-05
ENABLE_DISCUSSIONS_MFE = CourseWaffleFlag(
f"{WAFFLE_FLAG_NAMESPACE}.enable_discussions_mfe", __name__
)
ENABLE_DISCUSSIONS_MFE = CourseWaffleFlag(f'{WAFFLE_FLAG_NAMESPACE}.enable_discussions_mfe', __name__)

View File

@@ -2,7 +2,6 @@
This module contains various configuration settings via
waffle switches for the discussions app.
"""
from openedx.core.djangoapps.waffle_utils import CourseWaffleFlag
WAFFLE_FLAG_NAMESPACE = "discussions"
@@ -44,19 +43,3 @@ ENABLE_PAGES_AND_RESOURCES_MICROFRONTEND = CourseWaffleFlag(
ENABLE_NEW_STRUCTURE_DISCUSSIONS = CourseWaffleFlag(
f"{WAFFLE_FLAG_NAMESPACE}.enable_new_structure_discussions", __name__
)
# .. toggle_name: discussions.enable_forum_v2
# .. toggle_implementation: CourseWaffleFlag
# .. toggle_default: False
# .. toggle_description: Waffle flag to use the forum v2 instead of v1(cs_comment_service)
# .. toggle_use_cases: temporary, open_edx
# .. toggle_creation_date: 2024-9-26
# .. toggle_target_removal_date: 2025-12-05
ENABLE_FORUM_V2 = CourseWaffleFlag(f"{WAFFLE_FLAG_NAMESPACE}.enable_forum_v2", __name__)
def is_forum_v2_enabled(course_id):
"""
Returns a boolean if forum V2 is enabled on the course
"""
return ENABLE_FORUM_V2.is_enabled(course_id)

View File

@@ -4,9 +4,7 @@ from bs4 import BeautifulSoup
from openedx.core.djangoapps.django_comment_common.comment_client import models, settings
from .thread import Thread, _url_for_flag_abuse_thread, _url_for_unflag_abuse_thread
from .utils import CommentClientRequestError, get_course_key, perform_request
from forum import api as forum_api
from openedx.core.djangoapps.discussions.config.waffle import is_forum_v2_enabled
from .utils import CommentClientRequestError, perform_request
class Comment(models.Model):
@@ -70,21 +68,14 @@ class Comment(models.Model):
url = _url_for_flag_abuse_comment(voteable.id)
else:
raise CommentClientRequestError("Can only flag/unflag threads or comments")
course_key = get_course_key(self.attributes.get("course_id"))
if is_forum_v2_enabled(course_key):
if voteable.type == 'thread':
response = forum_api.update_thread_flag(voteable.id, "flag", user.id, str(course_key))
else:
response = forum_api.update_comment_flag(voteable.id, "flag", user.id, str(course_key))
else:
params = {'user_id': user.id}
response = perform_request(
'put',
url,
params,
metric_tags=self._metric_tags,
metric_action='comment.abuse.flagged'
)
params = {'user_id': user.id}
response = perform_request(
'put',
url,
params,
metric_tags=self._metric_tags,
metric_action='comment.abuse.flagged'
)
voteable._update_from_response(response)
def unFlagAbuse(self, user, voteable, removeAll):
@@ -94,37 +85,18 @@ class Comment(models.Model):
url = _url_for_unflag_abuse_comment(voteable.id)
else:
raise CommentClientRequestError("Can flag/unflag for threads or comments")
course_key = get_course_key(self.attributes.get("course_id"))
if is_forum_v2_enabled(course_key):
if voteable.type == "thread":
response = forum_api.update_thread_flag(
thread_id=voteable.id,
action="unflag",
user_id=user.id,
update_all=bool(removeAll),
course_id=str(course_key)
)
else:
response = forum_api.update_comment_flag(
comment_id=voteable.id,
action="unflag",
user_id=user.id,
update_all=bool(removeAll),
course_id=str(course_key)
)
else:
params = {'user_id': user.id}
params = {'user_id': user.id}
if removeAll:
params['all'] = True
if removeAll:
params['all'] = True
response = perform_request(
'put',
url,
params,
metric_tags=self._metric_tags,
metric_action='comment.abuse.unflagged'
)
response = perform_request(
'put',
url,
params,
metric_tags=self._metric_tags,
metric_action='comment.abuse.unflagged'
)
voteable._update_from_response(response)
@property

View File

@@ -7,10 +7,8 @@ from typing import Dict, Optional
from edx_django_utils.monitoring import function_trace
from opaque_keys.edx.keys import CourseKey
from forum import api as forum_api
from openedx.core.djangoapps.django_comment_common.comment_client import settings
from openedx.core.djangoapps.django_comment_common.comment_client.utils import perform_request
from openedx.core.djangoapps.discussions.config.waffle import is_forum_v2_enabled
def get_course_commentable_counts(course_key: CourseKey) -> Dict[str, Dict[str, int]]:
@@ -31,20 +29,17 @@ def get_course_commentable_counts(course_key: CourseKey) -> Dict[str, Dict[str,
}
"""
if is_forum_v2_enabled(course_key):
commentable_stats = forum_api.get_commentables_stats(str(course_key))
else:
url = f"{settings.PREFIX}/commentables/{course_key}/counts"
commentable_stats = perform_request(
'get',
url,
metric_tags=[
f"course_key:{course_key}",
"function:get_course_commentable_counts",
],
metric_action='commentable_stats.retrieve',
)
return commentable_stats
url = f"{settings.PREFIX}/commentables/{course_key}/counts"
response = perform_request(
'get',
url,
metric_tags=[
f"course_key:{course_key}",
"function:get_course_commentable_counts",
],
metric_action='commentable_stats.retrieve',
)
return response
@function_trace("get_course_user_stats")
@@ -81,21 +76,17 @@ def get_course_user_stats(course_key: CourseKey, params: Optional[Dict] = None)
"""
if params is None:
params = {}
if is_forum_v2_enabled(course_key):
course_stats = forum_api.get_user_course_stats(str(course_key), **params)
else:
url = f"{settings.PREFIX}/users/{course_key}/stats"
course_stats = perform_request(
'get',
url,
params,
metric_action='user.course_stats',
metric_tags=[
f"course_key:{course_key}",
"function:get_course_user_stats",
],
)
return course_stats
url = f"{settings.PREFIX}/users/{course_key}/stats"
return perform_request(
'get',
url,
params,
metric_action='user.course_stats',
metric_tags=[
f"course_key:{course_key}",
"function:get_course_user_stats",
],
)
@function_trace("update_course_users_stats")
@@ -109,17 +100,13 @@ def update_course_users_stats(course_key: CourseKey) -> Dict:
Returns:
dict: data returned by API. Contains count of users updated.
"""
if is_forum_v2_enabled(course_key):
course_stats = forum_api.update_users_in_course(str(course_key))
else:
url = f"{settings.PREFIX}/users/{course_key}/update_stats"
course_stats = perform_request(
'post',
url,
metric_action='user.update_course_stats',
metric_tags=[
f"course_key:{course_key}",
"function:update_course_users_stats",
],
)
return course_stats
url = f"{settings.PREFIX}/users/{course_key}/update_stats"
return perform_request(
'post',
url,
metric_action='user.update_course_stats',
metric_tags=[
f"course_key:{course_key}",
"function:update_course_users_stats",
],
)

View File

@@ -3,9 +3,7 @@
import logging
from .utils import CommentClientRequestError, extract, perform_request, get_course_key
from forum import api as forum_api
from openedx.core.djangoapps.discussions.config.waffle import is_forum_v2_enabled
from .utils import CommentClientRequestError, extract, perform_request
log = logging.getLogger(__name__)
@@ -71,25 +69,14 @@ class Model:
return self
def _retrieve(self, *args, **kwargs):
course_id = self.attributes.get("course_id") or kwargs.get("course_id")
if not course_id:
course_id = forum_api.get_course_id_by_comment(self.id)
course_key = get_course_key(course_id)
response = None
if is_forum_v2_enabled(course_key):
if self.type == "comment":
response = forum_api.get_parent_comment(comment_id=self.attributes["id"], course_id=str(course_key))
if response is None:
raise CommentClientRequestError("Forum v2 API call is missing")
else:
url = self.url(action='get', params=self.attributes)
response = perform_request(
'get',
url,
self.default_retrieve_params,
metric_tags=self._metric_tags,
metric_action='model.retrieve'
)
url = self.url(action='get', params=self.attributes)
response = perform_request(
'get',
url,
self.default_retrieve_params,
metric_tags=self._metric_tags,
metric_action='model.retrieve'
)
self._update_from_response(response)
@property
@@ -164,27 +151,33 @@ class Model:
"""
self.before_save(self)
if self.id: # if we have id already, treat this as an update
response = self.handle_update(params)
else: # otherwise, treat this as an insert
response = self.handle_create(params)
request_params = self.updatable_attributes()
if params:
request_params.update(params)
url = self.url(action='put', params=self.attributes)
response = perform_request(
'put',
url,
request_params,
metric_tags=self._metric_tags,
metric_action='model.update'
)
else: # otherwise, treat this as an insert
url = self.url(action='post', params=self.attributes)
response = perform_request(
'post',
url,
self.initializable_attributes(),
metric_tags=self._metric_tags,
metric_action='model.insert'
)
self.retrieved = True
self._update_from_response(response)
self.after_save(self)
def delete(self):
course_key = get_course_key(self.attributes.get("course_id"))
if is_forum_v2_enabled(course_key):
response = None
if self.type == "comment":
response = forum_api.delete_comment(comment_id=self.attributes["id"], course_id=str(course_key))
elif self.type == "thread":
response = forum_api.delete_thread(thread_id=self.attributes["id"], course_id=str(course_key))
if response is None:
raise CommentClientRequestError("Forum v2 API call is missing")
else:
url = self.url(action='delete', params=self.attributes)
response = perform_request('delete', url, metric_tags=self._metric_tags, metric_action='model.delete')
url = self.url(action='delete', params=self.attributes)
response = perform_request('delete', url, metric_tags=self._metric_tags, metric_action='model.delete')
self.retrieved = True
self._update_from_response(response)
@@ -215,157 +208,3 @@ class Model:
raise CommentClientRequestError(f"Cannot perform action {action} without id") # lint-amnesty, pylint: disable=raise-missing-from
else: # action must be in DEFAULT_ACTIONS_WITHOUT_ID now
return cls.url_without_id()
def handle_update(self, params=None):
request_params = self.updatable_attributes()
if params:
request_params.update(params)
course_id = self.attributes.get("course_id") or request_params.get("course_id")
course_key = get_course_key(course_id)
if is_forum_v2_enabled(course_key):
response = None
if self.type == "comment":
response = self.handle_update_comment(request_params, str(course_key))
elif self.type == "thread":
response = self.handle_update_thread(request_params, str(course_key))
elif self.type == "user":
response = self.handle_update_user(request_params, str(course_key))
if response is None:
raise CommentClientRequestError("Forum v2 API call is missing")
else:
response = self.perform_http_put_request(request_params)
return response
def handle_update_user(self, request_params, course_id):
try:
username = request_params["username"]
external_id = str(request_params["external_id"])
except KeyError as e:
raise e
response = forum_api.update_user(
external_id,
username=username,
course_id=course_id,
)
return response
def handle_update_comment(self, request_params, course_id):
request_data = {
"comment_id": self.attributes["id"],
"body": request_params.get("body"),
"course_id": request_params.get("course_id"),
"user_id": request_params.get("user_id"),
"anonymous": request_params.get("anonymous"),
"anonymous_to_peers": request_params.get("anonymous_to_peers"),
"endorsed": request_params.get("endorsed"),
"closed": request_params.get("closed"),
"editing_user_id": request_params.get("editing_user_id"),
"edit_reason_code": request_params.get("edit_reason_code"),
"endorsement_user_id": request_params.get("endorsement_user_id"),
"course_key": course_id
}
request_data = {k: v for k, v in request_data.items() if v is not None}
response = forum_api.update_comment(**request_data)
return response
def handle_update_thread(self, request_params, course_id):
request_data = {
"thread_id": self.attributes["id"],
"title": request_params.get("title"),
"body": request_params.get("body"),
"course_id": request_params.get("course_id"),
"anonymous": request_params.get("anonymous"),
"anonymous_to_peers": request_params.get("anonymous_to_peers"),
"closed": request_params.get("closed"),
"commentable_id": request_params.get("commentable_id"),
"user_id": request_params.get("user_id"),
"editing_user_id": request_params.get("editing_user_id"),
"pinned": request_params.get("pinned"),
"thread_type": request_params.get("thread_type"),
"edit_reason_code": request_params.get("edit_reason_code"),
"close_reason_code": request_params.get("close_reason_code"),
"closing_user_id": request_params.get("closing_user_id"),
"endorsed": request_params.get("endorsed"),
"course_key": course_id
}
request_data = {k: v for k, v in request_data.items() if v is not None}
response = forum_api.update_thread(**request_data)
return response
def perform_http_put_request(self, request_params):
url = self.url(action="put", params=self.attributes)
response = perform_request(
"put",
url,
request_params,
metric_tags=self._metric_tags,
metric_action="model.update",
)
return response
def perform_http_post_request(self):
url = self.url(action="post", params=self.attributes)
response = perform_request(
"post",
url,
self.initializable_attributes(),
metric_tags=self._metric_tags,
metric_action="model.insert",
)
return response
def handle_create(self, params=None):
course_id = self.attributes.get("course_id") or params.get("course_id")
course_key = get_course_key(course_id)
if is_forum_v2_enabled(course_key):
response = None
if self.type == "comment":
response = self.handle_create_comment(str(course_key))
elif self.type == "thread":
response = self.handle_create_thread(str(course_key))
if response is None:
raise CommentClientRequestError("Forum v2 API call is missing")
else:
response = self.perform_http_post_request()
return response
def handle_create_comment(self, course_id):
request_data = self.initializable_attributes()
body = request_data["body"]
user_id = request_data["user_id"]
course_id = course_id or str(request_data["course_id"])
if parent_id := self.attributes.get("parent_id"):
response = forum_api.create_child_comment(
parent_id,
body,
user_id,
course_id,
request_data.get("anonymous", False),
request_data.get("anonymous_to_peers", False),
)
else:
response = forum_api.create_parent_comment(
self.attributes["thread_id"],
body,
user_id,
course_id,
request_data.get("anonymous", False),
request_data.get("anonymous_to_peers", False),
)
return response
def handle_create_thread(self, course_id):
request_data = self.initializable_attributes()
response = forum_api.create_thread(
title=request_data["title"],
body=request_data["body"],
course_id=course_id or str(request_data["course_id"]),
user_id=str(request_data["user_id"]),
anonymous=request_data.get("anonymous", False),
anonymous_to_peers=request_data.get("anonymous_to_peers", False),
commentable_id=request_data.get("commentable_id", "course"),
thread_type=request_data.get("thread_type", "discussion"),
group_id=request_data.get("group_id", None),
context=request_data.get("context", None),
)
return response

View File

@@ -4,8 +4,6 @@ Subscription model is used to get users who are subscribed to the main thread/po
import logging
from . import models, settings, utils
from forum import api as forum_api
from openedx.core.djangoapps.discussions.config.waffle import is_forum_v2_enabled
log = logging.getLogger(__name__)
@@ -23,7 +21,7 @@ class Subscription(models.Model):
base_url = f"{settings.PREFIX}/threads"
@classmethod
def fetch(cls, thread_id, course_id, query_params):
def fetch(cls, thread_id, query_params):
"""
Fetches the subscriptions for a given thread_id
"""
@@ -35,23 +33,14 @@ class Subscription(models.Model):
params.update(
utils.strip_blank(utils.strip_none(query_params))
)
course_key = utils.get_course_key(course_id)
if is_forum_v2_enabled(course_key):
response = forum_api.get_thread_subscriptions(
thread_id=thread_id,
page=params["page"],
per_page=params["per_page"],
course_id=str(course_key)
)
else:
response = utils.perform_request(
'get',
cls.url(action='get', params=params) + "/subscriptions",
params,
metric_tags=[],
metric_action='subscription.get',
paged_results=True
)
response = utils.perform_request(
'get',
cls.url(action='get', params=params) + "/subscriptions",
params,
metric_tags=[],
metric_action='subscription.get',
paged_results=True
)
return utils.SubscriptionsPaginatedResult(
collection=response.get('collection', []),
page=response.get('page', 1),

View File

@@ -6,8 +6,6 @@ import logging
from eventtracking import tracker
from . import models, settings, utils
from forum import api as forum_api
from openedx.core.djangoapps.discussions.config.waffle import is_forum_v2_enabled
log = logging.getLogger(__name__)
@@ -61,35 +59,14 @@ class Thread(models.Model):
url = cls.url(action='get_all', params=utils.extract(params, 'commentable_id'))
if params.get('commentable_id'):
del params['commentable_id']
if is_forum_v2_enabled(utils.get_course_key(query_params['course_id'])):
if query_params.get('text'):
search_params = utils.strip_none(params)
if user_id := search_params.get('user_id'):
search_params['user_id'] = str(user_id)
if group_ids := search_params.get('group_ids'):
search_params['group_ids'] = [int(group_id) for group_id in group_ids.split(',')]
elif group_id := search_params.get('group_id'):
search_params['group_ids'] = [int(group_id)]
search_params.pop('group_id', None)
if commentable_ids := search_params.get('commentable_ids'):
search_params['commentable_ids'] = commentable_ids.split(',')
elif commentable_id := search_params.get('commentable_id'):
search_params['commentable_ids'] = [commentable_id]
search_params.pop('commentable_id', None)
response = forum_api.search_threads(**search_params)
else:
response = forum_api.get_user_threads(**params)
else:
response = utils.perform_request(
'get',
url,
params,
metric_tags=['course_id:{}'.format(query_params['course_id'])],
metric_action='thread.search',
paged_results=True
)
response = utils.perform_request(
'get',
url,
params,
metric_tags=['course_id:{}'.format(query_params['course_id'])],
metric_action='thread.search',
paged_results=True
)
if query_params.get('text'):
search_query = query_params['text']
course_id = query_params['course_id']
@@ -171,26 +148,14 @@ class Thread(models.Model):
'merge_question_type_responses': kwargs.get('merge_question_type_responses', False)
}
request_params = utils.strip_none(request_params)
course_id = kwargs.get("course_id")
if not course_id:
course_id = forum_api.get_course_id_by_thread(self.id)
course_key = utils.get_course_key(course_id)
if is_forum_v2_enabled(course_key):
if user_id := request_params.get('user_id'):
request_params['user_id'] = str(user_id)
response = forum_api.get_thread(
thread_id=self.id,
params=request_params,
course_id=str(course_key)
)
else:
response = utils.perform_request(
'get',
url,
request_params,
metric_action='model.retrieve',
metric_tags=self._metric_tags
)
response = utils.perform_request(
'get',
url,
request_params,
metric_action='model.retrieve',
metric_tags=self._metric_tags
)
self._update_from_response(response)
def flagAbuse(self, user, voteable):
@@ -198,18 +163,14 @@ class Thread(models.Model):
url = _url_for_flag_abuse_thread(voteable.id)
else:
raise utils.CommentClientRequestError("Can only flag/unflag threads or comments")
course_key = utils.get_course_key(self.attributes.get("course_id"))
if is_forum_v2_enabled(course_key):
response = forum_api.update_thread_flag(voteable.id, "flag", user.id, str(course_key))
else:
params = {'user_id': user.id}
response = utils.perform_request(
'put',
url,
params,
metric_action='thread.abuse.flagged',
metric_tags=self._metric_tags
)
params = {'user_id': user.id}
response = utils.perform_request(
'put',
url,
params,
metric_action='thread.abuse.flagged',
metric_tags=self._metric_tags
)
voteable._update_from_response(response)
def unFlagAbuse(self, user, voteable, removeAll):
@@ -217,68 +178,42 @@ class Thread(models.Model):
url = _url_for_unflag_abuse_thread(voteable.id)
else:
raise utils.CommentClientRequestError("Can only flag/unflag for threads or comments")
course_key = utils.get_course_key(self.attributes.get("course_id"))
if is_forum_v2_enabled(course_key):
response = forum_api.update_thread_flag(
thread_id=voteable.id,
action="unflag",
user_id=user.id,
update_all=bool(removeAll),
course_id=str(course_key)
)
else:
params = {'user_id': user.id}
#if you're an admin, when you unflag, remove ALL flags
if removeAll:
params['all'] = True
params = {'user_id': user.id}
#if you're an admin, when you unflag, remove ALL flags
if removeAll:
params['all'] = True
response = utils.perform_request(
'put',
url,
params,
metric_tags=self._metric_tags,
metric_action='thread.abuse.unflagged'
)
response = utils.perform_request(
'put',
url,
params,
metric_tags=self._metric_tags,
metric_action='thread.abuse.unflagged'
)
voteable._update_from_response(response)
def pin(self, user, thread_id):
course_key = utils.get_course_key(self.attributes.get("course_id"))
if is_forum_v2_enabled(course_key):
response = forum_api.pin_thread(
user_id=user.id,
thread_id=thread_id,
course_id=str(course_key)
)
else:
url = _url_for_pin_thread(thread_id)
params = {'user_id': user.id}
response = utils.perform_request(
'put',
url,
params,
metric_tags=self._metric_tags,
metric_action='thread.pin'
)
url = _url_for_pin_thread(thread_id)
params = {'user_id': user.id}
response = utils.perform_request(
'put',
url,
params,
metric_tags=self._metric_tags,
metric_action='thread.pin'
)
self._update_from_response(response)
def un_pin(self, user, thread_id):
course_key = utils.get_course_key(self.attributes.get("course_id"))
if is_forum_v2_enabled(course_key):
response = forum_api.unpin_thread(
user_id=user.id,
thread_id=thread_id,
course_id=str(course_key)
)
else:
url = _url_for_un_pin_thread(thread_id)
params = {'user_id': user.id}
response = utils.perform_request(
'put',
url,
params,
metric_tags=self._metric_tags,
metric_action='thread.unpin'
)
url = _url_for_un_pin_thread(thread_id)
params = {'user_id': user.id}
response = utils.perform_request(
'put',
url,
params,
metric_tags=self._metric_tags,
metric_action='thread.unpin'
)
self._update_from_response(response)

View File

@@ -1,10 +1,8 @@
# pylint: disable=missing-docstring,protected-access
""" User model wrapper for comment service"""
from . import models, settings, utils
from forum import api as forum_api
from forum.utils import ForumV2RequestError, str_to_bool
from openedx.core.djangoapps.discussions.config.waffle import is_forum_v2_enabled
class User(models.Model):
@@ -36,55 +34,34 @@ class User(models.Model):
"""
Calls cs_comments_service to mark thread as read for the user
"""
course_id = self.attributes.get("course_id")
course_key = utils.get_course_key(course_id)
if is_forum_v2_enabled(course_key):
forum_api.mark_thread_as_read(self.id, source.id, course_id=str(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}'],
)
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):
course_key = utils.get_course_key(self.attributes.get("course_id"))
if is_forum_v2_enabled(course_key):
forum_api.create_subscription(
user_id=self.id,
source_id=source.id,
course_id=str(course_key)
)
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}'],
)
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):
course_key = utils.get_course_key(self.attributes.get("course_id"))
if is_forum_v2_enabled(course_key):
forum_api.delete_subscription(
user_id=self.id,
source_id=source.id,
course_id=str(course_key)
)
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}'],
)
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':
@@ -93,31 +70,14 @@ class User(models.Model):
url = _url_for_vote_comment(voteable.id)
else:
raise utils.CommentClientRequestError("Can only vote / unvote for threads or comments")
course_key = utils.get_course_key(self.attributes.get("course_id"))
if is_forum_v2_enabled(course_key):
if voteable.type == 'thread':
response = forum_api.update_thread_votes(
thread_id=voteable.id,
user_id=self.id,
value=value,
course_id=str(course_key)
)
else:
response = forum_api.update_comment_votes(
comment_id=voteable.id,
user_id=self.id,
value=value,
course_id=str(course_key)
)
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}'],
)
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):
@@ -127,29 +87,14 @@ class User(models.Model):
url = _url_for_vote_comment(voteable.id)
else:
raise utils.CommentClientRequestError("Can only vote / unvote for threads or comments")
course_key = utils.get_course_key(self.attributes.get("course_id"))
if is_forum_v2_enabled(course_key):
if voteable.type == 'thread':
response = forum_api.delete_thread_vote(
thread_id=voteable.id,
user_id=self.id,
course_id=str(course_key)
)
else:
response = forum_api.delete_comment_vote(
comment_id=voteable.id,
user_id=self.id,
course_id=str(course_key)
)
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}'],
)
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):
@@ -160,28 +105,14 @@ class User(models.Model):
url = _url_for_user_active_threads(self.id)
params = {'course_id': str(self.course_id)}
params.update(query_params)
course_key = utils.get_course_key(self.attributes.get("course_id"))
if is_forum_v2_enabled(course_key):
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 not params.get("course_id"):
params["course_id"] = str(course_key)
response = forum_api.get_user_active_threads(**params)
else:
response = utils.perform_request(
'get',
url,
params,
metric_action='user.active_threads',
metric_tags=self._metric_tags,
paged_results=True,
)
response = utils.perform_request(
'get',
url,
params,
metric_action='user.active_threads',
metric_tags=self._metric_tags,
paged_results=True,
)
return response.get('collection', []), response.get('page', 1), response.get('num_pages', 1)
def subscribed_threads(self, query_params=None):
@@ -194,28 +125,14 @@ class User(models.Model):
url = _url_for_user_subscribed_threads(self.id)
params = {'course_id': str(self.course_id)}
params.update(query_params)
course_key = utils.get_course_key(self.attributes.get("course_id"))
if is_forum_v2_enabled(course_key):
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 not params.get("course_id"):
params["course_id"] = str(course_key)
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
)
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),
@@ -227,39 +144,23 @@ class User(models.Model):
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.course_id)
if self.attributes.get('group_id'):
retrieve_params['group_id'] = self.group_id
# course key -> id conversation
course_id = retrieve_params.get('course_id')
if course_id:
course_id = str(course_id)
retrieve_params['course_id'] = course_id
course_key = utils.get_course_key(course_id)
if is_forum_v2_enabled(course_key):
group_ids = [retrieve_params['group_id']] if 'group_id' in retrieve_params else []
is_complete = retrieve_params['complete']
try:
response = forum_api.get_user(
self.attributes["id"],
group_ids=group_ids,
course_id=course_id,
complete=is_complete
)
except ForumV2RequestError as e:
self.save({"course_id": course_id})
response = forum_api.get_user(
self.attributes["id"],
group_ids=group_ids,
course_id=course_id,
complete=is_complete
)
else:
try:
try:
response = utils.perform_request(
'get',
url,
retrieve_params,
metric_action='model.retrieve',
metric_tags=self._metric_tags,
)
except utils.CommentClientRequestError as e:
if e.status_code == 404:
# attempt to gracefully recover from a previous failure
# to sync this user to the comments service.
self.save()
response = utils.perform_request(
'get',
url,
@@ -267,52 +168,33 @@ class User(models.Model):
metric_action='model.retrieve',
metric_tags=self._metric_tags,
)
except utils.CommentClientRequestError as e:
if e.status_code == 404:
# attempt to gracefully recover from a previous failure
# to sync this user to the comments service.
self.save()
response = utils.perform_request(
'get',
url,
retrieve_params,
metric_action='model.retrieve',
metric_tags=self._metric_tags,
)
else:
raise
else:
raise
self._update_from_response(response)
def retire(self, retired_username):
course_key = utils.get_course_key(self.attributes.get("course_id"))
if is_forum_v2_enabled(course_key):
forum_api.retire_user(user_id=self.id, retired_username=retired_username, course_id=str(course_key))
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
)
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):
course_key = utils.get_course_key(self.attributes.get("course_id"))
if is_forum_v2_enabled(course_key):
forum_api.update_username(user_id=self.id, new_username=new_username, course_id=str(course_key))
else:
url = _url_for_username_replacement(self.id)
params = {"new_username": new_username}
url = _url_for_username_replacement(self.id)
params = {"new_username": new_username}
utils.perform_request(
'post',
url,
params,
raw=True,
)
utils.perform_request(
'post',
url,
params,
raw=True,
)
def _url_for_vote_comment(comment_id):

View File

@@ -7,7 +7,6 @@ from uuid import uuid4
import requests
from django.utils.translation import get_language
from opaque_keys.edx.keys import CourseKey
from .settings import SERVICE_HOST as COMMENTS_SERVICE
@@ -168,19 +167,3 @@ 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: CourseKey | str | None) -> CourseKey | None:
"""
Returns a CourseKey if the provided course_id is a valid string representation of a CourseKey.
If course_id is None or already a CourseKey object, it returns the course_id as is.
Args:
course_id (CourseKey | str | None): The course ID to be converted.
Returns:
CourseKey | None: The corresponding CourseKey object or None if the input is None.
Raises:
KeyError: If course_id is not a valid string representation of a CourseKey.
"""
if course_id and isinstance(course_id, str):
course_id = CourseKey.from_string(course_id)
return course_id

View File

@@ -57,9 +57,7 @@ backoff==1.10.0
bcrypt==4.2.1
# via paramiko
beautifulsoup4==4.12.3
# via
# openedx-forum
# pynliner
# via pynliner
billiard==4.2.1
# via celery
bleach[css]==6.2.0
@@ -236,7 +234,6 @@ django==4.2.17
# openedx-django-wiki
# openedx-events
# openedx-filters
# openedx-forum
# openedx-learning
# ora2
# social-auth-app-django
@@ -386,7 +383,6 @@ djangorestframework==3.14.0
# edx-organizations
# edx-proctoring
# edx-submissions
# openedx-forum
# openedx-learning
# ora2
# super-csv
@@ -520,9 +516,7 @@ edx-rest-api-client==6.0.0
# edx-enterprise
# edx-proctoring
edx-search==4.1.1
# via
# -r requirements/edx/kernel.in
# openedx-forum
# via -r requirements/edx/kernel.in
edx-sga==0.25.0
# via -r requirements/edx/bundled.in
edx-submissions==3.8.3
@@ -555,7 +549,6 @@ elasticsearch==7.9.1
# via
# -c requirements/edx/../common_constraints.txt
# edx-search
# openedx-forum
enmerkar==0.7.1
# via enmerkar-underscore
enmerkar-underscore==2.3.1
@@ -783,7 +776,6 @@ multidict==6.1.0
mysqlclient==2.2.6
# via
# -r requirements/edx/kernel.in
# openedx-forum
newrelic==10.3.1
# via edx-django-utils
nh3==0.2.19
@@ -815,7 +807,6 @@ openai==0.28.1
openedx-atlas==0.6.2
# via
# -r requirements/edx/kernel.in
# openedx-forum
openedx-calc==4.0.1
# via -r requirements/edx/kernel.in
openedx-django-pyfs==3.7.0
@@ -841,8 +832,6 @@ openedx-filters==1.11.0
# -r requirements/edx/kernel.in
# lti-consumer-xblock
# ora2
openedx-forum==0.1.4
# via -r requirements/edx/kernel.in
openedx-learning==0.18.1
# via
# -c requirements/edx/../constraints.txt
@@ -979,7 +968,6 @@ pymongo==4.4.0
# edx-opaque-keys
# event-tracking
# mongoengine
# openedx-forum
# openedx-mongodbproxy
pynacl==1.5.0
# via
@@ -1089,7 +1077,6 @@ requests==2.32.3
# mailsnake
# meilisearch
# openai
# openedx-forum
# optimizely-sdk
# pyjwkest
# pylti1p3

View File

@@ -122,7 +122,6 @@ beautifulsoup4==4.12.3
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
# openedx-forum
# pydata-sphinx-theme
# pynliner
billiard==4.2.1
@@ -407,7 +406,6 @@ django==4.2.17
# openedx-django-wiki
# openedx-events
# openedx-filters
# openedx-forum
# openedx-learning
# ora2
# social-auth-app-django
@@ -621,7 +619,6 @@ djangorestframework==3.14.0
# edx-organizations
# edx-proctoring
# edx-submissions
# openedx-forum
# openedx-learning
# ora2
# super-csv
@@ -818,7 +815,6 @@ edx-search==4.1.1
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
# openedx-forum
edx-sga==0.25.0
# via
# -r requirements/edx/doc.txt
@@ -865,7 +861,6 @@ elasticsearch==7.9.1
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
# edx-search
# openedx-forum
enmerkar==0.7.1
# via
# -r requirements/edx/doc.txt
@@ -1309,7 +1304,6 @@ mysqlclient==2.2.6
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
# openedx-forum
newrelic==10.3.1
# via
# -r requirements/edx/doc.txt
@@ -1360,7 +1354,6 @@ openedx-atlas==0.6.2
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
# openedx-forum
openedx-calc==4.0.1
# via
# -r requirements/edx/doc.txt
@@ -1396,10 +1389,6 @@ openedx-filters==1.11.0
# -r requirements/edx/testing.txt
# lti-consumer-xblock
# ora2
openedx-forum==0.1.4
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
openedx-learning==0.18.1
# via
# -c requirements/edx/../constraints.txt
@@ -1670,7 +1659,6 @@ pymongo==4.4.0
# edx-opaque-keys
# event-tracking
# mongoengine
# openedx-forum
# openedx-mongodbproxy
pynacl==1.5.0
# via
@@ -1867,7 +1855,6 @@ requests==2.32.3
# mailsnake
# meilisearch
# openai
# openedx-forum
# optimizely-sdk
# pact-python
# pyjwkest

View File

@@ -89,7 +89,6 @@ bcrypt==4.2.1
beautifulsoup4==4.12.3
# via
# -r requirements/edx/base.txt
# openedx-forum
# pydata-sphinx-theme
# pynliner
billiard==4.2.1
@@ -293,7 +292,6 @@ django==4.2.17
# openedx-django-wiki
# openedx-events
# openedx-filters
# openedx-forum
# openedx-learning
# ora2
# social-auth-app-django
@@ -459,7 +457,6 @@ djangorestframework==3.14.0
# edx-organizations
# edx-proctoring
# edx-submissions
# openedx-forum
# openedx-learning
# ora2
# super-csv
@@ -604,9 +601,7 @@ edx-rest-api-client==6.0.0
# edx-enterprise
# edx-proctoring
edx-search==4.1.1
# via
# -r requirements/edx/base.txt
# openedx-forum
# via -r requirements/edx/base.txt
edx-sga==0.25.0
# via -r requirements/edx/base.txt
edx-submissions==3.8.3
@@ -642,7 +637,6 @@ elasticsearch==7.9.1
# -c requirements/edx/../common_constraints.txt
# -r requirements/edx/base.txt
# edx-search
# openedx-forum
enmerkar==0.7.1
# via
# -r requirements/edx/base.txt
@@ -945,7 +939,6 @@ multidict==6.1.0
mysqlclient==2.2.6
# via
# -r requirements/edx/base.txt
# openedx-forum
newrelic==10.3.1
# via
# -r requirements/edx/base.txt
@@ -983,7 +976,6 @@ openai==0.28.1
openedx-atlas==0.6.2
# via
# -r requirements/edx/base.txt
# openedx-forum
openedx-calc==4.0.1
# via -r requirements/edx/base.txt
openedx-django-pyfs==3.7.0
@@ -1010,8 +1002,6 @@ openedx-filters==1.11.0
# -r requirements/edx/base.txt
# lti-consumer-xblock
# ora2
openedx-forum==0.1.4
# via -r requirements/edx/base.txt
openedx-learning==0.18.1
# via
# -c requirements/edx/../constraints.txt
@@ -1183,7 +1173,6 @@ pymongo==4.4.0
# edx-opaque-keys
# event-tracking
# mongoengine
# openedx-forum
# openedx-mongodbproxy
pynacl==1.5.0
# via
@@ -1309,7 +1298,6 @@ requests==2.32.3
# mailsnake
# meilisearch
# openai
# openedx-forum
# optimizely-sdk
# pyjwkest
# pylti1p3

View File

@@ -119,7 +119,6 @@ openedx-calc # Library supporting mathematical calculatio
openedx-django-require
openedx-events # Open edX Events from Hooks Extension Framework (OEP-50)
openedx-filters # Open edX Filters from Hooks Extension Framework (OEP-50)
openedx-forum # Open edX forum v2 application
openedx-learning # Open edX Learning core (experimental)
openedx-mongodbproxy
openedx-django-wiki

View File

@@ -87,7 +87,6 @@ beautifulsoup4==4.12.3
# via
# -r requirements/edx/base.txt
# -r requirements/edx/testing.in
# openedx-forum
# pynliner
billiard==4.2.1
# via
@@ -319,7 +318,6 @@ django==4.2.17
# openedx-django-wiki
# openedx-events
# openedx-filters
# openedx-forum
# openedx-learning
# ora2
# social-auth-app-django
@@ -485,7 +483,6 @@ djangorestframework==3.14.0
# edx-organizations
# edx-proctoring
# edx-submissions
# openedx-forum
# openedx-learning
# ora2
# super-csv
@@ -627,9 +624,7 @@ edx-rest-api-client==6.0.0
# edx-enterprise
# edx-proctoring
edx-search==4.1.1
# via
# -r requirements/edx/base.txt
# openedx-forum
# via -r requirements/edx/base.txt
edx-sga==0.25.0
# via -r requirements/edx/base.txt
edx-submissions==3.8.3
@@ -665,7 +660,6 @@ elasticsearch==7.9.1
# -c requirements/edx/../common_constraints.txt
# -r requirements/edx/base.txt
# edx-search
# openedx-forum
enmerkar==0.7.1
# via
# -r requirements/edx/base.txt
@@ -990,7 +984,6 @@ multidict==6.1.0
mysqlclient==2.2.6
# via
# -r requirements/edx/base.txt
# openedx-forum
newrelic==10.3.1
# via
# -r requirements/edx/base.txt
@@ -1028,7 +1021,6 @@ openai==0.28.1
openedx-atlas==0.6.2
# via
# -r requirements/edx/base.txt
# openedx-forum
openedx-calc==4.0.1
# via -r requirements/edx/base.txt
openedx-django-pyfs==3.7.0
@@ -1055,8 +1047,6 @@ openedx-filters==1.11.0
# -r requirements/edx/base.txt
# lti-consumer-xblock
# ora2
openedx-forum==0.1.4
# via -r requirements/edx/base.txt
openedx-learning==0.18.1
# via
# -c requirements/edx/../constraints.txt
@@ -1263,7 +1253,6 @@ pymongo==4.4.0
# edx-opaque-keys
# event-tracking
# mongoengine
# openedx-forum
# openedx-mongodbproxy
pynacl==1.5.0
# via
@@ -1420,7 +1409,6 @@ requests==2.32.3
# mailsnake
# meilisearch
# openai
# openedx-forum
# optimizely-sdk
# pact-python
# pyjwkest