application_setting_spec.rb 18.9 KB
Newer Older
1 2
require 'spec_helper'

3
describe ApplicationSetting do
4
  let(:setting) { described_class.create_from_defaults }
5

K
Kamil Trzcinski 已提交
6
  it { expect(setting).to be_valid }
7
  it { expect(setting.uuid).to be_present }
8
  it { expect(setting).to have_db_column(:auto_devops_enabled) }
9

R
Robert Speicher 已提交
10 11 12 13 14 15 16 17 18 19 20 21 22 23
  describe 'validations' do
    let(:http)  { 'http://example.com' }
    let(:https) { 'https://example.com' }
    let(:ftp)   { 'ftp://example.com' }

    it { is_expected.to allow_value(nil).for(:home_page_url) }
    it { is_expected.to allow_value(http).for(:home_page_url) }
    it { is_expected.to allow_value(https).for(:home_page_url) }
    it { is_expected.not_to allow_value(ftp).for(:home_page_url) }

    it { is_expected.to allow_value(nil).for(:after_sign_out_path) }
    it { is_expected.to allow_value(http).for(:after_sign_out_path) }
    it { is_expected.to allow_value(https).for(:after_sign_out_path) }
    it { is_expected.not_to allow_value(ftp).for(:after_sign_out_path) }
24

25 26 27 28 29 30 31 32
    describe 'disabled_oauth_sign_in_sources validations' do
      before do
        allow(Devise).to receive(:omniauth_providers).and_return([:github])
      end

      it { is_expected.to allow_value(['github']).for(:disabled_oauth_sign_in_sources) }
      it { is_expected.not_to allow_value(['test']).for(:disabled_oauth_sign_in_sources) }
    end
33

34
    describe 'default_artifacts_expire_in' do
35
      it 'sets an error if it cannot parse' do
36 37
        setting.update(default_artifacts_expire_in: 'a')

38
        expect_invalid
39 40
      end

41 42
      it 'sets an error if it is blank' do
        setting.update(default_artifacts_expire_in: ' ')
43

44
        expect_invalid
45 46
      end

47 48 49 50 51 52 53
      it 'sets the value if it is valid' do
        setting.update(default_artifacts_expire_in: '30 days')

        expect(setting).to be_valid
        expect(setting.default_artifacts_expire_in).to eq('30 days')
      end

54 55
      it 'sets the value if it is 0' do
        setting.update(default_artifacts_expire_in: '0')
56 57

        expect(setting).to be_valid
58 59 60 61 62 63
        expect(setting.default_artifacts_expire_in).to eq('0')
      end

      def expect_invalid
        expect(setting).to be_invalid
        expect(setting.errors.messages)
64
          .to have_key(:default_artifacts_expire_in)
65 66 67
      end
    end

68 69 70 71 72 73 74
    it { is_expected.to validate_presence_of(:max_attachment_size) }

    it do
      is_expected.to validate_numericality_of(:max_attachment_size)
        .only_integer
        .is_greater_than(0)
    end
75

76 77 78 79
    context 'key restrictions' do
      it 'supports all key types' do
        expect(described_class::SUPPORTED_KEY_TYPES).to contain_exactly(:rsa, :dsa, :ecdsa, :ed25519)
      end
80

N
Nick Thomas 已提交
81 82 83 84 85 86 87 88 89
      it 'does not allow all key types to be disabled' do
        described_class::SUPPORTED_KEY_TYPES.each do |type|
          setting["#{type}_key_restriction"] = described_class::FORBIDDEN_KEY_VALUE
        end

        expect(setting).not_to be_valid
        expect(setting.errors.messages).to have_key(:allowed_key_types)
      end

90 91 92
      where(:type) do
        described_class::SUPPORTED_KEY_TYPES
      end
93

94 95
      with_them do
        let(:field) { :"#{type}_key_restriction" }
96

97
        it { is_expected.to validate_presence_of(field) }
98
        it { is_expected.to allow_value(*KeyRestrictionValidator.supported_key_restrictions(type)).for(field) }
99 100
        it { is_expected.not_to allow_value(128).for(field) }
      end
101 102
    end

103 104 105
    it_behaves_like 'an object with email-formated attributes', :admin_notification_email do
      subject { setting }
    end
106

107 108
    # Upgraded databases will have this sort of content
    context 'repository_storages is a String, not an Array' do
109 110 111
      before do
        setting.__send__(:raw_write_attribute, :repository_storages, 'default')
      end
112 113 114 115 116

      it { expect(setting.repository_storages_before_type_cast).to eq('default') }
      it { expect(setting.repository_storages).to eq(['default']) }
    end

117
    context 'circuitbreaker settings' do
118 119
      [:circuitbreaker_backoff_threshold,
       :circuitbreaker_failure_count_threshold,
120 121 122 123 124 125 126 127 128
       :circuitbreaker_failure_wait_time,
       :circuitbreaker_failure_reset_time,
       :circuitbreaker_storage_timeout].each do |field|
        it "Validates #{field} as number" do
          is_expected.to validate_numericality_of(field)
                           .only_integer
                           .is_greater_than_or_equal_to(0)
        end
      end
129 130 131 132 133 134 135 136 137 138

      it 'requires the `backoff_threshold` to be lower than the `failure_count_threshold`' do
        setting.circuitbreaker_failure_count_threshold = 10
        setting.circuitbreaker_backoff_threshold = 15
        failure_message = "The circuitbreaker backoff threshold should be lower "\
                          "than the failure count threshold"

        expect(setting).not_to be_valid
        expect(setting.errors[:circuitbreaker_backoff_threshold]).to include(failure_message)
      end
139 140
    end

141
    context 'repository storages' do
142
      before do
143 144 145
        storages = {
          'custom1' => 'tmp/tests/custom_repositories_1',
          'custom2' => 'tmp/tests/custom_repositories_2',
146
          'custom3' => 'tmp/tests/custom_repositories_3'
147 148

        }
149 150 151
        allow(Gitlab.config.repositories).to receive(:storages).and_return(storages)
      end

152 153
      describe 'inclusion' do
        it { is_expected.to allow_value('custom1').for(:repository_storages) }
D
Douwe Maan 已提交
154
        it { is_expected.to allow_value(%w(custom2 custom3)).for(:repository_storages) }
155
        it { is_expected.not_to allow_value('alternative').for(:repository_storages) }
D
Douwe Maan 已提交
156
        it { is_expected.not_to allow_value(%w(alternative custom1)).for(:repository_storages) }
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
      end

      describe 'presence' do
        it { is_expected.not_to allow_value([]).for(:repository_storages) }
        it { is_expected.not_to allow_value("").for(:repository_storages) }
        it { is_expected.not_to allow_value(nil).for(:repository_storages) }
      end

      describe '.pick_repository_storage' do
        it 'uses Array#sample to pick a random storage' do
          array = double('array', sample: 'random')
          expect(setting).to receive(:repository_storages).and_return(array)

          expect(setting.pick_repository_storage).to eq('random')
        end

        describe '#repository_storage' do
          it 'returns the first storage' do
D
Douwe Maan 已提交
175
            setting.repository_storages = %w(good bad)
176 177 178 179 180 181 182 183 184 185 186 187 188

            expect(setting.repository_storage).to eq('good')
          end
        end

        describe '#repository_storage=' do
          it 'overwrites repository_storages' do
            setting.repository_storage = 'overwritten'

            expect(setting.repository_storages).to eq(['overwritten'])
          end
        end
      end
189
    end
J
Jacob Vosmaer 已提交
190 191 192 193

    context 'housekeeping settings' do
      it { is_expected.not_to allow_value(0).for(:housekeeping_incremental_repack_period) }

194
      it 'wants the full repack period to be at least the incremental repack period' do
J
Jacob Vosmaer 已提交
195 196 197 198 199 200
        subject.housekeeping_incremental_repack_period = 2
        subject.housekeeping_full_repack_period = 1

        expect(subject).not_to be_valid
      end

201 202 203
      it 'wants the gc period to be at least the full repack period' do
        subject.housekeeping_full_repack_period = 100
        subject.housekeeping_gc_period = 90
J
Jacob Vosmaer 已提交
204 205 206

        expect(subject).not_to be_valid
      end
