Commit ec4c5d6d authored by Jason Goodman's avatar Jason Goodman Committed by Nikola Milojevic

Add prevent_sharing_groups_outside_hierarchy to GET and PUT API

parent 9df0d972
...@@ -41,6 +41,11 @@ module NamespaceSettings ...@@ -41,6 +41,11 @@ module NamespaceSettings
settings_params.delete(:prevent_sharing_groups_outside_hierarchy) settings_params.delete(:prevent_sharing_groups_outside_hierarchy)
group.namespace_settings.errors.add(:prevent_sharing_groups_outside_hierarchy, _('can only be changed by a group admin.')) group.namespace_settings.errors.add(:prevent_sharing_groups_outside_hierarchy, _('can only be changed by a group admin.'))
end end
unless group.root?
settings_params.delete(:prevent_sharing_groups_outside_hierarchy)
group.namespace_settings.errors.add(:prevent_sharing_groups_outside_hierarchy, _('only available on top-level groups.'))
end
end end
end end
end end
......
...@@ -535,6 +535,7 @@ Example response: ...@@ -535,6 +535,7 @@ Example response:
"expires_at": null "expires_at": null
} }
], ],
"prevent_sharing_groups_outside_hierarchy": false,
"projects": [ // Deprecated and will be removed in API v5 "projects": [ // Deprecated and will be removed in API v5
{ {
"id": 7, "id": 7,
...@@ -673,6 +674,8 @@ Example response: ...@@ -673,6 +674,8 @@ Example response:
} }
``` ```
The `prevent_sharing_groups_outside_hierarchy` attribute is present only on top-level groups.
Users of [GitLab Premium or higher](https://about.gitlab.com/pricing/) also see Users of [GitLab Premium or higher](https://about.gitlab.com/pricing/) also see
the `shared_runners_minutes_limit` and `extra_shared_runners_minutes_limit` parameters: the `shared_runners_minutes_limit` and `extra_shared_runners_minutes_limit` parameters:
...@@ -851,31 +854,32 @@ Updates the project group. Only available to group owners and administrators. ...@@ -851,31 +854,32 @@ Updates the project group. Only available to group owners and administrators.
PUT /groups/:id PUT /groups/:id
``` ```
| Attribute | Type | Required | Description | | Attribute | Type | Required | Description |
| ------------------------------------ | ------- | -------- | ----------- | | ------------------------------------------ | ------- | -------- | ----------- |
| `id` | integer | yes | The ID of the group. | | `id` | integer | yes | The ID of the group. |
| `name` | string | no | The name of the group. | | `name` | string | no | The name of the group. |
| `path` | string | no | The path of the group. | | `path` | string | no | The path of the group. |
| `description` | string | no | The description of the group. | | `description` | string | no | The description of the group. |
| `membership_lock` | boolean | no | **(PREMIUM)** Prevent adding new members to project membership within this group. | | `membership_lock` | boolean | no | **(PREMIUM)** Prevent adding new members to project membership within this group. |
| `share_with_group_lock` | boolean | no | Prevent sharing a project with another group within this group. | | `share_with_group_lock` | boolean | no | Prevent sharing a project with another group within this group. |
| `visibility` | string | no | The visibility level of the group. Can be `private`, `internal`, or `public`. | | `visibility` | string | no | The visibility level of the group. Can be `private`, `internal`, or `public`. |
| `require_two_factor_authentication` | boolean | no | Require all users in this group to setup Two-factor authentication. | | `require_two_factor_authentication` | boolean | no | Require all users in this group to setup Two-factor authentication. |
| `two_factor_grace_period` | integer | no | Time before Two-factor authentication is enforced (in hours). | | `two_factor_grace_period` | integer | no | Time before Two-factor authentication is enforced (in hours). |
| `project_creation_level` | string | no | Determine if developers can create projects in the group. Can be `noone` (No one), `maintainer` (Maintainers), or `developer` (Developers + Maintainers). | | `project_creation_level` | string | no | Determine if developers can create projects in the group. Can be `noone` (No one), `maintainer` (Maintainers), or `developer` (Developers + Maintainers). |
| `auto_devops_enabled` | boolean | no | Default to Auto DevOps pipeline for all projects within this group. | | `auto_devops_enabled` | boolean | no | Default to Auto DevOps pipeline for all projects within this group. |
| `subgroup_creation_level` | string | no | Allowed to [create subgroups](../user/group/subgroups/index.md#creating-a-subgroup). Can be `owner` (Owners), or `maintainer` (Maintainers). | | `subgroup_creation_level` | string | no | Allowed to [create subgroups](../user/group/subgroups/index.md#creating-a-subgroup). Can be `owner` (Owners), or `maintainer` (Maintainers). |
| `emails_disabled` | boolean | no | Disable email notifications | | `emails_disabled` | boolean | no | Disable email notifications |
| `avatar` | mixed | no | Image file for avatar of the group. [Introduced in GitLab 12.9](https://gitlab.com/gitlab-org/gitlab/-/issues/36681) | | `avatar` | mixed | no | Image file for avatar of the group. [Introduced in GitLab 12.9](https://gitlab.com/gitlab-org/gitlab/-/issues/36681) |
| `mentions_disabled` | boolean | no | Disable the capability of a group from getting mentioned | | `mentions_disabled` | boolean | no | Disable the capability of a group from getting mentioned |
| `lfs_enabled` (optional) | boolean | no | Enable/disable Large File Storage (LFS) for the projects in this group. | | `lfs_enabled` (optional) | boolean | no | Enable/disable Large File Storage (LFS) for the projects in this group. |
| `request_access_enabled` | boolean | no | Allow users to request member access. | | `request_access_enabled` | boolean | no | Allow users to request member access. |
| `default_branch_protection` | integer | no | See [Options for `default_branch_protection`](#options-for-default_branch_protection). | | `default_branch_protection` | integer | no | See [Options for `default_branch_protection`](#options-for-default_branch_protection). |
| `file_template_project_id` | integer | no | **(PREMIUM)** The ID of a project to load custom file templates from. | | `file_template_project_id` | integer | no | **(PREMIUM)** The ID of a project to load custom file templates from. |
| `shared_runners_minutes_limit` | integer | no | **(PREMIUM SELF)** Pipeline minutes quota for this group (included in plan). Can be `nil` (default; inherit system default), `0` (unlimited) or `> 0` | | `shared_runners_minutes_limit` | integer | no | **(PREMIUM SELF)** Pipeline minutes quota for this group (included in plan). Can be `nil` (default; inherit system default), `0` (unlimited) or `> 0` |
| `extra_shared_runners_minutes_limit` | integer | no | **(PREMIUM SELF)** Extra pipeline minutes quota for this group (purchased in addition to the minutes included in the plan). | | `extra_shared_runners_minutes_limit` | integer | no | **(PREMIUM SELF)** Extra pipeline minutes quota for this group (purchased in addition to the minutes included in the plan). |
| `prevent_forking_outside_group` | boolean | no | **(PREMIUM)** When enabled, users can **not** fork projects from this group to external namespaces | `prevent_forking_outside_group` | boolean | no | **(PREMIUM)** When enabled, users can **not** fork projects from this group to external namespaces
| `shared_runners_setting` | string | no | See [Options for `shared_runners_setting`](#options-for-shared_runners_setting). Enable or disable shared runners for a group's subgroups and projects. | | `shared_runners_setting` | string | no | See [Options for `shared_runners_setting`](#options-for-shared_runners_setting). Enable or disable shared runners for a group's subgroups and projects. |
| `prevent_sharing_groups_outside_hierarchy` | boolean | no | See [Prevent group sharing outside the group hierarchy](../user/group/index.md#prevent-group-sharing-outside-the-group-hierarchy). This attribute is only available on top-level groups. [Introduced in GitLab 14.1](https://gitlab.com/gitlab-org/gitlab/-/issues/333721) |
NOTE: NOTE:
The `projects` and `shared_projects` attributes in the response are deprecated and [scheduled for removal in API v5](https://gitlab.com/gitlab-org/gitlab/-/issues/213797). The `projects` and `shared_projects` attributes in the response are deprecated and [scheduled for removal in API v5](https://gitlab.com/gitlab-org/gitlab/-/issues/213797).
...@@ -910,6 +914,7 @@ Example response: ...@@ -910,6 +914,7 @@ Example response:
"file_template_project_id": 1, "file_template_project_id": 1,
"parent_id": null, "parent_id": null,
"created_at": "2020-01-15T12:36:29.590Z", "created_at": "2020-01-15T12:36:29.590Z",
"prevent_sharing_groups_outside_hierarchy": false,
"projects": [ // Deprecated and will be removed in API v5 "projects": [ // Deprecated and will be removed in API v5
{ {
"id": 9, "id": 9,
...@@ -954,6 +959,8 @@ Example response: ...@@ -954,6 +959,8 @@ Example response:
} }
``` ```
The `prevent_sharing_groups_outside_hierarchy` attribute is present in the response only for top-level groups.
### Disable the results limit **(FREE SELF)** ### Disable the results limit **(FREE SELF)**
The 100 results limit can break integrations developed using GitLab 12.4 and earlier. The 100 results limit can break integrations developed using GitLab 12.4 and earlier.
......
...@@ -7,6 +7,7 @@ module API ...@@ -7,6 +7,7 @@ module API
SharedGroupWithGroup.represent(group.shared_with_group_links.public_or_visible_to_user(group, options[:current_user])) SharedGroupWithGroup.represent(group.shared_with_group_links.public_or_visible_to_user(group, options[:current_user]))
end end
expose :runners_token, if: lambda { |group, options| options[:user_can_admin_group] } expose :runners_token, if: lambda { |group, options| options[:user_can_admin_group] }
expose :prevent_sharing_groups_outside_hierarchy, if: ->(group) { group.root? }
expose :projects, using: Entities::Project do |group, options| expose :projects, using: Entities::Project do |group, options|
projects = GroupProjectsFinder.new( projects = GroupProjectsFinder.new(
......
...@@ -215,6 +215,7 @@ module API ...@@ -215,6 +215,7 @@ module API
optional :name, type: String, desc: 'The name of the group' optional :name, type: String, desc: 'The name of the group'
optional :path, type: String, desc: 'The path of the group' optional :path, type: String, desc: 'The path of the group'
use :optional_params use :optional_params
use :optional_update_params
use :optional_update_params_ee use :optional_update_params_ee
end end
put ':id' do put ':id' do
......
...@@ -30,6 +30,10 @@ module API ...@@ -30,6 +30,10 @@ module API
params :optional_params_ee do params :optional_params_ee do
end end
params :optional_update_params do
optional :prevent_sharing_groups_outside_hierarchy, type: Boolean, desc: 'Prevent sharing groups within this namespace with any groups outside the namespace. Only available on top-level groups.'
end
params :optional_update_params_ee do params :optional_update_params_ee do
end end
......
...@@ -39087,6 +39087,9 @@ msgstr "" ...@@ -39087,6 +39087,9 @@ msgstr ""
msgid "on track" msgid "on track"
msgstr "" msgstr ""
msgid "only available on top-level groups."
msgstr ""
msgid "open issue" msgid "open issue"
msgstr "" msgstr ""
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe API::Entities::GroupDetail do
describe '#as_json' do
it 'includes prevent_sharing_groups_outside_hierarchy for a root group' do
group = create(:group)
expect(described_class.new(group).as_json).to include(prevent_sharing_groups_outside_hierarchy: false)
end
it 'excludes prevent_sharing_groups_outside_hierarchy for a subgroup' do
subgroup = build(:group, :nested)
expect(described_class.new(subgroup).as_json.keys).not_to include(:prevent_sharing_groups_outside_hierarchy)
end
end
end
...@@ -490,6 +490,7 @@ RSpec.describe API::Groups do ...@@ -490,6 +490,7 @@ RSpec.describe API::Groups do
expect(json_response['visibility']).to eq(Gitlab::VisibilityLevel.string_level(group1.visibility_level)) expect(json_response['visibility']).to eq(Gitlab::VisibilityLevel.string_level(group1.visibility_level))
expect(json_response['avatar_url']).to eq(group1.avatar_url(only_path: false)) expect(json_response['avatar_url']).to eq(group1.avatar_url(only_path: false))
expect(json_response['share_with_group_lock']).to eq(group1.share_with_group_lock) expect(json_response['share_with_group_lock']).to eq(group1.share_with_group_lock)
expect(json_response['prevent_sharing_groups_outside_hierarchy']).to eq(group2.namespace_settings.prevent_sharing_groups_outside_hierarchy)
expect(json_response['require_two_factor_authentication']).to eq(group1.require_two_factor_authentication) expect(json_response['require_two_factor_authentication']).to eq(group1.require_two_factor_authentication)
expect(json_response['two_factor_grace_period']).to eq(group1.two_factor_grace_period) expect(json_response['two_factor_grace_period']).to eq(group1.two_factor_grace_period)
expect(json_response['auto_devops_enabled']).to eq(group1.auto_devops_enabled) expect(json_response['auto_devops_enabled']).to eq(group1.auto_devops_enabled)
...@@ -700,6 +701,7 @@ RSpec.describe API::Groups do ...@@ -700,6 +701,7 @@ RSpec.describe API::Groups do
project_creation_level: "noone", project_creation_level: "noone",
subgroup_creation_level: "maintainer", subgroup_creation_level: "maintainer",
default_branch_protection: ::Gitlab::Access::MAINTAINER_PROJECT_ACCESS, default_branch_protection: ::Gitlab::Access::MAINTAINER_PROJECT_ACCESS,
prevent_sharing_groups_outside_hierarchy: true,
avatar: fixture_file_upload(file_path) avatar: fixture_file_upload(file_path)
} }
...@@ -724,6 +726,7 @@ RSpec.describe API::Groups do ...@@ -724,6 +726,7 @@ RSpec.describe API::Groups do
expect(json_response['shared_projects'].length).to eq(0) expect(json_response['shared_projects'].length).to eq(0)
expect(json_response['default_branch_protection']).to eq(::Gitlab::Access::MAINTAINER_PROJECT_ACCESS) expect(json_response['default_branch_protection']).to eq(::Gitlab::Access::MAINTAINER_PROJECT_ACCESS)
expect(json_response['avatar_url']).to end_with('dk.png') expect(json_response['avatar_url']).to end_with('dk.png')
expect(json_response['prevent_sharing_groups_outside_hierarchy']).to eq(true)
end end
context 'updating the `default_branch_protection` attribute' do context 'updating the `default_branch_protection` attribute' do
...@@ -794,6 +797,15 @@ RSpec.describe API::Groups do ...@@ -794,6 +797,15 @@ RSpec.describe API::Groups do
expect(response).to have_gitlab_http_status(:bad_request) expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['message']['visibility_level']).to contain_exactly('private is not allowed since there are sub-groups with higher visibility.') expect(json_response['message']['visibility_level']).to contain_exactly('private is not allowed since there are sub-groups with higher visibility.')
end end
it 'does not update prevent_sharing_groups_outside_hierarchy' do
put api("/groups/#{subgroup.id}", user3), params: { description: 'it works', prevent_sharing_groups_outside_hierarchy: true }
expect(response).to have_gitlab_http_status(:ok)
expect(json_response.keys).not_to include('prevent_sharing_groups_outside_hierarchy')
expect(subgroup.reload.prevent_sharing_groups_outside_hierarchy).to eq(false)
expect(json_response['description']).to eq('it works')
end
end end
end end
......
...@@ -106,6 +106,22 @@ RSpec.describe NamespaceSettings::UpdateService do ...@@ -106,6 +106,22 @@ RSpec.describe NamespaceSettings::UpdateService do
expect(group.namespace_settings.errors.messages[:prevent_sharing_groups_outside_hierarchy]).to include('can only be changed by a group admin.') expect(group.namespace_settings.errors.messages[:prevent_sharing_groups_outside_hierarchy]).to include('can only be changed by a group admin.')
end end
end end
context 'with a subgroup' do
let(:subgroup) { create(:group, parent: group) }
before do
group.add_owner(user)
end
it 'does not change settings' do
service = described_class.new(user, subgroup, settings)
expect { service.execute }.not_to change { group.namespace_settings.prevent_sharing_groups_outside_hierarchy }
expect(subgroup.namespace_settings.errors.messages[:prevent_sharing_groups_outside_hierarchy]).to include('only available on top-level groups.')
end
end
end end
end end
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