From 1744c742f28afb1a89432fa2854fad93e1557fd8 Mon Sep 17 00:00:00 2001
From: Kamil Trzcinski <ayufan@ayufan.eu>
Date: Fri, 15 Jul 2016 17:05:41 +0200
Subject: [PATCH] Allow to access Container Registry for Public and Internal
 projects

---
 CHANGELOG                                     |   1 +
 app/models/ability.rb                         |   3 +-
 .../security/project/internal_access_spec.rb  |  19 ++++
 .../security/project/private_access_spec.rb   |  19 ++++
 .../security/project/public_access_spec.rb    |  19 ++++
 ...er_registry_authentication_service_spec.rb | 104 +++++++++++++-----
 6 files changed, 139 insertions(+), 26 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index 040926d270d5a..bb58672f7bf9e 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -79,6 +79,7 @@ v 8.10.0 (unreleased)
   - Don't garbage collect commits that have related DB records like comments
   - More descriptive message for git hooks and file locks
   - Handle custom Git hook result in GitLab UI
+  - Allow to access Container Registry for Public and Internal projects
   - Allow '?', or '&' for label names
   - Fix importer for GitHub Pull Requests when a branch was reused across Pull Requests
   - Add date when user joined the team on the member page
diff --git a/app/models/ability.rb b/app/models/ability.rb
index eeb0ceba08113..6fd18f2ee24bd 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -204,7 +204,8 @@ def public_project_rules
         :download_code,
         :fork_project,
         :read_commit_status,
-        :read_pipeline
+        :read_pipeline,
+        :read_container_image
       ]
     end
 
diff --git a/spec/features/security/project/internal_access_spec.rb b/spec/features/security/project/internal_access_spec.rb
index 13d980a326f51..b6acc509342af 100644
--- a/spec/features/security/project/internal_access_spec.rb
+++ b/spec/features/security/project/internal_access_spec.rb
@@ -426,4 +426,23 @@
     it { is_expected.to be_denied_for :external }
     it { is_expected.to be_denied_for :visitor }
   end
+
+  describe "GET /:project_path/container_registry" do
+    before do
+      stub_container_registry_tags('latest')
+      stub_container_registry_config(enabled: true)
+    end
+
+    subject { namespace_project_container_registry_index_path(project.namespace, project) }
+
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_allowed_for owner }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_allowed_for developer }
+    it { is_expected.to be_allowed_for reporter }
+    it { is_expected.to be_allowed_for guest }
+    it { is_expected.to be_allowed_for :user }
+    it { is_expected.to be_denied_for :external }
+    it { is_expected.to be_denied_for :visitor }
+  end
 end
diff --git a/spec/features/security/project/private_access_spec.rb b/spec/features/security/project/private_access_spec.rb
index ac9690cc12796..ccb5c06dab013 100644
--- a/spec/features/security/project/private_access_spec.rb
+++ b/spec/features/security/project/private_access_spec.rb
@@ -362,4 +362,23 @@
     it { is_expected.to be_denied_for :external }
     it { is_expected.to be_denied_for :visitor }
   end
+
+  describe "GET /:project_path/container_registry" do
+    before do
+      stub_container_registry_tags('latest')
+      stub_container_registry_config(enabled: true)
+    end
+
+    subject { namespace_project_container_registry_index_path(project.namespace, project) }
+
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_allowed_for owner }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_allowed_for developer }
+    it { is_expected.to be_allowed_for reporter }
+    it { is_expected.to be_denied_for guest }
+    it { is_expected.to be_denied_for :user }
+    it { is_expected.to be_denied_for :external }
+    it { is_expected.to be_denied_for :visitor }
+  end
 end
diff --git a/spec/features/security/project/public_access_spec.rb b/spec/features/security/project/public_access_spec.rb
index 737897de52b69..985663e7c989a 100644
--- a/spec/features/security/project/public_access_spec.rb
+++ b/spec/features/security/project/public_access_spec.rb
@@ -426,4 +426,23 @@
     it { is_expected.to be_denied_for :external }
     it { is_expected.to be_denied_for :visitor }
   end
+
+  describe "GET /:project_path/container_registry" do
+    before do
+      stub_container_registry_tags('latest')
+      stub_container_registry_config(enabled: true)
+    end
+
+    subject { namespace_project_container_registry_index_path(project.namespace, project) }
+
+    it { is_expected.to be_allowed_for :admin }
+    it { is_expected.to be_allowed_for owner }
+    it { is_expected.to be_allowed_for master }
+    it { is_expected.to be_allowed_for developer }
+    it { is_expected.to be_allowed_for reporter }
+    it { is_expected.to be_allowed_for guest }
+    it { is_expected.to be_allowed_for :user }
+    it { is_expected.to be_allowed_for :external }
+    it { is_expected.to be_allowed_for :visitor }
+  end
 end