207 208 209 210 211 212 213 214 215 216 217 218 219 220

      it 'allows the same period for incremental repack and full repack, effectively skipping incremental repack' do
        subject.housekeeping_incremental_repack_period = 2
        subject.housekeeping_full_repack_period = 2

        expect(subject).to be_valid
      end

      it 'allows the same period for full repack and gc, effectively skipping full repack' do
        subject.housekeeping_full_repack_period = 100
        subject.housekeeping_gc_period = 100

        expect(subject).to be_valid
      end
221 222 223 224 225 226 227
    end
  end

  describe '.current' do
    context 'redis unavailable' do
      it 'returns an ApplicationSetting' do
        allow(Rails.cache).to receive(:fetch).and_call_original
228
        allow(described_class).to receive(:last).and_return(:last)
229 230
        expect(Rails.cache).to receive(:fetch).with(ApplicationSetting::CACHE_KEY).and_raise(ArgumentError)

231
        expect(described_class.current).to eq(:last)
232
      end
J
Jacob Vosmaer 已提交
233
    end
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248

    context 'when an ApplicationSetting is not yet present' do
      it 'does not cache nil object' do
        # when missing settings a nil object is returned, but not cached
        allow(described_class).to receive(:last).and_return(nil).twice
        expect(described_class.current).to be_nil

        # when the settings are set the method returns a valid object
        allow(described_class).to receive(:last).and_return(:last)
        expect(described_class.current).to eq(:last)

        # subsequent calls get everything from cache
        expect(described_class.current).to eq(:last)
      end
    end
R
Robert Speicher 已提交
249 250
  end

251 252 253 254 255 256 257 258 259 260
  context 'restrict creating duplicates' do
    before do
      described_class.create_from_defaults
    end

    it 'raises an record creation violation if already created' do
      expect { described_class.create_from_defaults }.to raise_error(ActiveRecord::RecordNotUnique)
    end
  end

K
Kamil Trzcinski 已提交
261
  context 'restricted signup domains' do
262
    it 'sets single domain' do
263 264
      setting.domain_whitelist_raw = 'example.com'
      expect(setting.domain_whitelist).to eq(['example.com'])
265 266
    end

267
    it 'sets multiple domains with spaces' do
268 269
      setting.domain_whitelist_raw = 'example.com *.example.com'
      expect(setting.domain_whitelist).to eq(['example.com', '*.example.com'])
270 271
    end

272
    it 'sets multiple domains with newlines and a space' do
273 274
      setting.domain_whitelist_raw = "example.com\n *.example.com"
      expect(setting.domain_whitelist).to eq(['example.com', '*.example.com'])
275 276
    end

277
    it 'sets multiple domains with commas' do
278 279
      setting.domain_whitelist_raw = "example.com, *.example.com"
      expect(setting.domain_whitelist).to eq(['example.com', '*.example.com'])
280 281
    end
  end
282 283

  context 'blacklisted signup domains' do
284
    it 'sets single domain' do
285
      setting.domain_blacklist_raw = 'example.com'
286
      expect(setting.domain_blacklist).to contain_exactly('example.com')
287 288
    end

289
    it 'sets multiple domains with spaces' do
290
      setting.domain_blacklist_raw = 'example.com *.example.com'
291
      expect(setting.domain_blacklist).to contain_exactly('example.com', '*.example.com')
292 293
    end

294
    it 'sets multiple domains with newlines and a space' do
295
      setting.domain_blacklist_raw = "example.com\n *.example.com"
296
      expect(setting.domain_blacklist).to contain_exactly('example.com', '*.example.com')
297 298
    end

299
    it 'sets multiple domains with commas' do
300
      setting.domain_blacklist_raw = "example.com, *.example.com"
301
      expect(setting.domain_blacklist).to contain_exactly('example.com', '*.example.com')
302 303
    end

304
    it 'sets multiple domains with semicolon' do
305 306 307 308
      setting.domain_blacklist_raw = "example.com; *.example.com"
      expect(setting.domain_blacklist).to contain_exactly('example.com', '*.example.com')
    end

309
    it 'sets multiple domains with mixture of everything' do
