Commit 6cf07811 authored by Timothy Andrew's avatar Timothy Andrew Committed by Alfredo Sumaran

A protected branch can only have a single access level of a given type.

1. A validation restricts a protected branch so it can only have a
   single access level for a given role or user.

2. More context:

    - https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/581#note_14051822
    - https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/581#note_14052756
    - https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/581#note_14056066
    - https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/581#note_14058676
parent fb8dffb3
module ProtectedBranchAccess module ProtectedBranchAccess
extend ActiveSupport::Concern extend ActiveSupport::Concern
included do
validates_uniqueness_of :user_id, scope: :protected_branch, allow_nil: true
validates_uniqueness_of :access_level, scope: :protected_branch, unless: :user_id?
end
def type def type
if self.user.present? if self.user.present?
:user :user
......
FactoryGirl.define do
factory :protected_branch_merge_access_level, class: ProtectedBranch::MergeAccessLevel do
user nil
protected_branch
access_level { Gitlab::Access::MASTER }
end
end
FactoryGirl.define do
factory :protected_branch_push_access_level, class: ProtectedBranch::PushAccessLevel do
user nil
protected_branch
access_level { Gitlab::Access::MASTER }
end
end
...@@ -7,6 +7,45 @@ describe ProtectedBranch, models: true do ...@@ -7,6 +7,45 @@ describe ProtectedBranch, models: true do
it { is_expected.to belong_to(:project) } it { is_expected.to belong_to(:project) }
end end
describe "Uniqueness validations" do
[ProtectedBranch::MergeAccessLevel, ProtectedBranch::PushAccessLevel].each do |access_level_class|
let(:factory_name) { access_level_class.to_s.underscore.sub('/', '_').to_sym }
let(:association_name) { access_level_class.to_s.underscore.sub('protected_branch/', '').pluralize.to_sym }
human_association_name = access_level_class.to_s.underscore.humanize.sub('Protected branch/', '')
it "allows a single #{human_association_name} for a role (per protected branch)" do
first_protected_branch = create(:protected_branch, :remove_default_access_levels)
second_protected_branch = create(:protected_branch, :remove_default_access_levels)
first_protected_branch.send(association_name) << build(factory_name, access_level: Gitlab::Access::MASTER)
second_protected_branch.send(association_name) << build(factory_name, access_level: Gitlab::Access::MASTER)
expect(first_protected_branch).to be_valid
expect(second_protected_branch).to be_valid
first_protected_branch.send(association_name) << build(factory_name, access_level: Gitlab::Access::MASTER)
expect(first_protected_branch).to be_invalid
expect(first_protected_branch.errors.full_messages.first).to match("access level has already been taken")
end
it "allows a single #{human_association_name} for a user (per protected branch)" do
user = create(:user)
first_protected_branch = create(:protected_branch, :remove_default_access_levels)
second_protected_branch = create(:protected_branch, :remove_default_access_levels)
first_protected_branch.send(association_name) << build(factory_name, user: user)
second_protected_branch.send(association_name) << build(factory_name, user: user)
expect(first_protected_branch).to be_valid
expect(second_protected_branch).to be_valid
first_protected_branch.send(association_name) << build(factory_name, user: user)
expect(first_protected_branch).to be_invalid
expect(first_protected_branch.errors.full_messages.first).to match("user has already been taken")
end
end
end
describe "Mass assignment" do describe "Mass assignment" do
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