Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Boxiang Sun
gitlab-ce
Commits
387a9c4e
Commit
387a9c4e
authored
Nov 28, 2018
by
Chantal Rollison
Committed by
Cindy Pallares
Nov 28, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[master]Fixed ability to comment on and edit/delete comments on locked or confidential issues
parent
163469e9
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
187 additions
and
34 deletions
+187
-34
app/controllers/concerns/notes_actions.rb
app/controllers/concerns/notes_actions.rb
+10
-0
app/mailers/emails/notes.rb
app/mailers/emails/notes.rb
+1
-1
app/models/note.rb
app/models/note.rb
+1
-1
app/policies/commit_policy.rb
app/policies/commit_policy.rb
+2
-0
app/policies/note_policy.rb
app/policies/note_policy.rb
+9
-0
app/views/notify/note_project_snippet_email.html.haml
app/views/notify/note_project_snippet_email.html.haml
+0
-0
app/views/notify/note_project_snippet_email.text.erb
app/views/notify/note_project_snippet_email.text.erb
+0
-0
changelogs/unreleased/security-guest-comments.yml
changelogs/unreleased/security-guest-comments.yml
+5
-0
changelogs/unreleased/security-guest-comments_2.yml
changelogs/unreleased/security-guest-comments_2.yml
+5
-0
spec/controllers/projects/notes_controller_spec.rb
spec/controllers/projects/notes_controller_spec.rb
+76
-27
spec/mailers/notify_spec.rb
spec/mailers/notify_spec.rb
+1
-1
spec/models/note_spec.rb
spec/models/note_spec.rb
+1
-1
spec/policies/note_policy_spec.rb
spec/policies/note_policy_spec.rb
+76
-3
No files found.
app/controllers/concerns/notes_actions.rb
View file @
387a9c4e
...
@@ -6,6 +6,7 @@ module NotesActions
...
@@ -6,6 +6,7 @@ module NotesActions
extend
ActiveSupport
::
Concern
extend
ActiveSupport
::
Concern
included
do
included
do
prepend_before_action
:normalize_create_params
,
only:
[
:create
]
before_action
:set_polling_interval_header
,
only:
[
:index
]
before_action
:set_polling_interval_header
,
only:
[
:index
]
before_action
:require_noteable!
,
only:
[
:index
,
:create
]
before_action
:require_noteable!
,
only:
[
:index
,
:create
]
before_action
:authorize_admin_note!
,
only:
[
:update
,
:destroy
]
before_action
:authorize_admin_note!
,
only:
[
:update
,
:destroy
]
...
@@ -247,6 +248,15 @@ module NotesActions
...
@@ -247,6 +248,15 @@ module NotesActions
DiscussionSerializer
.
new
(
project:
project
,
noteable:
noteable
,
current_user:
current_user
,
note_entity:
ProjectNoteEntity
)
DiscussionSerializer
.
new
(
project:
project
,
noteable:
noteable
,
current_user:
current_user
,
note_entity:
ProjectNoteEntity
)
end
end
# Avoids checking permissions in the wrong object - this ensures that the object we checked permissions for
# is the object we're actually creating a note in.
def
normalize_create_params
params
[
:note
].
try
do
|
note
|
note
[
:noteable_id
]
=
params
[
:target_id
]
note
[
:noteable_type
]
=
params
[
:target_type
].
classify
end
end
def
note_project
def
note_project
strong_memoize
(
:note_project
)
do
strong_memoize
(
:note_project
)
do
next
nil
unless
project
next
nil
unless
project
...
...
app/mailers/emails/notes.rb
View file @
387a9c4e
...
@@ -26,7 +26,7 @@ module Emails
...
@@ -26,7 +26,7 @@ module Emails
mail_answer_note_thread
(
@merge_request
,
@note
,
note_thread_options
(
recipient_id
))
mail_answer_note_thread
(
@merge_request
,
@note
,
note_thread_options
(
recipient_id
))
end
end
def
note_snippet_email
(
recipient_id
,
note_id
)
def
note_
project_
snippet_email
(
recipient_id
,
note_id
)
setup_note_mail
(
note_id
,
recipient_id
)
setup_note_mail
(
note_id
,
recipient_id
)
@snippet
=
@note
.
noteable
@snippet
=
@note
.
noteable
...
...
app/models/note.rb
View file @
387a9c4e
...
@@ -324,7 +324,7 @@ class Note < ActiveRecord::Base
...
@@ -324,7 +324,7 @@ class Note < ActiveRecord::Base
end
end
def
to_ability_name
def
to_ability_name
for_
personal_snippet?
?
'personal_snippet'
:
noteable_type
.
underscore
for_
snippet?
?
noteable
.
class
.
name
.
underscore
:
noteable_type
.
underscore
end
end
def
can_be_discussion_note?
def
can_be_discussion_note?
...
...
app/policies/commit_policy.rb
View file @
387a9c4e
...
@@ -2,4 +2,6 @@
...
@@ -2,4 +2,6 @@
class
CommitPolicy
<
BasePolicy
class
CommitPolicy
<
BasePolicy
delegate
{
@subject
.
project
}
delegate
{
@subject
.
project
}
rule
{
can?
(
:download_code
)
}.
enable
:read_commit
end
end
app/policies/note_policy.rb
View file @
387a9c4e
...
@@ -9,8 +9,17 @@ class NotePolicy < BasePolicy
...
@@ -9,8 +9,17 @@ class NotePolicy < BasePolicy
condition
(
:editable
,
scope: :subject
)
{
@subject
.
editable?
}
condition
(
:editable
,
scope: :subject
)
{
@subject
.
editable?
}
condition
(
:can_read_noteable
)
{
can?
(
:"read_
#{
@subject
.
to_ability_name
}
"
)
}
rule
{
~
editable
}.
prevent
:admin_note
rule
{
~
editable
}.
prevent
:admin_note
# If user can't read the issue/MR/etc then they should not be allowed to do anything to their own notes
rule
{
~
can_read_noteable
}.
policy
do
prevent
:read_note
prevent
:admin_note
prevent
:resolve_note
end
rule
{
is_author
}.
policy
do
rule
{
is_author
}.
policy
do
enable
:read_note
enable
:read_note
enable
:admin_note
enable
:admin_note
...
...
app/views/notify/note_snippet_email.html.haml
→
app/views/notify/note_
project_
snippet_email.html.haml
View file @
387a9c4e
File moved
app/views/notify/note_snippet_email.text.erb
→
app/views/notify/note_
project_
snippet_email.text.erb
View file @
387a9c4e
File moved
changelogs/unreleased/security-guest-comments.yml
0 → 100644
View file @
387a9c4e
---
title
:
Fixed ability to comment on locked/confidential issues.
merge_request
:
author
:
type
:
security
changelogs/unreleased/security-guest-comments_2.yml
0 → 100644
View file @
387a9c4e
---
title
:
Fixed ability of guest users to edit/delete comments on locked or confidential issues.
merge_request
:
author
:
type
:
security
spec/controllers/projects/notes_controller_spec.rb
View file @
387a9c4e
...
@@ -283,14 +283,14 @@ describe Projects::NotesController do
...
@@ -283,14 +283,14 @@ describe Projects::NotesController do
def
post_create
(
extra_params
=
{})
def
post_create
(
extra_params
=
{})
post
:create
,
{
post
:create
,
{
note:
{
note:
'some other note'
},
note:
{
note:
'some other note'
,
noteable_id:
merge_request
.
id
},
namespace_id:
project
.
namespace
,
namespace_id:
project
.
namespace
,
project_id:
project
,
project_id:
project
,
target_type:
'merge_request'
,
target_type:
'merge_request'
,
target_id:
merge_request
.
id
,
target_id:
merge_request
.
id
,
note_project_id:
forked_project
.
id
,
note_project_id:
forked_project
.
id
,
in_reply_to_discussion_id:
existing_comment
.
discussion_id
in_reply_to_discussion_id:
existing_comment
.
discussion_id
}.
merge
(
extra_params
)
}.
merge
(
extra_params
)
end
end
context
'when the note_project_id is not correct'
do
context
'when the note_project_id is not correct'
do
...
@@ -324,6 +324,30 @@ describe Projects::NotesController do
...
@@ -324,6 +324,30 @@ describe Projects::NotesController do
end
end
end
end
context
'when target_id and noteable_id do not match'
do
let
(
:locked_issue
)
{
create
(
:issue
,
:locked
,
project:
project
)
}
let
(
:issue
)
{
create
(
:issue
,
project:
project
)}
before
do
project
.
update_attribute
(
:visibility_level
,
Gitlab
::
VisibilityLevel
::
PUBLIC
)
project
.
project_member
(
user
).
destroy
end
it
'uses target_id and ignores noteable_id'
do
request_params
=
{
note:
{
note:
'some note'
,
noteable_type:
'Issue'
,
noteable_id:
locked_issue
.
id
},
target_type:
'issue'
,
target_id:
issue
.
id
,
project_id:
project
,
namespace_id:
project
.
namespace
}
expect
{
post
:create
,
request_params
}.
to
change
{
issue
.
notes
.
count
}.
by
(
1
)
.
and
change
{
locked_issue
.
notes
.
count
}.
by
(
0
)
expect
(
response
).
to
have_gitlab_http_status
(
302
)
end
end
context
'when the merge request discussion is locked'
do
context
'when the merge request discussion is locked'
do
before
do
before
do
project
.
update_attribute
(
:visibility_level
,
Gitlab
::
VisibilityLevel
::
PUBLIC
)
project
.
update_attribute
(
:visibility_level
,
Gitlab
::
VisibilityLevel
::
PUBLIC
)
...
@@ -376,35 +400,60 @@ describe Projects::NotesController do
...
@@ -376,35 +400,60 @@ describe Projects::NotesController do
end
end
describe
'PUT update'
do
describe
'PUT update'
do
let
(
:request_params
)
do
context
"should update the note with a valid issue"
do
{
let
(
:request_params
)
do
namespace_id:
project
.
namespace
,
{
project_id:
project
,
namespace_id:
project
.
namespace
,
id:
note
,
project_id:
project
,
format: :json
,
id:
note
,
note:
{
format: :json
,
note:
"New comment"
note:
{
note:
"New comment"
}
}
}
}
end
end
before
do
before
do
sign_in
(
note
.
author
)
sign_in
(
note
.
author
)
project
.
add_developer
(
note
.
author
)
project
.
add_developer
(
note
.
author
)
end
it
"updates the note"
do
expect
{
put
:update
,
request_params
}.
to
change
{
note
.
reload
.
note
}
end
end
end
context
"doesnt update the note"
do
let
(
:issue
)
{
create
(
:issue
,
:confidential
,
project:
project
)
}
let
(
:note
)
{
create
(
:note
,
noteable:
issue
,
project:
project
)
}
it
"updates the note"
do
before
do
expect
{
put
:update
,
request_params
}.
to
change
{
note
.
reload
.
note
}
sign_in
(
user
)
project
.
add_guest
(
user
)
end
it
"disallows edits when the issue is confidential and the user has guest permissions"
do
request_params
=
{
namespace_id:
project
.
namespace
,
project_id:
project
,
id:
note
,
format: :json
,
note:
{
note:
"New comment"
}
}
expect
{
put
:update
,
request_params
}.
not_to
change
{
note
.
reload
.
note
}
expect
(
response
).
to
have_gitlab_http_status
(
404
)
end
end
end
end
end
describe
'DELETE destroy'
do
describe
'DELETE destroy'
do
let
(
:request_params
)
do
let
(
:request_params
)
do
{
{
namespace_id:
project
.
namespace
,
namespace_id:
project
.
namespace
,
project_id:
project
,
project_id:
project
,
id:
note
,
id:
note
,
format: :js
format: :js
}
}
end
end
...
...
spec/mailers/notify_spec.rb
View file @
387a9c4e
...
@@ -522,7 +522,7 @@ describe Notify do
...
@@ -522,7 +522,7 @@ describe Notify do
let
(
:project_snippet
)
{
create
(
:project_snippet
,
project:
project
)
}
let
(
:project_snippet
)
{
create
(
:project_snippet
,
project:
project
)
}
let
(
:project_snippet_note
)
{
create
(
:note_on_project_snippet
,
project:
project
,
noteable:
project_snippet
)
}
let
(
:project_snippet_note
)
{
create
(
:note_on_project_snippet
,
project:
project
,
noteable:
project_snippet
)
}
subject
{
described_class
.
note_snippet_email
(
project_snippet_note
.
author_id
,
project_snippet_note
.
id
)
}
subject
{
described_class
.
note_
project_
snippet_email
(
project_snippet_note
.
author_id
,
project_snippet_note
.
id
)
}
it_behaves_like
'an answer to an existing thread with reply-by-email enabled'
do
it_behaves_like
'an answer to an existing thread with reply-by-email enabled'
do
let
(
:model
)
{
project_snippet
}
let
(
:model
)
{
project_snippet
}
...
...
spec/models/note_spec.rb
View file @
387a9c4e
...
@@ -517,7 +517,7 @@ describe Note do
...
@@ -517,7 +517,7 @@ describe Note do
describe
'#to_ability_name'
do
describe
'#to_ability_name'
do
it
'returns snippet for a project snippet note'
do
it
'returns snippet for a project snippet note'
do
expect
(
build
(
:note_on_project_snippet
).
to_ability_name
).
to
eq
(
'snippet'
)
expect
(
build
(
:note_on_project_snippet
).
to_ability_name
).
to
eq
(
'
project_
snippet'
)
end
end
it
'returns personal_snippet for a personal snippet note'
do
it
'returns personal_snippet for a personal snippet note'
do
...
...
spec/policies/note_policy_spec.rb
View file @
387a9c4e
...
@@ -10,11 +10,50 @@ describe NotePolicy, mdoels: true do
...
@@ -10,11 +10,50 @@ describe NotePolicy, mdoels: true do
return
@policies
if
@policies
return
@policies
if
@policies
noteable
||=
issue
noteable
||=
issue
note
=
create
(
:note
,
noteable:
noteable
,
author:
user
,
project:
project
)
note
=
if
noteable
.
is_a?
(
Commit
)
create
(
:note_on_commit
,
commit_id:
noteable
.
id
,
author:
user
,
project:
project
)
else
create
(
:note
,
noteable:
noteable
,
author:
user
,
project:
project
)
end
@policies
=
described_class
.
new
(
user
,
note
)
@policies
=
described_class
.
new
(
user
,
note
)
end
end
shared_examples_for
'a discussion with a private noteable'
do
let
(
:noteable
)
{
issue
}
let
(
:policy
)
{
policies
(
noteable
)
}
context
'when the note author can no longer see the noteable'
do
it
'can not edit nor read the note'
do
expect
(
policy
).
to
be_disallowed
(
:admin_note
)
expect
(
policy
).
to
be_disallowed
(
:resolve_note
)
expect
(
policy
).
to
be_disallowed
(
:read_note
)
end
end
context
'when the note author can still see the noteable'
do
before
do
project
.
add_developer
(
user
)
end
it
'can edit the note'
do
expect
(
policy
).
to
be_allowed
(
:admin_note
)
expect
(
policy
).
to
be_allowed
(
:resolve_note
)
expect
(
policy
).
to
be_allowed
(
:read_note
)
end
end
end
context
'when the project is private'
do
let
(
:project
)
{
create
(
:project
,
:private
,
:repository
)
}
context
'when the noteable is a commit'
do
it_behaves_like
'a discussion with a private noteable'
do
let
(
:noteable
)
{
project
.
repository
.
head_commit
}
end
end
end
context
'when the project is public'
do
context
'when the project is public'
do
context
'when the note author is not a project member'
do
context
'when the note author is not a project member'
do
it
'can edit a note'
do
it
'can edit a note'
do
...
@@ -24,14 +63,48 @@ describe NotePolicy, mdoels: true do
...
@@ -24,14 +63,48 @@ describe NotePolicy, mdoels: true do
end
end
end
end
context
'when the noteable is a snippet'
do
context
'when the noteable is a project snippet'
do
it
'can edit note'
do
policies
=
policies
(
create
(
:project_snippet
,
:public
,
project:
project
))
expect
(
policies
).
to
be_allowed
(
:admin_note
)
expect
(
policies
).
to
be_allowed
(
:resolve_note
)
expect
(
policies
).
to
be_allowed
(
:read_note
)
end
context
'when it is private'
do
it_behaves_like
'a discussion with a private noteable'
do
let
(
:noteable
)
{
create
(
:project_snippet
,
:private
,
project:
project
)
}
end
end
end
context
'when the noteable is a personal snippet'
do
it
'can edit note'
do
it
'can edit note'
do
policies
=
policies
(
create
(
:p
roject_snippet
,
project:
project
))
policies
=
policies
(
create
(
:p
ersonal_snippet
,
:public
))
expect
(
policies
).
to
be_allowed
(
:admin_note
)
expect
(
policies
).
to
be_allowed
(
:admin_note
)
expect
(
policies
).
to
be_allowed
(
:resolve_note
)
expect
(
policies
).
to
be_allowed
(
:resolve_note
)
expect
(
policies
).
to
be_allowed
(
:read_note
)
expect
(
policies
).
to
be_allowed
(
:read_note
)
end
end
context
'when it is private'
do
it
'can not edit nor read the note'
do
policies
=
policies
(
create
(
:personal_snippet
,
:private
))
expect
(
policies
).
to
be_disallowed
(
:admin_note
)
expect
(
policies
).
to
be_disallowed
(
:resolve_note
)
expect
(
policies
).
to
be_disallowed
(
:read_note
)
end
end
end
context
'when a discussion is confidential'
do
before
do
issue
.
update_attribute
(
:confidential
,
true
)
end
it_behaves_like
'a discussion with a private noteable'
end
end
context
'when a discussion is locked'
do
context
'when a discussion is locked'
do
...
...
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