Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
b6cf9d23
Commit
b6cf9d23
authored
Jun 10, 2016
by
Brian Jacobel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Disallow reporting and upvoting of your own posts in discussion forums
parent
09cdc6f4
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
123 additions
and
7 deletions
+123
-7
common/static/coffee/spec/discussion/view/discussion_thread_view_spec.coffee
+21
-0
common/static/coffee/src/discussion/content.coffee
+4
-2
common/static/coffee/src/discussion/views/discussion_content_view.coffee
+6
-0
common/test/acceptance/pages/lms/discussion.py
+8
-0
common/test/acceptance/tests/discussion/test_discussion.py
+4
-4
lms/djangoapps/django_comment_client/tests/test_utils.py
+58
-0
lms/djangoapps/django_comment_client/utils.py
+22
-1
No files found.
common/static/coffee/spec/discussion/view/discussion_thread_view_spec.coffee
View file @
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'
)
common/static/coffee/src/discussion/content.coffee
View file @
b6cf9d23
...
...
@@ -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
)
...
...
common/static/coffee/src/discussion/views/discussion_content_view.coffee
View file @
b6cf9d23
...
...
@@ -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
()
...
...
common/test/acceptance/pages/lms/discussion.py
View file @
b6cf9d23
...
...
@@ -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
))
...
...
common/test/acceptance/tests/discussion/test_discussion.py
View file @
b6cf9d23
...
...
@@ -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'
)
...
...
lms/djangoapps/django_comment_client/tests/test_utils.py
View file @
b6cf9d23
...
...
@@ -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
))
lms/djangoapps/django_comment_client/utils.py
View file @
b6cf9d23
...
...
@@ -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
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment