Commit 38bd9ad0 by Brian Jacobel Committed by GitHub

Merge pull request #12740 from edx/bjacobel/discussions-self-post-interaction

Can't report or vote for your own posts
parents 8fa3bf32 b6cf9d23
......@@ -387,3 +387,24 @@ describe "DiscussionThreadView", ->
"Showing first 6 responses",
"Load all responses"
)
describe "post restrictions", ->
beforeEach ->
@thread.attributes.ability = _.extend(@thread.attributes.ability, {
can_report: false
can_vote: false
})
@view = new DiscussionThreadView(
model: @thread
el: $("#fixture-element")
mode: "tab"
course_settings: DiscussionSpecHelper.makeCourseSettings()
)
it "doesn't show report option if can_report ability is disabled", ->
@view.render()
expect(@view.$el.find(".action-report").closest(".actions-item")).toHaveClass('is-hidden')
it "doesn't show voting button if can_vote ability is disabled", ->
@view.render()
expect(@view.$el.find(".action-vote").closest(".actions-item")).toHaveClass('is-hidden')
......@@ -11,6 +11,8 @@ if Backbone?
can_reply: '.discussion-reply'
can_delete: '.admin-delete'
can_openclose: '.admin-openclose'
can_report: '.admin-report'
can_vote: '.admin-vote'
urlMappers: {}
......@@ -97,7 +99,7 @@ if Backbone?
pinned = @get("pinned")
@set("pinned",pinned)
@trigger "change", @
flagAbuse: ->
temp_array = @get("abuse_flaggers")
temp_array.push(window.user.get('id'))
......@@ -123,7 +125,7 @@ if Backbone?
unvote: ->
@incrementVote(-1)
class @Thread extends @Content
urlMappers:
'retrieve' : -> DiscussionUtil.urlFor('retrieve_single_thread', @.get('commentable_id'), @id)
......
......@@ -33,6 +33,12 @@ if Backbone?
[".action-close", ".action-pin"],
(selector) => @$(selector).closest(".actions-item").addClass("is-hidden")
)
can_report:
enable: -> @$(".action-report").closest(".actions-item").removeClass("is-hidden")
disable: -> @$(".action-report").closest(".actions-item").addClass("is-hidden")
can_vote:
enable: -> @$(".action-vote").closest(".actions-item").removeClass("is-hidden")
disable: -> @$(".action-vote").closest(".actions-item").addClass("is-hidden")
renderPartialAttrs: ->
for attr, value of @model.changedAttributes()
......
......@@ -181,6 +181,10 @@ class DiscussionThreadPage(PageObject, DiscussionPageMixin):
"Response is voted"
).fulfill()
def cannot_vote_response(self, response_id):
"""Assert that the voting button is not visible on this response"""
return not self.is_element_visible(".response_{} .discussion-response .action-vote".format(response_id))
def is_response_reported(self, response_id):
return self.is_element_visible(".response_{} .discussion-response .post-label-reported".format(response_id))
......@@ -193,6 +197,10 @@ class DiscussionThreadPage(PageObject, DiscussionPageMixin):
"Response is reported"
).fulfill()
def cannot_report_response(self, response_id):
"""Assert that the reporting button is not visible on this response"""
return not self.is_element_visible(".response_{} .discussion-response .action-report".format(response_id))
def is_response_endorsed(self, response_id):
return "endorsed" in self._get_element_text(".response_{} .discussion-response .posted-details".format(response_id))
......
......@@ -693,11 +693,11 @@ class DiscussionResponseEditTest(BaseDiscussionTestCase):
And I try to edit the response created by other users
Then the response should be edited and rendered successfully
And I try to vote the response created by moderator
Then the response should be voted successfully
Then the response should not be able to be voted
And I try to vote the response created by other users
Then the response should be voted successfully
And I try to report the response created by moderator
Then the response should be reported successfully
Then the response should not be able to be reported
And I try to report the response created by other users
Then the response should be reported successfully
And I try to endorse the response created by moderator
......@@ -711,9 +711,9 @@ class DiscussionResponseEditTest(BaseDiscussionTestCase):
page.visit()
self.edit_response(page, "response_self_author")
self.edit_response(page, "response_other_author")
page.vote_response('response_self_author')
page.cannot_vote_response('response_self_author')
page.vote_response('response_other_author')
page.report_response('response_self_author')
page.cannot_report_response('response_self_author')
page.report_response('response_other_author')
page.endorse_response('response_self_author')
page.endorse_response('response_other_author')
......
......@@ -1360,3 +1360,61 @@ class IsCommentableCohortedTestCase(ModuleStoreTestCase):
# Verify that team discussions are not cohorted, but other discussions are
self.assertFalse(utils.is_commentable_cohorted(course.id, team.discussion_topic_id))
self.assertTrue(utils.is_commentable_cohorted(course.id, "random"))
class PermissionsTestCase(ModuleStoreTestCase):
"""Test utils functionality related to forums "abilities" (permissions)"""
def test_get_ability(self):
content = {}
content['user_id'] = '1'
content['type'] = 'thread'
user = mock.Mock()
user.id = 1
with mock.patch('django_comment_client.utils.check_permissions_by_view') as check_perm:
check_perm.return_value = True
self.assertEqual(utils.get_ability(None, content, user), {
'editable': True,
'can_reply': True,
'can_delete': True,
'can_openclose': True,
'can_vote': False,
'can_report': False
})
content['user_id'] = '2'
self.assertEqual(utils.get_ability(None, content, user), {
'editable': True,
'can_reply': True,
'can_delete': True,
'can_openclose': True,
'can_vote': True,
'can_report': True
})
def test_is_content_authored_by(self):
content = {}
user = mock.Mock()
user.id = 1
# strict equality checking
content['user_id'] = 1
self.assertTrue(utils.is_content_authored_by(content, user))
# cast from string to int
content['user_id'] = '1'
self.assertTrue(utils.is_content_authored_by(content, user))
# strict equality checking, fails
content['user_id'] = 2
self.assertFalse(utils.is_content_authored_by(content, user))
# cast from string to int, fails
content['user_id'] = 'string'
self.assertFalse(utils.is_content_authored_by(content, user))
# content has no known author
del content['user_id']
self.assertFalse(utils.is_content_authored_by(content, user))
......@@ -510,7 +510,18 @@ def get_ability(course_id, content, user):
'can_reply': check_permissions_by_view(user, course_id, content, "create_comment" if content['type'] == 'thread' else "create_sub_comment"),
'can_delete': check_permissions_by_view(user, course_id, content, "delete_thread" if content['type'] == 'thread' else "delete_comment"),
'can_openclose': check_permissions_by_view(user, course_id, content, "openclose_thread") if content['type'] == 'thread' else False,
'can_vote': check_permissions_by_view(user, course_id, content, "vote_for_thread" if content['type'] == 'thread' else "vote_for_comment"),
'can_vote': not is_content_authored_by(content, user) and check_permissions_by_view(
user,
course_id,
content,
"vote_for_thread" if content['type'] == 'thread' else "vote_for_comment"
),
'can_report': not is_content_authored_by(content, user) and check_permissions_by_view(
user,
course_id,
content,
"flag_abuse_for_thread" if content['type'] == 'thread' else "flag_abuse_for_comment"
)
}
# TODO: RENAME
......@@ -798,3 +809,13 @@ def is_discussion_enabled(course_id):
if get_current_ccx(course_id):
return False
return settings.FEATURES.get('ENABLE_DISCUSSION_SERVICE')
def is_content_authored_by(content, user):
"""
Return True if the author is this content is the passed user, else False
"""
try:
return int(content.get('user_id')) == user.id
except (ValueError, TypeError):
return False
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment