diff --git a/app/models/group.rb b/app/models/group.rb
index 6d6fbaa5cfbb4a124cd906b6cc3407e4b04c5410..2640c26d6f23da1f17148530c209f3a1fc2a6d13 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -246,22 +246,10 @@ def of_ancestors_and_self
   end
 
   scope :project_creation_allowed, ->(user) do
-    project_creation_allowed_on_levels = [
-      ::Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS,
-      ::Gitlab::Access::MAINTAINER_PROJECT_ACCESS,
-      nil
-    ]
-
-    # When the value of application_settings.default_project_creation is set to `NO_ONE_PROJECT_ACCESS`,
-    # it means that a `nil` value for `groups.project_creation_level` is telling us:
-    # do not allow project creation in such groups.
-    # ie, `nil` is a placeholder value for inheriting the value from the ApplicationSetting.
-    # So we remove `nil` from the list when the application_setting's value is `NO_ONE_PROJECT_ACCESS`
-    if ::Gitlab::CurrentSettings.default_project_creation == ::Gitlab::Access::NO_ONE_PROJECT_ACCESS
-      project_creation_allowed_on_levels.delete(nil)
-    end
+    project_creation_levels_for_user = project_creation_levels_for_user(user)
 
-    with_project_creation_levels(project_creation_allowed_on_levels).excluding_restricted_visibility_levels_for_user(user)
+    with_project_creation_levels(project_creation_levels_for_user)
+      .excluding_restricted_visibility_levels_for_user(user)
   end
 
   scope :shared_into_ancestors, ->(group) do
@@ -414,6 +402,42 @@ def with_api_scopes
       preload(:namespace_settings, :group_feature, :parent)
     end
 
+    # Handle project creation permissions based on application setting and group setting. The `default_project_creation`
+    # application setting is the default value and can be overridden by the `project_creation_level` group setting.
+    # `nil` value of namespaces.project_creation_level` means that allowed creation level has not been explicitly set by
+    # the group owner and is a placeholder value for inheriting the value from the ApplicationSetting.
+    def project_creation_levels_for_user(user)
+      project_creation_allowed_on_levels = [
+        ::Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS,
+        ::Gitlab::Access::MAINTAINER_PROJECT_ACCESS,
+        nil
+      ]
+
+      if user.can_admin_all_resources?
+        project_creation_allowed_on_levels << ::Gitlab::Access::ADMINISTRATOR_PROJECT_ACCESS
+      end
+
+      default_project_creation = ::Gitlab::CurrentSettings.default_project_creation
+      prevent_project_creation_by_default = prevent_project_creation?(user, default_project_creation)
+
+      # Remove nil (i.e. inherited `default_project_creation`) when the application setting is:
+      # 1. NO_ONE_PROJECT_ACCESS
+      # 2. ADMINISTRATOR_PROJECT_ACCESS and the user is not an admin
+      #
+      # To prevent showing groups in the namespaces dropdown on the project creation page that have no explicit group
+      # setting for `project_creation_level`.
+      project_creation_allowed_on_levels.delete(nil) if prevent_project_creation_by_default
+
+      project_creation_allowed_on_levels
+    end
+
+    def prevent_project_creation?(user, project_creation_setting)
+      return true if project_creation_setting == ::Gitlab::Access::NO_ONE_PROJECT_ACCESS
+      return false if user.can_admin_all_resources?
+
+      project_creation_setting == ::Gitlab::Access::ADMINISTRATOR_PROJECT_ACCESS
+    end
+
     private
 
     def public_to_user_arel(user)
diff --git a/app/policies/group_policy.rb b/app/policies/group_policy.rb
index 643eedbf826913849dd65a7a8810aa5b9b3d29d7..20915e0f42dca054317ba927d92397874ba9cbb3 100644
--- a/app/policies/group_policy.rb
+++ b/app/policies/group_policy.rb
@@ -56,7 +56,7 @@ class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy
       Project.new(namespace: @subject).visibility_level_allowed?(level)
     end
 
