branch_check_spec.rb 8.0 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
# frozen_string_literal: true

require 'spec_helper'

describe Gitlab::Checks::BranchCheck do
  include_context 'change access checks context'

  describe '#validate!' do
    it 'does not raise any error' do
      expect { subject.validate! }.not_to raise_error
    end

    context 'trying to delete the default branch' do
      let(:newrev) { '0000000000000000000000000000000000000000' }
      let(:ref) { 'refs/heads/master' }

      it 'raises an error' do
18
        expect { subject.validate! }.to raise_error(Gitlab::GitAccess::ForbiddenError, 'The default branch of a project cannot be deleted.')
19 20 21
      end
    end

22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
    context "prohibited branches check" do
      it "prohibits 40-character hexadecimal branch names" do
        allow(subject).to receive(:branch_name).and_return("267208abfe40e546f5e847444276f7d43a39503e")

        expect { subject.validate! }.to raise_error(Gitlab::GitAccess::ForbiddenError, "You cannot create a branch with a 40-character hexadecimal branch name.")
      end

      it "doesn't prohibit a nested hexadecimal in a branch name" do
        allow(subject).to receive(:branch_name).and_return("fix-267208abfe40e546f5e847444276f7d43a39503e")

        expect { subject.validate! }.not_to raise_error
      end

      context "the feature flag is disabled" do
        it "doesn't prohibit a 40-character hexadecimal branch name" do
          stub_feature_flags(prohibit_hexadecimal_branch_names: false)
          allow(subject).to receive(:branch_name).and_return("267208abfe40e546f5e847444276f7d43a39503e")

          expect { subject.validate! }.not_to raise_error
        end
      end
    end

45 46 47 48 49 50 51 52 53
    context 'protected branches check' do
      before do
        allow(ProtectedBranch).to receive(:protected?).with(project, 'master').and_return(true)
        allow(ProtectedBranch).to receive(:protected?).with(project, 'feature').and_return(true)
      end

      it 'raises an error if the user is not allowed to do forced pushes to protected branches' do
        expect(Gitlab::Checks::ForcePush).to receive(:force_push?).and_return(true)

54
        expect { subject.validate! }.to raise_error(Gitlab::GitAccess::ForbiddenError, 'You are not allowed to force push code to a protected branch on this project.')
55 56 57
      end

      it 'raises an error if the user is not allowed to merge to protected branches' do
58 59 60
        expect_next_instance_of(Gitlab::Checks::MatchingMergeRequest) do |instance|
          expect(instance).to receive(:match?).and_return(true)
        end
61 62 63
        expect(user_access).to receive(:can_merge_to_branch?).and_return(false)
        expect(user_access).to receive(:can_push_to_branch?).and_return(false)

64
        expect { subject.validate! }.to raise_error(Gitlab::GitAccess::ForbiddenError, 'You are not allowed to merge code into protected branches on this project.')
65 66 67 68 69
      end

      it 'raises an error if the user is not allowed to push to protected branches' do
        expect(user_access).to receive(:can_push_to_branch?).and_return(false)

70
        expect { subject.validate! }.to raise_error(Gitlab::GitAccess::ForbiddenError, 'You are not allowed to push code to protected branches on this project.')
71 72 73 74 75
      end

      context 'when project repository is empty' do
        let(:project) { create(:project) }

P
Patrick Bajao 已提交
76 77 78 79 80 81 82 83
        context 'user is not allowed to push to protected branches' do
          before do
            allow(user_access)
              .to receive(:can_push_to_branch?)
              .and_return(false)
          end

          it 'raises an error' do
84
            expect { subject.validate! }.to raise_error(Gitlab::GitAccess::ForbiddenError, /Ask a project Owner or Maintainer to create a default branch/)
P
Patrick Bajao 已提交
85 86 87 88 89 90 91 92 93
          end
        end

        context 'user is allowed to push to protected branches' do
          before do
            allow(user_access)
              .to receive(:can_push_to_branch?)
              .and_return(true)
          end
