Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
gpt
large_projects
gitlabhq1
Commits
6b6b928c
Unverified
Commit
6b6b928c
authored
6 years ago
by
Imre Farkas
Browse files
Options
Download
Email Patches
Plain Diff
Share groups with groups
parent
623ef392
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
286 additions
and
32 deletions
+286
-32
app/controllers/groups/group_links_controller.rb
app/controllers/groups/group_links_controller.rb
+19
-0
app/models/group.rb
app/models/group.rb
+2
-0
app/models/group_group_link.rb
app/models/group_group_link.rb
+22
-0
app/services/groups/group_links/create_service.rb
app/services/groups/group_links/create_service.rb
+18
-0
app/views/groups/group_members/_new_shared_group.html.haml
app/views/groups/group_members/_new_shared_group.html.haml
+21
-0
app/views/groups/group_members/index.html.haml
app/views/groups/group_members/index.html.haml
+50
-31
config/routes/group.rb
config/routes/group.rb
+2
-0
db/migrate/20180902070406_create_group_group_links.rb
db/migrate/20180902070406_create_group_group_links.rb
+41
-0
db/schema.rb
db/schema.rb
+14
-1
spec/controllers/groups/group_links_controller_spec.rb
spec/controllers/groups/group_links_controller_spec.rb
+40
-0
spec/factories/group_group_links.rb
spec/factories/group_group_links.rb
+8
-0
spec/models/group_group_link_spec.rb
spec/models/group_group_link_spec.rb
+27
-0
spec/services/groups/group_links/create_service_spec.rb
spec/services/groups/group_links/create_service_spec.rb
+22
-0
No files found.
app/controllers/groups/group_links_controller.rb
0 → 100644
View file @
6b6b928c
class
Groups::GroupLinksController
<
Groups
::
ApplicationController
# before_action :authorize_admin_project!
# before_action :authorize_admin_project_member!, only: [:update]
before_action
:group
def
create
shared_group
=
Group
.
find
(
params
[
:shared_group_id
])
if
params
[
:shared_group_id
].
present?
Groups
::
GroupLinks
::
CreateService
.
new
(
group
,
current_user
,
group_link_create_params
).
execute
(
shared_group
)
redirect_to
group_group_members_path
(
group
)
end
protected
def
group_link_create_params
params
.
permit
(
:shared_group_access
,
:expires_at
)
end
end
This diff is collapsed.
Click to expand it.
app/models/group.rb
View file @
6b6b928c
...
...
@@ -27,6 +27,8 @@ class Group < Namespace
has_many
:members_and_requesters
,
as: :source
,
class_name:
'GroupMember'
has_many
:milestones
has_many
:group_group_links
,
foreign_key: :shared_with_group_id
has_many
:shared_groups
,
through: :group_group_links
,
source: :shared_group
has_many
:project_group_links
,
dependent: :destroy
# rubocop:disable Cop/ActiveRecordDependent
has_many
:shared_projects
,
through: :project_group_links
,
source: :project
...
...
This diff is collapsed.
Click to expand it.
app/models/group_group_link.rb
0 → 100644
View file @
6b6b928c
# frozen_string_literal: true
class
GroupGroupLink
<
ActiveRecord
::
Base
include
Expirable
belongs_to
:shared_group
,
class_name:
'Group'
,
foreign_key: :shared_group_id
belongs_to
:shared_with_group
,
class_name:
'Group'
,
foreign_key: :shared_with_group_id
validates
:shared_group
,
presence:
true
validates
:shared_group_id
,
uniqueness:
{
scope:
[
:shared_with_group_id
],
message:
'already shared with this group'
}
validates
:shared_with_group
,
presence:
true
validates
:group_access
,
presence:
true
validates
:group_access
,
inclusion:
{
in:
Gitlab
::
Access
.
values
},
presence:
true
def
self
.
access_options
Gitlab
::
Access
.
options
end
def
self
.
default_access
Gitlab
::
Access
::
DEVELOPER
end
end
This diff is collapsed.
Click to expand it.
app/services/groups/group_links/create_service.rb
0 → 100644
View file @
6b6b928c
# frozen_string_literal: true
module
Groups
module
GroupLinks
class
CreateService
<
BaseService
def
execute
(
shared_group
)
return
false
unless
shared_group
group
.
group_group_links
.
create
(
shared_group:
shared_group
,
shared_with_group:
group
,
group_access:
params
[
:shared_group_access
],
expires_at:
params
[
:expires_at
]
)
end
end
end
end
This diff is collapsed.
Click to expand it.
app/views/groups/group_members/_new_shared_group.html.haml
0 → 100644
View file @
6b6b928c
.row
.col-sm-12
=
form_tag
group_group_links_path
(
@group
),
class:
'js-requires-input'
,
method: :post
do
.form-group
=
label_tag
:shared_group_id
,
'Select a group to share with'
,
class:
'label-bold'
-#= groups_select_tag(:link_group_id, data: { skip_groups: [7] }, class: "input-clamp", required: true)
=
text_field_tag
:shared_group_id
,
nil
,
class:
'form-control'
,
id:
'foo'
.form-group
=
label_tag
:shared_group_access
,
'Max access level'
,
class:
'label-bold'
.select-wrapper
=
select_tag
:share_group_access
,
options_for_select
(
GroupGroupLink
.
access_options
,
GroupGroupLink
.
default_access
),
class:
'form-control select-control'
=
icon
(
'chevron-down'
)
.form-text.text-muted.append-bottom-10
=
link_to
'Read more'
,
help_page_path
(
'user/permissions'
),
class:
'vlink'
about role permissions
.form-group
=
label_tag
:expires_at
,
'Access expiration date'
,
class:
'label-bold'
.clearable-input
=
text_field_tag
:expires_at
,
nil
,
class:
'form-control js-access-expiration-date-groups'
,
placeholder:
'Expiration date'
,
id:
'expires_at_groups'
%i
.clear-icon.js-clear-input
=
submit_tag
'Share'
,
class:
'btn btn-create'
This diff is collapsed.
Click to expand it.
app/views/groups/group_members/index.html.haml
View file @
6b6b928c
-
page_title
"Members"
-
can_manage_members
=
can?
(
current_user
,
:admin_group_member
,
@group
)
.project-members-page.prepend-top-default
%h4
Members
%hr
-
if
can_manage_members
.project-members-new.append-bottom-default
%p
.clearfix
Add new member to
.row.prepend-top-default
.col-lg-12
%h4
Group members
-
if
can_manage_members
%p
You can add a new member to
%strong
=
@group
.
name
=
render
"new_group_member"
or share it with another group.
-
else
%p
Members can be added by project
%i
Maintainers
or
%i
Owners
.light
-
if
can_manage_members
%ul
.nav-links.nav.nav-tabs.gitlab-tabs
{
role:
'tablist'
}
%li
.nav-tab
{
role:
'presentation'
}
%a
.nav-link.active
{
href:
'#add-member-pane'
,
id:
'add-member-tab'
,
data:
{
toggle:
'tab'
},
role:
'tab'
}
Add member
-
#if @project.allowed_to_share_with_group?
%li
.nav-tab
{
role:
'presentation'
}
%a
.nav-link
{
href:
'#share-with-group-pane'
,
id:
'share-with-group-tab'
,
data:
{
toggle:
'tab'
},
role:
'tab'
}
Share with group
=
render
'shared/members/requests'
,
membership_source:
@group
,
requesters:
@requesters
.tab-content.gitlab-tab-content
.tab-pane.active
{
id:
'add-member-pane'
,
role:
'tabpanel'
}
=
render
'groups/group_members/new_group_member'
,
tab_title:
'Add member'
.tab-pane
{
id:
'share-with-group-pane'
,
role:
'tabpanel'
}
=
render
'groups/group_members/new_shared_group'
,
tab_title:
'Share with group'
.clearfix
%h5
.member.existing-title
Existing members
.card
.card-header.flex-project-members-panel
%span
.flex-project-title
Members with access to
%strong
=
@group
.
name
%span
.badge
=
@members
.
total_count
=
form_tag
group_group_members_path
(
@group
),
method: :get
,
class:
'form-inline member-search-form flex-project-members-form'
do
.form-group
.position-relative.append-right-8
=
search_field_tag
:search
,
params
[
:search
],
{
placeholder:
'Find existing members by name'
,
class:
'form-control'
,
spellcheck:
false
}
%button
.member-search-btn
{
type:
"submit"
,
"aria-label"
=>
"Submit search"
}
=
icon
(
"search"
)
-
if
can_manage_members
=
render
'shared/members/filter_2fa_dropdown'
=
render
'shared/members/sort_dropdown'
%ul
.content-list.members-list
=
render
partial:
'shared/members/member'
,
collection:
@members
,
as: :member
=
paginate
@members
,
theme:
'gitlab'
=
render
'shared/members/requests'
,
membership_source:
@group
,
requesters:
@requesters
.clearfix
%h5
.member.existing-title
Existing members
.card
.card-header.flex-project-members-panel
%span
.flex-project-title
Members with access to
%strong
=
@group
.
name
%span
.badge
=
@members
.
total_count
=
form_tag
group_group_members_path
(
@group
),
method: :get
,
class:
'form-inline member-search-form flex-project-members-form'
do
.form-group
.position-relative.append-right-8
=
search_field_tag
:search
,
params
[
:search
],
{
placeholder:
'Find existing members by name'
,
class:
'form-control'
,
spellcheck:
false
}
%button
.member-search-btn
{
type:
"submit"
,
"aria-label"
=>
"Submit search"
}
=
icon
(
"search"
)
-
if
can_manage_members
=
render
'shared/members/filter_2fa_dropdown'
=
render
'shared/members/sort_dropdown'
%ul
.content-list.members-list
=
render
partial:
'shared/members/member'
,
collection:
@members
,
as: :member
=
paginate
@members
,
theme:
'gitlab'
This diff is collapsed.
Click to expand it.
config/routes/group.rb
View file @
6b6b928c
...
...
@@ -51,6 +51,8 @@ constraints(::Constraints::GroupUrlConstrainer.new) do
delete
:leave
,
on: :collection
end
resources
:group_links
,
only:
[
:index
,
:create
,
:update
,
:destroy
],
constraints:
{
id:
/\d+/
}
resources
:uploads
,
only:
[
:create
]
do
collection
do
get
":secret/:filename"
,
action: :show
,
as: :show
,
constraints:
{
filename:
%r{[^/]+}
}
...
...
This diff is collapsed.
Click to expand it.
db/migrate/20180902070406_create_group_group_links.rb
0 → 100644
View file @
6b6b928c
# frozen_string_literal: true
class
CreateGroupGroupLinks
<
ActiveRecord
::
Migration
include
Gitlab
::
Database
::
MigrationHelpers
DOWNTIME
=
false
disable_ddl_transaction!
def
up
create_table
:group_group_links
do
|
t
|
t
.
integer
:shared_group_id
t
.
integer
:shared_with_group_id
t
.
integer
:group_access
,
default:
30
,
null:
false
t
.
date
:expires_at
end
add_concurrent_foreign_key
:group_group_links
,
:namespaces
,
column: :shared_group_id
,
on_delete: :cascade
add_concurrent_index
:group_group_links
,
:shared_group_id
change_column_null
:group_group_links
,
:shared_group_id
,
false
add_concurrent_foreign_key
:group_group_links
,
:namespaces
,
column: :shared_with_group_id
,
on_delete: :cascade
add_concurrent_index
:group_group_links
,
:shared_with_group_id
change_column_null
:group_group_links
,
:shared_with_group_id
,
false
add_concurrent_index
:group_group_links
,
[
:shared_group_id
,
:shared_with_group_id
],
unique:
true
,
name:
'index_group_group_links_on_shared_group_and_shared_with_group'
end
def
down
drop_table
:group_group_links
end
end
This diff is collapsed.
Click to expand it.
db/schema.rb
View file @
6b6b928c
...
...
@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20180
826111825
) do
ActiveRecord
::
Schema
.
define
(
version:
20180
902070406
)
do
# These are extensions that must be enabled in order to support this database
enable_extension
"plpgsql"
...
...
@@ -949,6 +949,17 @@ ActiveRecord::Schema.define(version: 20180826111825) do
add_index
"group_custom_attributes"
,
[
"group_id"
,
"key"
],
name:
"index_group_custom_attributes_on_group_id_and_key"
,
unique:
true
,
using: :btree
add_index
"group_custom_attributes"
,
[
"key"
,
"value"
],
name:
"index_group_custom_attributes_on_key_and_value"
,
using: :btree
create_table
"group_group_links"
,
force: :cascade
do
|
t
|
t
.
integer
"shared_group_id"
,
null:
false
t
.
integer
"shared_with_group_id"
,
null:
false
t
.
integer
"group_access"
,
default:
30
,
null:
false
t
.
date
"expires_at"
end
add_index
"group_group_links"
,
[
"shared_group_id"
,
"shared_with_group_id"
],
name:
"index_group_group_links_on_shared_group_and_shared_with_group"
,
unique:
true
,
using: :btree
add_index
"group_group_links"
,
[
"shared_group_id"
],
name:
"index_group_group_links_on_shared_group_id"
,
using: :btree
add_index
"group_group_links"
,
[
"shared_with_group_id"
],
name:
"index_group_group_links_on_shared_with_group_id"
,
using: :btree
create_table
"identities"
,
force: :cascade
do
|
t
|
t
.
string
"extern_uid"
t
.
string
"provider"
...
...
@@ -2318,6 +2329,8 @@ ActiveRecord::Schema.define(version: 20180826111825) do
add_foreign_key
"gpg_signatures"
,
"gpg_keys"
,
on_delete: :nullify
add_foreign_key
"gpg_signatures"
,
"projects"
,
on_delete: :cascade
add_foreign_key
"group_custom_attributes"
,
"namespaces"
,
column:
"group_id"
,
on_delete: :cascade
add_foreign_key
"group_group_links"
,
"namespaces"
,
column:
"shared_group_id"
,
name:
"fk_d3a0488427"
,
on_delete: :cascade
add_foreign_key
"group_group_links"
,
"namespaces"
,
column:
"shared_with_group_id"
,
name:
"fk_2b2353ca49"
,
on_delete: :cascade
add_foreign_key
"import_export_uploads"
,
"projects"
,
on_delete: :cascade
add_foreign_key
"internal_ids"
,
"namespaces"
,
name:
"fk_162941d509"
,
on_delete: :cascade
add_foreign_key
"internal_ids"
,
"projects"
,
on_delete: :cascade
...
...
This diff is collapsed.
Click to expand it.
spec/controllers/groups/group_links_controller_spec.rb
0 → 100644
View file @
6b6b928c
require
'spec_helper'
describe
Groups
::
GroupLinksController
do
let
(
:group
)
{
create
(
:group
,
:public
)
}
# TODO(ifarkas): why does it need to be public?
let
(
:shared_group
)
{
create
(
:group
,
:public
)
}
let
(
:user
)
{
create
(
:user
)
}
before
do
sign_in
(
user
)
end
describe
'#create'
do
subject
do
post
(
:create
,
group_id:
group
,
shared_group_id:
shared_group
.
id
,
shared_group_access:
GroupGroupLink
.
default_access
)
end
context
'when user has access to group he want to link another group to'
do
before
do
group
.
add_developer
(
user
)
shared_group
.
add_developer
(
user
)
end
it
'links group with selected group'
do
subject
expect
(
group
.
shared_groups
).
to
include
shared_group
end
it
'redirects to group links page'
do
subject
expect
(
response
).
to
(
redirect_to
(
group_group_members_path
(
group
)))
end
end
end
end
This diff is collapsed.
Click to expand it.
spec/factories/group_group_links.rb
0 → 100644
View file @
6b6b928c
FactoryBot
.
define
do
factory
:group_group_link
do
shared_group
{
group
}
shared_with_group
{
group
}
access_level
{
GroupMember
::
DEVELOPER
}
expires_at
nil
end
end
This diff is collapsed.
Click to expand it.
spec/models/group_group_link_spec.rb
0 → 100644
View file @
6b6b928c
require
'spec_helper'
describe
GroupGroupLink
do
describe
'validation'
do
let
(
:group
)
{
create
(
:group
)
}
let
(
:shared_group
)
{
create
(
:group
)
}
let!
(
:group_group_link
)
{
create
(
:group_group_link
,
shared_group:
shared_group
,
shared_with_group:
group
)
}
it
{
is_expected
.
to
validate_presence_of
(
:shared_group
)
}
it
{
is_expected
.
to
validate_uniqueness_of
(
:shared_group_id
).
scoped_to
(
:shared_with_group_id
).
with_message
(
/already shared/
)
}
it
{
is_expected
.
to
validate_presence_of
(
:shared_group
)
}
it
{
is_expected
.
to
validate_presence_of
(
:group_access
)
}
it
{
is_expected
.
to
validate_inclusion_of
(
:group_access
).
in_array
(
Gitlab
::
Access
.
values
)
}
# it 'does not allow a project to be shared with the group it is in' do
# project_group_link.group = group
#
# expect(project_group_link).not_to be_valid
# end
#
# it 'doesn not allow a project to be shared with an ancestor of the group it is in', :nested_groups do
# project_group_link.group = parent_group
#
# expect(project_group_link).not_to be_valid
# end
end
end
This diff is collapsed.
Click to expand it.
spec/services/groups/group_links/create_service_spec.rb
0 → 100644
View file @
6b6b928c
require
'spec_helper'
describe
Groups
::
GroupLinks
::
CreateService
,
'#execute'
do
let
(
:user
)
{
create
:user
}
let
(
:group
)
{
create
:group
}
let
(
:shared_group
)
{
create
:group
}
let
(
:opts
)
do
{
shared_group_access:
Gitlab
::
Access
::
DEVELOPER
,
expires_at:
nil
}
end
let
(
:subject
)
{
described_class
.
new
(
group
,
user
,
opts
)
}
it
'adds group to another group'
do
expect
{
subject
.
execute
(
group
)
}.
to
change
{
group
.
group_group_links
.
count
}.
from
(
0
).
to
(
1
)
end
it
'returns false if shared group is blank'
do
expect
{
subject
.
execute
(
nil
)
}.
not_to
change
{
group
.
group_group_links
.
count
}
end
end
This diff is collapsed.
Click to expand it.
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