-    @subject.project_creation_level == ::Gitlab::Access::NO_ONE_PROJECT_ACCESS || allowed_visibility_levels.empty?
+    Group.prevent_project_creation?(user, @subject.project_creation_level) || allowed_visibility_levels.empty?
   end
 
   condition(:create_subgroup_disabled, scope: :subject) do
diff --git a/config/application_setting_columns/default_project_creation.yml b/config/application_setting_columns/default_project_creation.yml
index 198ae170a37414ff331abb5c26d4bac7ad7fd08e..11fb2e8f08f76c4cde9ab338239a028a1f62051c 100644
--- a/config/application_setting_columns/default_project_creation.yml
+++ b/config/application_setting_columns/default_project_creation.yml
@@ -5,8 +5,8 @@ clusterwide: false
 column: default_project_creation
 db_type: integer
 default: '2'
-description: 'Default project creation protection. Can take: `0` _(No one)_, `1` _(Maintainers)_
-  or `2` _(Developers + Maintainers)_'
+description: 'Default project creation protection. Can take: `0` _(No one)_, `1` _(Maintainers)_,
+  `2` _(Developers + Maintainers)_ or `3` _(Administrators)_'
 encrypted: false
 gitlab_com_different_than_default: false
 jihu: false
diff --git a/doc/administration/settings/visibility_and_access_controls.md b/doc/administration/settings/visibility_and_access_controls.md
index 940689a8576e50afe7a9f1796da592cf008e7822..72cf99153e6fc36c7d83e849e2a8a72a0fee6b29 100644
--- a/doc/administration/settings/visibility_and_access_controls.md
+++ b/doc/administration/settings/visibility_and_access_controls.md
@@ -39,10 +39,15 @@ Prerequisites:
 1. Expand **Visibility and access controls**.
 1. For **Default project creation protection**, select the desired roles:
    - No one.
+   - Administrators.
    - Maintainers.
    - Developers and Maintainers.
 1. Select **Save changes**.
 