310 311 312 313
      setting.domain_blacklist_raw = "example.com; *.example.com\n test.com\sblock.com   yes.com"
      expect(setting.domain_blacklist).to contain_exactly('example.com', '*.example.com', 'test.com', 'block.com', 'yes.com')
    end

314
    it 'sets multiple domain with file' do
315
      setting.domain_blacklist_file = File.open(Rails.root.join('spec/fixtures/', 'domain_blacklist.txt'))
316
      expect(setting.domain_blacklist).to contain_exactly('example.com', 'test.com', 'foo.bar')
317 318
    end
  end
319

320
  describe 'performance bar settings' do
321 322 323 324 325
    describe 'performance_bar_allowed_group_id=' do
      context 'with a blank path' do
        before do
          setting.performance_bar_allowed_group_id = create(:group).full_path
        end
326

327 328
        it 'persists nil for a "" path and clears allowed user IDs cache' do
          expect(Gitlab::PerformanceBar).to receive(:expire_allowed_user_ids_cache)
329

330 331 332 333 334 335 336 337 338
          setting.performance_bar_allowed_group_id = ''

          expect(setting.performance_bar_allowed_group_id).to be_nil
        end
      end

      context 'with an invalid path' do
        it 'does not persist an invalid group path' do
          setting.performance_bar_allowed_group_id = 'foo'
339

340 341
          expect(setting.performance_bar_allowed_group_id).to be_nil
        end
342 343 344 345 346 347 348 349 350 351 352 353 354 355
      end

      context 'with a path to an existing group' do
        let(:group) { create(:group) }

        it 'persists a valid group path and clears allowed user IDs cache' do
          expect(Gitlab::PerformanceBar).to receive(:expire_allowed_user_ids_cache)

          setting.performance_bar_allowed_group_id = group.full_path

          expect(setting.performance_bar_allowed_group_id).to eq(group.id)
        end

        context 'when the given path is the same' do
356 357 358 359 360 361 362 363 364 365
          context 'with a blank path' do
            before do
              setting.performance_bar_allowed_group_id = nil
            end

            it 'clears the cached allowed user IDs' do
              expect(Gitlab::PerformanceBar).not_to receive(:expire_allowed_user_ids_cache)

              setting.performance_bar_allowed_group_id = ''
            end
366 367
          end

368 369 370 371 372 373 374
          context 'with a valid path' do
            before do
              setting.performance_bar_allowed_group_id = group.full_path
            end

            it 'clears the cached allowed user IDs' do
              expect(Gitlab::PerformanceBar).not_to receive(:expire_allowed_user_ids_cache)
375

376 377
              setting.performance_bar_allowed_group_id = group.full_path
            end
378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402
          end
        end
      end
    end

    describe 'performance_bar_allowed_group' do
      context 'with no performance_bar_allowed_group_id saved' do
        it 'returns nil' do
          expect(setting.performance_bar_allowed_group).to be_nil
        end
      end

      context 'with a performance_bar_allowed_group_id saved' do
        let(:group) { create(:group) }

        before do
          setting.performance_bar_allowed_group_id = group.full_path
        end

        it 'returns the group' do
          expect(setting.performance_bar_allowed_group).to eq(group)
        end
      end
    end

403 404 405
    describe 'performance_bar_enabled' do
      context 'with the Performance Bar is enabled' do
        let(:group) { create(:group) }
406 407

        before do
408
          setting.performance_bar_allowed_group_id = group.full_path
409 410 411
        end

        it 'returns true' do
412
          expect(setting.performance_bar_enabled).to be_truthy
413 414 415 416 417 418
        end
      end
    end

    describe 'performance_bar_enabled=' do
      context 'when the performance bar is enabled' do
419 420
        let(:group) { create(:group) }

421
        before do
422
          setting.performance_bar_allowed_group_id = group.full_path
423 424 425 426 427
        end

        context 'when passing true' do
          it 'does not clear allowed user IDs cache' do
            expect(Gitlab::PerformanceBar).not_to receive(:expire_allowed_user_ids_cache)
428

429 430
            setting.performance_bar_enabled = true

431 432
            expect(setting.performance_bar_allowed_group_id).to eq(group.id)
            expect(setting.performance_bar_enabled).to be_truthy
