Commit f7c17fb2 authored by Etienne Baqué's avatar Etienne Baqué

Added DeployKeyAccess class

Added rspec accordingly.
Adjusted PushAccessLevel class accordingly too.
parent ebe76ca5
......@@ -18,6 +18,14 @@ class ProtectedBranch::PushAccessLevel < ApplicationRecord
end
end
def check_access(user)
if Feature.enabled?(:deploy_keys_on_protected_branches, project) && user && deploy_key.present?
return true if user.can?(:read_project, project) && enabled_deploy_key_for_user?(deploy_key, user)
end
super
end
private
def validate_deploy_key_membership
......@@ -27,4 +35,9 @@ class ProtectedBranch::PushAccessLevel < ApplicationRecord
self.errors.add(:deploy_key, 'is not enabled for this project')
end
end
def enabled_deploy_key_for_user?(deploy_key, user)
DeployKey.with_write_access_for_project(protected_branch.project, deploy_key: deploy_key).any? &&
deploy_key.user_id == user.id
end
end
# frozen_string_literal: true
module Gitlab
class DeployKeyAccess < UserAccess
def initialize(deploy_key, container: nil, push_ability: :push_code)
@deploy_key = deploy_key
@user = deploy_key.user
@container = container
@push_ability = push_ability
end
private
attr_reader :deploy_key
def protected_tag_accessible_to?(ref, action:)
assert_project!
true
end
def can_collaborate?(ref)
assert_project!
project_has_active_user_keys?
end
def project_has_active_user_keys?
user.can?(:read_project, project) && DeployKey.with_write_access_for_project(project).id_in(deploy_key.id).exists?
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::DeployKeyAccess do
let_it_be(:user) { create(:user) }
let_it_be(:deploy_key) { create(:deploy_key, user: user) }
let(:project) { create(:project, :repository) }
let(:protected_branch) { create(:protected_branch, :no_one_can_push, project: project) }
let(:access) { described_class.new(deploy_key, container: project) }
before do
project.add_guest(user)
allow(project).to receive(:branch_allows_collaboration?).and_return(false)
stub_feature_flags(deploy_keys_on_protected_branches: true)
end
context 'push tag that matches a protected tag pattern via a deploy key' do
it 'still pushes that tag' do
create(:deploy_keys_project, :write_access, project: project, deploy_key: deploy_key)
create(:protected_tag, project: project, name: 'v*')
expect(access.can_create_tag?('v0.1.2')).to be_truthy
end
end
context 'push to a protected branch of this project via a deploy key' do
before do
create(:deploy_keys_project, :write_access, project: protected_branch.project, deploy_key: deploy_key)
create(:protected_branch_push_access_level, protected_branch: protected_branch, deploy_key: deploy_key)
end
context 'when the project has active deploy key owned by this user' do
it 'returns true' do
expect(access.can_push_to_branch?(protected_branch.name)).to be_truthy
end
end
context 'when the project has active deploy keys, but not by this user' do
let(:deploy_key) { create(:deploy_key, user: create(:user)) }
it 'returns false' do
expect(access.can_push_to_branch?(protected_branch.name)).to be_falsey
end
end
context 'when there is another branch no one can push to' do
let(:another_branch) { create(:protected_branch, :no_one_can_push, name: 'another_branch', project: project) }
it 'returns false when trying to push to that other branch' do
expect(access.can_push_to_branch?(another_branch.name)).to be_falsey
end
context 'and the deploy key added for the first protected branch is also added for this other branch' do
it 'returns true for both protected branches' do
create(:protected_branch_push_access_level, protected_branch: another_branch, deploy_key: deploy_key)
expect(access.can_push_to_branch?(protected_branch.name)).to be_truthy
expect(access.can_push_to_branch?(another_branch.name)).to be_truthy
end
end
end
end
end
......@@ -34,4 +34,34 @@ RSpec.describe ProtectedBranch::PushAccessLevel do
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) }
before do
project.add_guest(user)
stub_feature_flags(deploy_keys_on_protected_branches: true)
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
it 'is true' do
deploy_key.deploy_keys_projects.last.update!(can_push: true)
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
it 'is false' do
expect(push_access_level.check_access(user)).to be_falsey
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