+NOTE:
+If you select **Administrators** and [Admin Mode](sign_in_restrictions.md#admin-mode)
+is turned on, administrators must enter Admin Mode to create new projects.
+
 ## Restrict project deletion to administrators
 
 DETAILS:
diff --git a/doc/api/settings.md b/doc/api/settings.md
index d5afb8aaad9889e04fc86d1d5eb0018aeebe53eb..0fd62c03a2cfe467a55838c8f75eb2082bad9c70 100644
--- a/doc/api/settings.md
+++ b/doc/api/settings.md
@@ -428,7 +428,7 @@ listed in the descriptions of the relevant settings.
 | `default_ci_config_path`                 | string           | no                                   | Default CI/CD configuration file and path for new projects (`.gitlab-ci.yml` if not set). |
 | `default_group_visibility`               | string           | no                                   | What visibility level new groups receive. Can take `private`, `internal` and `public` as a parameter. Default is `private`. [Changed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131203) in GitLab 16.4: cannot be set to any levels in `restricted_visibility_levels`.|
 | `default_preferred_language`             | string           | no                                   | Default preferred language for users who are not logged in. |
-| `default_project_creation`               | integer          | no                                   | Default project creation protection. Can take: `0` _(No one)_, `1` _(Maintainers)_ or `2` _(Developers + Maintainers)_|
+| `default_project_creation`               | integer          | no                                   | Default project creation protection. Can take: `0` _(No one)_, `1` _(Maintainers)_, `2` _(Developers + Maintainers)_, or `3` _(Administrators)_.|
 | `default_project_visibility`             | string           | no                                   | What visibility level new projects receive. Can take `private`, `internal` and `public` as a parameter. Default is `private`. [Changed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131203) in GitLab 16.4: cannot be set to any levels in `restricted_visibility_levels`.|
 | `default_projects_limit`                 | integer          | no                                   | Project limit per user. Default is `100000`. |
 | `default_snippet_visibility`             | string           | no                                   | What visibility level new snippets receive. Can take `private`, `internal` and `public` as a parameter. Default is `private`. |
diff --git a/lib/gitlab/access.rb b/lib/gitlab/access.rb
index a95431b47e7b33aa912d8ffdf1fe5c65eb1d3e37..1ea6d4f106a21fac1323c6746e83ae9c5885b197 100644
--- a/lib/gitlab/access.rb
+++ b/lib/gitlab/access.rb
@@ -29,6 +29,7 @@ module Access
     NO_ONE_PROJECT_ACCESS = 0
     MAINTAINER_PROJECT_ACCESS = 1
     DEVELOPER_MAINTAINER_PROJECT_ACCESS = 2
+    ADMINISTRATOR_PROJECT_ACCESS = 3
 
     # Default subgroup creation level
     OWNER_SUBGROUP_ACCESS = 0
@@ -140,7 +141,8 @@ def project_creation_options
         {
           s_('ProjectCreationLevel|No one') => NO_ONE_PROJECT_ACCESS,
           s_('ProjectCreationLevel|Maintainers') => MAINTAINER_PROJECT_ACCESS,
-          s_('ProjectCreationLevel|Developers + Maintainers') => DEVELOPER_MAINTAINER_PROJECT_ACCESS
+          s_('ProjectCreationLevel|Developers + Maintainers') => DEVELOPER_MAINTAINER_PROJECT_ACCESS,
+          s_('ProjectCreationLevel|Administrators') => ADMINISTRATOR_PROJECT_ACCESS
         }
       end
 
@@ -148,7 +150,8 @@ def project_creation_string_options
         {
           'noone' => NO_ONE_PROJECT_ACCESS,
           'maintainer' => MAINTAINER_PROJECT_ACCESS,
-          'developer' => DEVELOPER_MAINTAINER_PROJECT_ACCESS
+          'developer' => DEVELOPER_MAINTAINER_PROJECT_ACCESS,
+          'administrator' => ADMINISTRATOR_PROJECT_ACCESS
         }
       end
 
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index fd3fdafde19202e633c53744176cd50492e11fa2..6faf8a5a490005221ff2e4f5ce0d69396fbf2f79 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -42749,6 +42749,9 @@ msgstr ""
 msgid "ProjectActivityRSS|Subscribe"
 msgstr ""
 
+msgid "ProjectCreationLevel|Administrators"
+msgstr ""
+
 msgid "ProjectCreationLevel|Default project creation protection"
 msgstr ""
 
diff --git a/spec/finders/groups/accepting_project_creations_finder_spec.rb b/spec/finders/groups/accepting_project_creations_finder_spec.rb
index 61d673d6a9933c96476aed2e2a028a65ce765bf6..a9b630a836a176ebd3a579a1c030f3a6de4e107f 100644
--- a/spec/finders/groups/accepting_project_creations_finder_spec.rb
+++ b/spec/finders/groups/accepting_project_creations_finder_spec.rb
@@ -5,6 +5,10 @@
 RSpec.describe Groups::AcceptingProjectCreationsFinder, feature_category: :groups_and_projects do
   let_it_be(:user) { create(:user) }
   let_it_be(:group_where_direct_owner) { create(:group) }
+  let_it_be(:group_where_direct_owner_with_admin_project_creation_level) do
+    create(:group, project_creation_level: Gitlab::Access::ADMINISTRATOR_PROJECT_ACCESS)
+  end
+
   let_it_be(:subgroup_of_group_where_direct_owner) { create(:group, parent: group_where_direct_owner) }
   let_it_be(:group_where_direct_maintainer) { create(:group) }
   let_it_be(:group_where_direct_maintainer_but_cant_create_projects) do
@@ -42,6 +46,7 @@
 
   before do
     group_where_direct_owner.add_owner(user)
+    group_where_direct_owner_with_admin_project_creation_level.add_owner(user)
     group_where_direct_maintainer.add_maintainer(user)
     group_where_direct_developer_but_developers_cannot_create_projects.add_developer(user)
     group_where_direct_developer.add_developer(user)
@@ -100,5 +105,26 @@
         shared_with_group_where_direct_owner_as_developer
       ])
     end
