Commit be7b5bdc authored by Rémy Coutable's avatar Rémy Coutable

Merge branch '2534-developers-should-be-able-to-create-new-projects-in-group' into 'master'

Resolve "Developers should be able to create new projects in group"

Closes #2534

See merge request gitlab-org/gitlab-ee!4046
parents 8100e98b ef6019e3
......@@ -3,6 +3,7 @@ class GroupsController < Groups::ApplicationController
include MergeRequestsAction
include ParamsBackwardCompatibility
include PreviewMarkdown
prepend EE::GroupsController
respond_to :html
......@@ -118,10 +119,10 @@ class GroupsController < Groups::ApplicationController
end
def group_params
params.require(:group).permit(group_params_ce << group_params_ee)
params.require(:group).permit(group_params_attributes)
end
def group_params_ce
def group_params_attributes
[
:avatar,
:description,
......@@ -140,13 +141,6 @@ class GroupsController < Groups::ApplicationController
]
end
def group_params_ee
[
:membership_lock,
:repository_size_limit
]
end
def load_events
params[:sort] ||= 'latest_activity_desc'
......
......@@ -7,6 +7,7 @@
= f.label :default_branch_protection, class: 'control-label col-sm-2'
.col-sm-10
= f.select :default_branch_protection, options_for_select(Gitlab::Access.protection_options, @application_setting.default_branch_protection), {}, class: 'form-control'
= render partial: 'admin/application_settings/ee/project_creation_level', locals: { form: f, application_setting: @application_setting }
.form-group.visibility-level-setting
= f.label :default_project_visibility, class: 'control-label col-sm-2'
.col-sm-10
......
- return unless License.feature_available?(:project_creation_level)
- form = local_assigns.fetch(:form)
- application_setting = local_assigns.fetch(:application_setting)
.form-group
= form.label s_('ProjectCreationLevel|Default project creation protection'), class: 'control-label col-sm-2'
.col-sm-10
= form.select :default_project_creation, options_for_select(Gitlab::Access.project_creation_options, application_setting.default_project_creation), {}, class: 'form-control'
......@@ -12,6 +12,7 @@
%span.descr This setting can be overridden in each project.
- if can? current_user, :admin_group, @group
= render partial: 'groups/ee/project_creation_level', locals: { form: f, group: @group }
.form-group
= f.label :require_two_factor_authentication, 'Two-factor authentication', class: 'control-label col-sm-2'
.col-sm-10
......
- return unless group.feature_available?(:project_creation_level)
- form = local_assigns.fetch(:form)
- group = local_assigns.fetch(:group)
.form-group
= form.label s_('ProjectCreationLevel|Allowed to create projects'), class: 'control-label col-sm-2'
.col-sm-10
= form.select :project_creation_level, options_for_select(::Gitlab::Access.project_creation_options, group.project_creation_level), {}, class: 'form-control'
---
title: "(EEP) Allow developers to create projects in group"
merge_request: 4046
author:
type: added
......@@ -264,6 +264,7 @@ Settings['issues_tracker'] ||= {}
# GitLab
#
Settings['gitlab'] ||= Settingslogic.new({})
Settings.gitlab['default_project_creation'] ||= ::EE::Gitlab::Access::DEVELOPER_MASTER_PROJECT_ACCESS
Settings.gitlab['default_projects_limit'] ||= 100000
Settings.gitlab['default_branch_protection'] ||= 2
Settings.gitlab['default_can_create_group'] = true if Settings.gitlab['default_can_create_group'].nil?
......
class AddDefaultProjectCreationSetting < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
add_column_with_default(:application_settings, :default_project_creation, :integer, default: 2)
end
def down
remove_column(:application_settings, :default_project_creation)
end
end
class AddProjectCreationLevelToGroups < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
def change
add_column :namespaces, :project_creation_level, :integer
end
end
......@@ -178,6 +178,7 @@ ActiveRecord::Schema.define(version: 20180115201419) do
t.integer "gitaly_timeout_medium", default: 30, null: false
t.integer "gitaly_timeout_fast", default: 10, null: false
t.boolean "mirror_available", default: true, null: false
t.integer "default_project_creation", default: 2, null: false
end
create_table "approvals", force: :cascade do |t|
......@@ -1546,6 +1547,7 @@ ActiveRecord::Schema.define(version: 20180115201419) do
t.integer "two_factor_grace_period", default: 48, null: false
t.integer "cached_markdown_version"
t.integer "plan_id"
t.integer "project_creation_level"
end
add_index "namespaces", ["created_at"], name: "index_namespaces_on_created_at", using: :btree
......
......@@ -152,6 +152,17 @@ There are two different ways to add a new project to a group:
![Select group](img/select_group_dropdown.png)
### (EEP) Default project creation level
This feature allows groups to define a default project creation level.
By default, `Developers` and `Masters` are allowed to create projects, but
this can be changed within the group settings for a group, or the default setting
changed within the Admin area (`Settings`, `Visibility and Access Controls`). This
can be `None`, `Masters`, or `Developers + Masters`.
It is available only in [GitLab Enterprise Edition Premium][eep].
## Transfer projects into groups
Learn how to [transfer a project into a group](../project/index.md#transfer-an-existing-project-into-a-group).
......@@ -282,4 +293,4 @@ you have an overview of the contributions (pushes, merge requests,
and issues) performed my your group members.
[ee]: https://about.gitlab.com/products/
[eep]: https://about.gitlab.com/gitlab-ee/ "GitLab Enterprise Edition Premium"
......@@ -8,6 +8,10 @@ module EE
attrs += EE::ApplicationSettingsHelper.repository_mirror_attributes
end
if License.feature_available?(:project_creation_level)
attrs << :default_project_creation
end
attrs
end
end
......
......@@ -20,7 +20,9 @@ module EE
:repository_size_limit,
:shared_runners_minutes_limit,
:plan_id
]
].tap do |params_ee|
params_ee << :project_creation_level if @group&.feature_available?(:project_creation_level)
end
end
end
end
......
module EE
module GroupsController
def group_params_attributes
super + group_params_ee
end
private
def group_params_ee
[
:membership_lock,
:repository_size_limit
].tap do |params_ee|
params_ee << :project_creation_level if current_group&.feature_available?(:project_creation_level)
end
end
def current_group
@group
end
end
end
......@@ -32,6 +32,7 @@ module EE
module ClassMethods
def defaults
super.merge(
default_project_creation: ::EE::Gitlab::Access::DEVELOPER_MASTER_PROJECT_ACCESS,
elasticsearch_url: ENV['ELASTIC_URL'] || 'http://localhost:9200',
elasticsearch_aws: false,
elasticsearch_aws_region: ENV['ELASTIC_REGION'] || 'us-east-1',
......
......@@ -58,5 +58,9 @@ module EE
fail_ldap_sync
update_column(:ldap_sync_error, ::Gitlab::UrlSanitizer.sanitize(error_message))
end
def project_creation_level
super || current_application_settings.default_project_creation
end
end
end
......@@ -50,6 +50,7 @@ class License < ActiveRecord::Base
variable_environment_scope
reject_unsigned_commits
commit_committer_check
project_creation_level
].freeze
EEU_FEATURES = EEP_FEATURES + %i[
......
......@@ -7,6 +7,16 @@ module EE
condition(:ldap_synced) { @subject.ldap_synced? }
condition(:epics_disabled) { !@subject.feature_available?(:epics) }
condition(:project_creation_level_enabled) { @subject.feature_available?(:project_creation_level) }
condition(:create_projects_disabled) do
@subject.project_creation_level == ::EE::Gitlab::Access::NO_ONE_PROJECT_ACCESS
end
condition(:developer_master_access) do
@subject.project_creation_level == ::EE::Gitlab::Access::DEVELOPER_MASTER_PROJECT_ACCESS
end
rule { reporter }.policy do
enable :admin_list
enable :admin_board
......@@ -55,6 +65,9 @@ module EE
prevent :update_epic
prevent :destroy_epic
end
rule { project_creation_level_enabled & developer & developer_master_access }.enable :create_projects
rule { project_creation_level_enabled & create_projects_disabled }.prevent :create_projects
end
end
end
# Gitlab::Access module
#
# Define allowed roles that can be used
# in GitLab code to determine authorization level
#
module EE
module Gitlab
module Access
extend self
# Default project creation level
NO_ONE_PROJECT_ACCESS = 0
MASTER_PROJECT_ACCESS = 1
DEVELOPER_MASTER_PROJECT_ACCESS = 2
def project_creation_options
{
s_('ProjectCreationLevel|No one') => NO_ONE_PROJECT_ACCESS,
s_('ProjectCreationLevel|Masters') => MASTER_PROJECT_ACCESS,
s_('ProjectCreationLevel|Developers + Masters') => DEVELOPER_MASTER_PROJECT_ACCESS
}
end
end
end
end
......@@ -5,6 +5,8 @@
#
module Gitlab
module Access
extend ::EE::Gitlab::Access
AccessDeniedError = Class.new(StandardError)
NO_ACCESS = 0
......
......@@ -157,6 +157,9 @@ msgstr ""
msgid "All"
msgstr ""
msgid "Allowed to create projects"
msgstr ""
msgid "All changes are committed"
msgstr ""
......@@ -259,6 +262,9 @@ msgstr ""
msgid "Avatar will be removed. Are you sure?"
msgstr ""
msgid "Avatar will be removed. Are you sure?"
msgstr ""
msgid "Billing"
msgstr ""
......@@ -486,6 +492,9 @@ msgstr ""
msgid "Check interval"
msgstr ""
msgid "Check interval"
msgstr ""
msgid "Checking %{text} availability…"
msgstr ""
......@@ -507,6 +516,15 @@ msgstr ""
msgid "Choose file..."
msgstr ""
msgid "Choose File ..."
msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
msgid "Choose file..."
msgstr ""
msgid "Choose which groups you wish to replicate to this secondary node. Leave blank to replicate all."
msgstr ""
......@@ -570,6 +588,9 @@ msgstr ""
msgid "Click to expand text"
msgstr ""
msgid "Click to expand text"
msgstr ""
msgid "Clone repository"
msgstr ""
......@@ -603,6 +624,9 @@ msgstr ""
msgid "ClusterIntegration|Are you sure you want to remove this cluster's integration? This will not delete your actual cluster."
msgstr ""
msgid "ClusterIntegration|Are you sure you want to remove this cluster's integration? This will not delete your actual cluster."
msgstr ""
msgid "ClusterIntegration|CA Certificate"
msgstr ""
......@@ -720,6 +744,9 @@ msgstr ""
msgid "ClusterIntegration|Integration status"
msgstr ""
msgid "ClusterIntegration|Integration status"
msgstr ""
msgid "ClusterIntegration|Learn more about %{link_to_documentation}"
msgstr ""
......@@ -834,6 +861,9 @@ msgstr ""
msgid "ClusterIntegration|check the pricing here"
msgstr ""
msgid "ClusterIntegration|check the pricing here"
msgstr ""
msgid "ClusterIntegration|cluster"
msgstr ""
......@@ -920,6 +950,27 @@ msgstr ""
msgid "CompareBranches|There isn't anything to compare."
msgstr ""
msgid "Compare Git revisions"
msgstr ""
msgid "Compare Revisions"
msgstr ""
msgid "CompareBranches|%{source_branch} and %{target_branch} are the same."
msgstr ""
msgid "CompareBranches|Compare"
msgstr ""
msgid "CompareBranches|Source"
msgstr ""
msgid "CompareBranches|Target"
msgstr ""
msgid "CompareBranches|There isn't anything to compare."
msgstr ""
msgid "Container Registry"
msgstr ""
......@@ -1126,12 +1177,18 @@ msgstr ""
msgid "Disable"
msgstr ""
msgid "Disable"
msgstr ""
msgid "Discard changes"
msgstr ""
msgid "Discover GitLab Geo."
msgstr ""
msgid "Discover GitLab Geo."
msgstr ""
msgid "Dismiss Cycle Analytics introduction box"
msgstr ""
......@@ -1183,6 +1240,9 @@ msgstr ""
msgid "Enable"
msgstr ""
msgid "Enable"
msgstr ""
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
......@@ -1651,6 +1711,9 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests to categorize them."
msgstr ""
msgid "Labels can be applied to issues and merge requests to categorize them."
msgstr ""
msgid "Last %d day"
msgid_plural "Last %d days"
msgstr[0] ""
......@@ -1719,6 +1782,9 @@ msgstr ""
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr ""
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr ""
msgid "Mar"
msgstr ""
......@@ -1952,6 +2018,9 @@ msgstr ""
msgid "Open"
msgstr ""
msgid "Open"
msgstr ""
msgid "Opened"
msgstr ""
......@@ -2096,6 +2165,12 @@ msgstr ""
msgid "Please <a href=%{link_to_billing} target=\"_blank\" rel=\"noopener noreferrer\">enable billing for one of your projects to be able to create a cluster</a>, then try again."
msgstr ""
msgid "Play"
msgstr ""
msgid "Please <a href=%{link_to_billing} target=\"_blank\" rel=\"noopener noreferrer\">enable billing for one of your projects to be able to create a cluster</a>, then try again."
msgstr ""
msgid "Please solve the reCAPTCHA"
msgstr ""
......@@ -2105,6 +2180,9 @@ msgstr ""
msgid "Primary"
msgstr ""
msgid "Primary"
msgstr ""
msgid "Private - Project access must be granted explicitly to each user."
msgstr ""
......@@ -2174,6 +2252,15 @@ msgstr ""
msgid "Project cache successfully reset."
msgstr ""
msgid "Project avatar"
msgstr ""
msgid "Project avatar in repository: %{link}"
msgstr ""
msgid "Project cache successfully reset."
msgstr ""
msgid "Project details"
msgstr ""
......@@ -2192,6 +2279,21 @@ msgstr ""
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
msgid "ProjectCreationLevel|Allowed to create projects"
msgstr ""
msgid "ProjectCreationLevel|Default project creation protection"
msgstr ""
msgid "ProjectCreationLevel|Developers + Masters"
msgstr ""
msgid "ProjectCreationLevel|Masters"
msgstr ""
msgid "ProjectCreationLevel|No one"
msgstr ""
msgid "ProjectFeature|Disabled"
msgstr ""
......@@ -2318,6 +2420,9 @@ msgstr ""
msgid "Register / Sign In"
msgstr ""
msgid "Register / Sign In"
msgstr ""
msgid "Registry"
msgstr ""
......@@ -2348,12 +2453,21 @@ msgstr ""
msgid "Remove avatar"
msgstr ""
msgid "Remove"
msgstr ""
msgid "Remove avatar"
msgstr ""
msgid "Remove project"
msgstr ""
msgid "Repair authentication"
msgstr ""
msgid "Repair authentication"
msgstr ""
msgid "Repository"
msgstr ""
......@@ -2419,6 +2533,9 @@ msgstr ""
msgid "Select branch/tag"
msgstr ""
msgid "Select branch/tag"
msgstr ""
msgid "Select target branch"
msgstr ""
......@@ -2810,6 +2927,12 @@ msgstr ""
msgid "There are no merge requests to show"
msgstr ""
msgid "There are no issues to show"
msgstr ""
msgid "There are no merge requests to show"
msgstr ""
msgid "There are problems accessing Git storage: "
msgstr ""
......@@ -3030,6 +3153,12 @@ msgstr ""
msgid "ToggleButton|Toggle Status: ON"
msgstr ""
msgid "ToggleButton|Toggle Status: OFF"
msgstr ""
msgid "ToggleButton|Toggle Status: ON"
msgstr ""
msgid "Total Time"
msgstr ""
......@@ -3048,6 +3177,9 @@ msgstr ""
msgid "Trigger this manual action"
msgstr ""
msgid "Trigger this manual action"
msgstr ""
msgid "Turn on Service Desk"
msgstr ""
......@@ -3057,6 +3189,12 @@ msgstr ""
msgid "Unknown"
msgstr ""
msgid "Unable to reset project cache."
msgstr ""
msgid "Unknown"
msgstr ""
msgid "Unlock"
msgstr ""
......@@ -3093,6 +3231,9 @@ msgstr ""
msgid "Upload new avatar"
msgstr ""
msgid "Upload new avatar"
msgstr ""
msgid "UploadLink|click to upload"
msgstr ""
......@@ -3132,6 +3273,9 @@ msgstr ""
msgid "We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
msgid "We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
......@@ -3370,6 +3514,11 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
msgid "merge request"
msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
msgid "mrWidget|Cancel automatic merge"
msgstr ""
......
......@@ -323,6 +323,13 @@ describe GroupsController do
expect(controller).to set_flash[:notice]
end
it 'updates the project_creation_level successfully' do
post :update, id: group.to_param, group: { project_creation_level: ::EE::Gitlab::Access::MASTER_PROJECT_ACCESS }
expect(response).to have_gitlab_http_status(302)
expect(group.reload.project_creation_level).to eq(::EE::Gitlab::Access::MASTER_PROJECT_ACCESS)
end
it 'does not update the path on error' do
allow_any_instance_of(Group).to receive(:move_dir).and_raise(Gitlab::UpdatePathError)
post :update, id: group.to_param, group: { path: 'new_path' }
......
......@@ -80,5 +80,13 @@ describe Admin::ApplicationSettingsController do
expect(ApplicationSetting.current.public_send(setting)).to eq(value)
end
end
it 'updates the default_project_creation for string value' do
stub_licensed_features(project_creation_level: true)
put :update, application_setting: { default_project_creation: ::EE::Gitlab::Access::MASTER_PROJECT_ACCESS }
expect(response).to redirect_to(admin_application_settings_path)
expect(ApplicationSetting.current.default_project_creation).to eq(::EE::Gitlab::Access::MASTER_PROJECT_ACCESS)
end
end
end
......@@ -13,7 +13,7 @@ describe Admin::GroupsController do
before do
allow_any_instance_of(ClearNamespaceSharedRunnersMinutesService)
.to receive(:execute).and_return(clear_runners_minutes_service_result)
.to receive(:execute).and_return(clear_runners_minutes_service_result)
end
context 'when the reset is successful' do
......@@ -38,4 +38,24 @@ describe Admin::GroupsController do
end
end
end
context 'PUT update' do
context 'no license' do
it 'does not update the project_creation_level successfully' do
expect do
post :update, id: group.to_param, group: { project_creation_level: ::EE::Gitlab::Access::NO_ONE_PROJECT_ACCESS }
end.not_to change { group.reload.project_creation_level }
end
end
context 'licensed' do
it 'updates the project_creation_level successfully' do
stub_licensed_features(project_creation_level: true)
expect do
post :update, id: group.to_param, group: { project_creation_level: ::EE::Gitlab::Access::NO_ONE_PROJECT_ACCESS }
end.to change { group.reload.project_creation_level }.to(::EE::Gitlab::Access::NO_ONE_PROJECT_ACCESS)
end
end
end
end
......@@ -32,4 +32,24 @@ feature 'Edit group settings' do
end
end
end
context 'with project_creation_level feature enabled' do
it 'shows the selection menu' do
stub_licensed_features(project_creation_level: true)
visit edit_group_path(group)
expect(page).to have_content('Allowed to create projects')
end
end
context 'with project_creation_level feature disabled' do
it 'shows the selection menu' do
stub_licensed_features(project_creation_level: false)
visit edit_group_path(group)
expect(page).not_to have_content('Allowed to create projects')
end
end
end
......@@ -114,4 +114,14 @@ describe Group do
expect(group.repository_size_limit).to eql(8.exabytes - 1)
end
end
describe 'project_creation_level' do
it 'outputs the default one if it is nil' do
stub_application_setting(default_project_creation: ::EE::Gitlab::Access::MASTER_PROJECT_ACCESS)
group = create(:group, project_creation_level: nil)
expect(group.project_creation_level).to eq(current_application_settings.default_project_creation)
end
end
end
......@@ -124,4 +124,238 @@ describe GroupPolicy do
it { is_expected.to be_allowed(:admin_ldap_group_links) }
end
end
context "create_projects" do
context 'project_creation_level enabled' do
before do
stub_licensed_features(project_creation_level: true)
end
context 'when group has no project creation level set' do
let(:group) { create(:group, project_creation_level: nil) }
context 'reporter' do
let(:current_user) { reporter }
it { is_expected.to be_disallowed(:create_projects) }
end
context 'developer' do
let(:current_user) { developer }
it { is_expected.to be_allowed(:create_projects) }
end
context 'master' do
let(:current_user) { master }
it { is_expected.to be_allowed(:create_projects) }
end
context 'owner' do
let(:current_user) { owner }
it { is_expected.to be_allowed(:create_projects) }
end
end
context 'when group has project creation level set to no one' do
let(:group) { create(:group, project_creation_level: ::EE::Gitlab::Access::NO_ONE_PROJECT_ACCESS) }
context 'reporter' do
let(:current_user) { reporter }
it { is_expected.to be_disallowed(:create_projects) }
end
context 'developer' do
let(:current_user) { developer }
it { is_expected.to be_disallowed(:create_projects) }
end
context 'master' do
let(:current_user) { master }
it { is_expected.to be_disallowed(:create_projects) }
end
context 'owner' do
let(:current_user) { owner }
it { is_expected.to be_disallowed(:create_projects) }
end
end
context 'when group has project creation level set to master only' do
let(:group) { create(:group, project_creation_level: ::EE::Gitlab::Access::MASTER_PROJECT_ACCESS) }
context 'reporter' do
let(:current_user) { reporter }
it { is_expected.to be_disallowed(:create_projects) }
end
context 'developer' do
let(:current_user) { developer }
it { is_expected.to be_disallowed(:create_projects) }
end
context 'master' do
let(:current_user) { master }
it { is_expected.to be_allowed(:create_projects) }
end
context 'owner' do
let(:current_user) { owner }
it { is_expected.to be_allowed(:create_projects) }
end
end
context 'when group has project creation level set to developers + master' do
let(:group) { create(:group, project_creation_level: ::EE::Gitlab::Access::DEVELOPER_MASTER_PROJECT_ACCESS) }
context 'reporter' do
let(:current_user) { reporter }
it { is_expected.to be_disallowed(:create_projects) }
end
context 'developer' do
let(:current_user) { developer }
it { is_expected.to be_allowed(:create_projects) }
end
context 'master' do
let(:current_user) { master }
it { is_expected.to be_allowed(:create_projects) }
end
context 'owner' do
let(:current_user) { owner }
it { is_expected.to be_allowed(:create_projects) }
end
end
end
context 'project_creation_level disabled' do
context 'when group has no project creation level set' do
let(:group) { create(:group, project_creation_level: nil) }
context 'reporter' do
let(:current_user) { reporter }
it { is_expected.to be_disallowed(:create_projects) }
end
context 'developer' do
let(:current_user) { developer }
it { is_expected.to be_disallowed(:create_projects) }
end
context 'master' do
let(:current_user) { master }
it { is_expected.to be_allowed(:create_projects) }
end
context 'owner' do
let(:current_user) { owner }
it { is_expected.to be_allowed(:create_projects) }
end
end
context 'when group has project creation level set to no one' do
let(:group) { create(:group, project_creation_level: ::EE::Gitlab::Access::NO_ONE_PROJECT_ACCESS) }
context 'reporter' do
let(:current_user) { reporter }
it { is_expected.to be_disallowed(:create_projects) }
end
context 'developer' do
let(:current_user) { developer }
it { is_expected.to be_disallowed(:create_projects) }
end
context 'master' do
let(:current_user) { master }
it { is_expected.to be_allowed(:create_projects) }
end
context 'owner' do
let(:current_user) { owner }
it { is_expected.to be_allowed(:create_projects) }
end
end
context 'when group has project creation level set to master only' do
let(:group) { create(:group, project_creation_level: ::EE::Gitlab::Access::MASTER_PROJECT_ACCESS) }
context 'reporter' do
let(:current_user) { reporter }
it { is_expected.to be_disallowed(:create_projects) }
end
context 'developer' do
let(:current_user) { developer }
it { is_expected.to be_disallowed(:create_projects) }
end
context 'master' do
let(:current_user) { master }
it { is_expected.to be_allowed(:create_projects) }
end
context 'owner' do
let(:current_user) { owner }
it { is_expected.to be_allowed(:create_projects) }
end
end
context 'when group has project creation level set to developers + master' do
let(:group) { create(:group, project_creation_level: ::EE::Gitlab::Access::DEVELOPER_MASTER_PROJECT_ACCESS) }
context 'reporter' do
let(:current_user) { reporter }
it { is_expected.to be_disallowed(:create_projects) }
end
context 'developer' do
let(:current_user) { developer }
it { is_expected.to be_disallowed(:create_projects) }
end
context 'master' do
let(:current_user) { master }
it { is_expected.to be_allowed(:create_projects) }
end
context 'owner' do
let(:current_user) { owner }
it { is_expected.to be_allowed(:create_projects) }
end
end
end
end
end
......@@ -4,6 +4,7 @@ FactoryBot.define do
path { name.downcase.gsub(/\s/, '_') }
type 'Group'
owner nil
project_creation_level ::EE::Gitlab::Access::MASTER_PROJECT_ACCESS
trait :public do
visibility_level Gitlab::VisibilityLevel::PUBLIC
......
......@@ -3,6 +3,18 @@ require Rails.root.join('db', 'post_migrate', '20171207150343_remove_soft_remove
describe RemoveSoftRemovedObjects, :migration do
describe '#up' do
let!(:groups) do
table(:namespaces).tap do |t|
t.inheritance_column = nil
end
end
let!(:routes) do
table(:routes).tap do |t|
t.inheritance_column = nil
end
end
it 'removes various soft removed objects' do
5.times do
create_with_deleted_at(:issue)
......@@ -28,19 +40,21 @@ describe RemoveSoftRemovedObjects, :migration do
it 'removes routes of soft removed personal namespaces' do
namespace = create_with_deleted_at(:namespace)
group = create(:group)
group = groups.create!(name: 'group', path: 'group_path', type: 'Group')
routes.create!(source_id: group.id, source_type: 'Group', name: 'group', path: 'group_path')
expect(Route.where(source: namespace).exists?).to eq(true)
expect(Route.where(source: group).exists?).to eq(true)
expect(routes.where(source_id: namespace.id).exists?).to eq(true)
expect(routes.where(source_id: group.id).exists?).to eq(true)
run_migration
expect(Route.where(source: namespace).exists?).to eq(false)
expect(Route.where(source: group).exists?).to eq(true)
expect(routes.where(source_id: namespace.id).exists?).to eq(false)
expect(routes.where(source_id: group.id).exists?).to eq(true)
end
it 'schedules the removal of soft removed groups' do
group = create_with_deleted_at(:group)
group = create_deleted_group
admin = create(:user, admin: true)
expect_any_instance_of(GroupDestroyWorker)
......@@ -51,7 +65,7 @@ describe RemoveSoftRemovedObjects, :migration do
end
it 'does not remove soft removed groups when no admin user could be found' do
create_with_deleted_at(:group)
create_deleted_group
expect_any_instance_of(GroupDestroyWorker)
.not_to receive(:perform)
......@@ -74,4 +88,13 @@ describe RemoveSoftRemovedObjects, :migration do
row
end
def create_deleted_group
group = groups.create!(name: 'group', path: 'group_path', type: 'Group')
routes.create!(source_id: group.id, source_type: 'Group', name: 'group', path: 'group_path')
groups.where(id: group.id).update_all(deleted_at: 1.year.ago)
group
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment