project_policy_spec.rb 10.8 KB
Newer Older
1 2
require 'spec_helper'

3
describe ProjectPolicy do
4 5 6 7 8 9
  set(:guest) { create(:user) }
  set(:reporter) { create(:user) }
  set(:developer) { create(:user) }
  set(:master) { create(:user) }
  set(:owner) { create(:user) }
  set(:admin) { create(:admin) }
10
  let(:project) { create(:project, :public, namespace: owner.namespace) }
11

12
  let(:base_guest_permissions) do
D
Douwe Maan 已提交
13 14 15 16 17
    %i[
      read_project read_board read_list read_wiki read_issue read_label
      read_milestone read_project_snippet read_project_member
      read_note create_project create_issue create_note
      upload_file
A
Alejandro Rodríguez 已提交
18
    ]
19 20
  end

21
  let(:base_reporter_permissions) do
D
Douwe Maan 已提交
22 23 24 25 26
    %i[
      download_code fork_project create_project_snippet update_issue
      admin_issue admin_label admin_list read_commit_status read_build
      read_container_image read_pipeline read_environment read_deployment
      read_merge_request download_wiki_code
A
Alejandro Rodríguez 已提交
27 28 29 30
    ]
  end

  let(:team_member_reporter_permissions) do
D
Douwe Maan 已提交
31
    %i[build_download_code build_read_container_image]
A
Alejandro Rodríguez 已提交
32 33 34
  end

  let(:developer_permissions) do
D
Douwe Maan 已提交
35
    %i[
36
      admin_milestone admin_merge_request update_merge_request create_commit_status
D
Douwe Maan 已提交
37 38 39 40
      update_commit_status create_build update_build create_pipeline
      update_pipeline create_merge_request create_wiki push_code
      resolve_note create_container_image update_container_image
      create_environment create_deployment
A
Alejandro Rodríguez 已提交
41 42 43
    ]
  end

44
  let(:base_master_permissions) do
D
Douwe Maan 已提交
45
    %i[
46
      delete_protected_branch update_project_snippet update_environment
47
      update_deployment admin_project_snippet
D
Douwe Maan 已提交
48 49 50
      admin_project_member admin_note admin_wiki admin_project
      admin_commit_status admin_build admin_container_image
      admin_pipeline admin_environment admin_deployment
A
Alejandro Rodríguez 已提交
51 52 53 54
    ]
  end

  let(:public_permissions) do
D
Douwe Maan 已提交
55 56 57 58
    %i[
      download_code fork_project read_commit_status read_pipeline
      read_container_image build_download_code build_read_container_image
      download_wiki_code
A
Alejandro Rodríguez 已提交
59 60 61 62
    ]
  end

  let(:owner_permissions) do
D
Douwe Maan 已提交
63 64 65
    %i[
      change_namespace change_visibility_level rename_project remove_project
      archive_project remove_fork_project destroy_merge_request destroy_issue
A
Alejandro Rodríguez 已提交
66
    ]
67 68
  end

69 70 71 72 73 74 75 76 77
  # Used in EE specs
  let(:additional_guest_permissions)  { [] }
  let(:additional_reporter_permissions) { [] }
  let(:additional_master_permissions) { [] }

  let(:guest_permissions) { base_guest_permissions + additional_guest_permissions }
  let(:reporter_permissions) { base_reporter_permissions + additional_reporter_permissions }
  let(:master_permissions) { base_master_permissions + additional_master_permissions }

78
  before do
79 80 81 82
    project.add_guest(guest)
    project.add_master(master)
    project.add_developer(developer)
    project.add_reporter(reporter)
83
  end
84

85 86 87 88 89 90 91 92
  def expect_allowed(*permissions)
    permissions.each { |p| is_expected.to be_allowed(p) }
  end

  def expect_disallowed(*permissions)
    permissions.each { |p| is_expected.not_to be_allowed(p) }
  end

93
  it 'does not include the read_issue permission when the issue author is not a member of the private project' do
94
    project = create(:project, :private)
95
    issue   = create(:issue, project: project, author: create(:user))
96 97
    user    = issue.author

98
    expect(project.team.member?(issue.author)).to be false
99

100
    expect(Ability).not_to be_allowed(user, :read_issue, project)
101
  end
A
Alejandro Rodríguez 已提交
102

103 104
  context 'when the feature is disabled' do
    subject { described_class.new(owner, project) }
105

106 107 108
    before do
      project.project_feature.update_attribute(:wiki_access_level, ProjectFeature::DISABLED)
    end
109

110 111 112
    it 'does not include the wiki permissions' do
      expect_disallowed :read_wiki, :create_wiki, :update_wiki, :admin_wiki, :download_wiki_code
    end
113 114
  end

115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
  context 'issues feature' do
    subject { described_class.new(owner, project) }

    context 'when the feature is disabled' do
      it 'does not include the issues permissions' do
        project.issues_enabled = false
        project.save!

        expect_disallowed :read_issue, :create_issue, :update_issue, :admin_issue
      end
    end

    context 'when the feature is disabled and external tracker configured' do
      it 'does not include the issues permissions' do
        create(:jira_service, project: project)

        project.issues_enabled = false
        project.save!

        expect_disallowed :read_issue, :create_issue, :update_issue, :admin_issue
      end
    end
  end

139 140 141 142 143 144 145
  shared_examples 'project policies as anonymous' do
    context 'abilities for public projects' do
      context 'when a project has pending invites' do
        let(:group) { create(:group, :public) }
        let(:project) { create(:project, :public, namespace: group) }
        let(:user_permissions) { [:create_project, :create_issue, :create_note, :upload_file] }
        let(:anonymous_permissions) { guest_permissions - user_permissions }
146

147
        subject { described_class.new(nil, project) }
148

149 150 151
        before do
          create(:group_member, :invited, group: group)
        end
152

153 154 155 156 157
        it 'does not grant owner access' do
          expect_allowed(*anonymous_permissions)
          expect_disallowed(*user_permissions)
        end
      end
158 159
    end

160 161
    context 'abilities for non-public projects' do
      let(:project) { create(:project, namespace: owner.namespace) }
A
Alejandro Rodríguez 已提交
162

163
      subject { described_class.new(nil, project) }
A
Alejandro Rodríguez 已提交
164

165
      it { is_expected.to be_banned }
A
Alejandro Rodríguez 已提交
166
    end
167
  end
A
Alejandro Rodríguez 已提交
168

169 170
  shared_examples 'project policies as guest' do
    subject { described_class.new(guest, project) }
A
Alejandro Rodríguez 已提交
171

172 173
    context 'abilities for non-public projects' do
      let(:project) { create(:project, namespace: owner.namespace) }
Z
Z.J. van de Weg 已提交
174 175 176 177 178
      let(:reporter_public_build_permissions) do
        reporter_permissions - [:read_build, :read_pipeline]
      end

      it do
179 180 181 182 183 184
        expect_allowed(*guest_permissions)
        expect_disallowed(*reporter_public_build_permissions)
        expect_disallowed(*team_member_reporter_permissions)
        expect_disallowed(*developer_permissions)
        expect_disallowed(*master_permissions)
        expect_disallowed(*owner_permissions)
Z
Z.J. van de Weg 已提交
185
      end
186

Z
Z.J. van de Weg 已提交
187
      context 'public builds enabled' do
188
        it do
189 190
          expect_allowed(*guest_permissions)
          expect_allowed(:read_build, :read_pipeline)
191 192 193
        end
      end

194
      context 'when public builds disabled' do
195
        before do
Z
Z.J. van de Weg 已提交
196
          project.update(public_builds: false)
197 198 199
        end

        it do
200 201
          expect_allowed(*guest_permissions)
          expect_disallowed(:read_build, :read_pipeline)
202
        end
A
Alejandro Rodríguez 已提交
203
      end
K
Kamil Trzcinski 已提交
204 205 206

      context 'when builds are disabled' do
        before do
207
          project.project_feature.update(builds_access_level: ProjectFeature::DISABLED)
K
Kamil Trzcinski 已提交
208 209 210
        end

        it do
211 212
          expect_disallowed(:read_build)
          expect_allowed(:read_pipeline)
K
Kamil Trzcinski 已提交
213 214
        end
      end
A
Alejandro Rodríguez 已提交
215
    end
216 217 218 219 220
  end

  shared_examples 'project policies as reporter' do
    context 'abilities for non-public projects' do
      let(:project) { create(:project, namespace: owner.namespace) }
A
Alejandro Rodríguez 已提交
221

222
      subject { described_class.new(reporter, project) }
A
Alejandro Rodríguez 已提交
223 224

      it do
225 226 227 228 229 230 231
        expect_allowed(*guest_permissions)
        expect_allowed(*reporter_permissions)
        expect_allowed(*reporter_permissions)
        expect_allowed(*team_member_reporter_permissions)
        expect_disallowed(*developer_permissions)
        expect_disallowed(*master_permissions)
        expect_disallowed(*owner_permissions)
A
Alejandro Rodríguez 已提交
232 233
      end
    end
234
  end
A
Alejandro Rodríguez 已提交
235

236 237 238 239 240
  shared_examples 'project policies as developer' do
    context 'abilities for non-public projects' do
      let(:project) { create(:project, namespace: owner.namespace) }

      subject { described_class.new(developer, project) }
A
Alejandro Rodríguez 已提交
241 242

      it do
243 244 245 246 247 248
        expect_allowed(*guest_permissions)
        expect_allowed(*reporter_permissions)
        expect_allowed(*team_member_reporter_permissions)
        expect_allowed(*developer_permissions)
        expect_disallowed(*master_permissions)
        expect_disallowed(*owner_permissions)
A
Alejandro Rodríguez 已提交
249 250
      end
    end
251 252 253 254 255
  end

  shared_examples 'project policies as master' do
    context 'abilities for non-public projects' do
      let(:project) { create(:project, namespace: owner.namespace) }
A
Alejandro Rodríguez 已提交
256

257
      subject { described_class.new(master, project) }
A
Alejandro Rodríguez 已提交
258 259

      it do
260 261 262 263 264 265
        expect_allowed(*guest_permissions)
        expect_allowed(*reporter_permissions)
        expect_allowed(*team_member_reporter_permissions)
        expect_allowed(*developer_permissions)
        expect_allowed(*master_permissions)
        expect_disallowed(*owner_permissions)
A
Alejandro Rodríguez 已提交
266 267
      end
    end
268 269 270 271 272
  end

  shared_examples 'project policies as owner' do
    context 'abilities for non-public projects' do
      let(:project) { create(:project, namespace: owner.namespace) }
A
Alejandro Rodríguez 已提交
273

274
      subject { described_class.new(owner, project) }
A
Alejandro Rodríguez 已提交
275

276
      it do
277 278 279 280 281 282
        expect_allowed(*guest_permissions)
        expect_allowed(*reporter_permissions)
        expect_allowed(*team_member_reporter_permissions)
        expect_allowed(*developer_permissions)
        expect_allowed(*master_permissions)
        expect_allowed(*owner_permissions)
283 284
      end
    end
285
  end
286

287 288 289 290 291
  shared_examples 'project policies as admin' do
    context 'abilities for non-public projects' do
      let(:project) { create(:project, namespace: owner.namespace) }

      subject { described_class.new(admin, project) }
292

A
Alejandro Rodríguez 已提交
293
      it do
294 295 296 297 298 299
        expect_allowed(*guest_permissions)
        expect_allowed(*reporter_permissions)
        expect_disallowed(*team_member_reporter_permissions)
        expect_allowed(*developer_permissions)
        expect_allowed(*master_permissions)
        expect_allowed(*owner_permissions)
A
Alejandro Rodríguez 已提交
300 301 302
      end
    end
  end
303 304 305 306 307 308 309 310

  it_behaves_like 'project policies as anonymous'
  it_behaves_like 'project policies as guest'
  it_behaves_like 'project policies as reporter'
  it_behaves_like 'project policies as developer'
  it_behaves_like 'project policies as master'
  it_behaves_like 'project policies as owner'
  it_behaves_like 'project policies as admin'
311 312 313 314 315 316 317 318 319 320 321 322 323 324 325

  context 'when a public project has merge requests allowing access' do
    include ProjectForksHelper
    let(:user) { create(:user) }
    let(:target_project) { create(:project, :public) }
    let(:project) { fork_project(target_project) }
    let!(:merge_request) do
      create(
        :merge_request,
        target_project: target_project,
        source_project: project,
        allow_maintainer_to_push: true
      )
    end
    let(:maintainer_abilities) do
326
      %w(create_build update_build create_pipeline update_pipeline)
327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347
    end

    subject { described_class.new(user, project) }

    it 'does not allow pushing code' do
      expect_disallowed(*maintainer_abilities)
    end

    it 'allows pushing if the user is a member with push access to the target project' do
      target_project.add_developer(user)

      expect_allowed(*maintainer_abilities)
    end

    it 'dissallows abilities to a maintainer if the merge request was closed' do
      target_project.add_developer(user)
      merge_request.close!

      expect_disallowed(*maintainer_abilities)
    end
  end
348
end