+
+    context 'with admin user', :enable_admin_mode do
+      let_it_be(:user) { create(:admin) }
+
+      it 'only returns groups where the user has access to create projects' do
+        expect(result).to match_array([
+          group_where_direct_owner,
+          group_where_direct_owner_with_admin_project_creation_level,
+          subgroup_of_group_where_direct_owner,
+          group_where_direct_maintainer,
+          group_where_direct_developer,
+          # groups arising from group shares
+          shared_with_group_where_direct_owner_as_owner,
+          shared_with_group_where_direct_owner_as_maintainer,
+          subgroup_of_shared_with_group_where_direct_owner_as_maintainer,
+          shared_with_group_where_direct_developer_as_owner,
+          shared_with_group_where_direct_developer_as_maintainer,
+          shared_with_group_where_direct_owner_as_developer
+        ])
+      end
+    end
   end
 end
diff --git a/spec/finders/groups/accepting_project_transfers_finder_spec.rb b/spec/finders/groups/accepting_project_transfers_finder_spec.rb
index 47c293bf74b9849820216cc0c3e030efb86609b6..b71b54447dc40d08009efd3e5cbd46f2993b9fc6 100644
--- a/spec/finders/groups/accepting_project_transfers_finder_spec.rb
+++ b/spec/finders/groups/accepting_project_transfers_finder_spec.rb
@@ -5,8 +5,13 @@
 RSpec.describe Groups::AcceptingProjectTransfersFinder, feature_category: :groups_and_projects do
   let_it_be(:user) { create(:user) }
   let_it_be(:group_where_direct_owner) { create(:group) }
+  let_it_be(:group_where_direct_owner_with_admin_project_creation_level) do
+    create(:group, project_creation_level: Gitlab::Access::ADMINISTRATOR_PROJECT_ACCESS)
+  end
+
   let_it_be(:subgroup_of_group_where_direct_owner) { create(:group, parent: group_where_direct_owner) }
   let_it_be(:group_where_direct_maintainer) { create(:group) }
+
   let_it_be(:group_where_direct_maintainer_but_cant_create_projects) do
     create(:group, project_creation_level: Gitlab::Access::NO_ONE_PROJECT_ACCESS)
   end
@@ -22,6 +27,7 @@
 
   before do
     group_where_direct_owner.add_owner(user)
+    group_where_direct_owner_with_admin_project_creation_level.add_owner(user)
     group_where_direct_maintainer.add_maintainer(user)
     group_where_direct_developer.add_developer(user)
 
@@ -63,5 +69,21 @@
         subgroup_of_shared_with_group_where_direct_owner_as_maintainer
       ])
     end
+
+    context 'with admin user', :enable_admin_mode do
+      let_it_be(:user) { create(:admin) }
+
+      it 'returns all accessible groups including with admin project creation level' do
+        expect(result).to match_array([
+          group_where_direct_owner,
+          subgroup_of_group_where_direct_owner,
+          group_where_direct_maintainer,
+          shared_with_group_where_direct_owner_as_owner,
+          shared_with_group_where_direct_owner_as_maintainer,
+          subgroup_of_shared_with_group_where_direct_owner_as_maintainer,
+          group_where_direct_owner_with_admin_project_creation_level
+        ])
+      end
+    end
   end
 end
diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb
index 215665a9b585b22afbbe41933de1baa38074c279..7ff9af46645c050541f96db86eeb9581c34d4302 100644
--- a/spec/models/group_spec.rb
+++ b/spec/models/group_spec.rb
@@ -5,10 +5,16 @@
 RSpec.describe Group, feature_category: :groups_and_projects do
   include ReloadHelpers
   include StubGitlabCalls
+  include AdminModeHelper
   using RSpec::Parameterized::TableSyntax
 
   let!(:group) { create(:group) }
 
+  let(:developer_access) { Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS }
+  let(:maintainer_access) { Gitlab::Access::MAINTAINER_PROJECT_ACCESS }
+  let(:admin_access) { Gitlab::Access::ADMINISTRATOR_PROJECT_ACCESS }
+  let(:no_one_access) { Gitlab::Access::NO_ONE_PROJECT_ACCESS }
+
   describe 'associations' do
     it { is_expected.to have_many :projects }
     it { is_expected.to have_many(:all_group_members).dependent(:destroy) }
