Merge branch '30473-allow-creation-of-subgroups-with-gitlab_default_can_create_group-set-to-false' into 'master'

Make Members with Owner and Master roles always able to create subgroups

Closes #30473

See merge request !14046
This commit is contained in:
Douwe Maan 2017-09-07 22:11:20 +00:00
commit 3955dcb4cc
9 changed files with 235 additions and 31 deletions

View file

@ -10,7 +10,7 @@ class GroupsController < Groups::ApplicationController
# Authorize
before_action :authorize_admin_group!, only: [:edit, :update, :destroy, :projects]
before_action :authorize_create_group!, only: [:new, :create]
before_action :authorize_create_group!, only: [:new]
before_action :group_projects, only: [:projects, :activity, :issues, :merge_requests]
before_action :group_merge_requests, only: [:merge_requests]
@ -25,14 +25,7 @@ class GroupsController < Groups::ApplicationController
end
def new
@group = Group.new
if params[:parent_id].present?
parent = Group.find_by(id: params[:parent_id])
if can?(current_user, :create_subgroup, parent)
@group.parent = parent
end
end
@group = Group.new(params.permit(:parent_id))
end
def create
@ -128,9 +121,14 @@ class GroupsController < Groups::ApplicationController
end
def authorize_create_group!
unless can?(current_user, :create_group)
return render_404
allowed = if params[:parent_id].present?
parent = Group.find_by(id: params[:parent_id])
can?(current_user, :create_subgroup, parent)
else
can?(current_user, :create_group)
end
render_404 unless allowed
end
def determine_layout

View file

@ -49,7 +49,7 @@ class GroupPolicy < BasePolicy
enable :change_visibility_level
end
rule { owner & can_create_group & nested_groups_supported }.enable :create_subgroup
rule { owner & nested_groups_supported }.enable :create_subgroup
rule { public_group | logged_in_viewable }.enable :view_globally

View file

@ -8,15 +8,7 @@ module Groups
def execute
@group = Group.new(params)
unless Gitlab::VisibilityLevel.allowed_for?(current_user, params[:visibility_level])
deny_visibility_level(@group)
return @group
end
if @group.parent && !can?(current_user, :create_subgroup, @group.parent)
@group.parent = nil
@group.errors.add(:parent_id, 'You dont have permission to create a subgroup in this group.')
unless can_use_visibility_level? && can_create_group?
return @group
end
@ -39,5 +31,33 @@ module Groups
def create_chat_team?
Gitlab.config.mattermost.enabled && @chat_team && group.chat_team.nil?
end
def can_create_group?
if @group.subgroup?
unless can?(current_user, :create_subgroup, @group.parent)
@group.parent = nil
@group.errors.add(:parent_id, 'You dont have permission to create a subgroup in this group.')
return false
end
else
unless can?(current_user, :create_group)
@group.errors.add(:base, 'You dont have permission to create groups.')
return false
end
end
true
end
def can_use_visibility_level?
unless Gitlab::VisibilityLevel.allowed_for?(current_user, params[:visibility_level])
deny_visibility_level(@group)
return false
end
true
end
end
end

View file

@ -74,7 +74,12 @@ module API
use :optional_params
end
post do
parent_group = find_group!(params[:parent_id]) if params[:parent_id].present?
if parent_group
authorize! :create_subgroup, parent_group
else
authorize! :create_group
end
group = ::Groups::CreateService.new(current_user, declared_params(include_missing: false)).execute

View file

@ -93,7 +93,7 @@ module API
end
def find_group(id)
if id =~ /^\d+$/
if id.to_s =~ /^\d+$/
Group.find_by(id: id)
else
Group.find_by_full_path(id)

View file