diff --git a/spec/services/auth/container_registry_authentication_service_spec.rb b/spec/services/auth/container_registry_authentication_service_spec.rb
index 67777ad48bc69..7cc71f706ce6c 100644
--- a/spec/services/auth/container_registry_authentication_service_spec.rb
+++ b/spec/services/auth/container_registry_authentication_service_spec.rb
@@ -87,51 +87,105 @@
   end
 
   context 'user authorization' do
-    let(:project) { create(:project) }
     let(:current_user) { create(:user) }
 
-    context 'allow to use scope-less authentication' do
-      it_behaves_like 'a valid token'
-    end
+    context 'for private project' do
+      let(:project) { create(:empty_project) }
 
-    context 'allow developer to push images' do
-      before { project.team << [current_user, :developer] }
+      context 'allow to use scope-less authentication' do
+        it_behaves_like 'a valid token'
+      end
 
-      let(:current_params) do
-        { scope: "repository:#{project.path_with_namespace}:push" }
+      context 'allow developer to push images' do
+        before { project.team << [current_user, :developer] }
+
+        let(:current_params) do
+          { scope: "repository:#{project.path_with_namespace}:push" }
+        end
+
+        it_behaves_like 'a pushable'
       end
 
-      it_behaves_like 'a pushable'
-    end
+      context 'allow reporter to pull images' do
+        before { project.team << [current_user, :reporter] }
+
+        let(:current_params) do
+          { scope: "repository:#{project.path_with_namespace}:pull" }
+        end
 
-    context 'allow reporter to pull images' do
-      before { project.team << [current_user, :reporter] }
+        it_behaves_like 'a pullable'
+      end
 
-      let(:current_params) do
-        { scope: "repository:#{project.path_with_namespace}:pull" }
+      context 'return a least of privileges' do
+        before { project.team << [current_user, :reporter] }
+
+        let(:current_params) do
+          { scope: "repository:#{project.path_with_namespace}:push,pull" }
+        end
+
+        it_behaves_like 'a pullable'
       end
 
-      it_behaves_like 'a pullable'
+      context 'disallow guest to pull or push images' do
+        before { project.team << [current_user, :guest] }
+
+        let(:current_params) do
+          { scope: "repository:#{project.path_with_namespace}:pull,push" }
+        end
+
+        it_behaves_like 'an inaccessible'
+      end
     end
 
-    context 'return a least of privileges' do
-      before { project.team << [current_user, :reporter] }
+    context 'for public project' do
+      let(:project) { create(:empty_project, :public) }
 
-      let(:current_params) do
-        { scope: "repository:#{project.path_with_namespace}:push,pull" }
+      context 'allow anyone to pull images' do
+        let(:current_params) do
+          { scope: "repository:#{project.path_with_namespace}:pull" }
+        end
+
+        it_behaves_like 'a pullable'
       end
 
-      it_behaves_like 'a pullable'
+      context 'disallow anyone to push images' do
+        let(:current_params) do
+          { scope: "repository:#{project.path_with_namespace}:push" }
+        end
+
+        it_behaves_like 'an inaccessible'
+      end
     end
 
-    context 'disallow guest to pull or push images' do
-      before { project.team << [current_user, :guest] }
+    context 'for internal project' do
+      let(:project) { create(:empty_project, :internal) }
 
-      let(:current_params) do
-        { scope: "repository:#{project.path_with_namespace}:pull,push" }
+      context 'for internal user' do
+        context 'allow anyone to pull images' do
+          let(:current_params) do
+            { scope: "repository:#{project.path_with_namespace}:pull" }
+          end
+
+          it_behaves_like 'a pullable'
+        end
+
+        context 'disallow anyone to push images' do
+          let(:current_params) do
+            { scope: "repository:#{project.path_with_namespace}:push" }
+          end
+
+          it_behaves_like 'an inaccessible'
+        end
       end
 
-      it_behaves_like 'an inaccessible'
+      context 'for external user' do
+        let(:current_user) { create(:user, external: true) }
+        let(:current_params) do
+          { scope: "repository:#{project.path_with_namespace}:pull,push" }
+        end
+
+        it_behaves_like 'an inaccessible'
+      end
     end
   end
 
-- 
GitLab