@@ -141,7 +147,7 @@
     end
 
     describe '#namespace_members_and_requesters' do
-      let_it_be(:group) { create(:group) }
+      let_it_be_with_reload(:group) { create(:group) }
       let_it_be(:requester) { create(:user) }
       let_it_be(:developer) { create(:user) }
       let_it_be(:invited_member) { create(:group_member, :invited, :owner, group: group) }
@@ -1207,8 +1213,6 @@
       subject { described_class.excluding_restricted_visibility_levels_for_user(user1) }
 
       context 'with table syntax' do
-        using RSpec::Parameterized::TableSyntax
-
         where(:restricted_visibility_levels, :expected_groups) do
           nil                                     | lazy { [private_group, internal_group, group] }
           []                                      | lazy { [private_group, internal_group, group] }
@@ -1241,32 +1245,39 @@
       let_it_be(:group_1) { create(:group, project_creation_level: Gitlab::Access::NO_ONE_PROJECT_ACCESS) }
       let_it_be(:group_2) { create(:group, project_creation_level: Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS) }
       let_it_be(:group_3) { create(:group, project_creation_level: Gitlab::Access::MAINTAINER_PROJECT_ACCESS) }
-      let_it_be(:group_4) { create(:group, project_creation_level: nil) }
-
-      it 'only includes groups where project creation is allowed' do
-        expect(described_class).to receive(:excluding_restricted_visibility_levels_for_user).and_call_original
-
-        result = described_class.project_creation_allowed(user1)
-
-        expect(result).to include(group_2, group_3, group_4)
-        expect(result).not_to include(group_1)
+      let_it_be(:group_4) { create(:group, project_creation_level: Gitlab::Access::ADMINISTRATOR_PROJECT_ACCESS) }
+      let_it_be(:group_5) { create(:group, project_creation_level: nil) } # `nil` inherits `default_project_creation`
+      let_it_be(:all_groups) { described_class.id_in([group_1, group_2, group_3, group_4, group_5]) }
+
+      where(:admin_user?, :admin_mode, :default_project_creation, :expected_groups) do
+        false | false | Gitlab::Access::NO_ONE_PROJECT_ACCESS               | lazy { [group_2, group_3] }
+        false | false | Gitlab::Access::MAINTAINER_PROJECT_ACCESS           | lazy { [group_2, group_3, group_5] }
+        false | false | Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS | lazy { [group_2, group_3, group_5] }
+        false | false | Gitlab::Access::ADMINISTRATOR_PROJECT_ACCESS        | lazy { [group_2, group_3] }
+        true  | false | Gitlab::Access::NO_ONE_PROJECT_ACCESS               | lazy { [group_2, group_3] }
+        true  | false | Gitlab::Access::MAINTAINER_PROJECT_ACCESS           | lazy { [group_2, group_3, group_5] }
+        true  | false | Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS | lazy { [group_2, group_3, group_5] }
+        true  | false | Gitlab::Access::ADMINISTRATOR_PROJECT_ACCESS        | lazy { [group_2, group_3] }
+        true  | true  | Gitlab::Access::NO_ONE_PROJECT_ACCESS               | lazy { [group_2, group_3, group_4] }
+        true  | true  | Gitlab::Access::MAINTAINER_PROJECT_ACCESS           | lazy { [group_2, group_3, group_4, group_5] }
+        true  | true  | Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS | lazy { [group_2, group_3, group_4, group_5] }
+        true  | true  | Gitlab::Access::ADMINISTRATOR_PROJECT_ACCESS        | lazy { [group_2, group_3, group_4, group_5] }
       end
 
-      context 'when the application_setting is set to `NO_ONE_PROJECT_ACCESS`' do
+      with_them do
+        let(:user) { admin_user? ? create(:admin) : create(:user) }
+
         before do