@ -2,9 +2,133 @@ require 'rails_helper'
describe GroupsController do
let(:user) { create(:user) }
let(:admin) { create(:admin) }
let(:group) { create(:group, :public) }
let(:project) { create(:project, namespace: group) }
let!(:group_member) { create(:group_member, group: group, user: user) }
let!(:owner) { group.add_owner(create(:user)).user }
let!(:master) { group.add_master(create(:user)).user }
let!(:developer) { group.add_developer(create(:user)).user }
let!(:guest) { group.add_guest(create(:user)).user }
shared_examples 'member with ability to create subgroups' do
it 'renders the new page' do
sign_in(member)
get :new, parent_id: group.id
expect(response).to render_template(:new)
end
end
shared_examples 'member without ability to create subgroups' do
it 'renders the 404 page' do
sign_in(member)
get :new, parent_id: group.id
expect(response).not_to render_template(:new)
expect(response.status).to eq(404)
end
end
describe 'GET #new' do
context 'when creating subgroups', :nested_groups do
[true, false].each do |can_create_group_status|
context "and can_create_group is #{can_create_group_status}" do
before do
User.where(id: [admin, owner, master, developer, guest]).update_all(can_create_group: can_create_group_status)
end
[:admin, :owner].each do |member_type|
context "and logged in as #{member_type.capitalize}" do
it_behaves_like 'member with ability to create subgroups' do
let(:member) { send(member_type) }
end
end
end
[:guest, :developer, :master].each do |member_type|
context "and logged in as #{member_type.capitalize}" do
it_behaves_like 'member without ability to create subgroups' do
let(:member) { send(member_type) }
end
end
end
end
end
end
end
describe 'POST #create' do
context 'when creating subgroups', :nested_groups do
[true, false].each do |can_create_group_status|
context "and can_create_group is #{can_create_group_status}" do
context 'and logged in as Owner' do
it 'creates the subgroup' do
owner.update_attribute(:can_create_group, can_create_group_status)
sign_in(owner)
post :create, group: { parent_id: group.id, path: 'subgroup' }
expect(response).to be_redirect
expect(response.body).to match(%r{http://test.host/#{group.path}/subgroup})
end
end
context 'and logged in as Developer' do
it 'renders the new template' do
developer.update_attribute(:can_create_group, can_create_group_status)
sign_in(developer)
previous_group_count = Group.count
post :create, group: { parent_id: group.id, path: 'subgroup' }
expect(response).to render_template(:new)
expect(Group.count).to eq(previous_group_count)
end
end
end
end
end
context 'when creating a top level group' do
before do
sign_in(developer)
end
context 'and can_create_group is enabled' do
before do
developer.update_attribute(:can_create_group, true)
end
it 'creates the Group' do
original_group_count = Group.count
post :create, group: { path: 'subgroup' }
expect(Group.count).to eq(original_group_count + 1)
expect(response).to be_redirect
end
end
context 'and can_create_group is disabled' do
before do
developer.update_attribute(:can_create_group, false)
end
it 'does not create the Group' do
original_group_count = Group.count
post :create, group: { path: 'subgroup' }
expect(Group.count).to eq(original_group_count)
expect(response).to render_template(:new)
end
end
end
end
describe 'GET #index' do
context 'as a user' do

View file

@ -24,8 +24,8 @@ describe GroupPolicy do
:admin_namespace,
:admin_group_member,
:change_visibility_level,
:create_subgroup
]
(Gitlab::Database.postgresql? ? :create_subgroup : nil)
].compact
end
before do

View file

@ -431,6 +431,30 @@ describe API::Groups do
expect(response).to have_http_status(403)
end
context 'as owner', :nested_groups do
before do
group2.add_owner(user1)
end
it 'can create subgroups' do
post api("/groups", user1), parent_id: group2.id, name: 'foo', path: 'foo'
expect(response).to have_http_status(201)
end
end
context 'as master', :nested_groups do
before do
group2.add_master(user1)
end
it 'cannot create subgroups' do
post api("/groups", user1), parent_id: group2.id, name: 'foo', path: 'foo'
expect(response).to have_http_status(403)
end
end
end
context "when authenticated as user with group permissions" do

View file

@ -22,6 +22,26 @@ describe Groups::CreateService, '#execute' do
end
end
describe 'creating a top level group' do
let(:service) { described_class.new(user, group_params) }
context 'when user can create a group' do
before do
user.update_attribute(:can_create_group, true)
end
it { is_expected.to be_persisted }
end
context 'when user can not create a group' do
before do
user.update_attribute(:can_create_group, false)
end
it { is_expected.not_to be_persisted }
end
end
describe 'creating subgroup', :nested_groups do
let!(:group) { create(:group) }
let!(:service) { described_class.new(user, group_params.merge(parent_id: group.id)) }
@ -44,15 +64,28 @@ describe Groups::CreateService, '#execute' do
end
end
context 'when nested groups feature is enabled' do
before do
allow(Group).to receive(:supports_nested_groups?).and_return(true)
end
context 'as guest' do
it 'does not save group and returns an error' do
allow(Group).to receive(:supports_nested_groups?).and_return(true)
is_expected.not_to be_persisted
expect(subject.errors[:parent_id].first).to eq('You dont have permission to create a subgroup in this group.')
expect(subject.parent_id).to be_nil
end
end
context 'as owner' do
before do
group.add_owner(user)
end
it { is_expected.to be_persisted }
end
end
end
describe 'creating a mattermost team' do