94

P
Patrick Bajao 已提交
95 96 97
          it 'allows branch creation' do
            expect { subject.validate! }.not_to raise_error
          end
98 99 100
        end
      end

101 102 103 104
      context 'branch creation' do
        let(:oldrev) { '0000000000000000000000000000000000000000' }
        let(:ref) { 'refs/heads/feature' }

105
        context 'user can push to branch' do
106
          before do
107 108 109 110
            allow(user_access)
              .to receive(:can_push_to_branch?)
              .with('feature')
              .and_return(true)
111 112
          end

113 114
          it 'does not raise an error' do
            expect { subject.validate! }.not_to raise_error
115
          end
116
        end
117

118 119 120 121 122 123
        context 'user cannot push to branch' do
          before do
            allow(user_access)
              .to receive(:can_push_to_branch?)
              .with('feature')
              .and_return(false)
124 125
          end

126
          context 'user cannot merge to branch' do
127 128
            before do
              allow(user_access)
129
                .to receive(:can_merge_to_branch?)
130
                .with('feature')
131
                .and_return(false)
132 133
            end

134
            it 'raises an error' do
135
              expect { subject.validate! }.to raise_error(Gitlab::GitAccess::ForbiddenError, 'You are not allowed to create protected branches on this project.')
136 137 138
            end
          end

139
          context 'user can merge to branch' do
140 141
            before do
              allow(user_access)
142
                .to receive(:can_merge_to_branch?)
143
                .with('feature')
144 145 146 147 148 149
                .and_return(true)

              allow(project.repository)
                .to receive(:branch_names_contains_sha)
                .with(newrev)
                .and_return(['branch'])
150 151
            end

152
            context "newrev isn't in any protected branches" do
153
              before do
154 155 156
                allow(ProtectedBranch)
                  .to receive(:any_protected?)
                  .with(project, ['branch'])
157 158 159 160
                  .and_return(false)
              end

              it 'raises an error' do
161
                expect { subject.validate! }.to raise_error(Gitlab::GitAccess::ForbiddenError, 'You can only use an existing protected branch ref as the basis of a new protected branch.')
162 163 164
              end
            end

165
            context 'newrev is included in a protected branch' do
166
              before do
167 168 169
                allow(ProtectedBranch)
                  .to receive(:any_protected?)
                  .with(project, ['branch'])
170 171 172
                  .and_return(true)
              end

173 174
              context 'via web interface' do
                let(:protocol) { 'web' }
175

176 177
                it 'allows branch creation' do
                  expect { subject.validate! }.not_to raise_error
178 179 180
                end
              end

181 182
              context 'via SSH' do
                it 'raises an error' do
183
                  expect { subject.validate! }.to raise_error(Gitlab::GitAccess::ForbiddenError, 'You can only create protected branches using the web interface and API.')
184 185 186 187 188 189 190
                end
              end
            end
          end
        end
      end

191 192 193 194 195 196
      context 'branch deletion' do
        let(:newrev) { '0000000000000000000000000000000000000000' }
        let(:ref) { 'refs/heads/feature' }

        context 'if the user is not allowed to delete protected branches' do
          it 'raises an error' do
197
            expect { subject.validate! }.to raise_error(Gitlab::GitAccess::ForbiddenError, 'You are not allowed to delete protected branches from this project. Only a project maintainer or owner can delete a protected branch.')
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
          end
        end

        context 'if the user is allowed to delete protected branches' do
          before do
            project.add_maintainer(user)
          end

          context 'through the web interface' do
            let(:protocol) { 'web' }

            it 'allows branch deletion' do
              expect { subject.validate! }.not_to raise_error
            end
          end

          context 'over SSH or HTTP' do
            it 'raises an error' do
216
              expect { subject.validate! }.to raise_error(Gitlab::GitAccess::ForbiddenError, 'You can only delete protected branches using the web interface.')
217 218 219 220 221 222 223
            end
          end
        end
      end
    end
  end
end