1# frozen_string_literal: true
2
3require 'spec_helper'
4
5RSpec.describe ProjectPolicy do
6  include ExternalAuthorizationServiceHelpers
7  include AdminModeHelper
8  include_context 'ProjectPolicy context'
9
10  let(:project) { public_project }
11
12  subject { described_class.new(current_user, project) }
13
14  def expect_allowed(*permissions)
15    permissions.each { |p| is_expected.to be_allowed(p) }
16  end
17
18  def expect_disallowed(*permissions)
19    permissions.each { |p| is_expected.not_to be_allowed(p) }
20  end
21
22  context 'with no project feature' do
23    let(:current_user) { owner }
24
25    before do
26      project.project_feature.destroy!
27      project.reload
28    end
29
30    it 'returns false' do
31      is_expected.to be_disallowed(:read_build)
32    end
33  end
34
35  it 'does not include the read_issue permission when the issue author is not a member of the private project' do
36    project = create(:project, :private)
37    issue   = create(:issue, project: project, author: create(:user))
38    user    = issue.author
39
40    expect(project.team.member?(issue.author)).to be false
41
42    expect(Ability).not_to be_allowed(user, :read_issue, project)
43  end
44
45  it_behaves_like 'model with wiki policies' do
46    let(:container) { project }
47    let_it_be(:user) { owner }
48
49    def set_access_level(access_level)
50      project.project_feature.update_attribute(:wiki_access_level, access_level)
51    end
52  end
53
54  context 'issues feature' do
55    let(:current_user) { owner }
56
57    context 'when the feature is disabled' do
58      before do
59        project.issues_enabled = false
60        project.save!
61      end
62
63      it 'does not include the issues permissions' do
64        expect_disallowed :read_issue, :read_issue_iid, :create_issue, :update_issue, :admin_issue, :create_incident
65      end
66
67      it 'disables boards and lists permissions' do
68        expect_disallowed :read_issue_board, :create_board, :update_board
69        expect_disallowed :read_issue_board_list, :create_list, :update_list, :admin_issue_board_list
70      end
71
72      context 'when external tracker configured' do
73        it 'does not include the issues permissions' do
74          create(:jira_integration, project: project)
75
76          expect_disallowed :read_issue, :read_issue_iid, :create_issue, :update_issue, :admin_issue, :create_incident
77        end
78      end
79    end
80  end
81
82  context 'merge requests feature' do
83    let(:current_user) { owner }
84
85    it 'disallows all permissions when the feature is disabled' do
86      project.project_feature.update!(merge_requests_access_level: ProjectFeature::DISABLED)
87
88      mr_permissions = [:create_merge_request_from, :read_merge_request,
89                        :update_merge_request, :admin_merge_request,
90                        :create_merge_request_in]
91
92      expect_disallowed(*mr_permissions)
93    end
94  end
95
96  context 'for a guest in a private project' do
97    let(:current_user) { guest }
98    let(:project) { private_project }
99
100    it 'disallows the guest from reading the merge request and merge request iid' do
101      expect_disallowed(:read_merge_request)
102      expect_disallowed(:read_merge_request_iid)
103    end
104  end
105
106  context 'pipeline feature' do
107    let(:project)      { private_project }
108    let(:current_user) { developer }
109    let(:pipeline)     { create(:ci_pipeline, project: project) }
110
111    describe 'for confirmed user' do
112      it 'allows modify pipelines' do
113        expect_allowed(:create_pipeline)
114        expect_allowed(:update_pipeline)
115        expect_allowed(:create_pipeline_schedule)
116      end
117    end
118
119    describe 'for unconfirmed user' do
120      let(:current_user) { project.owner.tap { |u| u.update!(confirmed_at: nil) } }
121
122      it 'disallows to modify pipelines' do
123        expect_disallowed(:create_pipeline)
124        expect_disallowed(:update_pipeline)
125        expect_disallowed(:destroy_pipeline)
126        expect_disallowed(:create_pipeline_schedule)
127      end
128    end
129
130    describe 'destroy permission' do
131      describe 'for developers' do
132        it 'prevents :destroy_pipeline' do
133          expect(current_user.can?(:destroy_pipeline, pipeline)).to be_falsey
134        end
135      end
136
137      describe 'for maintainers' do
138        let(:current_user) { maintainer }
139
140        it 'prevents :destroy_pipeline' do
141          project.add_maintainer(maintainer)
142          expect(current_user.can?(:destroy_pipeline, pipeline)).to be_falsey
143        end
144      end
145
146      describe 'for project owner' do
147        let(:current_user) { project.owner }
148
149        it 'allows :destroy_pipeline' do
150          expect(current_user.can?(:destroy_pipeline, pipeline)).to be_truthy
151        end
152
153        context 'on archived projects' do
154          before do
155            project.update!(archived: true)
156          end
157
158          it 'prevents :destroy_pipeline' do
159            expect(current_user.can?(:destroy_pipeline, pipeline)).to be_falsey
160          end
161        end
162
163        context 'on archived pending_delete projects' do
164          before do
165            project.update!(archived: true, pending_delete: true)
166          end
167
168          it 'allows :destroy_pipeline' do
169            expect(current_user.can?(:destroy_pipeline, pipeline)).to be_truthy
170          end
171        end
172      end
173    end
174  end
175
176  context 'builds feature' do
177    context 'when builds are disabled' do
178      let(:current_user) { owner }
179
180      before do
181        project.project_feature.update!(builds_access_level: ProjectFeature::DISABLED)
182      end
183
184      it 'disallows all permissions except pipeline when the feature is disabled' do
185        builds_permissions = [
186          :create_build, :read_build, :update_build, :admin_build, :destroy_build,
187          :create_pipeline_schedule, :read_pipeline_schedule_variables, :update_pipeline_schedule, :admin_pipeline_schedule, :destroy_pipeline_schedule,
188          :create_environment, :read_environment, :update_environment, :admin_environment, :destroy_environment,
189          :create_cluster, :read_cluster, :update_cluster, :admin_cluster, :destroy_cluster,
190          :create_deployment, :read_deployment, :update_deployment, :admin_deployment, :destroy_deployment
191        ]
192
193        expect_disallowed(*builds_permissions)
194      end
195    end
196
197    context 'when builds are disabled only for some users' do
198      let(:current_user) { guest }
199
200      before do
201        project.project_feature.update!(builds_access_level: ProjectFeature::PRIVATE)
202      end
203
204      it 'disallows pipeline and commit_status permissions' do
205        builds_permissions = [
206          :create_pipeline, :update_pipeline, :admin_pipeline, :destroy_pipeline,
207          :create_commit_status, :update_commit_status, :admin_commit_status, :destroy_commit_status
208        ]
209
210        expect_disallowed(*builds_permissions)
211      end
212    end
213  end
214
215  context 'repository feature' do
216    let(:repository_permissions) do
217      [
218        :create_pipeline, :update_pipeline, :admin_pipeline, :destroy_pipeline,
219        :create_build, :read_build, :update_build, :admin_build, :destroy_build,
220        :create_pipeline_schedule, :read_pipeline_schedule, :update_pipeline_schedule, :admin_pipeline_schedule, :destroy_pipeline_schedule,
221        :create_environment, :read_environment, :update_environment, :admin_environment, :destroy_environment,
222        :create_cluster, :read_cluster, :update_cluster, :admin_cluster,
223        :create_deployment, :read_deployment, :update_deployment, :admin_deployment, :destroy_deployment,
224        :destroy_release, :download_code, :build_download_code
225      ]
226    end
227
228    context 'when user is a project member' do
229      let(:current_user) { owner }
230
231      context 'when it is disabled' do
232        before do
233          project.project_feature.update!(
234            repository_access_level: ProjectFeature::DISABLED,
235            merge_requests_access_level: ProjectFeature::DISABLED,
236            builds_access_level: ProjectFeature::DISABLED,
237            forking_access_level: ProjectFeature::DISABLED
238          )
239        end
240
241        it 'disallows all permissions' do
242          expect_disallowed(*repository_permissions)
243        end
244      end
245    end
246
247    context 'when user is non-member' do
248      let(:current_user) { non_member }
249
250      context 'when access level is private' do
251        before do
252          project.project_feature.update!(
253            repository_access_level: ProjectFeature::PRIVATE,
254            merge_requests_access_level: ProjectFeature::PRIVATE,
255            builds_access_level: ProjectFeature::PRIVATE,
256            forking_access_level: ProjectFeature::PRIVATE
257          )
258        end
259
260        it 'disallows all permissions' do
261          expect_disallowed(*repository_permissions)
262        end
263      end
264    end
265  end
266
267  it_behaves_like 'project policies as anonymous'
268  it_behaves_like 'project policies as guest'
269  it_behaves_like 'project policies as reporter'
270  it_behaves_like 'project policies as developer'
271  it_behaves_like 'project policies as maintainer'
272  it_behaves_like 'project policies as owner'
273  it_behaves_like 'project policies as admin with admin mode'
274  it_behaves_like 'project policies as admin without admin mode'
275
276  context 'when a public project has merge requests allowing access' do
277    include ProjectForksHelper
278    let(:current_user) { create(:user) }
279    let(:target_project) { create(:project, :public) }
280    let(:project) { fork_project(target_project) }
281    let!(:merge_request) do
282      create(
283        :merge_request,
284        target_project: target_project,
285        source_project: project,
286        allow_collaboration: true
287      )
288    end
289
290    let(:maintainer_abilities) do
291      %w(create_build create_pipeline)
292    end
293
294    it 'does not allow pushing code' do
295      expect_disallowed(*maintainer_abilities)
296    end
297
298    it 'allows pushing if the user is a member with push access to the target project' do
299      target_project.add_developer(current_user)
300
301      expect_allowed(*maintainer_abilities)
302    end
303
304    it 'disallows abilities to a maintainer if the merge request was closed' do
305      target_project.add_developer(current_user)
306      merge_request.close!
307
308      expect_disallowed(*maintainer_abilities)
309    end
310  end
311
312  it_behaves_like 'clusterable policies' do
313    let_it_be(:clusterable) { create(:project, :repository) }
314    let_it_be(:cluster) do
315      create(:cluster, :provided_by_gcp, :project, projects: [clusterable])
316    end
317  end
318
319  context 'reading a project' do
320    it 'allows access when a user has read access to the repo' do
321      expect(described_class.new(owner, project)).to be_allowed(:read_project)
322      expect(described_class.new(developer, project)).to be_allowed(:read_project)
323      expect(described_class.new(admin, project)).to be_allowed(:read_project)
324    end
325
326    it 'never checks the external service' do
327      expect(::Gitlab::ExternalAuthorization).not_to receive(:access_allowed?)
328
329      expect(described_class.new(owner, project)).to be_allowed(:read_project)
330    end
331
332    context 'with an external authorization service' do
333      before do
334        enable_external_authorization_service_check
335      end
336
337      it 'allows access when the external service allows it' do
338        external_service_allow_access(owner, project)
339        external_service_allow_access(developer, project)
340
341        expect(described_class.new(owner, project)).to be_allowed(:read_project)
342        expect(described_class.new(developer, project)).to be_allowed(:read_project)
343      end
344
345      context 'with an admin' do
346        context 'when admin mode is enabled', :enable_admin_mode do
347          it 'does not check the external service and allows access' do
348            expect(::Gitlab::ExternalAuthorization).not_to receive(:access_allowed?)
349
350            expect(described_class.new(admin, project)).to be_allowed(:read_project)
351          end
352        end
353
354        context 'when admin mode is disabled' do
355          it 'checks the external service and allows access' do
356            external_service_allow_access(admin, project)
357
358            expect(::Gitlab::ExternalAuthorization).to receive(:access_allowed?)
359
360            expect(described_class.new(admin, project)).to be_allowed(:read_project)
361          end
362        end
363      end
364
365      it 'prevents all but seeing a public project in a list when access is denied' do
366        [developer, owner, build(:user), nil].each do |user|
367          external_service_deny_access(user, project)
368          policy = described_class.new(user, project)
369
370          expect(policy).not_to be_allowed(:read_project)
371          expect(policy).not_to be_allowed(:owner_access)
372          expect(policy).not_to be_allowed(:change_namespace)
373        end
374      end
375
376      it 'passes the full path to external authorization for logging purposes' do
377        expect(::Gitlab::ExternalAuthorization)
378          .to receive(:access_allowed?).with(owner, 'default_label', project.full_path).and_call_original
379
380        described_class.new(owner, project).allowed?(:read_project)
381      end
382    end
383  end
384
385  context 'forking a project' do
386    context 'anonymous user' do
387      let(:current_user) { anonymous }
388
389      it { is_expected.to be_disallowed(:fork_project) }
390    end
391
392    context 'project member' do
393      let(:project) { private_project }
394
395      context 'guest' do
396        let(:current_user) { guest }
397
398        it { is_expected.to be_disallowed(:fork_project) }
399      end
400
401      %w(reporter developer maintainer).each do |role|
402        context role do
403          let(:current_user) { send(role) }
404
405          it { is_expected.to be_allowed(:fork_project) }
406        end
407      end
408    end
409  end
410
411  describe 'update_max_artifacts_size' do
412    context 'when no user' do
413      let(:current_user) { anonymous }
414
415      it { expect_disallowed(:update_max_artifacts_size) }
416    end
417
418    context 'admin' do
419      let(:current_user) { admin }
420
421      context 'when admin mode is enabled', :enable_admin_mode do
422        it { expect_allowed(:update_max_artifacts_size) }
423      end
424
425      context 'when admin mode is disabled' do
426        it { expect_disallowed(:update_max_artifacts_size) }
427      end
428    end
429
430    %w(guest reporter developer maintainer owner).each do |role|
431      context role do
432        let(:current_user) { send(role) }
433
434        it { expect_disallowed(:update_max_artifacts_size) }
435      end
436    end
437  end
438
439  describe 'read_storage_disk_path' do
440    context 'when no user' do
441      let(:current_user) { anonymous }
442
443      it { expect_disallowed(:read_storage_disk_path) }
444    end
445
446    context 'admin' do
447      let(:current_user) { admin }
448
449      context 'when admin mode is enabled', :enable_admin_mode do
450        it { expect_allowed(:read_storage_disk_path) }
451      end
452
453      context 'when admin mode is disabled' do
454        it { expect_disallowed(:read_storage_disk_path) }
455      end
456    end
457
458    %w(guest reporter developer maintainer owner).each do |role|
459      context role do
460        let(:current_user) { send(role) }
461
462        it { expect_disallowed(:read_storage_disk_path) }
463      end
464    end
465  end
466
467  context 'alert bot' do
468    let(:current_user) { User.alert_bot }
469
470    it { is_expected.to be_allowed(:reporter_access) }
471
472    context 'within a private project' do
473      let(:project) { private_project }
474
475      it { is_expected.to be_allowed(:admin_issue) }
476    end
477  end
478
479  describe 'set_pipeline_variables' do
480    context 'when user is developer' do
481      let(:current_user) { developer }
482
483      context 'when project allows user defined variables' do
484        before do
485          project.update!(restrict_user_defined_variables: false)
486        end
487
488        it { is_expected.to be_allowed(:set_pipeline_variables) }
489      end
490
491      context 'when project restricts use of user defined variables' do
492        before do
493          project.update!(restrict_user_defined_variables: true)
494        end
495
496        it { is_expected.not_to be_allowed(:set_pipeline_variables) }
497      end
498    end
499
500    context 'when user is maintainer' do
501      let(:current_user) { maintainer }
502
503      context 'when project allows user defined variables' do
504        before do
505          project.update!(restrict_user_defined_variables: false)
506        end
507
508        it { is_expected.to be_allowed(:set_pipeline_variables) }
509      end
510
511      context 'when project restricts use of user defined variables' do
512        before do
513          project.update!(restrict_user_defined_variables: true)
514        end
515
516        it { is_expected.to be_allowed(:set_pipeline_variables) }
517      end
518    end
519  end
520
521  context 'support bot' do
522    let(:current_user) { User.support_bot }
523
524    context 'with service desk disabled' do
525      it { expect_allowed(:public_access) }
526      it { expect_disallowed(:guest_access, :create_note, :read_project) }
527    end
528
529    context 'with service desk enabled' do
530      before do
531        allow(project).to receive(:service_desk_enabled?).and_return(true)
532      end
533
534      it { expect_allowed(:reporter_access, :create_note, :read_issue) }
535
536      context 'when issues are protected members only' do
537        before do
538          project.project_feature.update!(issues_access_level: ProjectFeature::PRIVATE)
539        end
540
541        it { expect_allowed(:reporter_access, :create_note, :read_issue) }
542      end
543    end
544  end
545
546  context "project bots" do
547    let(:project_bot) { create(:user, :project_bot) }
548    let(:user) { create(:user) }
549
550    context "project_bot_access" do
551      context "when regular user and part of the project" do
552        let(:current_user) { user }
553
554        before do
555          project.add_developer(user)
556        end
557
558        it { is_expected.not_to be_allowed(:project_bot_access)}
559      end
560
561      context "when project bot and not part of the project" do
562        let(:current_user) { project_bot }
563
564        it { is_expected.not_to be_allowed(:project_bot_access)}
565      end
566
567      context "when project bot and part of the project" do
568        let(:current_user) { project_bot }
569
570        before do
571          project.add_developer(project_bot)
572        end
573
574        it { is_expected.to be_allowed(:project_bot_access)}
575      end
576    end
577
578    context 'with resource access tokens' do
579      let(:current_user) { project_bot }
580
581      before do
582        project.add_maintainer(project_bot)
583      end
584
585      it { is_expected.not_to be_allowed(:create_resource_access_tokens)}
586    end
587  end
588
589  describe 'read_prometheus_alerts' do
590    context 'with admin' do
591      let(:current_user) { admin }
592
593      context 'when admin mode is enabled', :enable_admin_mode do
594        it { is_expected.to be_allowed(:read_prometheus_alerts) }
595      end
596
597      context 'when admin mode is disabled' do
598        it { is_expected.to be_disallowed(:read_prometheus_alerts) }
599      end
600    end
601
602    context 'with owner' do
603      let(:current_user) { owner }
604
605      it { is_expected.to be_allowed(:read_prometheus_alerts) }
606    end
607
608    context 'with maintainer' do
609      let(:current_user) { maintainer }
610
611      it { is_expected.to be_allowed(:read_prometheus_alerts) }
612    end
613
614    context 'with developer' do
615      let(:current_user) { developer }
616
617      it { is_expected.to be_disallowed(:read_prometheus_alerts) }
618    end
619
620    context 'with reporter' do
621      let(:current_user) { reporter }
622
623      it { is_expected.to be_disallowed(:read_prometheus_alerts) }
624    end
625
626    context 'with guest' do
627      let(:current_user) { guest }
628
629      it { is_expected.to be_disallowed(:read_prometheus_alerts) }
630    end
631
632    context 'with anonymous' do
633      let(:current_user) { anonymous }
634
635      it { is_expected.to be_disallowed(:read_prometheus_alerts) }
636    end
637  end
638
639  describe 'metrics_dashboard feature' do
640    context 'public project' do
641      let(:project) { public_project }
642
643      context 'feature private' do
644        context 'with reporter' do
645          let(:current_user) { reporter }
646
647          it { is_expected.to be_allowed(:metrics_dashboard) }
648          it { is_expected.to be_allowed(:read_prometheus) }
649          it { is_expected.to be_allowed(:read_deployment) }
650          it { is_expected.to be_allowed(:read_metrics_user_starred_dashboard) }
651          it { is_expected.to be_allowed(:create_metrics_user_starred_dashboard) }
652        end
653
654        context 'with guest' do
655          let(:current_user) { guest }
656
657          it { is_expected.to be_disallowed(:metrics_dashboard) }
658        end
659
660        context 'with anonymous' do
661          let(:current_user) { anonymous }
662
663          it { is_expected.to be_disallowed(:metrics_dashboard) }
664        end
665      end
666
667      context 'feature enabled' do
668        before do
669          project.project_feature.update!(metrics_dashboard_access_level: ProjectFeature::ENABLED)
670        end
671
672        context 'with reporter' do
673          let(:current_user) { reporter }
674
675          it { is_expected.to be_allowed(:metrics_dashboard) }
676          it { is_expected.to be_allowed(:read_prometheus) }
677          it { is_expected.to be_allowed(:read_deployment) }
678          it { is_expected.to be_allowed(:read_metrics_user_starred_dashboard) }
679          it { is_expected.to be_allowed(:create_metrics_user_starred_dashboard) }
680        end
681
682        context 'with guest' do
683          let(:current_user) { guest }
684
685          it { is_expected.to be_allowed(:metrics_dashboard) }
686          it { is_expected.to be_allowed(:read_prometheus) }
687          it { is_expected.to be_allowed(:read_deployment) }
688          it { is_expected.to be_allowed(:read_metrics_user_starred_dashboard) }
689          it { is_expected.to be_allowed(:create_metrics_user_starred_dashboard) }
690        end
691
692        context 'with anonymous' do
693          let(:current_user) { anonymous }
694
695          it { is_expected.to be_allowed(:metrics_dashboard) }
696          it { is_expected.to be_allowed(:read_prometheus) }
697          it { is_expected.to be_allowed(:read_deployment) }
698          it { is_expected.to be_disallowed(:read_metrics_user_starred_dashboard) }
699          it { is_expected.to be_disallowed(:create_metrics_user_starred_dashboard) }
700        end
701      end
702    end
703
704    context 'internal project' do
705      let(:project) { internal_project }
706
707      context 'feature private' do
708        context 'with reporter' do
709          let(:current_user) { reporter }
710
711          it { is_expected.to be_allowed(:metrics_dashboard) }
712          it { is_expected.to be_allowed(:read_prometheus) }
713          it { is_expected.to be_allowed(:read_deployment) }
714          it { is_expected.to be_allowed(:read_metrics_user_starred_dashboard) }
715          it { is_expected.to be_allowed(:create_metrics_user_starred_dashboard) }
716        end
717
718        context 'with guest' do
719          let(:current_user) { guest }
720
721          it { is_expected.to be_disallowed(:metrics_dashboard) }
722        end
723
724        context 'with anonymous' do
725          let(:current_user) { anonymous }
726
727          it { is_expected.to be_disallowed(:metrics_dashboard)}
728        end
729      end
730
731      context 'feature enabled' do
732        before do
733          project.project_feature.update!(metrics_dashboard_access_level: ProjectFeature::ENABLED)
734        end
735
736        context 'with reporter' do
737          let(:current_user) { reporter }
738
739          it { is_expected.to be_allowed(:metrics_dashboard) }
740          it { is_expected.to be_allowed(:read_prometheus) }
741          it { is_expected.to be_allowed(:read_deployment) }
742          it { is_expected.to be_allowed(:read_metrics_user_starred_dashboard) }
743          it { is_expected.to be_allowed(:create_metrics_user_starred_dashboard) }
744        end
745
746        context 'with guest' do
747          let(:current_user) { guest }
748
749          it { is_expected.to be_allowed(:metrics_dashboard) }
750          it { is_expected.to be_allowed(:read_prometheus) }
751          it { is_expected.to be_allowed(:read_deployment) }
752          it { is_expected.to be_allowed(:read_metrics_user_starred_dashboard) }
753          it { is_expected.to be_allowed(:create_metrics_user_starred_dashboard) }
754        end
755
756        context 'with anonymous' do
757          let(:current_user) { anonymous }
758
759          it { is_expected.to be_disallowed(:metrics_dashboard) }
760        end
761      end
762    end
763
764    context 'private project' do
765      let(:project) { private_project }
766
767      context 'feature private' do
768        context 'with reporter' do
769          let(:current_user) { reporter }
770
771          it { is_expected.to be_allowed(:metrics_dashboard) }
772          it { is_expected.to be_allowed(:read_prometheus) }
773          it { is_expected.to be_allowed(:read_deployment) }
774          it { is_expected.to be_allowed(:read_metrics_user_starred_dashboard) }
775          it { is_expected.to be_allowed(:create_metrics_user_starred_dashboard) }
776        end
777
778        context 'with guest' do
779          let(:current_user) { guest }
780
781          it { is_expected.to be_disallowed(:metrics_dashboard) }
782        end
783
784        context 'with anonymous' do
785          let(:current_user) { anonymous }
786
787          it { is_expected.to be_disallowed(:metrics_dashboard) }
788        end
789      end
790
791      context 'feature enabled' do
792        context 'with reporter' do
793          let(:current_user) { reporter }
794
795          it { is_expected.to be_allowed(:metrics_dashboard) }
796          it { is_expected.to be_allowed(:read_prometheus) }
797          it { is_expected.to be_allowed(:read_deployment) }
798          it { is_expected.to be_allowed(:read_metrics_user_starred_dashboard) }
799          it { is_expected.to be_allowed(:create_metrics_user_starred_dashboard) }
800        end
801
802        context 'with guest' do
803          let(:current_user) { guest }
804
805          it { is_expected.to be_disallowed(:metrics_dashboard) }
806        end
807
808        context 'with anonymous' do
809          let(:current_user) { anonymous }
810
811          it { is_expected.to be_disallowed(:metrics_dashboard) }
812        end
813      end
814    end
815
816    context 'feature disabled' do
817      before do
818        project.project_feature.update!(metrics_dashboard_access_level: ProjectFeature::DISABLED)
819      end
820
821      context 'with reporter' do
822        let(:current_user) { reporter }
823
824        it { is_expected.to be_disallowed(:metrics_dashboard) }
825      end
826
827      context 'with guest' do
828        let(:current_user) { guest }
829
830        it { is_expected.to be_disallowed(:metrics_dashboard) }
831      end
832
833      context 'with anonymous' do
834        let(:current_user) { anonymous }
835
836        it { is_expected.to be_disallowed(:metrics_dashboard) }
837      end
838    end
839  end
840
841  context 'deploy key access' do
842    context 'private project' do
843      let(:project) { private_project }
844      let!(:deploy_key) { create(:deploy_key, user: owner) }
845
846      subject { described_class.new(deploy_key, project) }
847
848      context 'when a read deploy key is enabled in the project' do
849        let!(:deploy_keys_project) { create(:deploy_keys_project, project: project, deploy_key: deploy_key) }
850
851        it { is_expected.to be_allowed(:download_code) }
852        it { is_expected.to be_disallowed(:push_code) }
853        it { is_expected.to be_disallowed(:read_project) }
854      end
855
856      context 'when a write deploy key is enabled in the project' do
857        let!(:deploy_keys_project) { create(:deploy_keys_project, :write_access, project: project, deploy_key: deploy_key) }
858
859        it { is_expected.to be_allowed(:download_code) }
860        it { is_expected.to be_allowed(:push_code) }
861        it { is_expected.to be_disallowed(:read_project) }
862      end
863
864      context 'when the deploy key is not enabled in the project' do
865        it { is_expected.to be_disallowed(:download_code) }
866        it { is_expected.to be_disallowed(:push_code) }
867        it { is_expected.to be_disallowed(:read_project) }
868      end
869    end
870  end
871
872  context 'deploy token access' do
873    let!(:project_deploy_token) do
874      create(:project_deploy_token, project: project, deploy_token: deploy_token)
875    end
876
877    subject { described_class.new(deploy_token, project) }
878
879    context 'a deploy token with read_package_registry scope' do
880      let(:deploy_token) { create(:deploy_token, read_package_registry: true) }
881
882      it { is_expected.to be_allowed(:read_package) }
883      it { is_expected.to be_allowed(:read_project) }
884      it { is_expected.to be_disallowed(:create_package) }
885
886      it_behaves_like 'package access with repository disabled'
887    end
888
889    context 'a deploy token with write_package_registry scope' do
890      let(:deploy_token) { create(:deploy_token, write_package_registry: true) }
891
892      it { is_expected.to be_allowed(:create_package) }
893      it { is_expected.to be_allowed(:read_package) }
894      it { is_expected.to be_allowed(:read_project) }
895      it { is_expected.to be_disallowed(:destroy_package) }
896
897      it_behaves_like 'package access with repository disabled'
898    end
899  end
900
901  describe 'create_web_ide_terminal' do
902    context 'with admin' do
903      let(:current_user) { admin }
904
905      context 'when admin mode enabled', :enable_admin_mode do
906        it { is_expected.to be_allowed(:create_web_ide_terminal) }
907      end
908
909      context 'when admin mode disabled' do
910        it { is_expected.to be_disallowed(:create_web_ide_terminal) }
911      end
912    end
913
914    context 'with owner' do
915      let(:current_user) { owner }
916
917      it { is_expected.to be_allowed(:create_web_ide_terminal) }
918    end
919
920    context 'with maintainer' do
921      let(:current_user) { maintainer }
922
923      it { is_expected.to be_allowed(:create_web_ide_terminal) }
924    end
925
926    context 'with developer' do
927      let(:current_user) { developer }
928
929      it { is_expected.to be_disallowed(:create_web_ide_terminal) }
930    end
931
932    context 'with reporter' do
933      let(:current_user) { reporter }
934
935      it { is_expected.to be_disallowed(:create_web_ide_terminal) }
936    end
937
938    context 'with guest' do
939      let(:current_user) { guest }
940
941      it { is_expected.to be_disallowed(:create_web_ide_terminal) }
942    end
943
944    context 'with non member' do
945      let(:current_user) { non_member }
946
947      it { is_expected.to be_disallowed(:create_web_ide_terminal) }
948    end
949
950    context 'with anonymous' do
951      let(:current_user) { anonymous }
952
953      it { is_expected.to be_disallowed(:create_web_ide_terminal) }
954    end
955  end
956
957  describe 'read_repository_graphs' do
958    let(:current_user) { guest }
959
960    before do
961      allow(subject).to receive(:allowed?).with(:read_repository_graphs).and_call_original
962      allow(subject).to receive(:allowed?).with(:download_code).and_return(can_download_code)
963    end
964
965    context 'when user can download_code' do
966      let(:can_download_code) { true }
967
968      it { is_expected.to be_allowed(:read_repository_graphs) }
969    end
970
971    context 'when user cannot download_code' do
972      let(:can_download_code) { false }
973
974      it { is_expected.to be_disallowed(:read_repository_graphs) }
975    end
976  end
977
978  context 'security configuration feature' do
979    %w(guest reporter).each do |role|
980      context role do
981        let(:current_user) { send(role) }
982
983        it 'prevents reading security configuration' do
984          expect_disallowed(:read_security_configuration)
985        end
986      end
987    end
988
989    %w(developer maintainer owner).each do |role|
990      context role do
991        let(:current_user) { send(role) }
992
993        it 'allows reading security configuration' do
994          expect_allowed(:read_security_configuration)
995        end
996      end
997    end
998  end
999
1000  context 'infrastructure google cloud feature' do
1001    %w(guest reporter developer).each do |role|
1002      context role do
1003        let(:current_user) { send(role) }
1004
1005        it 'disallows managing google cloud' do
1006          expect_disallowed(:admin_project_google_cloud)
1007        end
1008      end
1009    end
1010
1011    %w(maintainer owner).each do |role|
1012      context role do
1013        let(:current_user) { send(role) }
1014
1015        it 'allows managing google cloud' do
1016          expect_allowed(:admin_project_google_cloud)
1017        end
1018      end
1019    end
1020  end
1021
1022  describe 'design permissions' do
1023    include DesignManagementTestHelpers
1024
1025    let(:current_user) { guest }
1026
1027    let(:design_permissions) do
1028      %i[read_design_activity read_design]
1029    end
1030
1031    context 'when design management is not available' do
1032      before do
1033        enable_design_management(false)
1034      end
1035
1036      it { is_expected.not_to be_allowed(*design_permissions) }
1037    end
1038
1039    context 'when design management is available' do
1040      before do
1041        enable_design_management
1042      end
1043
1044      it { is_expected.to be_allowed(*design_permissions) }
1045    end
1046  end
1047
1048  describe 'read_build_report_results' do
1049    let(:current_user) { guest }
1050
1051    before do
1052      allow(subject).to receive(:allowed?).with(:read_build_report_results).and_call_original
1053      allow(subject).to receive(:allowed?).with(:read_build).and_return(can_read_build)
1054      allow(subject).to receive(:allowed?).with(:read_pipeline).and_return(can_read_pipeline)
1055    end
1056
1057    context 'when user can read_build and read_pipeline' do
1058      let(:can_read_build) { true }
1059      let(:can_read_pipeline) { true }
1060
1061      it { is_expected.to be_allowed(:read_build_report_results) }
1062    end
1063
1064    context 'when user can read_build but cannot read_pipeline' do
1065      let(:can_read_build) { true }
1066      let(:can_read_pipeline) { false }
1067
1068      it { is_expected.to be_disallowed(:read_build_report_results) }
1069    end
1070
1071    context 'when user cannot read_build but can read_pipeline' do
1072      let(:can_read_build) { false }
1073      let(:can_read_pipeline) { true }
1074
1075      it { is_expected.to be_disallowed(:read_build_report_results) }
1076    end
1077
1078    context 'when user cannot read_build and cannot read_pipeline' do
1079      let(:can_read_build) { false }
1080      let(:can_read_pipeline) { false }
1081
1082      it { is_expected.to be_disallowed(:read_build_report_results) }
1083    end
1084  end
1085
1086  describe 'read_package' do
1087    context 'with admin' do
1088      let(:current_user) { admin }
1089
1090      it { is_expected.to be_allowed(:read_package) }
1091
1092      it_behaves_like 'package access with repository disabled'
1093    end
1094
1095    context 'with owner' do
1096      let(:current_user) { owner }
1097
1098      it { is_expected.to be_allowed(:read_package) }
1099    end
1100
1101    context 'with maintainer' do
1102      let(:current_user) { maintainer }
1103
1104      it { is_expected.to be_allowed(:read_package) }
1105    end
1106
1107    context 'with developer' do
1108      let(:current_user) { developer }
1109
1110      it { is_expected.to be_allowed(:read_package) }
1111    end
1112
1113    context 'with reporter' do
1114      let(:current_user) { reporter }
1115
1116      it { is_expected.to be_allowed(:read_package) }
1117    end
1118
1119    context 'with guest' do
1120      let(:current_user) { guest }
1121
1122      it { is_expected.to be_allowed(:read_package) }
1123    end
1124
1125    context 'with non member' do
1126      let(:current_user) { non_member }
1127
1128      it { is_expected.to be_allowed(:read_package) }
1129    end
1130
1131    context 'with anonymous' do
1132      let(:current_user) { anonymous }
1133
1134      it { is_expected.to be_allowed(:read_package) }
1135    end
1136  end
1137
1138  describe 'read_feature_flag' do
1139    subject { described_class.new(current_user, project) }
1140
1141    context 'with maintainer' do
1142      let(:current_user) { maintainer }
1143
1144      context 'when repository is available' do
1145        it { is_expected.to be_allowed(:read_feature_flag) }
1146      end
1147
1148      context 'when repository is disabled' do
1149        before do
1150          project.project_feature.update!(
1151            merge_requests_access_level: ProjectFeature::DISABLED,
1152            builds_access_level: ProjectFeature::DISABLED,
1153            repository_access_level: ProjectFeature::DISABLED
1154          )
1155        end
1156
1157        it { is_expected.to be_disallowed(:read_feature_flag) }
1158      end
1159    end
1160
1161    context 'with developer' do
1162      let(:current_user) { developer }
1163
1164      context 'when repository is available' do
1165        it { is_expected.to be_allowed(:read_feature_flag) }
1166      end
1167    end
1168
1169    context 'with reporter' do
1170      let(:current_user) { reporter }
1171
1172      context 'when repository is available' do
1173        it { is_expected.to be_disallowed(:read_feature_flag) }
1174      end
1175    end
1176  end
1177
1178  describe 'read_analytics' do
1179    context 'anonymous user' do
1180      let(:current_user) { anonymous }
1181
1182      it { is_expected.to be_allowed(:read_analytics) }
1183    end
1184
1185    context 'with various analytics features' do
1186      let_it_be(:project_with_analytics_disabled) { create(:project, :analytics_disabled) }
1187      let_it_be(:project_with_analytics_private) { create(:project, :analytics_private) }
1188      let_it_be(:project_with_analytics_enabled) { create(:project, :analytics_enabled) }
1189
1190      before do
1191        project_with_analytics_disabled.add_guest(guest)
1192        project_with_analytics_private.add_guest(guest)
1193        project_with_analytics_enabled.add_guest(guest)
1194
1195        project_with_analytics_disabled.add_reporter(reporter)
1196        project_with_analytics_private.add_reporter(reporter)
1197        project_with_analytics_enabled.add_reporter(reporter)
1198
1199        project_with_analytics_disabled.add_developer(developer)
1200        project_with_analytics_private.add_developer(developer)
1201        project_with_analytics_enabled.add_developer(developer)
1202      end
1203
1204      context 'when analytics is disabled for the project' do
1205        let(:project) { project_with_analytics_disabled }
1206
1207        context 'for guest user' do
1208          let(:current_user) { guest }
1209
1210          it { is_expected.to be_disallowed(:read_cycle_analytics) }
1211          it { is_expected.to be_disallowed(:read_insights) }
1212          it { is_expected.to be_disallowed(:read_repository_graphs) }
1213          it { is_expected.to be_disallowed(:read_ci_cd_analytics) }
1214        end
1215
1216        context 'for reporter user' do
1217          let(:current_user) { reporter }
1218
1219          it { is_expected.to be_disallowed(:read_cycle_analytics) }
1220          it { is_expected.to be_disallowed(:read_insights) }
1221          it { is_expected.to be_disallowed(:read_repository_graphs) }
1222          it { is_expected.to be_disallowed(:read_ci_cd_analytics) }
1223        end
1224
1225        context 'for developer' do
1226          let(:current_user) { developer }
1227
1228          it { is_expected.to be_disallowed(:read_cycle_analytics) }
1229          it { is_expected.to be_disallowed(:read_insights) }
1230          it { is_expected.to be_disallowed(:read_repository_graphs) }
1231          it { is_expected.to be_disallowed(:read_ci_cd_analytics) }
1232        end
1233      end
1234
1235      context 'when analytics is private for the project' do
1236        let(:project) { project_with_analytics_private }
1237
1238        context 'for guest user' do
1239          let(:current_user) { guest }
1240
1241          it { is_expected.to be_allowed(:read_cycle_analytics) }
1242          it { is_expected.to be_allowed(:read_insights) }
1243          it { is_expected.to be_disallowed(:read_repository_graphs) }
1244          it { is_expected.to be_disallowed(:read_ci_cd_analytics) }
1245        end
1246
1247        context 'for reporter user' do
1248          let(:current_user) { reporter }
1249
1250          it { is_expected.to be_allowed(:read_cycle_analytics) }
1251          it { is_expected.to be_allowed(:read_insights) }
1252          it { is_expected.to be_allowed(:read_repository_graphs) }
1253          it { is_expected.to be_allowed(:read_ci_cd_analytics) }
1254        end
1255
1256        context 'for developer' do
1257          let(:current_user) { developer }
1258
1259          it { is_expected.to be_allowed(:read_cycle_analytics) }
1260          it { is_expected.to be_allowed(:read_insights) }
1261          it { is_expected.to be_allowed(:read_repository_graphs) }
1262          it { is_expected.to be_allowed(:read_ci_cd_analytics) }
1263        end
1264      end
1265
1266      context 'when analytics is enabled for the project' do
1267        let(:project) { project_with_analytics_enabled }
1268
1269        context 'for guest user' do
1270          let(:current_user) { guest }
1271
1272          it { is_expected.to be_allowed(:read_cycle_analytics) }
1273          it { is_expected.to be_allowed(:read_insights) }
1274          it { is_expected.to be_disallowed(:read_repository_graphs) }
1275          it { is_expected.to be_disallowed(:read_ci_cd_analytics) }
1276        end
1277
1278        context 'for reporter user' do
1279          let(:current_user) { reporter }
1280
1281          it { is_expected.to be_allowed(:read_cycle_analytics) }
1282          it { is_expected.to be_allowed(:read_insights) }
1283          it { is_expected.to be_allowed(:read_repository_graphs) }
1284          it { is_expected.to be_allowed(:read_ci_cd_analytics) }
1285        end
1286
1287        context 'for developer' do
1288          let(:current_user) { developer }
1289
1290          it { is_expected.to be_allowed(:read_cycle_analytics) }
1291          it { is_expected.to be_allowed(:read_insights) }
1292          it { is_expected.to be_allowed(:read_repository_graphs) }
1293          it { is_expected.to be_allowed(:read_ci_cd_analytics) }
1294        end
1295      end
1296    end
1297
1298    context 'project member' do
1299      let(:project) { private_project }
1300
1301      %w(guest reporter developer maintainer).each do |role|
1302        context role do
1303          let(:current_user) { send(role) }
1304
1305          it { is_expected.to be_allowed(:read_analytics) }
1306
1307          context "without access to Analytics" do
1308            before do
1309              project.project_feature.update!(analytics_access_level: ProjectFeature::DISABLED)
1310            end
1311
1312            it { is_expected.to be_disallowed(:read_analytics) }
1313          end
1314        end
1315      end
1316    end
1317  end
1318
1319  it_behaves_like 'Self-managed Core resource access tokens'
1320
1321  describe 'operations feature' do
1322    using RSpec::Parameterized::TableSyntax
1323
1324    let(:guest_operations_permissions) { [:read_environment, :read_deployment] }
1325
1326    let(:developer_operations_permissions) do
1327      guest_operations_permissions + [
1328        :read_feature_flag, :read_sentry_issue, :read_alert_management_alert, :read_terraform_state,
1329        :metrics_dashboard, :read_pod_logs, :read_prometheus, :create_feature_flag,
1330        :create_environment, :create_deployment, :update_feature_flag, :update_environment,
1331        :update_sentry_issue, :update_alert_management_alert, :update_deployment,
1332        :destroy_feature_flag, :destroy_environment, :admin_feature_flag
1333      ]
1334    end
1335
1336    let(:maintainer_operations_permissions) do
1337      developer_operations_permissions + [
1338        :read_cluster, :create_cluster, :update_cluster, :admin_environment,
1339        :admin_cluster, :admin_terraform_state, :admin_deployment
1340      ]
1341    end
1342
1343    where(:project_visibility, :access_level, :role, :allowed) do
1344      :public   | ProjectFeature::ENABLED   | :maintainer | true
1345      :public   | ProjectFeature::ENABLED   | :developer  | true
1346      :public   | ProjectFeature::ENABLED   | :guest      | true
1347      :public   | ProjectFeature::ENABLED   | :anonymous  | true
1348      :public   | ProjectFeature::PRIVATE   | :maintainer | true
1349      :public   | ProjectFeature::PRIVATE   | :developer  | true
1350      :public   | ProjectFeature::PRIVATE   | :guest      | true
1351      :public   | ProjectFeature::PRIVATE   | :anonymous  | false
1352      :public   | ProjectFeature::DISABLED  | :maintainer | false
1353      :public   | ProjectFeature::DISABLED  | :developer  | false
1354      :public   | ProjectFeature::DISABLED  | :guest      | false
1355      :public   | ProjectFeature::DISABLED  | :anonymous  | false
1356      :internal | ProjectFeature::ENABLED   | :maintainer | true
1357      :internal | ProjectFeature::ENABLED   | :developer  | true
1358      :internal | ProjectFeature::ENABLED   | :guest      | true
1359      :internal | ProjectFeature::ENABLED   | :anonymous  | false
1360      :internal | ProjectFeature::PRIVATE   | :maintainer | true
1361      :internal | ProjectFeature::PRIVATE   | :developer  | true
1362      :internal | ProjectFeature::PRIVATE   | :guest      | true
1363      :internal | ProjectFeature::PRIVATE   | :anonymous  | false
1364      :internal | ProjectFeature::DISABLED  | :maintainer | false
1365      :internal | ProjectFeature::DISABLED  | :developer  | false
1366      :internal | ProjectFeature::DISABLED  | :guest      | false
1367      :internal | ProjectFeature::DISABLED  | :anonymous  | false
1368      :private  | ProjectFeature::ENABLED   | :maintainer | true
1369      :private  | ProjectFeature::ENABLED   | :developer  | true
1370      :private  | ProjectFeature::ENABLED   | :guest      | false
1371      :private  | ProjectFeature::ENABLED   | :anonymous  | false
1372      :private  | ProjectFeature::PRIVATE   | :maintainer | true
1373      :private  | ProjectFeature::PRIVATE   | :developer  | true
1374      :private  | ProjectFeature::PRIVATE   | :guest      | false
1375      :private  | ProjectFeature::PRIVATE   | :anonymous  | false
1376      :private  | ProjectFeature::DISABLED  | :maintainer | false
1377      :private  | ProjectFeature::DISABLED  | :developer  | false
1378      :private  | ProjectFeature::DISABLED  | :guest      | false
1379      :private  | ProjectFeature::DISABLED  | :anonymous  | false
1380    end
1381
1382    with_them do
1383      let(:current_user) { user_subject(role) }
1384      let(:project) { project_subject(project_visibility) }
1385
1386      it 'allows/disallows the abilities based on the operation feature access level' do
1387        project.project_feature.update!(operations_access_level: access_level)
1388
1389        if allowed
1390          expect_allowed(*permissions_abilities(role))
1391        else
1392          expect_disallowed(*permissions_abilities(role))
1393        end
1394      end
1395
1396      def project_subject(project_type)
1397        case project_type
1398        when :public
1399          public_project
1400        when :internal
1401          internal_project
1402        else
1403          private_project
1404        end
1405      end
1406
1407      def user_subject(role)
1408        case role
1409        when :maintainer
1410          maintainer
1411        when :developer
1412          developer
1413        when :guest
1414          guest
1415        when :anonymous
1416          anonymous
1417        end
1418      end
1419
1420      def permissions_abilities(role)
1421        case role
1422        when :maintainer
1423          maintainer_operations_permissions
1424        when :developer
1425          developer_operations_permissions
1426        else
1427          guest_operations_permissions
1428        end
1429      end
1430    end
1431  end
1432
1433  describe 'access_security_and_compliance' do
1434    context 'when the "Security & Compliance" is enabled' do
1435      before do
1436        project.project_feature.update!(security_and_compliance_access_level: Featurable::PRIVATE)
1437      end
1438
1439      %w[owner maintainer developer].each do |role|
1440        context "when the role is #{role}" do
1441          let(:current_user) { public_send(role) }
1442
1443          it { is_expected.to be_allowed(:access_security_and_compliance) }
1444        end
1445      end
1446
1447      context 'with admin' do
1448        let(:current_user) { admin }
1449
1450        context 'when admin mode enabled', :enable_admin_mode do
1451          it { is_expected.to be_allowed(:access_security_and_compliance) }
1452        end
1453
1454        context 'when admin mode disabled' do
1455          it { is_expected.to be_disallowed(:access_security_and_compliance) }
1456        end
1457      end
1458
1459      %w[reporter guest].each do |role|
1460        context "when the role is #{role}" do
1461          let(:current_user) { public_send(role) }
1462
1463          it { is_expected.to be_disallowed(:access_security_and_compliance) }
1464        end
1465      end
1466
1467      context 'with non member' do
1468        let(:current_user) { non_member }
1469
1470        it { is_expected.to be_disallowed(:access_security_and_compliance) }
1471      end
1472
1473      context 'with anonymous' do
1474        let(:current_user) { anonymous }
1475
1476        it { is_expected.to be_disallowed(:access_security_and_compliance) }
1477      end
1478    end
1479
1480    context 'when the "Security & Compliance" is not enabled' do
1481      before do
1482        project.project_feature.update!(security_and_compliance_access_level: Featurable::DISABLED)
1483      end
1484
1485      %w[owner maintainer developer reporter guest].each do |role|
1486        context "when the role is #{role}" do
1487          let(:current_user) { public_send(role) }
1488
1489          it { is_expected.to be_disallowed(:access_security_and_compliance) }
1490        end
1491      end
1492
1493      context 'with admin' do
1494        let(:current_user) { admin }
1495
1496        context 'when admin mode enabled', :enable_admin_mode do
1497          it { is_expected.to be_disallowed(:access_security_and_compliance) }
1498        end
1499
1500        context 'when admin mode disabled' do
1501          it { is_expected.to be_disallowed(:access_security_and_compliance) }
1502        end
1503      end
1504
1505      context 'with non member' do
1506        let(:current_user) { non_member }
1507
1508        it { is_expected.to be_disallowed(:access_security_and_compliance) }
1509      end
1510
1511      context 'with anonymous' do
1512        let(:current_user) { anonymous }
1513
1514        it { is_expected.to be_disallowed(:access_security_and_compliance) }
1515      end
1516    end
1517  end
1518
1519  describe 'when user is authenticated via CI_JOB_TOKEN', :request_store do
1520    using RSpec::Parameterized::TableSyntax
1521
1522    where(:project_visibility, :user_role, :external_user, :scope_project_type, :token_scope_enabled, :result) do
1523      :private  | :reporter | false | :same      | true  | true
1524      :private  | :reporter | false | :same      | false | true
1525      :private  | :reporter | false | :different | true  | false
1526      :private  | :reporter | false | :different | false | true
1527      :private  | :guest    | false | :same      | true  | true
1528      :private  | :guest    | false | :same      | false | true
1529      :private  | :guest    | false | :different | true  | false
1530      :private  | :guest    | false | :different | false | true
1531
1532      :internal | :reporter | false | :same      | true  | true
1533      :internal | :reporter | true  | :same      | true  | true
1534      :internal | :reporter | false | :same      | false | true
1535      :internal | :reporter | false | :different | true  | true
1536      :internal | :reporter | true  | :different | true  | false
1537      :internal | :reporter | false | :different | false | true
1538      :internal | :guest    | false | :same      | true  | true
1539      :internal | :guest    | true  | :same      | true  | true
1540      :internal | :guest    | false | :same      | false | true
1541      :internal | :guest    | false | :different | true  | true
1542      :internal | :guest    | true  | :different | true  | false
1543      :internal | :guest    | false | :different | false | true
1544
1545      :public   | :reporter | false | :same      | true  | true
1546      :public   | :reporter | false | :same      | false | true
1547      :public   | :reporter | false | :different | true  | true
1548      :public   | :reporter | false | :different | false | true
1549      :public   | :guest    | false | :same      | true  | true
1550      :public   | :guest    | false | :same      | false | true
1551      :public   | :guest    | false | :different | true  | true
1552      :public   | :guest    | false | :different | false | true
1553    end
1554
1555    with_them do
1556      let(:current_user) { public_send(user_role) }
1557      let(:project) { public_send("#{project_visibility}_project") }
1558      let(:job) { build_stubbed(:ci_build, project: scope_project, user: current_user) }
1559
1560      let(:scope_project) do
1561        if scope_project_type == :same
1562          project
1563        else
1564          create(:project, :private)
1565        end
1566      end
1567
1568      before do
1569        current_user.set_ci_job_token_scope!(job)
1570        current_user.external = external_user
1571        scope_project.update!(ci_job_token_scope_enabled: token_scope_enabled)
1572      end
1573
1574      it "enforces the expected permissions" do
1575        if result
1576          is_expected.to be_allowed("#{user_role}_access".to_sym)
1577        else
1578          is_expected.to be_disallowed("#{user_role}_access".to_sym)
1579        end
1580      end
1581    end
1582  end
1583
1584  describe 'container_image policies' do
1585    using RSpec::Parameterized::TableSyntax
1586
1587    # These are permissions that admins should not have when the project is private
1588    # or the container registry is private.
1589    let(:admin_excluded_permissions) { [:build_read_container_image] }
1590
1591    let(:anonymous_operations_permissions) { [:read_container_image] }
1592    let(:guest_operations_permissions) { anonymous_operations_permissions + [:build_read_container_image] }
1593
1594    let(:developer_operations_permissions) do
1595      guest_operations_permissions + [
1596        :create_container_image, :update_container_image, :destroy_container_image
1597      ]
1598    end
1599
1600    let(:maintainer_operations_permissions) do
1601      developer_operations_permissions + [
1602        :admin_container_image
1603      ]
1604    end
1605
1606    let(:all_permissions) { maintainer_operations_permissions }
1607
1608    where(:project_visibility, :access_level, :role, :allowed) do
1609      :public   | ProjectFeature::ENABLED   | :admin      | true
1610      :public   | ProjectFeature::ENABLED   | :owner      | true
1611      :public   | ProjectFeature::ENABLED   | :maintainer | true
1612      :public   | ProjectFeature::ENABLED   | :developer  | true
1613      :public   | ProjectFeature::ENABLED   | :reporter   | true
1614      :public   | ProjectFeature::ENABLED   | :guest      | true
1615      :public   | ProjectFeature::ENABLED   | :anonymous  | true
1616      :public   | ProjectFeature::PRIVATE   | :admin      | true
1617      :public   | ProjectFeature::PRIVATE   | :owner      | true
1618      :public   | ProjectFeature::PRIVATE   | :maintainer | true
1619      :public   | ProjectFeature::PRIVATE   | :developer  | true
1620      :public   | ProjectFeature::PRIVATE   | :reporter   | true
1621      :public   | ProjectFeature::PRIVATE   | :guest      | false
1622      :public   | ProjectFeature::PRIVATE   | :anonymous  | false
1623      :public   | ProjectFeature::DISABLED  | :admin      | false
1624      :public   | ProjectFeature::DISABLED  | :owner      | false
1625      :public   | ProjectFeature::DISABLED  | :maintainer | false
1626      :public   | ProjectFeature::DISABLED  | :developer  | false
1627      :public   | ProjectFeature::DISABLED  | :reporter   | false
1628      :public   | ProjectFeature::DISABLED  | :guest      | false
1629      :public   | ProjectFeature::DISABLED  | :anonymous  | false
1630      :internal | ProjectFeature::ENABLED   | :admin      | true
1631      :internal | ProjectFeature::ENABLED   | :owner      | true
1632      :internal | ProjectFeature::ENABLED   | :maintainer | true
1633      :internal | ProjectFeature::ENABLED   | :developer  | true
1634      :internal | ProjectFeature::ENABLED   | :reporter   | true
1635      :internal | ProjectFeature::ENABLED   | :guest      | true
1636      :internal | ProjectFeature::ENABLED   | :anonymous  | false
1637      :internal | ProjectFeature::PRIVATE   | :admin      | true
1638      :internal | ProjectFeature::PRIVATE   | :owner      | true
1639      :internal | ProjectFeature::PRIVATE   | :maintainer | true
1640      :internal | ProjectFeature::PRIVATE   | :developer  | true
1641      :internal | ProjectFeature::PRIVATE   | :reporter   | true
1642      :internal | ProjectFeature::PRIVATE   | :guest      | false
1643      :internal | ProjectFeature::PRIVATE   | :anonymous  | false
1644      :internal | ProjectFeature::DISABLED  | :admin      | false
1645      :internal | ProjectFeature::DISABLED  | :owner      | false
1646      :internal | ProjectFeature::DISABLED  | :maintainer | false
1647      :internal | ProjectFeature::DISABLED  | :developer  | false
1648      :internal | ProjectFeature::DISABLED  | :reporter   | false
1649      :internal | ProjectFeature::DISABLED  | :guest      | false
1650      :internal | ProjectFeature::DISABLED  | :anonymous  | false
1651      :private  | ProjectFeature::ENABLED   | :admin      | true
1652      :private  | ProjectFeature::ENABLED   | :owner      | true
1653      :private  | ProjectFeature::ENABLED   | :maintainer | true
1654      :private  | ProjectFeature::ENABLED   | :developer  | true
1655      :private  | ProjectFeature::ENABLED   | :reporter   | true
1656      :private  | ProjectFeature::ENABLED   | :guest      | false
1657      :private  | ProjectFeature::ENABLED   | :anonymous  | false
1658      :private  | ProjectFeature::PRIVATE   | :admin      | true
1659      :private  | ProjectFeature::PRIVATE   | :owner      | true
1660      :private  | ProjectFeature::PRIVATE   | :maintainer | true
1661      :private  | ProjectFeature::PRIVATE   | :developer  | true
1662      :private  | ProjectFeature::PRIVATE   | :reporter   | true
1663      :private  | ProjectFeature::PRIVATE   | :guest      | false
1664      :private  | ProjectFeature::PRIVATE   | :anonymous  | false
1665      :private  | ProjectFeature::DISABLED  | :admin      | false
1666      :private  | ProjectFeature::DISABLED  | :owner      | false
1667      :private  | ProjectFeature::DISABLED  | :maintainer | false
1668      :private  | ProjectFeature::DISABLED  | :developer  | false
1669      :private  | ProjectFeature::DISABLED  | :reporter   | false
1670      :private  | ProjectFeature::DISABLED  | :guest      | false
1671      :private  | ProjectFeature::DISABLED  | :anonymous  | false
1672    end
1673
1674    with_them do
1675      let(:current_user) { send(role) }
1676      let(:project) { send("#{project_visibility}_project") }
1677
1678      before do
1679        enable_admin_mode!(admin) if role == :admin
1680        project.project_feature.update!(container_registry_access_level: access_level)
1681      end
1682
1683      it 'allows/disallows the abilities based on the container_registry feature access level' do
1684        if allowed
1685          expect_allowed(*permissions_abilities(role))
1686          expect_disallowed(*(all_permissions - permissions_abilities(role)))
1687        else
1688          expect_disallowed(*all_permissions)
1689        end
1690      end
1691
1692      it 'allows build_read_container_image to admins who are also team members' do
1693        if allowed && role == :admin
1694          project.add_reporter(current_user)
1695
1696          expect_allowed(:build_read_container_image)
1697        end
1698      end
1699
1700      def permissions_abilities(role)
1701        case role
1702        when :admin
1703          if project_visibility == :private || access_level == ProjectFeature::PRIVATE
1704            maintainer_operations_permissions - admin_excluded_permissions
1705          else
1706            maintainer_operations_permissions
1707          end
1708        when :maintainer, :owner
1709          maintainer_operations_permissions
1710        when :developer
1711          developer_operations_permissions
1712        when :reporter, :guest
1713          guest_operations_permissions
1714        when :anonymous
1715          anonymous_operations_permissions
1716        else
1717          raise "Unknown role #{role}"
1718        end
1719      end
1720    end
1721  end
1722
1723  describe 'update_runners_registration_token' do
1724    context 'when anonymous' do
1725      let(:current_user) { anonymous }
1726
1727      it { is_expected.not_to be_allowed(:update_runners_registration_token) }
1728    end
1729
1730    context 'admin' do
1731      let(:current_user) { create(:admin) }
1732
1733      context 'when admin mode is enabled', :enable_admin_mode do
1734        it { is_expected.to be_allowed(:update_runners_registration_token) }
1735      end
1736
1737      context 'when admin mode is disabled' do
1738        it { is_expected.to be_disallowed(:update_runners_registration_token) }
1739      end
1740    end
1741
1742    %w(guest reporter developer).each do |role|
1743      context role do
1744        let(:current_user) { send(role) }
1745
1746        it { is_expected.to be_disallowed(:update_runners_registration_token) }
1747      end
1748    end
1749
1750    %w(maintainer owner).each do |role|
1751      context role do
1752        let(:current_user) { send(role) }
1753
1754        it { is_expected.to be_allowed(:update_runners_registration_token) }
1755      end
1756    end
1757  end
1758end
1759