-          stub_application_setting(default_project_creation: Gitlab::Access::NO_ONE_PROJECT_ACCESS)
+          enable_admin_mode!(user) if admin_mode
+          stub_application_setting(default_project_creation: default_project_creation)
         end
 
-        it 'only includes groups where project creation is allowed' do
+        it 'returns expected groups' do
           expect(described_class).to receive(:excluding_restricted_visibility_levels_for_user).and_call_original
 
-          result = described_class.project_creation_allowed(user1)
-
-          expect(result).to include(group_2, group_3)
+          result = all_groups.project_creation_allowed(user)
 
-          # group_4 won't be included because it has `project_creation_level: nil`,
-          # and that means it behaves like the value of the application_setting will inherited.
-          expect(result).not_to include(group_1, group_4)
+          expect(result).to match_array(expected_groups)
         end
       end
     end
@@ -1443,6 +1454,65 @@
     end
   end
 
+  describe '.project_creation_levels_for_user' do
+    where(:admin_user?, :admin_mode, :default_project_creation, :expected_levels) do
+      false | false | no_one_access     | lazy { [developer_access, maintainer_access] }
+      false | false | admin_access      | lazy { [developer_access, maintainer_access] }
+      false | false | maintainer_access | lazy { [developer_access, maintainer_access, nil] }
+      false | false | developer_access  | lazy { [developer_access, maintainer_access, nil] }
+      true  | false | no_one_access     | lazy { [developer_access, maintainer_access] }
+      true  | false | admin_access      | lazy { [developer_access, maintainer_access] }
+      true  | false | maintainer_access | lazy { [developer_access, maintainer_access, nil] }
+      true  | false | developer_access  | lazy { [developer_access, maintainer_access, nil] }
+      true  | true  | no_one_access     | lazy { [developer_access, maintainer_access, admin_access] }
+      true  | true  | admin_access      | lazy { [developer_access, maintainer_access, admin_access, nil] }
+      true  | true  | maintainer_access | lazy { [developer_access, maintainer_access, admin_access, nil] }
+      true  | true  | developer_access  | lazy { [developer_access, maintainer_access, admin_access, nil] }
+    end
+
+    with_them do
+      let(:user) { admin_user? ? create(:admin) : create(:user) }
+
+      before do
+        stub_application_setting(default_project_creation: default_project_creation)
+        enable_admin_mode!(user) if admin_mode
+      end
+
+      it 'returns correct project creation levels' do
+        expect(described_class.project_creation_levels_for_user(user)).to match_array(expected_levels)
+      end
+    end
+  end
+
+  describe '.prevent_project_creation?' do
+    where(:admin_user?, :admin_mode, :project_creation_setting, :expected_result) do
+      false | false | lazy { no_one_access }     | true
+      false | false | lazy { admin_access }      | true
+      false | false | lazy { maintainer_access } | false
+      false | false | lazy { developer_access }  | false
+      true  | false | lazy { no_one_access }     | true
+      true  | false | lazy { admin_access }      | true
+      true  | false | lazy { maintainer_access } | false
+      true  | false | lazy { developer_access }  | false
+      true  | true  | lazy { no_one_access }     | true
+      true  | true  | lazy { admin_access }      | false
+      true  | true  | lazy { maintainer_access } | false
+      true  | true  | lazy { developer_access }  | false
+    end
+
+    with_them do
+      let(:user) { admin_user? ? create(:admin) : create(:user) }
+
+      before do
+        enable_admin_mode!(user) if admin_mode
+      end
+
+      subject { described_class.prevent_project_creation?(user, project_creation_setting) }
+
+      it { is_expected.to be(expected_result) }
+    end
+  end
+
   describe '#to_reference' do
     it 'returns a String reference to the object' do
       expect(group.to_reference).to eq "@#{group.name}"
diff --git a/spec/policies/group_policy_spec.rb b/spec/policies/group_policy_spec.rb
index 8eb243dc295de78062aa1b3024af68304bf35f41..b2dbe59241ebd28958c71de81a3e61b56ccd9267 100644
--- a/spec/policies/group_policy_spec.rb
+++ b/spec/policies/group_policy_spec.rb
@@ -576,123 +576,42 @@
   end
 
   context 'create_projects' do