433 434 435 436 437 438
          end
        end

        context 'when passing false' do
          it 'disables the performance bar and clears allowed user IDs cache' do
            expect(Gitlab::PerformanceBar).to receive(:expire_allowed_user_ids_cache)
439

440 441
            setting.performance_bar_enabled = false

442 443
            expect(setting.performance_bar_allowed_group_id).to be_nil
            expect(setting.performance_bar_enabled).to be_falsey
444 445 446 447 448 449
          end
        end
      end

      context 'when the performance bar is disabled' do
        context 'when passing true' do
450 451 452
          it 'does nothing and does not clear allowed user IDs cache' do
            expect(Gitlab::PerformanceBar).not_to receive(:expire_allowed_user_ids_cache)

453 454
            setting.performance_bar_enabled = true

455 456
            expect(setting.performance_bar_allowed_group_id).to be_nil
            expect(setting.performance_bar_enabled).to be_falsey
457 458 459 460
          end
        end

        context 'when passing false' do
461
          it 'does nothing and does not clear allowed user IDs cache' do
462
            expect(Gitlab::PerformanceBar).not_to receive(:expire_allowed_user_ids_cache)
463

464 465
            setting.performance_bar_enabled = false

466 467
            expect(setting.performance_bar_allowed_group_id).to be_nil
            expect(setting.performance_bar_enabled).to be_falsey
468 469 470 471 472 473
          end
        end
      end
    end
  end

474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534
  describe 'usage ping settings' do
    context 'when the usage ping is disabled in gitlab.yml' do
      before do
        allow(Settings.gitlab).to receive(:usage_ping_enabled).and_return(false)
      end

      it 'does not allow the usage ping to be configured' do
        expect(setting.usage_ping_can_be_configured?).to be_falsey
      end

      context 'when the usage ping is disabled in the DB' do
        before do
          setting.usage_ping_enabled = false
        end

        it 'returns false for usage_ping_enabled' do
          expect(setting.usage_ping_enabled).to be_falsey
        end
      end

      context 'when the usage ping is enabled in the DB' do
        before do
          setting.usage_ping_enabled = true
        end

        it 'returns false for usage_ping_enabled' do
          expect(setting.usage_ping_enabled).to be_falsey
        end
      end
    end

    context 'when the usage ping is enabled in gitlab.yml' do
      before do
        allow(Settings.gitlab).to receive(:usage_ping_enabled).and_return(true)
      end

      it 'allows the usage ping to be configured' do
        expect(setting.usage_ping_can_be_configured?).to be_truthy
      end

      context 'when the usage ping is disabled in the DB' do
        before do
          setting.usage_ping_enabled = false
        end

        it 'returns false for usage_ping_enabled' do
          expect(setting.usage_ping_enabled).to be_falsey
        end
      end

      context 'when the usage ping is enabled in the DB' do
        before do
          setting.usage_ping_enabled = true
        end

        it 'returns true for usage_ping_enabled' do
          expect(setting.usage_ping_enabled).to be_truthy
        end
      end
    end
  end
535

536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560
  describe '#allowed_key_types' do
    it 'includes all key types by default' do
      expect(setting.allowed_key_types).to contain_exactly(*described_class::SUPPORTED_KEY_TYPES)
    end

    it 'excludes disabled key types' do
      expect(setting.allowed_key_types).to include(:ed25519)

      setting.ed25519_key_restriction = described_class::FORBIDDEN_KEY_VALUE

      expect(setting.allowed_key_types).not_to include(:ed25519)
    end
  end

  describe '#key_restriction_for' do
    it 'returns the restriction value for recognised types' do
      setting.rsa_key_restriction = 1024

      expect(setting.key_restriction_for(:rsa)).to eq(1024)
    end

    it 'allows types to be passed as a string' do
      setting.rsa_key_restriction = 1024

      expect(setting.key_restriction_for('rsa')).to eq(1024)
561 562
    end

563 564
    it 'returns forbidden for unrecognised type' do
      expect(setting.key_restriction_for(:foo)).to eq(described_class::FORBIDDEN_KEY_VALUE)
565 566
    end
  end
567
end