Commit 086dc3e0 authored by Gosia Ksionek's avatar Gosia Ksionek Committed by Douglas Barbosa Alexandre
Browse files

Add part of needed code

Add columns to store project creation settings

Add project creation level column in groups
 and default project creation column in application settings

Remove obsolete line from schema

Update migration with project_creation_level column existence check

Rename migrations to avoid conflicts

Update migration methods

Update migration method
parent 2ede111b61a3
......@@ -89,7 +89,8 @@ def allowed_group_params
:request_access_enabled,
:visibility_level,
:require_two_factor_authentication,
:two_factor_grace_period
:two_factor_grace_period,
:project_creation_level
]
end
end
......@@ -187,7 +187,8 @@ def group_params_attributes
:create_chat_team,
:chat_team_name,
:require_two_factor_authentication,
:two_factor_grace_period
:two_factor_grace_period,
:project_creation_level
]
end
......
......@@ -137,6 +137,7 @@ def visible_attributes
:default_artifacts_expire_in,
:default_branch_protection,
:default_group_visibility,
:default_project_creation,
:default_project_visibility,
:default_projects_limit,
:default_snippet_visibility,
......
......@@ -49,6 +49,13 @@ def namespace_icon(namespace, size = 40)
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
......
......@@ -26,6 +26,7 @@ def defaults
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'],
......
......@@ -404,6 +404,10 @@ def group_clusters_enabled?
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
......
......@@ -105,6 +105,7 @@ def update_tracked_fields!(request)
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 @@ def recent_push(project = nil)
# 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 @@ def manageable_namespaces
@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 @@ def self.create_unique_internal(scope, username, email_pattern, &creation_block)
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
......@@ -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?
......
......@@ -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)
......
......@@ -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'
......
......@@ -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
......
.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'
......@@ -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: "" }})
......
---
title: Move allow developers to create projects in groups to Core
merge_request: 25975
author:
type: added
......@@ -126,6 +126,7 @@
# GitLab
#
Settings['gitlab'] ||= Settingslogic.new({})
Settings.gitlab['default_project_creation'] ||= ::Gitlab::Access::DEVELOPER_MAINTAINER_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?
......
# frozen_string_literal: true
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class AddDefaultProjectCreationApplicationSetting < ActiveRecord::Migration[5.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
def up
unless column_exists?(:application_settings, :default_project_creation)
add_column(:application_settings, :default_project_creation, :integer, default: 2, null: false)
end
end
def down
if column_exists?(:application_settings, :default_project_creation)
remove_column(:application_settings, :default_project_creation)
end
end
end
# frozen_string_literal: true
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class AddProjectCreationLevelToNamespaces < ActiveRecord::Migration[5.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
def up
unless column_exists?(:namespaces, :project_creation_level)
add_column :namespaces, :project_creation_level, :integer
end
end
def down
unless column_exists?(:namespaces, :project_creation_level)
remove_column :namespaces, :project_creation_level, :integer
end
end
end
......@@ -177,6 +177,7 @@
t.string "runners_registration_token_encrypted"
t.integer "local_markdown_version", default: 0, null: false
t.integer "first_day_of_week", default: 0, null: false
t.integer "default_project_creation", default: 2, null: false
t.index ["usage_stats_set_by_user_id"], name: "index_application_settings_on_usage_stats_set_by_user_id", using: :btree
end
......@@ -1391,6 +1392,7 @@
t.integer "cached_markdown_version"
t.string "runners_token"
t.string "runners_token_encrypted"
t.integer "project_creation_level"
t.boolean "auto_devops_enabled"
t.index ["created_at"], name: "index_namespaces_on_created_at", using: :btree
t.index ["name", "parent_id"], name: "index_namespaces_on_name_and_parent_id", unique: true, using: :btree
......
......@@ -151,6 +151,17 @@ There are two different ways to add a new project to a group:
![Select group](img/select_group_dropdown.png)
### Default project creation level
Group owners or administrators can allow users with the
Developer role to create projects under groups.
By default, [Developers and Maintainers](../permissions.md##group-members-permissions) can create projects under agroup, but this can be changed either within the group settings for a group, or
be set globally by a GitLab administrator in the Admin area
at **Settings > General > Visibility and access controls**.
Available settings are `No one`, `Maintainers`, or `Developers + Maintainers`.
## Transfer projects into groups
Learn how to [transfer a project into a group](../project/settings/index.md#transferring-an-existing-project-into-another-namespace).
......
......@@ -40,7 +40,8 @@ def filter_attributes_using_license(attrs)
end
optional :container_registry_token_expire_delay, type: Integer, desc: 'Authorization token duration (minutes)'
optional :default_artifacts_expire_in, type: String, desc: "Set the default expiration time for each job's artifacts"
optional :default_branch_protection, type: Integer, values: Gitlab::Access.protection_values, desc: 'Determine if developers can push to master'
optional :default_project_creation, type: Integer, values: ::Gitlab::Access.project_creation_values, desc: 'Determine if developers can create projects in the group'
optional :default_branch_protection, type: Integer, values: ::Gitlab::Access.protection_values, desc: 'Determine if developers can push to master'
optional :default_group_visibility, type: String, values: Gitlab::VisibilityLevel.string_values, desc: 'The default group visibility'
optional :default_project_visibility, type: String, values: Gitlab::VisibilityLevel.string_values, desc: 'The default project visibility'
optional :default_projects_limit, type: Integer, desc: 'The maximum number of personal projects'
......
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