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
1
Merge Requests
1
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
nexedi
gitlab-ce
Commits
6b7ef4ee
Commit
6b7ef4ee
authored
Jun 23, 2020
by
Sarah Yasonik
Committed by
Natalia Tepluhina
Jun 23, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Limit alert assignment to only users who can read alerts
parent
a6eb8c15
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
130 additions
and
76 deletions
+130
-76
app/assets/javascripts/alert_management/components/sidebar/sidebar_assignees.vue
...alert_management/components/sidebar/sidebar_assignees.vue
+13
-2
app/services/alert_management/alerts/update_service.rb
app/services/alert_management/alerts/update_service.rb
+13
-14
changelogs/unreleased/limit-alert-assignees.yml
changelogs/unreleased/limit-alert-assignees.yml
+5
-0
locale/gitlab.pot
locale/gitlab.pot
+6
-0
spec/frontend/alert_management/components/alert_managment_sidebar_assignees_spec.js
...ment/components/alert_managment_sidebar_assignees_spec.js
+21
-1
spec/services/alert_management/alerts/update_service_spec.rb
spec/services/alert_management/alerts/update_service_spec.rb
+72
-59
No files found.
app/assets/javascripts/alert_management/components/sidebar/sidebar_assignees.vue
View file @
6b7ef4ee
...
@@ -25,6 +25,9 @@ export default {
...
@@ -25,6 +25,9 @@ export default {
UPDATE_ALERT_ASSIGNEES_ERROR
:
s__
(
UPDATE_ALERT_ASSIGNEES_ERROR
:
s__
(
'
AlertManagement|There was an error while updating the assignee(s) of the alert. Please try again.
'
,
'
AlertManagement|There was an error while updating the assignee(s) of the alert. Please try again.
'
,
),
),
UPDATE_ALERT_ASSIGNEES_GRAPHQL_ERROR
:
s__
(
'
AlertManagement|This assignee cannot be assigned to this alert.
'
,
),
components
:
{
components
:
{
GlIcon
,
GlIcon
,
GlDropdown
,
GlDropdown
,
...
@@ -156,9 +159,17 @@ export default {
...
@@ -156,9 +159,17 @@ export default {
projectPath
:
this
.
projectPath
,
projectPath
:
this
.
projectPath
,
},
},
})
})
.
then
(()
=>
{
.
then
((
{
data
:
{
alertSetAssignees
:
{
errors
}
=
[]
}
=
{}
}
=
{}
)
=>
{
this
.
hideDropdown
();
this
.
hideDropdown
();
this
.
$emit
(
'
alert-refresh
'
);
if
(
errors
[
0
])
{
return
this
.
$emit
(
'
alert-sidebar-error
'
,
`
${
this
.
$options
.
UPDATE_ALERT_ASSIGNEES_GRAPHQL_ERROR
}
${
errors
[
0
]}
.`
,
);
}
return
this
.
$emit
(
'
alert-refresh
'
);
})
})
.
catch
(()
=>
{
.
catch
(()
=>
{
this
.
$emit
(
'
alert-sidebar-error
'
,
this
.
$options
.
UPDATE_ALERT_ASSIGNEES_ERROR
);
this
.
$emit
(
'
alert-sidebar-error
'
,
this
.
$options
.
UPDATE_ALERT_ASSIGNEES_ERROR
);
...
...
app/services/alert_management/alerts/update_service.rb
View file @
6b7ef4ee
...
@@ -19,6 +19,8 @@ module AlertManagement
...
@@ -19,6 +19,8 @@ module AlertManagement
return
error_no_updates
if
params
.
empty?
return
error_no_updates
if
params
.
empty?
filter_assignees
filter_assignees
return
error_no_assignee_permissions
if
unauthorized_assignees?
old_assignees
=
alert
.
assignees
.
to_a
old_assignees
=
alert
.
assignees
.
to_a
if
alert
.
update
(
params
)
if
alert
.
update
(
params
)
...
@@ -38,10 +40,6 @@ module AlertManagement
...
@@ -38,10 +40,6 @@ module AlertManagement
current_user
&
.
can?
(
:update_alert_management_alert
,
alert
)
current_user
&
.
can?
(
:update_alert_management_alert
,
alert
)
end
end
def
assignee_todo_allowed?
assignee
&
.
can?
(
:read_alert_management_alert
,
alert
)
end
def
todo_service
def
todo_service
strong_memoize
(
:todo_service
)
do
strong_memoize
(
:todo_service
)
do
TodoService
.
new
TodoService
.
new
...
@@ -64,18 +62,20 @@ module AlertManagement
...
@@ -64,18 +62,20 @@ module AlertManagement
error
(
_
(
'Please provide attributes to update'
))
error
(
_
(
'Please provide attributes to update'
))
end
end
def
error_no_assignee_permissions
error
(
_
(
'Assignee has no permissions'
))
end
# ----- Assignee-related behavior ------
# ----- Assignee-related behavior ------
def
unauthorized_assignees?
params
[
:assignees
]
&
.
any?
{
|
user
|
!
user
.
can?
(
:read_alert_management_alert
,
alert
)
}
end
def
filter_assignees
def
filter_assignees
return
if
params
[
:assignees
].
nil?
return
if
params
[
:assignees
].
nil?
params
[
:assignees
]
=
Array
(
assignee
)
# Always take first assignee while multiple are not currently supported
end
params
[
:assignees
]
=
Array
(
params
[
:assignees
].
first
)
def
assignee
strong_memoize
(
:assignee
)
do
# Take first assignee while multiple are not currently supported
params
[
:assignees
]
&
.
first
end
end
end
def
process_assignement
(
old_assignees
)
def
process_assignement
(
old_assignees
)
...
@@ -84,8 +84,7 @@ module AlertManagement
...
@@ -84,8 +84,7 @@ module AlertManagement
end
end
def
assign_todo
def
assign_todo
# Remove check in follow-up issue https://gitlab.com/gitlab-org/gitlab/-/issues/222672
return
if
alert
.
assignees
.
empty?
return
unless
assignee_todo_allowed?
todo_service
.
assign_alert
(
alert
,
current_user
)
todo_service
.
assign_alert
(
alert
,
current_user
)
end
end
...
...
changelogs/unreleased/limit-alert-assignees.yml
0 → 100644
View file @
6b7ef4ee
---
title
:
Limit alert assignment to only users who can read alerts
merge_request
:
34681
author
:
type
:
fixed
locale/gitlab.pot
View file @
6b7ef4ee
...
@@ -2011,6 +2011,9 @@ msgstr ""
...
@@ -2011,6 +2011,9 @@ msgstr ""
msgid "AlertManagement|There was an error while updating the status of the alert. Please try again."
msgid "AlertManagement|There was an error while updating the status of the alert. Please try again."
msgstr ""
msgstr ""
msgid "AlertManagement|This assignee cannot be assigned to this alert."
msgstr ""
msgid "AlertManagement|Tool"
msgid "AlertManagement|Tool"
msgstr ""
msgstr ""
...
@@ -3020,6 +3023,9 @@ msgid_plural "%d Assignees"
...
@@ -3020,6 +3023,9 @@ msgid_plural "%d Assignees"
msgstr[0] ""
msgstr[0] ""
msgstr[1] ""
msgstr[1] ""
msgid "Assignee has no permissions"
msgstr ""
msgid "Assignee lists not available with your current license"
msgid "Assignee lists not available with your current license"
msgstr ""
msgstr ""
...
...
spec/frontend/alert_management/components/alert_managment_sidebar_assignees_spec.js
View file @
6b7ef4ee
...
@@ -59,7 +59,7 @@ describe('Alert Details Sidebar Assignees', () => {
...
@@ -59,7 +59,7 @@ describe('Alert Details Sidebar Assignees', () => {
describe
(
'
updating the alert status
'
,
()
=>
{
describe
(
'
updating the alert status
'
,
()
=>
{
const
mockUpdatedMutationResult
=
{
const
mockUpdatedMutationResult
=
{
data
:
{
data
:
{
updateAlertStatu
s
:
{
alertSetAssignee
s
:
{
errors
:
[],
errors
:
[],
alert
:
{
alert
:
{
assigneeUsernames
:
[
'
root
'
],
assigneeUsernames
:
[
'
root
'
],
...
@@ -125,6 +125,26 @@ describe('Alert Details Sidebar Assignees', () => {
...
@@ -125,6 +125,26 @@ describe('Alert Details Sidebar Assignees', () => {
});
});
});
});
it
(
'
shows an error when request contains error messages
'
,
()
=>
{
wrapper
.
setData
({
isDropdownSearching
:
false
});
const
errorMutationResult
=
{
data
:
{
alertSetAssignees
:
{
errors
:
[
'
There was a problem for sure.
'
],
alert
:
{},
},
},
};
jest
.
spyOn
(
wrapper
.
vm
.
$apollo
,
'
mutate
'
).
mockResolvedValue
(
errorMutationResult
);
return
wrapper
.
vm
.
$nextTick
().
then
(()
=>
{
const
SideBarAssigneeItem
=
wrapper
.
findAll
(
SidebarAssignee
).
at
(
0
);
SideBarAssigneeItem
.
vm
.
$emit
(
'
click
'
);
expect
(
wrapper
.
emitted
(
'
alert-refresh
'
)).
toBeUndefined
();
});
});
it
(
'
stops updating and cancels loading when the request fails
'
,
()
=>
{
it
(
'
stops updating and cancels loading when the request fails
'
,
()
=>
{
jest
.
spyOn
(
wrapper
.
vm
.
$apollo
,
'
mutate
'
).
mockReturnValue
(
Promise
.
reject
(
new
Error
()));
jest
.
spyOn
(
wrapper
.
vm
.
$apollo
,
'
mutate
'
).
mockReturnValue
(
Promise
.
reject
(
new
Error
()));
wrapper
.
vm
.
updateAlertAssignees
(
'
root
'
);
wrapper
.
vm
.
updateAlertAssignees
(
'
root
'
);
...
...
spec/services/alert_management/alerts/update_service_spec.rb
View file @
6b7ef4ee
...
@@ -4,6 +4,7 @@ require 'spec_helper'
...
@@ -4,6 +4,7 @@ require 'spec_helper'
describe
AlertManagement
::
Alerts
::
UpdateService
do
describe
AlertManagement
::
Alerts
::
UpdateService
do
let_it_be
(
:user_with_permissions
)
{
create
(
:user
)
}
let_it_be
(
:user_with_permissions
)
{
create
(
:user
)
}
let_it_be
(
:other_user_with_permissions
)
{
create
(
:user
)
}
let_it_be
(
:user_without_permissions
)
{
create
(
:user
)
}
let_it_be
(
:user_without_permissions
)
{
create
(
:user
)
}
let_it_be
(
:alert
,
reload:
true
)
{
create
(
:alert_management_alert
)
}
let_it_be
(
:alert
,
reload:
true
)
{
create
(
:alert_management_alert
)
}
let_it_be
(
:project
)
{
alert
.
project
}
let_it_be
(
:project
)
{
alert
.
project
}
...
@@ -15,119 +16,131 @@ describe AlertManagement::Alerts::UpdateService do
...
@@ -15,119 +16,131 @@ describe AlertManagement::Alerts::UpdateService do
before_all
do
before_all
do
project
.
add_developer
(
user_with_permissions
)
project
.
add_developer
(
user_with_permissions
)
project
.
add_developer
(
other_user_with_permissions
)
end
end
describe
'#execute'
do
describe
'#execute'
do
shared_examples
'does not add a todo'
do
specify
{
expect
{
response
}.
not_to
change
(
Todo
,
:count
)
}
end
shared_examples
'does not add a system note'
do
specify
{
expect
{
response
}.
not_to
change
(
Note
,
:count
)
}
end
shared_examples
'error response'
do
|
message
|
it_behaves_like
'does not add a todo'
it_behaves_like
'does not add a system note'
it
'has an informative message'
do
expect
(
response
).
to
be_error
expect
(
response
.
message
).
to
eq
(
message
)
end
end
subject
(
:response
)
{
service
.
execute
}
subject
(
:response
)
{
service
.
execute
}
context
'when the current_user is nil'
do
context
'when the current_user is nil'
do
let
(
:current_user
)
{
nil
}
let
(
:current_user
)
{
nil
}
it
'results in an error'
do
it_behaves_like
'error response'
,
'You have no permissions'
expect
(
response
).
to
be_error
expect
(
response
.
message
).
to
eq
(
'You have no permissions'
)
end
end
end
context
'when user does not have permission to update alerts'
do
context
'when
current_
user does not have permission to update alerts'
do
let
(
:current_user
)
{
user_without_permissions
}
let
(
:current_user
)
{
user_without_permissions
}
it
'results in an error'
do
it_behaves_like
'error response'
,
'You have no permissions'
expect
(
response
).
to
be_error
expect
(
response
.
message
).
to
eq
(
'You have no permissions'
)
end
end
end
context
'when no parameters are included'
do
context
'when no parameters are included'
do
it
'results in an error'
do
it_behaves_like
'error response'
,
'Please provide attributes to update'
expect
(
response
).
to
be_error
expect
(
response
.
message
).
to
eq
(
'Please provide attributes to update'
)
end
end
end
context
'when an error occur
e
s during update'
do
context
'when an error occurs during update'
do
let
(
:params
)
{
{
title:
nil
}
}
let
(
:params
)
{
{
title:
nil
}
}
it
'results in an error'
do
it_behaves_like
'error response'
,
"Title can't be blank"
expect
{
response
}.
not_to
change
{
alert
.
reload
.
notes
.
count
}
expect
(
response
).
to
be_error
expect
(
response
.
message
).
to
eq
(
"Title can't be blank"
)
end
end
end
context
'when a model attribute is included without assignees'
do
context
'when a model attribute is included without assignees'
do
let
(
:params
)
{
{
title:
'This is an updated alert.'
}
}
let
(
:params
)
{
{
title:
'This is an updated alert.'
}
}
it_behaves_like
'does not add a todo'
it_behaves_like
'does not add a system note'
it
'updates the attribute'
do
it
'updates the attribute'
do
original_title
=
alert
.
title
original_title
=
alert
.
title
expect
{
response
}.
to
change
{
alert
.
title
}.
from
(
original_title
).
to
(
params
[
:title
])
expect
{
response
}.
to
change
{
alert
.
title
}.
from
(
original_title
).
to
(
params
[
:title
])
expect
(
response
).
to
be_success
expect
(
response
).
to
be_success
end
end
end
it
'skips adding a todo'
do
context
'when assignees are included'
do
expect
{
response
}.
not_to
change
(
Todo
,
:count
)
shared_examples
'adds a todo'
do
let
(
:assignee
)
{
expected_assignees
.
first
}
specify
do
expect
{
response
}.
to
change
{
assignee
.
reload
.
todos
.
count
}.
by
(
1
)
expect
(
assignee
.
todos
.
last
.
author
).
to
eq
(
current_user
)
end
end
end
end
context
'when assignees are included'
do
shared_examples
'adds a system note'
do
let
(
:params
)
{
{
assignees:
[
user_with_permissions
]
}
}
specify
{
expect
{
response
}.
to
change
{
alert
.
reload
.
notes
.
count
}.
by
(
1
)
}
end
shared_examples
'successful assignment'
do
it_behaves_like
'adds a system note'
it_behaves_like
'adds a todo'
after
do
after
do
alert
.
assignees
=
[]
alert
.
assignees
=
[]
end
end
it
'assigns the user'
do
specify
do
expect
{
response
}.
to
change
{
alert
.
reload
.
assignees
}.
from
([]).
to
(
params
[
:assignees
]
)
expect
{
response
}.
to
change
{
alert
.
reload
.
assignees
}.
from
([]).
to
(
expected_assignees
)
expect
(
response
).
to
be_success
expect
(
response
).
to
be_success
end
end
it
'creates a system note for the assignment'
do
expect
{
response
}.
to
change
{
alert
.
reload
.
notes
.
count
}.
by
(
1
)
end
end
it
'adds a todo'
do
let
(
:expected_assignees
)
{
params
[
:assignees
]
}
expect
{
response
}.
to
change
{
Todo
.
where
(
user:
user_with_permissions
).
count
}.
by
(
1
)
end
context
'when current user is not the assignee'
do
context
'when the assignee is the current user'
do
let
(
:assignee_user
)
{
create
(
:user
)
}
let
(
:params
)
{
{
assignees:
[
current_user
]
}
}
let
(
:params
)
{
{
assignees:
[
assignee_user
]
}
}
it
'skips adding todo for assignee without permission to read alert'
do
it_behaves_like
'successful assignment'
expect
{
response
}.
not_to
change
(
Todo
,
:count
)
end
end
context
'when assignee has read permission'
do
context
'when the assignee has read permissions'
do
before
do
let
(
:params
)
{
{
assignees:
[
other_user_with_permissions
]
}
}
project
.
add_developer
(
assignee_user
)
it_behaves_like
'successful assignment'
end
end
it
'adds a todo
'
do
context
'when the assignee does not have read permissions
'
do
response
let
(
:params
)
{
{
assignees:
[
user_without_permissions
]
}
}
expect
(
Todo
.
first
.
author
).
to
eq
(
current_user
)
it_behaves_like
'error response'
,
'Assignee has no permissions'
end
end
end
context
'when current_user is nil'
do
let
(
:current_user
)
{
nil
}
it
'skips adding todo if current_user is nil
'
do
context
'when user is already assigned
'
do
project
.
add_developer
(
assignee_user
)
let
(
:params
)
{
{
assignees:
[
user_with_permissions
]
}
}
expect
{
response
}.
not_to
change
(
Todo
,
:count
)
before
do
end
alert
.
assignees
<<
user_with_permissions
end
end
it_behaves_like
'does not add a system note'
# TODO: We should not add another todo in this scenario
it_behaves_like
'adds a todo'
end
end
context
'with multiple users included'
do
context
'with multiple users included'
do
let
(
:params
)
{
{
assignees:
[
user_with_permissions
,
user_without_permissions
]
}
}
let
(
:params
)
{
{
assignees:
[
user_with_permissions
,
user_without_permissions
]
}
}
let
(
:expected_assignees
)
{
[
user_with_permissions
]
}
it
'assigns the first permissioned user'
do
it_behaves_like
'successful assignment'
expect
{
response
}.
to
change
{
alert
.
reload
.
assignees
}.
from
([]).
to
([
user_with_permissions
])
expect
(
response
).
to
be_success
end
end
end
end
end
end
end
...
...
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