diff options
Diffstat (limited to 'app')
-rw-r--r-- | app/controllers/admin/groups_controller.rb | 3 | ||||
-rw-r--r-- | app/controllers/groups_controller.rb | 3 | ||||
-rw-r--r-- | app/helpers/application_settings_helper.rb | 1 | ||||
-rw-r--r-- | app/helpers/namespaces_helper.rb | 7 | ||||
-rw-r--r-- | app/models/application_setting_implementation.rb | 1 | ||||
-rw-r--r-- | app/models/group.rb | 4 | ||||
-rw-r--r-- | app/models/user.rb | 40 | ||||
-rw-r--r-- | app/policies/group_policy.rb | 11 | ||||
-rw-r--r-- | app/views/admin/application_settings/_visibility_and_access.html.haml | 4 | ||||
-rw-r--r-- | app/views/groups/_group_admin_settings.html.haml | 4 | ||||
-rw-r--r-- | app/views/groups/settings/_permissions.html.haml | 1 | ||||
-rw-r--r-- | app/views/groups/settings/_project_creation_level.html.haml | 3 | ||||
-rw-r--r-- | app/views/projects/_new_project_fields.html.haml | 6 |
13 files changed, 77 insertions, 11 deletions
diff --git a/app/controllers/admin/groups_controller.rb b/app/controllers/admin/groups_controller.rb index e0ecdb0c0e9..15f7ef881c8 100644 --- a/app/controllers/admin/groups_controller.rb +++ b/app/controllers/admin/groups_controller.rb @@ -89,7 +89,8 @@ class Admin::GroupsController < Admin::ApplicationController :request_access_enabled, :visibility_level, :require_two_factor_authentication, - :two_factor_grace_period + :two_factor_grace_period, + :project_creation_level ] end end diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index 87b8ef03313..e936d771502 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -187,7 +187,8 @@ class GroupsController < Groups::ApplicationController :create_chat_team, :chat_team_name, :require_two_factor_authentication, - :two_factor_grace_period + :two_factor_grace_period, + :project_creation_level ] end diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb index e635f608237..e275e4278a4 100644 --- a/app/helpers/application_settings_helper.rb +++ b/app/helpers/application_settings_helper.rb @@ -137,6 +137,7 @@ module ApplicationSettingsHelper :default_artifacts_expire_in, :default_branch_protection, :default_group_visibility, + :default_project_creation, :default_project_visibility, :default_projects_limit, :default_snippet_visibility, diff --git a/app/helpers/namespaces_helper.rb b/app/helpers/namespaces_helper.rb index ea3bcfc791a..572d68cb4a3 100644 --- a/app/helpers/namespaces_helper.rb +++ b/app/helpers/namespaces_helper.rb @@ -49,6 +49,13 @@ module NamespacesHelper end end + def namespaces_options_with_developer_maintainer_access(options = {}) + selected = options.delete(:selected) || :current_user + options[:groups] = current_user.manageable_groups_with_routes(include_groups_with_developer_maintainer_access: true) + + namespaces_options(selected, options) + end + private # Many importers create a temporary Group, so use the real diff --git a/app/models/application_setting_implementation.rb b/app/models/application_setting_implementation.rb index 265aa1d4965..b413ffddb9d 100644 --- a/app/models/application_setting_implementation.rb +++ b/app/models/application_setting_implementation.rb @@ -26,6 +26,7 @@ module ApplicationSettingImplementation default_artifacts_expire_in: '30 days', default_branch_protection: Settings.gitlab['default_branch_protection'], default_group_visibility: Settings.gitlab.default_projects_features['visibility_level'], + default_project_creation: Settings.gitlab['default_project_creation'], default_project_visibility: Settings.gitlab.default_projects_features['visibility_level'], default_projects_limit: Settings.gitlab['default_projects_limit'], default_snippet_visibility: Settings.gitlab.default_projects_features['visibility_level'], diff --git a/app/models/group.rb b/app/models/group.rb index ac66815705c..8bc9b75f0a9 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -404,6 +404,10 @@ class Group < Namespace Feature.enabled?(:group_clusters, root_ancestor, default_enabled: true) end + def project_creation_level + super || ::Gitlab::CurrentSettings.default_project_creation + end + private def update_two_factor_requirement diff --git a/app/models/user.rb b/app/models/user.rb index 259889995d3..d3524bfd6ae 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -105,6 +105,7 @@ class User < ApplicationRecord has_many :groups, through: :group_members has_many :owned_groups, -> { where(members: { access_level: Gitlab::Access::OWNER }) }, through: :group_members, source: :group has_many :maintainers_groups, -> { where(members: { access_level: Gitlab::Access::MAINTAINER }) }, through: :group_members, source: :group + has_many :developer_groups, -> { where(members: { access_level: ::Gitlab::Access::DEVELOPER }) }, through: :group_members, source: :group has_many :owned_or_maintainers_groups, -> { where(members: { access_level: [Gitlab::Access::MAINTAINER, Gitlab::Access::OWNER] }) }, through: :group_members, @@ -883,7 +884,12 @@ class User < ApplicationRecord # rubocop: enable CodeReuse/ServiceClass def several_namespaces? - owned_groups.any? || maintainers_groups.any? + union_sql = ::Gitlab::SQL::Union.new( + [owned_groups, + maintainers_groups, + groups_with_developer_maintainer_project_access]).to_sql + + ::Group.from("(#{union_sql}) #{::Group.table_name}").any? end def namespace_id @@ -1169,12 +1175,24 @@ class User < ApplicationRecord @manageable_namespaces ||= [namespace] + manageable_groups end - def manageable_groups - Gitlab::ObjectHierarchy.new(owned_or_maintainers_groups).base_and_descendants + def manageable_groups(include_groups_with_developer_maintainer_access: false) + owned_and_maintainer_group_hierarchy = Gitlab::ObjectHierarchy.new(owned_or_maintainers_groups).base_and_descendants + + if include_groups_with_developer_maintainer_access + union_sql = ::Gitlab::SQL::Union.new( + [owned_and_maintainer_group_hierarchy, + groups_with_developer_maintainer_project_access]).to_sql + + ::Group.from("(#{union_sql}) #{::Group.table_name}") + else + owned_and_maintainer_group_hierarchy + end end - def manageable_groups_with_routes - manageable_groups.eager_load(:route).order('routes.path') + def manageable_groups_with_routes(include_groups_with_developer_maintainer_access: false) + manageable_groups(include_groups_with_developer_maintainer_access: include_groups_with_developer_maintainer_access) + .eager_load(:route) + .order('routes.path') end def namespaces @@ -1573,4 +1591,16 @@ class User < ApplicationRecord ensure Gitlab::ExclusiveLease.cancel(lease_key, uuid) end + + def groups_with_developer_maintainer_project_access + project_creation_levels = [::Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS] + + if ::Gitlab::CurrentSettings.default_project_creation == ::Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS + project_creation_levels << nil + end + + developer_groups_hierarchy = ::Gitlab::ObjectHierarchy.new(developer_groups).base_and_descendants + ::Group.where(id: developer_groups_hierarchy.select(:id), + project_creation_level: project_creation_levels) + end end diff --git a/app/policies/group_policy.rb b/app/policies/group_policy.rb index db49d3bed9c..eb2e536e8e9 100644 --- a/app/policies/group_policy.rb +++ b/app/policies/group_policy.rb @@ -35,6 +35,14 @@ class GroupPolicy < BasePolicy with_options scope: :subject, score: 0 condition(:request_access_enabled) { @subject.request_access_enabled } + condition(:create_projects_disabled) do + @subject.project_creation_level == ::Gitlab::Access::NO_ONE_PROJECT_ACCESS + end + + condition(:developer_maintainer_access) do + @subject.project_creation_level == ::Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS + end + rule { public_group }.policy do enable :read_group enable :read_list @@ -115,6 +123,9 @@ class GroupPolicy < BasePolicy rule { ~can_have_multiple_clusters & has_clusters }.prevent :add_cluster + rule { developer & developer_maintainer_access }.enable :create_projects + rule { create_projects_disabled }.prevent :create_projects + def access_level return GroupMember::NO_ACCESS if @user.nil? diff --git a/app/views/admin/application_settings/_visibility_and_access.html.haml b/app/views/admin/application_settings/_visibility_and_access.html.haml index 8122d81f578..03ef2924617 100644 --- a/app/views/admin/application_settings/_visibility_and_access.html.haml +++ b/app/views/admin/application_settings/_visibility_and_access.html.haml @@ -5,7 +5,9 @@ .form-group = f.label :default_branch_protection, class: 'label-bold' = f.select :default_branch_protection, options_for_select(Gitlab::Access.protection_options, @application_setting.default_branch_protection), {}, class: 'form-control' - = render_if_exists 'admin/application_settings/project_creation_level', form: f, application_setting: @application_setting + .form-group + = f.label s_('ProjectCreationLevel|Default project creation protection'), class: 'label-bold' + = f.select :default_project_creation, options_for_select(Gitlab::Access.project_creation_options, @application_setting.default_project_creation), {}, class: 'form-control' .form-group.visibility-level-setting = f.label :default_project_visibility, class: 'label-bold' = render('shared/visibility_radios', model_method: :default_project_visibility, form: f, selected_level: @application_setting.default_project_visibility, form_model: Project.new) diff --git a/app/views/groups/_group_admin_settings.html.haml b/app/views/groups/_group_admin_settings.html.haml index ff59013ed67..7390c42aba2 100644 --- a/app/views/groups/_group_admin_settings.html.haml +++ b/app/views/groups/_group_admin_settings.html.haml @@ -9,6 +9,10 @@ = link_to icon('question-circle'), help_page_path('workflow/lfs/manage_large_binaries_with_git_lfs') %br/ %span.descr This setting can be overridden in each project. +.form-group.row + = f.label s_('ProjectCreationLevel|Allowed to create projects'), class: 'col-form-label col-sm-2' + .col-sm-10 + = f.select :project_creation_level, options_for_select(::Gitlab::Access.project_creation_options, @group.project_creation_level), {}, class: 'form-control' .form-group.row = f.label :require_two_factor_authentication, 'Two-factor authentication', class: 'col-form-label col-sm-2 pt-0' diff --git a/app/views/groups/settings/_permissions.html.haml b/app/views/groups/settings/_permissions.html.haml index 6b0a6e7ed99..0a14830c666 100644 --- a/app/views/groups/settings/_permissions.html.haml +++ b/app/views/groups/settings/_permissions.html.haml @@ -18,6 +18,7 @@ %span.descr.text-muted= share_with_group_lock_help_text(@group) = render 'groups/settings/lfs', f: f + = render 'groups/settings/project_creation_level', f: f, group: @group = render 'groups/settings/two_factor_auth', f: f = render_if_exists 'groups/member_lock_setting', f: f, group: @group diff --git a/app/views/groups/settings/_project_creation_level.html.haml b/app/views/groups/settings/_project_creation_level.html.haml new file mode 100644 index 00000000000..9f711e6aade --- /dev/null +++ b/app/views/groups/settings/_project_creation_level.html.haml @@ -0,0 +1,3 @@ +.form-group + = f.label s_('ProjectCreationLevel|Allowed to create projects'), class: 'label-bold' + = f.select :project_creation_level, options_for_select(::Gitlab::Access.project_creation_options, group.project_creation_level), {}, class: 'form-control' diff --git a/app/views/projects/_new_project_fields.html.haml b/app/views/projects/_new_project_fields.html.haml index 5129f11875c..1c1c7d832bd 100644 --- a/app/views/projects/_new_project_fields.html.haml +++ b/app/views/projects/_new_project_fields.html.haml @@ -19,9 +19,9 @@ = root_url - namespace_id = namespace_id_from(params) = f.select(:namespace_id, - namespaces_options(namespace_id || :current_user, - display_path: true, - extra_group: namespace_id), + namespaces_options_with_developer_maintainer_access(selected: namespace_id, + display_path: true, + extra_group: namespace_id), {}, { class: 'select2 js-select-namespace qa-project-namespace-select block-truncated', tabindex: 1, data: { track_label: "#{track_label}", track_event: "activate_form_input", track_property: "project_path", track_value: "" }}) |