BigW Consortium Gitlab
Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
gitlab-ce
Project
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
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Forest Godfrey
gitlab-ce
Commits
9b835d10
Commit
9b835d10
authored
Jun 16, 2017
by
Douwe Maan
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'tc-fix-group-finder-subgrouping' into 'master'
Show private subgroups if member of parent group Closes #32135 See merge request !11764
parents
11b3e54c
aeaf5860
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
127 additions
and
32 deletions
+127
-32
groups_finder.rb
app/finders/groups_finder.rb
+15
-3
group_hierarchy.rb
lib/gitlab/group_hierarchy.rb
+25
-18
groups_controller_spec.rb
spec/controllers/groups_controller_spec.rb
+5
-4
groups_finder_spec.rb
spec/finders/groups_finder_spec.rb
+58
-7
group_hierarchy_spec.rb
spec/lib/gitlab/group_hierarchy_spec.rb
+24
-0
No files found.
app/finders/groups_finder.rb
View file @
9b835d10
...
...
@@ -5,8 +5,10 @@ class GroupsFinder < UnionFinder
end
def
execute
groups
=
find_union
(
all_groups
,
Group
).
with_route
.
order_id_desc
by_parent
(
groups
)
items
=
all_groups
.
map
do
|
item
|
by_parent
(
item
)
end
find_union
(
items
,
Group
).
with_route
.
order_id_desc
end
private
...
...
@@ -16,12 +18,22 @@ class GroupsFinder < UnionFinder
def
all_groups
groups
=
[]
groups
<<
current_user
.
authorized_groups
if
current_user
if
current_user
groups
<<
Gitlab
::
GroupHierarchy
.
new
(
groups_for_ancestors
,
groups_for_descendants
).
all_groups
end
groups
<<
Group
.
unscoped
.
public_to_user
(
current_user
)
groups
end
def
groups_for_ancestors
current_user
.
authorized_groups
end
def
groups_for_descendants
current_user
.
groups
end
def
by_parent
(
groups
)
return
groups
unless
params
[
:parent
]
...
...
lib/gitlab/group_hierarchy.rb
View file @
9b835d10
...
...
@@ -3,33 +3,38 @@ module Gitlab
#
# This class uses recursive CTEs and as a result will only work on PostgreSQL.
class
GroupHierarchy
attr_reader
:base
,
:model
# base - An instance of ActiveRecord::Relation for which to get parent or
# child groups.
def
initialize
(
base
)
@base
=
base
@model
=
base
.
model
attr_reader
:ancestors_base
,
:descendants_base
,
:model
# ancestors_base - An instance of ActiveRecord::Relation for which to
# get parent groups.
# descendants_base - An instance of ActiveRecord::Relation for which to
# get child groups. If omitted, ancestors_base is used.
def
initialize
(
ancestors_base
,
descendants_base
=
ancestors_base
)
raise
ArgumentError
.
new
(
"Model of ancestors_base does not match model of descendants_base"
)
if
ancestors_base
.
model
!=
descendants_base
.
model
@ancestors_base
=
ancestors_base
@descendants_base
=
descendants_base
@model
=
ancestors_base
.
model
end
# Returns a relation that includes the
base set of groups and all their
# ancestors (recursively).
# Returns a relation that includes the
ancestors_base set of groups
# an
d all their an
cestors (recursively).
def
base_and_ancestors
return
model
.
non
e
unless
Group
.
supports_nested_groups?
return
ancestors_bas
e
unless
Group
.
supports_nested_groups?
base_and_ancestors_cte
.
apply_to
(
model
.
all
)
end
# Returns a relation that includes the
base set of groups and all their
# descendants (recursively).
# Returns a relation that includes the
descendants_base set of groups
#
and all their
descendants (recursively).
def
base_and_descendants
return
model
.
non
e
unless
Group
.
supports_nested_groups?
return
descendants_bas
e
unless
Group
.
supports_nested_groups?
base_and_descendants_cte
.
apply_to
(
model
.
all
)
end
# Returns a relation that includes the base groups, their ancestors,
and the
# descendants of the base groups.
# Returns a relation that includes the base groups, their ancestors,
#
and the
descendants of the base groups.
#
# The resulting query will roughly look like the following:
#
...
...
@@ -48,8 +53,10 @@ module Gitlab
#
# Using this approach allows us to further add criteria to the relation with
# Rails thinking it's selecting data the usual way.
#
# If nested groups are not supported, ancestors_base is returned.
def
all_groups
return
base
unless
Group
.
supports_nested_groups?
return
ancestors_
base
unless
Group
.
supports_nested_groups?
ancestors
=
base_and_ancestors_cte
descendants
=
base_and_descendants_cte
...
...
@@ -72,7 +79,7 @@ module Gitlab
def
base_and_ancestors_cte
cte
=
SQL
::
RecursiveCTE
.
new
(
:base_and_ancestors
)
cte
<<
base
.
except
(
:order
)
cte
<<
ancestors_
base
.
except
(
:order
)
# Recursively get all the ancestors of the base set.
cte
<<
model
.
...
...
@@ -86,7 +93,7 @@ module Gitlab
def
base_and_descendants_cte
cte
=
SQL
::
RecursiveCTE
.
new
(
:base_and_descendants
)
cte
<<
base
.
except
(
:order
)
cte
<<
descendants_
base
.
except
(
:order
)
# Recursively get all the descendants of the base set.
cte
<<
model
.
...
...
spec/controllers/groups_controller_spec.rb
View file @
9b835d10
...
...
@@ -2,7 +2,7 @@ require 'rails_helper'
describe
GroupsController
do
let
(
:user
)
{
create
(
:user
)
}
let
(
:group
)
{
create
(
:group
)
}
let
(
:group
)
{
create
(
:group
,
:public
)
}
let
(
:project
)
{
create
(
:empty_project
,
namespace:
group
)
}
let!
(
:group_member
)
{
create
(
:group_member
,
group:
group
,
user:
user
)
}
...
...
@@ -35,14 +35,15 @@ describe GroupsController do
sign_in
(
user
)
end
it
'shows
the public
subgroups'
do
it
'shows
all
subgroups'
do
get
:subgroups
,
id:
group
.
to_param
expect
(
assigns
(
:nested_groups
)).
to
contain_exactly
(
public_subgroup
)
expect
(
assigns
(
:nested_groups
)).
to
contain_exactly
(
public_subgroup
,
private_subgroup
)
end
context
'being member'
do
context
'being member
of private subgroup
'
do
it
'shows public and private subgroups the user is member of'
do
group_member
.
destroy!
private_subgroup
.
add_guest
(
user
)
get
:subgroups
,
id:
group
.
to_param
...
...
spec/finders/groups_finder_spec.rb
View file @
9b835d10
...
...
@@ -38,28 +38,79 @@ describe GroupsFinder do
end
end
context
'subgroups'
do
context
'subgroups'
,
:nested_groups
do
let!
(
:parent_group
)
{
create
(
:group
,
:public
)
}
let!
(
:public_subgroup
)
{
create
(
:group
,
:public
,
parent:
parent_group
)
}
let!
(
:internal_subgroup
)
{
create
(
:group
,
:internal
,
parent:
parent_group
)
}
let!
(
:private_subgroup
)
{
create
(
:group
,
:private
,
parent:
parent_group
)
}
context
'without a user'
do
it
'only returns public subgroups'
do
expect
(
described_class
.
new
(
nil
,
parent:
parent_group
).
execute
).
to
contain_exactly
(
public_subgroup
)
it
'only returns p
arent and p
ublic subgroups'
do
expect
(
described_class
.
new
(
nil
).
execute
).
to
contain_exactly
(
parent_group
,
public_subgroup
)
end
end
context
'with a user'
do
it
'returns public and internal subgroups'
do
expect
(
described_class
.
new
(
user
,
parent:
parent_group
).
execute
).
to
contain_exactly
(
public_subgroup
,
internal_subgroup
)
subject
{
described_class
.
new
(
user
).
execute
}
it
'returns parent, public, and internal subgroups'
do
is_expected
.
to
contain_exactly
(
parent_group
,
public_subgroup
,
internal_subgroup
)
end
context
'being member'
do
it
'returns public subgroups, internal subgroups, and private subgroups user is member of'
do
it
'returns p
arent, p
ublic subgroups, internal subgroups, and private subgroups user is member of'
do
private_subgroup
.
add_guest
(
user
)
expect
(
described_class
.
new
(
user
,
parent:
parent_group
).
execute
).
to
contain_exactly
(
public_subgroup
,
internal_subgroup
,
private_subgroup
)
is_expected
.
to
contain_exactly
(
parent_group
,
public_subgroup
,
internal_subgroup
,
private_subgroup
)
end
end
context
'parent group private'
do
before
do
parent_group
.
update_attribute
(
:visibility_level
,
Gitlab
::
VisibilityLevel
::
PRIVATE
)
end
context
'being member of parent group'
do
it
'returns all subgroups'
do
parent_group
.
add_guest
(
user
)
is_expected
.
to
contain_exactly
(
parent_group
,
public_subgroup
,
internal_subgroup
,
private_subgroup
)
end
end
context
'authorized to private project'
do
context
'project one level deep'
do
let!
(
:subproject
)
{
create
(
:empty_project
,
:private
,
namespace:
private_subgroup
)
}
before
do
subproject
.
add_guest
(
user
)
end
it
'includes the subgroup of the project'
do
is_expected
.
to
include
(
private_subgroup
)
end
it
'does not include private subgroups deeper down'
do
subsubgroup
=
create
(
:group
,
:private
,
parent:
private_subgroup
)
is_expected
.
not_to
include
(
subsubgroup
)
end
end
context
'project two levels deep'
do
let!
(
:private_subsubgroup
)
{
create
(
:group
,
:private
,
parent:
private_subgroup
)
}
let!
(
:subsubproject
)
{
create
(
:empty_project
,
:private
,
namespace:
private_subsubgroup
)
}
before
do
subsubproject
.
add_guest
(
user
)
end
it
'returns all the ancestor groups'
do
is_expected
.
to
include
(
private_subsubgroup
,
private_subgroup
,
parent_group
)
end
it
'returns the groups for a given parent'
do
expect
(
described_class
.
new
(
user
,
parent:
parent_group
).
execute
).
to
include
(
private_subgroup
)
end
end
end
end
end
...
...
spec/lib/gitlab/group_hierarchy_spec.rb
View file @
9b835d10
...
...
@@ -17,6 +17,12 @@ describe Gitlab::GroupHierarchy, :postgresql do
it
'includes all of the ancestors'
do
expect
(
relation
).
to
include
(
parent
,
child1
)
end
it
'uses ancestors_base #initialize argument'
do
relation
=
described_class
.
new
(
Group
.
where
(
id:
child2
.
id
),
Group
.
none
).
base_and_ancestors
expect
(
relation
).
to
include
(
parent
,
child1
,
child2
)
end
end
describe
'#base_and_descendants'
do
...
...
@@ -31,6 +37,12 @@ describe Gitlab::GroupHierarchy, :postgresql do
it
'includes all the descendants'
do
expect
(
relation
).
to
include
(
child1
,
child2
)
end
it
'uses descendants_base #initialize argument'
do
relation
=
described_class
.
new
(
Group
.
none
,
Group
.
where
(
id:
parent
.
id
)).
base_and_descendants
expect
(
relation
).
to
include
(
parent
,
child1
,
child2
)
end
end
describe
'#all_groups'
do
...
...
@@ -49,5 +61,17 @@ describe Gitlab::GroupHierarchy, :postgresql do
it
'includes the descendants'
do
expect
(
relation
).
to
include
(
child2
)
end
it
'uses ancestors_base #initialize argument for ancestors'
do
relation
=
described_class
.
new
(
Group
.
where
(
id:
child1
.
id
),
Group
.
where
(
id:
Group
.
maximum
(
:id
).
succ
)).
all_groups
expect
(
relation
).
to
include
(
parent
)
end
it
'uses descendants_base #initialize argument for descendants'
do
relation
=
described_class
.
new
(
Group
.
where
(
id:
Group
.
maximum
(
:id
).
succ
),
Group
.
where
(
id:
child1
.
id
)).
all_groups
expect
(
relation
).
to
include
(
child2
)
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