diff --git a/app/models/concerns/protected_ref_access.rb b/app/models/concerns/protected_ref_access.rb
index c1c670db5433f63d802792d9480ee89c68f482ec..ce520f946140fb407252f09dcb05f1829f164663 100644
--- a/app/models/concerns/protected_ref_access.rb
+++ b/app/models/concerns/protected_ref_access.rb
@@ -29,14 +29,23 @@ def allowed_access_levels
     def humanize(access_level)
       human_access_levels[access_level]
     end
+
+    def non_role_types
+      []
+    end
   end
 
   included do
     scope :maintainer, -> { where(access_level: Gitlab::Access::MAINTAINER) }
     scope :developer, -> { where(access_level: Gitlab::Access::DEVELOPER) }
-    scope :for_role, -> { where(user_id: nil, group_id: nil) }
-
-    validates :access_level, presence: true, if: :role?, inclusion: { in: allowed_access_levels }
+    scope :for_role, -> { non_role_types.present? ? where.missing(*non_role_types) : all }
+
+    protected_ref_fk = "#{module_parent.model_name.singular}_id"
+    validates :access_level,
+      presence: true,
+      inclusion: { in: allowed_access_levels },
+      uniqueness: { scope: protected_ref_fk, conditions: -> { for_role } },
+      if: :role?
   end
 
   def humanize
diff --git a/app/models/concerns/protected_ref_deploy_key_access.rb b/app/models/concerns/protected_ref_deploy_key_access.rb
new file mode 100644
index 0000000000000000000000000000000000000000..a62cce1368d5ce33bddd4905fe7cbade3576248b
--- /dev/null
+++ b/app/models/concerns/protected_ref_deploy_key_access.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+module ProtectedRefDeployKeyAccess
+  extend ActiveSupport::Concern
+
+  included do
+    belongs_to :deploy_key
+
+    protected_ref_fk = "#{module_parent.model_name.singular}_id"
+    validates :deploy_key_id, uniqueness: { scope: protected_ref_fk, allow_nil: true }
+    validate :validate_deploy_key_membership
+  end
+
+  class_methods do
+    def non_role_types
+      super << :deploy_key
+    end
+  end
+
+  def type
+    return :deploy_key if deploy_key.present?
+
+    super
+  end
+
+  def humanize
+    return "Deploy key" if deploy_key.present?
+
+    super
+  end
+
+  def check_access(current_user)
+    super do
+      break enabled_deploy_key_for_user?(current_user) if deploy_key?
+
+      yield if block_given?
+    end
+  end
+
+  private
+
+  def deploy_key?
+    type == :deploy_key
+  end
+
+  def validate_deploy_key_membership
+    return if deploy_key.nil? || deploy_key_has_write_access_to_project?
+
+    errors.add(:deploy_key, 'is not enabled for this project')
+  end
+
+  def enabled_deploy_key_for_user?(current_user)
+    current_user.can?(:read_project, project) &&
+      deploy_key.user_id == current_user.id &&
+      deploy_key_has_write_access_to_project?
+  end
+
+  def deploy_key_has_write_access_to_project?
+    DeployKey.with_write_access_for_project(project, deploy_key: deploy_key).exists?
+  end
+end
diff --git a/app/models/protected_branch/push_access_level.rb b/app/models/protected_branch/push_access_level.rb
index c86ca5723fa39f989c70d702597d621c800a36a8..53cec0c551101b6815192aa9f0a0dd319cabca0f 100644
--- a/app/models/protected_branch/push_access_level.rb
+++ b/app/models/protected_branch/push_access_level.rb
@@ -3,49 +3,7 @@
 class ProtectedBranch::PushAccessLevel < ApplicationRecord
   include Importable
   include ProtectedBranchAccess
+  include ProtectedRefDeployKeyAccess
   # default value for the access_level column
   GITLAB_DEFAULT_ACCESS_LEVEL = Gitlab::Access::MAINTAINER