-    context 'when group has no project creation level set' do
-      before do
-        group.update!(project_creation_level: nil)
-      end
-
-      context 'reporter' do
-        let(:current_user) { reporter }
-
-        it { is_expected.to be_disallowed(:create_projects) }
+    context 'without visibility levels restricted' do
+      where(:project_creation_level, :current_user, :create_projects_allowed?) do
+        nil                                                    | lazy { reporter }   | false
+        nil                                                    | lazy { developer }  | true
+        nil                                                    | lazy { maintainer } | true
+        nil                                                    | lazy { owner }      | true
+        nil                                                    | lazy { admin }      | true
+        ::Gitlab::Access::NO_ONE_PROJECT_ACCESS                | lazy { reporter }   | false
+        ::Gitlab::Access::NO_ONE_PROJECT_ACCESS                | lazy { developer }  | false
+        ::Gitlab::Access::NO_ONE_PROJECT_ACCESS                | lazy { maintainer } | false
+        ::Gitlab::Access::NO_ONE_PROJECT_ACCESS                | lazy { owner }      | false
+        ::Gitlab::Access::NO_ONE_PROJECT_ACCESS                | lazy { admin }      | false
+        ::Gitlab::Access::MAINTAINER_PROJECT_ACCESS            | lazy { reporter }   | false
+        ::Gitlab::Access::MAINTAINER_PROJECT_ACCESS            | lazy { developer }  | false
+        ::Gitlab::Access::MAINTAINER_PROJECT_ACCESS            | lazy { maintainer } | true
+        ::Gitlab::Access::MAINTAINER_PROJECT_ACCESS            | lazy { owner }      | true
+        ::Gitlab::Access::MAINTAINER_PROJECT_ACCESS            | lazy { admin }      | true
+        ::Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS  | lazy { reporter }   | false
+        ::Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS  | lazy { developer }  | true
+        ::Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS  | lazy { maintainer } | true
+        ::Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS  | lazy { owner }      | true
+        ::Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS  | lazy { admin }      | true
+        ::Gitlab::Access::ADMINISTRATOR_PROJECT_ACCESS         | lazy { reporter }   | false
+        ::Gitlab::Access::ADMINISTRATOR_PROJECT_ACCESS         | lazy { developer }  | false
+        ::Gitlab::Access::ADMINISTRATOR_PROJECT_ACCESS         | lazy { maintainer } | false
+        ::Gitlab::Access::ADMINISTRATOR_PROJECT_ACCESS         | lazy { owner }      | false
+        ::Gitlab::Access::ADMINISTRATOR_PROJECT_ACCESS         | lazy { admin }      | true
       end
 
-      context 'developer' do
-        let(:current_user) { developer }
-
-        it { is_expected.to be_allowed(:create_projects) }
-      end
-
-      context 'maintainer' do
-        let(:current_user) { maintainer }
-
-        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
-      before do
-        group.update!(project_creation_level: ::Gitlab::Access::NO_ONE_PROJECT_ACCESS)
-      end
-
-      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 'maintainer' do
-        let(:current_user) { maintainer }
-
-        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 maintainer only' do
-      before do
-        group.update!(project_creation_level: ::Gitlab::Access::MAINTAINER_PROJECT_ACCESS)
-      end
-
-      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 'maintainer' do
-        let(:current_user) { maintainer }
-
-        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 + maintainer' do
-      before do
-        group.update!(project_creation_level: ::Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS)
-      end
-
-      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 'maintainer' do
-        let(:current_user) { maintainer }
-
-        it { is_expected.to be_allowed(:create_projects) }
-      end
-
-      context 'owner' do
-        let(:current_user) { owner }
+      with_them do
+        before do
+          group.update!(project_creation_level: project_creation_level)
+          enable_admin_mode!(current_user) if current_user.admin?
+        end
 
-        it { is_expected.to be_allowed(:create_projects) }
+        it { is_expected.to(create_projects_allowed? ? be_allowed(:create_projects) : be_disallowed(:create_projects)) }
       end
     end