Disallow reporting and upvoting of your own posts in discussion forums
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user