-
-  belongs_to :deploy_key
-
-  validates :access_level, uniqueness: { scope: :protected_branch_id, if: :role?,
-                                         conditions: -> { where(user_id: nil, group_id: nil, deploy_key_id: nil) } }
-  validates :deploy_key_id, uniqueness: { scope: :protected_branch_id, allow_nil: true }
-  validate :validate_deploy_key_membership
-
-  def type
-    if self.deploy_key.present?
-      :deploy_key
-    else
-      super
-    end
-  end
-
-  def humanize
-    return "Deploy key" if deploy_key.present?
-
-    super
-  end
-
-  def check_access(user)
-    if user && deploy_key.present?
-      return user.can?(:read_project, project) && enabled_deploy_key_for_user?(deploy_key, user)
-    end
-
-    super
-  end
-
-  private
-
-  def validate_deploy_key_membership
-    return unless deploy_key
-
-    unless project.deploy_keys_projects.where(deploy_key: deploy_key).exists?
-      self.errors.add(:deploy_key, 'is not enabled for this project')
-    end
-  end
-
-  def enabled_deploy_key_for_user?(deploy_key, user)
-    deploy_key.user_id == user.id && DeployKey.with_write_access_for_project(protected_branch.project, deploy_key: deploy_key).any?
-  end
 end
diff --git a/app/models/protected_tag/create_access_level.rb b/app/models/protected_tag/create_access_level.rb
index 5837f3a5afb88f270388dbae478c042faa07384d..0eff99241536ab6436d0bcc3e2f8669bf6e4a7e8 100644
--- a/app/models/protected_tag/create_access_level.rb
+++ b/app/models/protected_tag/create_access_level.rb
@@ -3,48 +3,5 @@
 class ProtectedTag::CreateAccessLevel < ApplicationRecord
   include Importable
   include ProtectedTagAccess
-
-  belongs_to :deploy_key
-
-  validates :access_level, uniqueness: { scope: :protected_tag_id, if: :role?,
-                                         conditions: -> { where(user_id: nil, group_id: nil, deploy_key_id: nil) } }
-  validates :deploy_key_id, uniqueness: { scope: :protected_tag_id, allow_nil: true }
-  validate :validate_deploy_key_membership
-
-  def type
-    return :deploy_key if deploy_key.present?
-
-    super
-  end
-
-  def humanize
-    return "Deploy key" if deploy_key.present?
-
-    super
-  end
-
-  def check_access(current_user)
-    super do
-      break enabled_deploy_key_for_user?(current_user) if deploy_key?
-    end
-  end
-
-  private
-
-  def deploy_key?
-    type == :deploy_key
-  end
-
-  def validate_deploy_key_membership
-    return unless deploy_key
-    return if project.deploy_keys_projects.where(deploy_key: deploy_key).exists?
-
-    errors.add(:deploy_key, 'is not enabled for this project')
-  end
-
-  def enabled_deploy_key_for_user?(current_user)
-    current_user.can?(:read_project, project) &&
-      deploy_key.user_id == current_user.id &&
-      DeployKey.with_write_access_for_project(protected_tag.project, deploy_key: deploy_key).any?
-  end
+  include ProtectedRefDeployKeyAccess
 end
diff --git a/doc/user/project/deploy_keys/index.md b/doc/user/project/deploy_keys/index.md
index 60cad9d6fe97031b2f9bb1e73072c32050672d81..84567c8de416b7db7d2a3adcca3bc75bfe6bb8b5 100644
--- a/doc/user/project/deploy_keys/index.md
+++ b/doc/user/project/deploy_keys/index.md
@@ -127,6 +127,20 @@ To grant a public deploy key access to a project:
    1. In the key's row, select **Edit** (**{pencil}**).
    1. Select the **Grant write permissions to this key** checkbox.
 
+### Edit project access permissions of a deploy key
+
+Prerequisites:
+
+- You must have at least the Maintainer role for the project.
+
+To edit the project access permissions of a deploy key:
+
+1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your project.
+1. Select **Settings > Repository**.
+1. Expand **Deploy keys**.
+1. In the key's row, select **Edit** (**{pencil}**).
+1. Select or clear the **Grant write permissions to this key** checkbox.
+
 ## Revoke project access of a deploy key
 
 To revoke a deploy key's access to a project, you can disable it. Any service that relies on
@@ -158,8 +172,10 @@ What happens to the deploy key when it is disabled depends on the following:
 There are a few scenarios where a deploy key fails to push to a
 [protected branch](../protected_branches.md).
 
-- The owner associated to a deploy key does not have access to the protected branch.
 - The owner associated to a deploy key does not have [membership](../members/index.md) to the project of the protected branch.
