summaryrefslogtreecommitdiff
path: root/spec/lib/gitlab/middleware/go_spec.rb
blob: 67121937398c659e6030f88abd2b5ee55889eef4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
require 'spec_helper'

describe Gitlab::Middleware::Go do
  let(:app) { double(:app) }
  let(:middleware) { described_class.new(app) }

  describe '#call' do
    describe 'when go-get=0' do
      it 'skips go-import generation' do
        env = { 'rack.input' => '',
                'QUERY_STRING' => 'go-get=0' }
        expect(app).to receive(:call).with(env).and_return('no-go')
        middleware.call(env)
      end
    end

    describe 'when go-get=1' do
      let(:current_user) { nil }

      shared_examples 'go-get=1' do |enabled_protocol:|
        context 'with simple 2-segment project path' do
          let!(:project) { create(:project, :private) }

          context 'with subpackages' do
            let(:path) { "#{project.full_path}/subpackage" }

            it 'returns the full project path' do
              expect_response_with_path(go, enabled_protocol, project.full_path)
            end
          end

          context 'without subpackages' do
            let(:path) { project.full_path }

            it 'returns the full project path' do
              expect_response_with_path(go, enabled_protocol, project.full_path)
            end
          end
        end

        context 'with a nested project path' do
          let(:group) { create(:group, :nested) }
          let!(:project) { create(:project, :public, namespace: group) }

          shared_examples 'a nested project' do
            context 'when the project is public' do
              it 'returns the full project path' do
                expect_response_with_path(go, enabled_protocol, project.full_path)
              end
            end

            context 'when the project is private' do
              before do
                project.update_attribute(:visibility_level, Project::PRIVATE)
              end

              context 'with access to the project' do
                let(:current_user) { project.creator }

                before do
                  project.team.add_master(current_user)
                end

                it 'returns the full project path' do
                  expect_response_with_path(go, enabled_protocol, project.full_path)
                end
              end

              context 'without access to the project' do
                it 'returns the 2-segment group path' do
                  expect_response_with_path(go, enabled_protocol, group.full_path)
                end
              end
            end
          end

          context 'with subpackages' do
            let(:path) { "#{project.full_path}/subpackage" }

            it_behaves_like 'a nested project'
          end

          context 'with a subpackage that is not a valid project path' do
            let(:path) { "#{project.full_path}/---subpackage" }

            it_behaves_like 'a nested project'
          end

          context 'without subpackages' do
            let(:path) { project.full_path }

            it_behaves_like 'a nested project'
          end
        end

        context 'with a bogus path' do
          let(:path) { "http:;url=http://www.example.com'http-equiv='refresh'x='?go-get=1" }

          it 'skips go-import generation' do
            expect(app).to receive(:call).and_return('no-go')

            go
          end
        end
      end

      context 'with SSH disabled' do
        before do
          stub_application_setting(enabled_git_access_protocol: 'http')
        end

        include_examples 'go-get=1', enabled_protocol: :http
      end

      context 'with HTTP disabled' do
        before do
          stub_application_setting(enabled_git_access_protocol: 'ssh')
        end

        include_examples 'go-get=1', enabled_protocol: :ssh
      end

      context 'with nothing disabled' do
        before do
          stub_application_setting(enabled_git_access_protocol: nil)
        end

        include_examples 'go-get=1', enabled_protocol: nil
      end
    end

    def go
      env = {
        'rack.input' => '',
        'QUERY_STRING' => 'go-get=1',
        'PATH_INFO' => "/#{path}",
        'warden' => double(authenticate: current_user)
      }
      middleware.call(env)
    end

    def expect_response_with_path(response, protocol, path)
      repository_url = case protocol
                       when :ssh
                         "ssh://git@#{Gitlab.config.gitlab.host}/#{path}.git"
                       when :http, nil
                         "http://#{Gitlab.config.gitlab.host}/#{path}.git"
                       end
      expect(response[0]).to eq(200)
      expect(response[1]['Content-Type']).to eq('text/html')
      expected_body = %{<html><head><meta name="go-import" content="#{Gitlab.config.gitlab.host}/#{path} git #{repository_url}" /></head></html>}
      expect(response[2].body).to eq([expected_body])
    end
  end
end