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
c5aabfb7
Commit
c5aabfb7
authored
Jul 03, 2017
by
Nick Thomas
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Remove an unnecessary "included do ... end" block in app/models/concerns/approvable.rb
parent
eb24ebf4
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
122 additions
and
126 deletions
+122
-126
app/models/concerns/approvable.rb
app/models/concerns/approvable.rb
+122
-126
No files found.
app/models/concerns/approvable.rb
View file @
c5aabfb7
module
Approvable
extend
ActiveSupport
::
Concern
included
do
def
requires_approve?
approvals_required
.
nonzero?
end
def
requires_approve?
approvals_required
.
nonzero?
end
def
approved?
approvals_left
<
1
end
def
approved?
approvals_left
<
1
end
# Number of approvals remaining (excluding existing approvals) before the MR is
# considered approved. If there are fewer potential approvers than approvals left,
# choose the lower so the MR doesn't get 'stuck' in a state where it can't be approved.
#
def
approvals_left
[
[
approvals_required
-
approvals
.
count
,
number_of_potential_approvers
].
min
,
0
].
max
end
# Number of approvals remaining (excluding existing approvals) before the MR is
# considered approved. If there are fewer potential approvers than approvals left,
# choose the lower so the MR doesn't get 'stuck' in a state where it can't be approved.
#
def
approvals_left
[
[
approvals_required
-
approvals
.
count
,
number_of_potential_approvers
].
min
,
0
].
max
end
def
approvals_required
approvals_before_merge
||
target_project
.
approvals_before_merge
end
def
approvals_required
approvals_before_merge
||
target_project
.
approvals_before_merge
end
# An MR can potentially be approved by:
# - anyone in the approvers list
# - any other project member with developer access or higher (if there are no approvers
# left)
#
# It cannot be approved by:
# - a user who has already approved the MR
# - the MR author
#
def
number_of_potential_approvers
has_access
=
[
'access_level > ?'
,
Member
::
REPORTER
]
users_with_access
=
{
id:
project
.
project_authorizations
.
where
(
has_access
).
select
(
:user_id
)
}
all_approvers
=
all_approvers_including_groups
users_relation
=
User
.
active
.
where
.
not
(
id:
approvals
.
select
(
:user_id
))
users_relation
=
users_relation
.
where
.
not
(
id:
author
.
id
)
if
author
# This is an optimisation for large instances. Instead of getting the
# count of all users who meet the conditions in a single query, which
# produces a slow query plan, we get the union of all users with access
# and all users in the approvers list, and count them.
if
all_approvers
.
any?
specific_approvers
=
{
id:
all_approvers
.
map
(
&
:id
)
}
union
=
Gitlab
::
SQL
::
Union
.
new
([
users_relation
.
where
(
users_with_access
).
select
(
:id
),
users_relation
.
where
(
specific_approvers
).
select
(
:id
)
])
User
.
from
(
"(
#{
union
.
to_sql
}
) subquery"
).
count
else
users_relation
.
where
(
users_with_access
).
count
end
# An MR can potentially be approved by:
# - anyone in the approvers list
# - any other project member with developer access or higher (if there are no approvers
# left)
#
# It cannot be approved by:
# - a user who has already approved the MR
# - the MR author
#
def
number_of_potential_approvers
has_access
=
[
'access_level > ?'
,
Member
::
REPORTER
]
users_with_access
=
{
id:
project
.
project_authorizations
.
where
(
has_access
).
select
(
:user_id
)
}
all_approvers
=
all_approvers_including_groups
users_relation
=
User
.
active
.
where
.
not
(
id:
approvals
.
select
(
:user_id
))
users_relation
=
users_relation
.
where
.
not
(
id:
author
.
id
)
if
author
# This is an optimisation for large instances. Instead of getting the
# count of all users who meet the conditions in a single query, which
# produces a slow query plan, we get the union of all users with access
# and all users in the approvers list, and count them.
if
all_approvers
.
any?
specific_approvers
=
{
id:
all_approvers
.
map
(
&
:id
)
}
union
=
Gitlab
::
SQL
::
Union
.
new
([
users_relation
.
where
(
users_with_access
).
select
(
:id
),
users_relation
.
where
(
specific_approvers
).
select
(
:id
)
])
User
.
from
(
"(
#{
union
.
to_sql
}
) subquery"
).
count
else
users_relation
.
where
(
users_with_access
).
count
end
end
# Users in the list of approvers who have not already approved this MR.
#
def
approvers_left
User
.
where
(
id:
all_approvers_including_groups
.
map
(
&
:id
)).
where
.
not
(
id:
approvals
.
select
(
:user_id
))
end
# Users in the list of approvers who have not already approved this MR.
#
def
approvers_left
User
.
where
(
id:
all_approvers_including_groups
.
map
(
&
:id
)).
where
.
not
(
id:
approvals
.
select
(
:user_id
))
end
# The list of approvers from either this MR (if they've been set on the MR) or the
# target project. Excludes the author by default.
#
# Before a merge request has been created, author will be nil, so pass the current user
# on the MR create page.
#
def
overall_approvers
approvers_relation
=
approvers_overwritten?
?
approvers
:
target_project
.
approvers
approvers_relation
=
approvers_relation
.
where
.
not
(
user_id:
author
.
id
)
if
author
approvers_relation
end
# The list of approvers from either this MR (if they've been set on the MR) or the
# target project. Excludes the author by default.
#
# Before a merge request has been created, author will be nil, so pass the current user
# on the MR create page.
#
def
overall_approvers
approvers_relation
=
approvers_overwritten?
?
approvers
:
target_project
.
approvers
approvers_relation
=
approvers_relation
.
where
.
not
(
user_id:
author
.
id
)
if
author
approvers_relation
end
def
overall_approver_groups
approvers_overwritten?
?
approver_groups
:
target_project
.
approver_groups
end
def
overall_approver_groups
approvers_overwritten?
?
approver_groups
:
target_project
.
approver_groups
end
def
all_approvers_including_groups
approvers
=
[]
def
all_approvers_including_groups
approvers
=
[]
# Approvers from direct assignment
approvers
<<
approvers_from_users
# Approvers from direct assignment
approvers
<<
approvers_from_users
approvers
<<
approvers_from_groups
approvers
<<
approvers_from_groups
approvers
.
flatten
end
approvers
.
flatten
end
def
approvers_from_users
overall_approvers
.
map
(
&
:user
)
end
def
approvers_from_users
overall_approvers
.
map
(
&
:user
)
end
def
approvers_from_groups
group_approvers
=
[]
def
approvers_from_groups
group_approvers
=
[]
overall_approver_groups
.
each
do
|
approver_group
|
group_approvers
<<
approver_group
.
users
end
overall_approver_groups
.
each
do
|
approver_group
|
group_approvers
<<
approver_group
.
users
end
group_approvers
.
flatten!
group_approvers
.
flatten!
group_approvers
.
delete
(
author
)
group_approvers
.
delete
(
author
)
group_approvers
end
group_approvers
end
def
approvers_overwritten?
approvers
.
to_a
.
any?
||
approver_groups
.
to_a
.
any?
end
def
approvers_overwritten?
approvers
.
to_a
.
any?
||
approver_groups
.
to_a
.
any?
end
def
can_approve?
(
user
)
return
false
unless
user
return
true
if
approvers_left
.
include?
(
user
)
return
false
if
user
==
author
return
false
unless
user
.
can?
(
:update_merge_request
,
self
)
def
can_approve?
(
user
)
return
false
unless
user
return
true
if
approvers_left
.
include?
(
user
)
return
false
if
user
==
author
return
false
unless
user
.
can?
(
:update_merge_request
,
self
)
any_approver_allowed?
&&
approvals
.
where
(
user:
user
).
empty?
end
any_approver_allowed?
&&
approvals
.
where
(
user:
user
).
empty?
end
def
has_approved?
(
user
)
return
false
unless
user
def
has_approved?
(
user
)
return
false
unless
user
approved_by_users
.
include?
(
user
)
end
approved_by_users
.
include?
(
user
)
end
# Once there are fewer approvers left in the list than approvals required, allow other
# project members to approve the MR.
#
def
any_approver_allowed?
approvals_left
>
approvers_left
.
count
end
# Once there are fewer approvers left in the list than approvals required, allow other
# project members to approve the MR.
#
def
any_approver_allowed?
approvals_left
>
approvers_left
.
count
end
def
approved_by_users
approvals
.
map
(
&
:user
)
end
def
approved_by_users
approvals
.
map
(
&
:user
)
end
def
approver_ids
=
(
value
)
value
.
split
(
","
).
map
(
&
:strip
).
each
do
|
user_id
|
next
if
author
&&
user_id
==
author
.
id
def
approver_ids
=
(
value
)
value
.
split
(
","
).
map
(
&
:strip
).
each
do
|
user_id
|
next
if
author
&&
user_id
==
author
.
id
approvers
.
find_or_initialize_by
(
user_id:
user_id
,
target_id:
id
)
end
approvers
.
find_or_initialize_by
(
user_id:
user_id
,
target_id:
id
)
end
end
def
approver_group_ids
=
(
value
)
value
.
split
(
","
).
map
(
&
:strip
).
each
do
|
group_id
|
approver_groups
.
find_or_initialize_by
(
group_id:
group_id
,
target_id:
id
)
end
def
approver_group_ids
=
(
value
)
value
.
split
(
","
).
map
(
&
:strip
).
each
do
|
group_id
|
approver_groups
.
find_or_initialize_by
(
group_id:
group_id
,
target_id:
id
)
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