+- The owner associated to a deploy key has [project membership permissions](../../../user/permissions.md#project-members-permissions) lower than required to **View project code**.
+- The deploy key does not have [read-write permissions for the project](#edit-project-access-permissions-of-a-deploy-key).
+- The deploy key has been [revoked](#revoke-project-access-of-a-deploy-key).
 - **No one** is selected in [the **Allowed to push and merge** section](../protected_branches.md#add-protection-to-existing-branches) of the protected branch.
 
 All deploy keys are associated to an account. Since the permissions for an account can change, this might lead to scenarios where a deploy key that was working is suddenly unable to push to a protected branch.
diff --git a/ee/app/models/concerns/ee/protected_ref_access.rb b/ee/app/models/concerns/ee/protected_ref_access.rb
index 4a6a406c8679deb3dd3015d8dd73ad6b3efad0ac..9f2dc86dfb7d81d8aafd3cf1ab5a1b187f78bd9b 100644
--- a/ee/app/models/concerns/ee/protected_ref_access.rb
+++ b/ee/app/models/concerns/ee/protected_ref_access.rb
@@ -19,11 +19,10 @@ module Scopes
         belongs_to :user
         belongs_to :group
 
-        protected_type = module_parent.model_name.singular
-        validates :group_id, uniqueness: { scope: protected_type, allow_nil: true }
-        validates :user_id, uniqueness: { scope: protected_type, allow_nil: true }
-        validates :access_level, uniqueness: { scope: protected_type, if: :role?,
-                                               conditions: -> { where(user_id: nil, group_id: nil) } }
+        with_options uniqueness: { scope: "#{module_parent.model_name.singular}_id", allow_nil: true } do
+          validates :group_id
+          validates :user_id
+        end
         validates :group, :user, absence: true,
           unless: -> { importing? || protected_refs_for_users_required_and_available }
 
@@ -37,6 +36,12 @@ module Scopes
       end
     end
 
+    class_methods do
+      def non_role_types
+        super.concat(%i[user group])
+      end
+    end
+
     override :type
     def type
       return :user if user.present?
diff --git a/spec/models/protected_branch/push_access_level_spec.rb b/spec/models/protected_branch/push_access_level_spec.rb
index e56ff2241b1715c9dab1d6f4c53fb020f4503047..05e10fd6763d4514f6d2face36d52f1f024be512 100644
--- a/spec/models/protected_branch/push_access_level_spec.rb
+++ b/spec/models/protected_branch/push_access_level_spec.rb
@@ -4,81 +4,6 @@
 
 RSpec.describe ProtectedBranch::PushAccessLevel, feature_category: :source_code_management do
   include_examples 'protected branch access'
+  include_examples 'protected ref deploy_key access'
   include_examples 'protected ref access allowed_access_levels'
-
-  describe 'associations' do
-    it { is_expected.to belong_to(:deploy_key) }
-  end
-
-  describe 'validations' do
-    it 'is not valid when a record exists with the same access level' do
-      protected_branch = create(:protected_branch)
-      create(:protected_branch_push_access_level, protected_branch: protected_branch)
-      level = build(:protected_branch_push_access_level, protected_branch: protected_branch)
-
-      expect(level).to be_invalid
-    end
-
-    it 'is not valid when a record exists with the same access level' do
-      protected_branch = create(:protected_branch)
-      deploy_key = create(:deploy_key, projects: [protected_branch.project])
-      create(:protected_branch_push_access_level, protected_branch: protected_branch, deploy_key: deploy_key)
-      level = build(:protected_branch_push_access_level, protected_branch: protected_branch, deploy_key: deploy_key)
-
-      expect(level).to be_invalid
-    end
-
-    it 'checks that a deploy key is enabled for the same project as the protected branch\'s' do
-      level = build(:protected_branch_push_access_level, deploy_key: create(:deploy_key))
-
-      expect { level.save! }.to raise_error(ActiveRecord::RecordInvalid)
-      expect(level.errors.full_messages).to contain_exactly('Deploy key is not enabled for this project')
-    end
-  end
-
-  describe '#check_access' do
-    let_it_be(:project) { create(:project) }
-    let_it_be(:protected_branch) { create(:protected_branch, :no_one_can_push, project: project) }
-    let_it_be(:user) { create(:user) }
-    let_it_be(:deploy_key) { create(:deploy_key, user: user) }
-
-    let!(:deploy_keys_project) { create(:deploy_keys_project, project: project, deploy_key: deploy_key, can_push: can_push) }
-    let(:can_push) { true }
-
-    before_all do
-      project.add_maintainer(user)
-    end
-
-    context 'when this push_access_level is tied to a deploy key' do
-      let(:push_access_level) { create(:protected_branch_push_access_level, protected_branch: protected_branch, deploy_key: deploy_key) }
-
-      context 'when the deploy key is among the active keys for this project' do
-        specify do
-          expect(push_access_level.check_access(user)).to be_truthy
-        end
-      end
-
-      context 'when the deploy key is not among the active keys of this project' do
-        let(:can_push) { false }
-
-        it 'is false' do
-          expect(push_access_level.check_access(user)).to be_falsey
-        end
-      end
-    end
-  end
-
-  describe '#type' do
-    let(:push_level_access) { build(:protected_branch_push_access_level) }
-
-    it 'returns :deploy_key when a deploy key is tied to the protected branch' do
-      push_level_access.deploy_key = create(:deploy_key)
-
-      expect(push_level_access.type).to eq(:deploy_key)
-    end
-
-    it 'returns :role by default' do
-      expect(push_level_access.type).to eq(:role)
-    end
-  end
 end
diff --git a/spec/models/protected_tag/create_access_level_spec.rb b/spec/models/protected_tag/create_access_level_spec.rb
index 8eeccdc9b342e97f3acc62699d6eaa62bc5524a9..d795399060e3da2fbceebb9dd69cc134448db58f 100644
--- a/spec/models/protected_tag/create_access_level_spec.rb
+++ b/spec/models/protected_tag/create_access_level_spec.rb
@@ -4,134 +4,6 @@
 
 RSpec.describe ProtectedTag::CreateAccessLevel, feature_category: :source_code_management do
   include_examples 'protected tag access'
+  include_examples 'protected ref deploy_key access'
   include_examples 'protected ref access allowed_access_levels'
-
-  describe 'associations' do
-    it { is_expected.to belong_to(:deploy_key) }
-  end
-
-  describe 'validations', :aggregate_failures do
-    let_it_be(:protected_tag) { create(:protected_tag) }
-
-    context 'when deploy key enabled for the project' do
-      let(:deploy_key) { create(:deploy_key, projects: [protected_tag.project]) }
-
-      it 'is valid' do
-        level = build(:protected_tag_create_access_level, protected_tag: protected_tag, deploy_key: deploy_key)
-
-        expect(level).to be_valid
-      end
-    end
-
-    context 'when a record exists with the same access level' do
-      before do
-        create(:protected_tag_create_access_level, protected_tag: protected_tag)
-      end
-
-      it 'is not valid' do
-        level = build(:protected_tag_create_access_level, protected_tag: protected_tag)
-
-        expect(level).to be_invalid
-        expect(level.errors.full_messages).to include('Access level has already been taken')
-      end
-    end
-
-    context 'when a deploy key already added for this access level' do
-      let!(:create_access_level) do
-        create(:protected_tag_create_access_level, protected_tag: protected_tag, deploy_key: deploy_key)
-      end
-
-      let(:deploy_key) { create(:deploy_key, projects: [protected_tag.project]) }
-
-      it 'is not valid' do
-        level = build(:protected_tag_create_access_level, protected_tag: protected_tag, deploy_key: deploy_key)
-
-        expect(level).to be_invalid
-        expect(level.errors.full_messages).to contain_exactly('Deploy key has already been taken')
-      end
-    end
-
-    context 'when deploy key is not enabled for the project' do
-      let(:create_access_level) do
-        build(:protected_tag_create_access_level, protected_tag: protected_tag, deploy_key: create(:deploy_key))
-      end
-
-      it 'returns an error' do
-        expect(create_access_level).to be_invalid
-        expect(create_access_level.errors.full_messages).to contain_exactly(
-          'Deploy key is not enabled for this project'
-        )
-      end
-    end
-  end
-
-  describe '#check_access' do
-    let_it_be(:project) { create(:project) }
-    let_it_be(:protected_tag) { create(:protected_tag, :no_one_can_create, project: project) }
-    let_it_be(:user) { create(:user) }
-    let_it_be(:deploy_key) { create(:deploy_key, user: user) }
-
-    let!(:deploy_keys_project) do
-      create(:deploy_keys_project, project: project, deploy_key: deploy_key, can_push: can_push)
-    end
-
-    let(:create_access_level) { protected_tag.create_access_levels.first }
-    let(:can_push) { true }
-
-    before_all do
-      project.add_maintainer(user)
-    end
-
-    it { expect(create_access_level.check_access(user)).to be_falsey }
-
-    context 'when this create_access_level is tied to a deploy key' do
-      let(:create_access_level) do
-        create(:protected_tag_create_access_level, protected_tag: protected_tag, deploy_key: deploy_key)
-      end
-
-      context 'when the deploy key is among the active keys for this project' do
-        it { expect(create_access_level.check_access(user)).to be_truthy }
-      end
-
-      context 'when user is missing' do
-        it { expect(create_access_level.check_access(nil)).to be_falsey }
-      end
-
-      context 'when deploy key does not belong to the user' do
-        let(:another_user) { create(:user) }
-
-        it { expect(create_access_level.check_access(another_user)).to be_falsey }
-      end
-
-      context 'when user cannot access the project' do
-        before do
-          allow(user).to receive(:can?).with(:read_project, project).and_return(false)
-        end
-
-        it { expect(create_access_level.check_access(user)).to be_falsey }
-      end
-
-      context 'when the deploy key is not among the active keys of this project' do
-        let(:can_push) { false }
-
-        it { expect(create_access_level.check_access(user)).to be_falsey }
-      end
-    end
-  end
-
-  describe '#type' do
-    let(:create_access_level) { build(:protected_tag_create_access_level) }
-
-    it 'returns :role by default' do
-      expect(create_access_level.type).to eq(:role)
-    end
-
-    context 'when a deploy key is tied to the protected branch' do
-      let(:create_access_level) { build(:protected_tag_create_access_level, deploy_key: build(:deploy_key)) }
-
-      it 'returns :deploy_key' do
-        expect(create_access_level.type).to eq(:deploy_key)
-      end
-    end
-  end
 end
diff --git a/spec/support/shared_examples/models/concerns/protected_ref_access_examples.rb b/spec/support/shared_examples/models/concerns/protected_ref_access_examples.rb
index 4753d7a4556ebcc4afcd4c4ed5ef64bae62a124b..0e9200f1fd9346218b29aca712dbbcc881b2c91c 100644
--- a/spec/support/shared_examples/models/concerns/protected_ref_access_examples.rb
+++ b/spec/support/shared_examples/models/concerns/protected_ref_access_examples.rb
@@ -6,16 +6,34 @@
   let_it_be(:project) { create(:project) }
   let_it_be(:protected_ref) { create(association, project: project) } # rubocop:disable Rails/SaveBang
 
-  it { is_expected.to validate_inclusion_of(:access_level).in_array(described_class.allowed_access_levels) }
+  describe 'validations' do
+    subject { build(described_class.model_name.singular) }
 
-  it { is_expected.to validate_presence_of(:access_level) }
+    context 'when role?' do
+      it { is_expected.to validate_inclusion_of(:access_level).in_array(described_class.allowed_access_levels) }
 
-  context 'when not role?' do
-    before do
-      allow(subject).to receive(:role?).and_return(false)
+      it { is_expected.to validate_presence_of(:access_level) }
+
+      it do
+        is_expected.to validate_uniqueness_of(:access_level)
+          .scoped_to("#{described_class.module_parent.model_name.singular}_id")
+      end
     end
 
-    it { is_expected.not_to validate_presence_of(:access_level) }
+    context 'when not role?' do
+      before do
+        allow(subject).to receive(:role?).and_return(false)
+      end
+
+      it { is_expected.not_to validate_presence_of(:access_level) }
+
+      it { is_expected.not_to validate_inclusion_of(:access_level).in_array(described_class.allowed_access_levels) }
+
+      it do
+        is_expected.not_to validate_uniqueness_of(:access_level)
+          .scoped_to("#{described_class.module_parent.model_name.singular}_id")
+      end
+    end
   end
 
   describe '::human_access_levels' do
diff --git a/spec/support/shared_examples/models/concerns/protected_ref_deploy_key_access_examples.rb b/spec/support/shared_examples/models/concerns/protected_ref_deploy_key_access_examples.rb
new file mode 100644
index 0000000000000000000000000000000000000000..f2e79dc377b63ad4ce3b9d2f66a79d27ac25fba4
--- /dev/null
+++ b/spec/support/shared_examples/models/concerns/protected_ref_deploy_key_access_examples.rb
@@ -0,0 +1,132 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'protected ref deploy_key access' do
+  let_it_be(:described_instance) { described_class.model_name.singular }
+  let_it_be(:protected_ref_name) { described_class.module_parent.model_name.singular }
+  let_it_be(:project) { create(:project) }
+  let_it_be(:protected_ref) { create(protected_ref_name, project: project) } # rubocop:disable Rails/SaveBang
+
+  describe 'associations' do
+    it { is_expected.to belong_to(:deploy_key) }
+  end
+
+  describe 'validations' do
+    context 'when deploy_key?' do
+      context 'when deploy key enabled for the project' do
+        let(:deploy_key) do
+          create(:deploy_keys_project, :write_access, project: project).deploy_key
+        end
+
+        it 'is valid' do
+          level = build(described_instance, protected_ref_name => protected_ref, deploy_key: deploy_key)
+
+          expect(level).to be_valid
+        end
+      end
+
+      context 'when a deploy key already added for this access level' do
+        let(:deploy_key) { create(:deploy_keys_project, :write_access, project: project).deploy_key }
+
+        before do
+          create(described_instance, protected_ref_name => protected_ref, deploy_key: deploy_key)
+        end
+
+        subject(:access_level) do
+          build(described_instance, protected_ref_name => protected_ref, deploy_key: deploy_key)
+        end
+
+        it 'is not valid', :aggregate_failures do
+          is_expected.to be_invalid
+          expect(access_level.errors.full_messages).to contain_exactly('Deploy key has already been taken')
+        end
+      end
+
+      context 'when deploy key is not enabled for the project' do
+        subject(:access_level) do
+          build(described_instance, protected_ref_name => protected_ref, deploy_key: create(:deploy_key))
+        end
+
+        it 'is not valid', :aggregate_failures do
+          is_expected.to be_invalid
+          expect(access_level.errors.full_messages).to contain_exactly('Deploy key is not enabled for this project')
+        end
+      end
+
+      context 'when deploy key is not active for the project' do
+        subject(:access_level) do
+          deploy_key = create(:deploy_keys_project, :readonly_access, project: project).deploy_key
+          build(described_instance, protected_ref_name => protected_ref, deploy_key: deploy_key)
+        end
+
+        it 'is not valid', :aggregate_failures do
+          is_expected.to be_invalid
+          expect(access_level.errors.full_messages).to contain_exactly('Deploy key is not enabled for this project')
+        end
+      end
+    end
+  end
+
+  describe '#check_access' do
+    let_it_be(:user) { create(:user) }
+    let_it_be(:deploy_key) { create(:deploy_key, user: user) }
+    let_it_be(:deploy_keys_project) do
+      create(:deploy_keys_project, :write_access, project: project, deploy_key: deploy_key)
+    end
+
+    before_all do
+      project.add_maintainer(user)
+    end
+
+    context "when this #{described_class.model_name.singular} is tied to a deploy key" do
+      let!(:access_level) do
+        create(described_instance, protected_ref_name => protected_ref, deploy_key: deploy_key)
+      end
+
+      context 'when the deploy key is among the active keys for this project' do
+        it { expect(access_level.check_access(user)).to be_truthy }
+      end
+
+      context 'when user is missing' do
+        it { expect(access_level.check_access(nil)).to be_falsey }
+      end
+
+      context 'when deploy key does not belong to the user' do
+        let(:another_user) { create(:user) }
+
+        it { expect(access_level.check_access(another_user)).to be_falsey }
+      end
+
+      context 'when user cannot access the project' do
+        before do
+          allow(user).to receive(:can?).with(:read_project, project).and_return(false)
+        end
+
+        it { expect(access_level.check_access(user)).to be_falsey }
+      end
+
+      context 'when the deploy key is not among the active keys of this project' do
+        before do
+          deploy_keys_project.update!(can_push: false)
+        end
+
+        after do
+          deploy_keys_project.update!(can_push: true)
+        end
+
+        it { expect(access_level.check_access(user)).to be_falsey }
+      end
+    end
+  end
+
+  describe '#type' do
+    let(:access_level) { build(described_instance) }
+
+    context 'when deploy_key?' do
+      let(:access_level) { build(described_instance, deploy_key: build(:deploy_key)) }
+
+      it 'returns :deploy_key' do
+        expect(access_level.type).to eq(:deploy_key)
+      end
+    end
+  end
+end