Skip to content
Snippets Groups Projects
Commit d3f2c2f2 authored by Carla Drago's avatar Carla Drago :red_circle:
Browse files

Merge branch '405168-fix-group-visibility-level' into 'master'

Include and process visibility_level

See merge request !122754



Merged-by: default avatarCarla Drago <cdrago@gitlab.com>
Approved-by: default avatarPetar Prokić <pprokic@gitlab.com>
Reviewed-by: default avatarGeorge Koltsov <gkoltsov@gitlab.com>
Reviewed-by: default avatarRodrigo Tomonari <rtomonari@gitlab.com>
Reviewed-by: default avatarBojan Marjanovic <bmarjanovic@gitlab.com>
parents 266746a0 0e96d3db
No related branches found
No related tags found
No related merge requests found
Pipeline #902770650 passed
Pipeline: E2E Omnibus GitLab EE

#902843637

    Pipeline: E2E GDK

    #902788628

      Pipeline: GitLab

      #902772606

        Showing
        with 622 additions and 23 deletions
        ......@@ -56,7 +56,6 @@ excluded_attributes:
        - :runners_token
        - :runners_token_encrypted
        - :saml_discovery_token
        - :visibility_level
        - :trial_ends_on
        - :shared_runners_minute_limit
        - :extra_shared_runners_minutes_limit
        ......
        ......@@ -65,6 +65,15 @@ def process_root(group_id)
        # with existing groups name and/or path.
        group_attributes.delete_attributes('name', 'path')
        if @top_level_group.has_parent?
        group_attributes.attributes['visibility_level'] = sub_group_visibility_level(
        group_attributes.attributes['visibility_level'],
        @top_level_group.parent
        )
        elsif Gitlab::VisibilityLevel.restricted_level?(group_attributes.attributes['visibility_level'])
        group_attributes.delete_attribute('visibility_level')
        end
        restore_group(@top_level_group, group_attributes)
        end
        ......@@ -86,6 +95,7 @@ def create_group(group_attributes)
        parent_id = group_attributes.delete_attribute('parent_id')
        name = group_attributes.delete_attribute('name')
        path = group_attributes.delete_attribute('path')
        visibility_level = group_attributes.delete_attribute('visibility_level')
        parent_group = @groups_mapping.fetch(parent_id) { raise(ArgumentError, 'Parent group not found') }
        ......@@ -94,7 +104,7 @@ def create_group(group_attributes)
        name: name,
        path: path,
        parent_id: parent_group.id,
        visibility_level: sub_group_visibility_level(group_attributes.attributes, parent_group)
        visibility_level: sub_group_visibility_level(visibility_level, parent_group)
        ).execute
        group.validate!
        ......@@ -124,16 +134,23 @@ def relation_reader
        end
        end
        def sub_group_visibility_level(group_hash, parent_group)
        original_visibility_level = group_hash['visibility_level'] || Gitlab::VisibilityLevel::PRIVATE
        def sub_group_visibility_level(visibility_level, parent_group)
        parent_visibility_level = parent_group.visibility_level
        if parent_group && parent_group.visibility_level < original_visibility_level
        Gitlab::VisibilityLevel.closest_allowed_level(parent_group.visibility_level)
        original_visibility_level = visibility_level ||
        closest_allowed_level(parent_visibility_level)
        if parent_visibility_level < original_visibility_level
        closest_allowed_level(parent_visibility_level)
        else
        original_visibility_level
        closest_allowed_level(original_visibility_level)
        end
        end
        def closest_allowed_level(visibility_level)
        Gitlab::VisibilityLevel.closest_allowed_level(visibility_level)
        end
        def reader
        strong_memoize(:reader) do
        Gitlab::ImportExport::Reader.new(
        ......
        {
        "depth": 1,
        "tree_path": [
        1689
        ],
        "tree_cycle": false,
        "id": 1689,
        "name": "public-group-3",
        "path": "public-group-3",
        "description": "",
        "avatar": {
        "url": null
        },
        "membership_lock": false,
        "share_with_group_lock": false,
        "visibility_level": 20,
        "request_access_enabled": true,
        "ldap_sync_status": "ready",
        "ldap_sync_error": null,
        "ldap_sync_last_update_at": null,
        "ldap_sync_last_successful_update_at": null,
        "ldap_sync_last_sync_at": null,
        "lfs_enabled": null,
        "parent_id": null,
        "shared_runners_minutes_limit": null,
        "require_two_factor_authentication": false,
        "two_factor_grace_period": 48,
        "project_creation_level": 2,
        "file_template_project_id": null,
        "custom_project_templates_group_id": null,
        "auto_devops_enabled": null,
        "last_ci_minutes_notification_at": null,
        "last_ci_minutes_usage_notification_level": null,
        "subgroup_creation_level": 1,
        "emails_disabled": null,
        "max_artifacts_size": null,
        "mentions_disabled": null,
        "default_branch_protection": 2,
        "unlock_membership_to_ldap": null,
        "max_personal_access_token_lifetime": null,
        "push_rule_id": null,
        "shared_runners_enabled": true,
        "allow_descendants_override_disabled_shared_runners": false,
        "traversal_ids": [
        1689
        ],
        "organization_id": 1
        }
        {
        "depth": 2,
        "tree_path": [
        1689,
        1690
        ],
        "tree_cycle": false,
        "id": 1690,
        "name": "private-subgroup",
        "path": "private-subgroup",
        "description": "",
        "avatar": {
        "url": null
        },
        "membership_lock": false,
        "share_with_group_lock": false,
        "visibility_level": 0,
        "request_access_enabled": true,
        "ldap_sync_status": "ready",
        "ldap_sync_error": null,
        "ldap_sync_last_update_at": null,
        "ldap_sync_last_successful_update_at": null,
        "ldap_sync_last_sync_at": null,
        "lfs_enabled": null,
        "parent_id": 1689,
        "shared_runners_minutes_limit": null,
        "require_two_factor_authentication": false,
        "two_factor_grace_period": 48,
        "project_creation_level": 2,
        "file_template_project_id": null,
        "custom_project_templates_group_id": null,
        "auto_devops_enabled": null,
        "last_ci_minutes_notification_at": null,
        "last_ci_minutes_usage_notification_level": null,
        "subgroup_creation_level": 1,
        "emails_disabled": null,
        "max_artifacts_size": null,
        "mentions_disabled": null,
        "default_branch_protection": 2,
        "unlock_membership_to_ldap": null,
        "max_personal_access_token_lifetime": null,
        "push_rule_id": null,
        "shared_runners_enabled": true,
        "allow_descendants_override_disabled_shared_runners": false,
        "traversal_ids": [
        1689,
        1690
        ],
        "organization_id": 1
        }
        {
        "depth": 2,
        "tree_path": [
        1689,
        1691
        ],
        "tree_cycle": false,
        "id": 1691,
        "name": "internal-subgroup",
        "path": "internal-subgroup",
        "description": "",
        "avatar": {
        "url": null
        },
        "membership_lock": false,
        "share_with_group_lock": false,
        "visibility_level": 10,
        "request_access_enabled": true,
        "ldap_sync_status": "ready",
        "ldap_sync_error": null,
        "ldap_sync_last_update_at": null,
        "ldap_sync_last_successful_update_at": null,
        "ldap_sync_last_sync_at": null,
        "lfs_enabled": null,
        "parent_id": 1689,
        "shared_runners_minutes_limit": null,
        "require_two_factor_authentication": false,
        "two_factor_grace_period": 48,
        "project_creation_level": 2,
        "file_template_project_id": null,
        "custom_project_templates_group_id": null,
        "auto_devops_enabled": null,
        "last_ci_minutes_notification_at": null,
        "last_ci_minutes_usage_notification_level": null,
        "subgroup_creation_level": 1,
        "emails_disabled": null,
        "max_artifacts_size": null,
        "mentions_disabled": null,
        "default_branch_protection": 2,
        "unlock_membership_to_ldap": null,
        "max_personal_access_token_lifetime": null,
        "push_rule_id": null,
        "shared_runners_enabled": true,
        "allow_descendants_override_disabled_shared_runners": false,
        "traversal_ids": [
        1689,
        1691
        ],
        "organization_id": 1
        }
        {
        "depth": 2,
        "tree_path": [
        1689,
        1692
        ],
        "tree_cycle": false,
        "id": 1692,
        "name": "public-subgroup",
        "path": "public-subgroup",
        "description": "",
        "avatar": {
        "url": null
        },
        "membership_lock": false,
        "share_with_group_lock": false,
        "visibility_level": 20,
        "request_access_enabled": true,
        "ldap_sync_status": "ready",
        "ldap_sync_error": null,
        "ldap_sync_last_update_at": null,
        "ldap_sync_last_successful_update_at": null,
        "ldap_sync_last_sync_at": null,
        "lfs_enabled": null,
        "parent_id": 1689,
        "shared_runners_minutes_limit": null,
        "require_two_factor_authentication": false,
        "two_factor_grace_period": 48,
        "project_creation_level": 2,
        "file_template_project_id": null,
        "custom_project_templates_group_id": null,
        "auto_devops_enabled": null,
        "last_ci_minutes_notification_at": null,
        "last_ci_minutes_usage_notification_level": null,
        "subgroup_creation_level": 1,
        "emails_disabled": null,
        "max_artifacts_size": null,
        "mentions_disabled": null,
        "default_branch_protection": 2,
        "unlock_membership_to_ldap": null,
        "max_personal_access_token_lifetime": null,
        "push_rule_id": null,
        "shared_runners_enabled": true,
        "allow_descendants_override_disabled_shared_runners": false,
        "traversal_ids": [
        1689,
        1692
        ],
        "organization_id": 1
        }
        {
        "depth": 3,
        "tree_path": [
        1689,
        1691,
        2106
        ],
        "tree_cycle": false,
        "id": 2106,
        "name": "internal-sub-subgroup",
        "path": "internal-sub-subgroup",
        "description": "",
        "avatar": {
        "url": null
        },
        "membership_lock": false,
        "share_with_group_lock": false,
        "visibility_level": 10,
        "request_access_enabled": true,
        "ldap_sync_status": "ready",
        "ldap_sync_error": null,
        "ldap_sync_last_update_at": null,
        "ldap_sync_last_successful_update_at": null,
        "ldap_sync_last_sync_at": null,
        "lfs_enabled": null,
        "parent_id": 1691,
        "shared_runners_minutes_limit": null,
        "require_two_factor_authentication": false,
        "two_factor_grace_period": 48,
        "project_creation_level": 2,
        "file_template_project_id": null,
        "custom_project_templates_group_id": null,
        "auto_devops_enabled": null,
        "last_ci_minutes_notification_at": null,
        "last_ci_minutes_usage_notification_level": null,
        "subgroup_creation_level": 1,
        "emails_disabled": null,
        "max_artifacts_size": null,
        "mentions_disabled": null,
        "default_branch_protection": 2,
        "unlock_membership_to_ldap": null,
        "max_personal_access_token_lifetime": null,
        "push_rule_id": null,
        "shared_runners_enabled": true,
        "allow_descendants_override_disabled_shared_runners": false,
        "traversal_ids": [
        1689,
        1691,
        2106
        ],
        "organization_id": 1
        }
        {
        "depth": 3,
        "tree_path": [
        1689,
        1692,
        2107
        ],
        "tree_cycle": false,
        "id": 2107,
        "name": "internal-sub-subgroup",
        "path": "internal-sub-subgroup",
        "description": "",
        "avatar": {
        "url": null
        },
        "membership_lock": false,
        "share_with_group_lock": false,
        "visibility_level": 10,
        "request_access_enabled": true,
        "ldap_sync_status": "ready",
        "ldap_sync_error": null,
        "ldap_sync_last_update_at": null,
        "ldap_sync_last_successful_update_at": null,
        "ldap_sync_last_sync_at": null,
        "lfs_enabled": null,
        "parent_id": 1692,
        "shared_runners_minutes_limit": null,
        "require_two_factor_authentication": false,
        "two_factor_grace_period": 48,
        "project_creation_level": 2,
        "file_template_project_id": null,
        "custom_project_templates_group_id": null,
        "auto_devops_enabled": null,
        "last_ci_minutes_notification_at": null,
        "last_ci_minutes_usage_notification_level": null,
        "subgroup_creation_level": 1,
        "emails_disabled": null,
        "max_artifacts_size": null,
        "mentions_disabled": null,
        "default_branch_protection": 2,
        "unlock_membership_to_ldap": null,
        "max_personal_access_token_lifetime": null,
        "push_rule_id": null,
        "shared_runners_enabled": true,
        "allow_descendants_override_disabled_shared_runners": false,
        "traversal_ids": [
        1689,
        1692,
        2107
        ],
        "organization_id": 1
        }
        {
        "depth": 3,
        "tree_path": [
        1689,
        1692,
        2108
        ],
        "tree_cycle": false,
        "id": 2108,
        "name": "public-sub-subgroup",
        "path": "public-sub-subgroup",
        "description": "",
        "avatar": {
        "url": null
        },
        "membership_lock": false,
        "share_with_group_lock": false,
        "visibility_level": 20,
        "request_access_enabled": true,
        "ldap_sync_status": "ready",
        "ldap_sync_error": null,
        "ldap_sync_last_update_at": null,
        "ldap_sync_last_successful_update_at": null,
        "ldap_sync_last_sync_at": null,
        "lfs_enabled": null,
        "parent_id": 1692,
        "shared_runners_minutes_limit": null,
        "require_two_factor_authentication": false,
        "two_factor_grace_period": 48,
        "project_creation_level": 2,
        "file_template_project_id": null,
        "custom_project_templates_group_id": null,
        "auto_devops_enabled": null,
        "last_ci_minutes_notification_at": null,
        "last_ci_minutes_usage_notification_level": null,
        "subgroup_creation_level": 1,
        "emails_disabled": null,
        "max_artifacts_size": null,
        "mentions_disabled": null,
        "default_branch_protection": 2,
        "unlock_membership_to_ldap": null,
        "max_personal_access_token_lifetime": null,
        "push_rule_id": null,
        "shared_runners_enabled": true,
        "allow_descendants_override_disabled_shared_runners": false,
        "traversal_ids": [
        1689,
        1692,
        2108
        ],
        "organization_id": 1
        }
        {
        "depth": 3,
        "tree_path": [
        1689,
        1692,
        2109
        ],
        "tree_cycle": false,
        "id": 2109,
        "name": "private-sub-subgroup",
        "path": "private-sub-subgroup",
        "description": "",
        "avatar": {
        "url": null
        },
        "membership_lock": false,
        "share_with_group_lock": false,
        "visibility_level": 0,
        "request_access_enabled": true,
        "ldap_sync_status": "ready",
        "ldap_sync_error": null,
        "ldap_sync_last_update_at": null,
        "ldap_sync_last_successful_update_at": null,
        "ldap_sync_last_sync_at": null,
        "lfs_enabled": null,
        "parent_id": 1692,
        "shared_runners_minutes_limit": null,
        "require_two_factor_authentication": false,
        "two_factor_grace_period": 48,
        "project_creation_level": 2,
        "file_template_project_id": null,
        "custom_project_templates_group_id": null,
        "auto_devops_enabled": null,
        "last_ci_minutes_notification_at": null,
        "last_ci_minutes_usage_notification_level": null,
        "subgroup_creation_level": 1,
        "emails_disabled": null,
        "max_artifacts_size": null,
        "mentions_disabled": null,
        "default_branch_protection": 2,
        "unlock_membership_to_ldap": null,
        "max_personal_access_token_lifetime": null,
        "push_rule_id": null,
        "shared_runners_enabled": true,
        "allow_descendants_override_disabled_shared_runners": false,
        "traversal_ids": [
        1689,
        1692,
        2109
        ],
        "organization_id": 1
        }
        {
        "depth": 3,
        "tree_path": [
        1689,
        1690,
        2110
        ],
        "tree_cycle": false,
        "id": 2110,
        "name": "private-sub-subgroup",
        "path": "private-sub-subgroup",
        "description": "",
        "avatar": {
        "url": null
        },
        "membership_lock": false,
        "share_with_group_lock": false,
        "visibility_level": 0,
        "request_access_enabled": true,
        "ldap_sync_status": "ready",
        "ldap_sync_error": null,
        "ldap_sync_last_update_at": null,
        "ldap_sync_last_successful_update_at": null,
        "ldap_sync_last_sync_at": null,
        "lfs_enabled": null,
        "parent_id": 1690,
        "shared_runners_minutes_limit": null,
        "require_two_factor_authentication": false,
        "two_factor_grace_period": 48,
        "project_creation_level": 2,
        "file_template_project_id": null,
        "custom_project_templates_group_id": null,
        "auto_devops_enabled": null,
        "last_ci_minutes_notification_at": null,
        "last_ci_minutes_usage_notification_level": null,
        "subgroup_creation_level": 1,
        "emails_disabled": null,
        "max_artifacts_size": null,
        "mentions_disabled": null,
        "default_branch_protection": 2,
        "unlock_membership_to_ldap": null,
        "max_personal_access_token_lifetime": null,
        "push_rule_id": null,
        "shared_runners_enabled": true,
        "allow_descendants_override_disabled_shared_runners": false,
        "traversal_ids": [
        1689,
        1690,
        2110
        ],
        "organization_id": 1
        }
        1689
        1690
        1691
        1692
        2110
        2106
        2107
        2108
        2109
        ......@@ -177,30 +177,146 @@
        end
        context 'group visibility levels' do
        let(:user) { create(:user) }
        let(:shared) { Gitlab::ImportExport::Shared.new(group) }
        let(:group_tree_restorer) { described_class.new(user: user, shared: shared, group: group) }
        context 'when the @top_level_group is the destination_group' do
        let(:user) { create(:user) }
        let(:shared) { Gitlab::ImportExport::Shared.new(group) }
        let(:group_tree_restorer) { described_class.new(user: user, shared: shared, group: group) }
        shared_examples 'with visibility level' do |visibility_level, expected_visibilities|
        context "when visibility level is #{visibility_level}" do
        let(:group) { create(:group, visibility_level) }
        let(:filepath) { "group_exports/visibility_levels/#{visibility_level}" }
        before do
        setup_import_export_config(filepath)
        group_tree_restorer.restore
        end
        before do
        setup_import_export_config(filepath)
        it "imports all subgroups as #{visibility_level}" do
        expect(group.children.map(&:visibility_level)).to match_array(expected_visibilities)
        end
        end
        end
        group_tree_restorer.restore
        include_examples 'with visibility level', :public, [20, 10, 0]
        include_examples 'with visibility level', :private, [0, 0, 0]
        include_examples 'with visibility level', :internal, [10, 10, 0]
        end
        shared_examples 'with visibility level' do |visibility_level, expected_visibilities|
        context "when visibility level is #{visibility_level}" do
        let(:group) { create(:group, visibility_level) }
        let(:filepath) { "group_exports/visibility_levels/#{visibility_level}" }
        context 'when the destination_group is the @top_level_group.parent' do
        let(:user) { create(:user) }
        let(:shared) { Gitlab::ImportExport::Shared.new(group) }
        let(:group_tree_restorer) { described_class.new(user: user, shared: shared, group: group) }
        shared_examples 'with visibility level' do |visibility_level, expected_visibilities, group_visibility|
        context "when source level is #{visibility_level}" do
        let(:parent) { create(:group, visibility_level) }
        let(:group) { create(:group, visibility_level, parent: parent) }
        let(:filepath) { "group_exports/visibility_levels/#{visibility_level}" }
        before do
        setup_import_export_config(filepath)
        parent.add_maintainer(user)
        group_tree_restorer.restore
        end
        it "imports all subgroups as #{visibility_level}" do
        expect(group.children.map(&:visibility_level)).to match_array(expected_visibilities)
        it "imports all subgroups as #{visibility_level}" do
        expect(group.visibility_level).to eq(group_visibility)
        expect(group.children.map(&:visibility_level)).to match_array(expected_visibilities)
        end
        end
        end
        include_examples 'with visibility level', :public, [20, 10, 0], 20
        include_examples 'with visibility level', :private, [0, 0, 0], 0
        include_examples 'with visibility level', :internal, [10, 10, 0], 10
        end
        context 'when the visibility level is restricted' do
        let(:user) { create(:user) }
        let(:shared) { Gitlab::ImportExport::Shared.new(group) }
        let(:group_tree_restorer) { described_class.new(user: user, shared: shared, group: group) }
        let(:group) { create(:group, :internal) }
        let(:filepath) { "group_exports/visibility_levels/internal" }
        before do
        setup_import_export_config(filepath)
        Gitlab::CurrentSettings.restricted_visibility_levels = [10]
        group_tree_restorer.restore
        end
        after do
        Gitlab::CurrentSettings.restricted_visibility_levels = []
        end
        it 'updates the visibility_level' do
        expect(group.children.map(&:visibility_level)).to match_array([0, 0, 0])
        end
        end
        end
        context 'when there are nested subgroups' do
        let(:filepath) { "group_exports/visibility_levels/nested_subgroups" }
        include_examples 'with visibility level', :public, [20, 10, 0]
        include_examples 'with visibility level', :private, [0, 0, 0]
        include_examples 'with visibility level', :internal, [10, 10, 0]
        context "when destination level is :public" do
        let(:user) { create(:user) }
        let(:shared) { Gitlab::ImportExport::Shared.new(group) }
        let(:group_tree_restorer) { described_class.new(user: user, shared: shared, group: group) }
        let(:parent) { create(:group, :public) }
        let(:group) { create(:group, :public, parent: parent) }
        before do
        setup_import_export_config(filepath)
        parent.add_maintainer(user)
        group_tree_restorer.restore
        end
        it "imports all subgroups with original visibility_level" do
        expect(group.visibility_level).to eq(Gitlab::VisibilityLevel::PUBLIC)
        expect(group.descendants.map(&:visibility_level))
        .to match_array([0, 0, 0, 10, 10, 10, 20, 20])
        end
        end
        context "when destination level is :internal" do
        let(:user) { create(:user) }
        let(:shared) { Gitlab::ImportExport::Shared.new(group) }
        let(:group_tree_restorer) { described_class.new(user: user, shared: shared, group: group) }
        let(:parent) { create(:group, :internal) }
        let(:group) { create(:group, :internal, parent: parent) }
        before do
        setup_import_export_config(filepath)
        parent.add_maintainer(user)
        group_tree_restorer.restore
        end
        it "imports non-public subgroups with original level and public subgroups as internal" do
        expect(group.visibility_level).to eq(Gitlab::VisibilityLevel::INTERNAL)
        expect(group.descendants.map(&:visibility_level))
        .to match_array([0, 0, 0, 10, 10, 10, 10, 10])
        end
        end
        context "when destination level is :private" do
        let(:user) { create(:user) }
        let(:shared) { Gitlab::ImportExport::Shared.new(group) }
        let(:group_tree_restorer) { described_class.new(user: user, shared: shared, group: group) }
        let(:parent) { create(:group, :private) }
        let(:group) { create(:group, :private, parent: parent) }
        before do
        setup_import_export_config(filepath)
        parent.add_maintainer(user)
        group_tree_restorer.restore
        end
        it "imports all subgroups as private" do
        expect(group.visibility_level).to eq(Gitlab::VisibilityLevel::PRIVATE)
        expect(group.descendants.map(&:visibility_level))
        .to match_array([0, 0, 0, 0, 0, 0, 0, 0])
        end
        end
        end
        end
        ......
        ......@@ -69,7 +69,7 @@ def upload_archive(file, headers = {}, params = {})
        expect(GroupImportWorker).to have_received(:perform_async).with(user.id, group.id)
        expect(group.description).to eq 'A voluptate non sequi temporibus quam at.'
        expect(group.visibility_level).to eq Gitlab::VisibilityLevel::PRIVATE
        expect(group.visibility_level).to eq Gitlab::VisibilityLevel::PUBLIC
        end
        end
        ......
        0% Loading or .
        You are about to add 0 people to the discussion. Proceed with caution.
        Finish editing this message first!
        Please register or to comment