From 157c05f49da1d6992d6b491e4fba8d90a7d821c8 Mon Sep 17 00:00:00 2001
From: Timothy Andrew <mail@timothyandrew.net>
Date: Tue, 20 Jun 2017 09:35:59 +0000
Subject: [PATCH] Test `/users` endpoints for the `read_user` scope.

- Test `GET` endpoints to check that the scope is allowed.
- Test `POST` endpoints to check that the scope is disallowed.
- Test both `v3` and `v4` endpoints.
---
 spec/requests/api/users_spec.rb               | 54 ++++++++-----------
 spec/requests/api/v3/users_spec.rb            | 21 ++++++++
 .../api/scopes/read_user_shared_examples.rb   | 33 ++++++++++++
 spec/support/api_helpers.rb                   |  4 +-
 4 files changed, 78 insertions(+), 34 deletions(-)
 create mode 100644 spec/support/api/scopes/read_user_shared_examples.rb

diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index 982c1a50e3b..f0edc06cd0b 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -50,28 +50,6 @@ describe API::Users do
         end['username']).to eq(username)
       end
 
-      context "scopes" do
-        context 'when the requesting token has the "read_user" scope' do
-          let(:token) { create(:personal_access_token, scopes: ['read_user']) }
-
-          it 'returns a "200" response' do
-            get api("/users", user, personal_access_token: token)
-
-            expect(response).to have_http_status(200)
-          end
-        end
-
-        context 'when the requesting token does not have any required scope' do
-          let(:token) { create(:personal_access_token, scopes: ['read_registry']) }
-
-          it 'returns a "401" response' do
-            get api("/users", user, personal_access_token: token)
-
-            expect(response).to have_http_status(401)
-          end
-        end
-      end
-
       it "returns an array of blocked users" do
         ldap_blocked_user
         create(:user, state: 'blocked')
@@ -104,6 +82,13 @@ describe API::Users do
 
         expect(json_response.first.keys).not_to include 'is_admin'
       end
+
+      context "scopes" do
+        let(:path) { "/users" }
+        let(:api_call) { method(:api) }
+
+        include_examples 'allows the "read_user" scope'
+      end
     end
 
     context "when admin" do
@@ -186,6 +171,13 @@ describe API::Users do
 
       expect(response).to have_http_status(404)
     end
+
+    context "scopes" do
+      let(:path) { "/users/#{user.id}" }
+      let(:api_call) { method(:api) }
+
+      include_examples 'allows the "read_user" scope'
+    end
   end
 
   describe "POST /users" do
@@ -321,16 +313,6 @@ describe API::Users do
         .to eq([Gitlab::PathRegex.namespace_format_message])
     end
 
-    context 'when the requesting token has the "read_user" scope' do
-      let(:token) { create(:personal_access_token, scopes: ['read_user'], user: admin) }
-
-      it 'returns a "401" response' do
-        post api("/users", admin, personal_access_token: token), attributes_for(:user, projects_limit: 3)
-
-        expect(response).to have_http_status(401)
-      end
-    end
-
     it "is not available for non admin users" do
       post api("/users", user), attributes_for(:user)
       expect(response).to have_http_status(403)
@@ -377,6 +359,14 @@ describe API::Users do
         expect(json_response['identities'].first['provider']).to eq('github')
       end
     end
+
+    context "scopes" do
+      let(:user) { admin }
+      let(:path) { '/users' }
+      let(:api_call) { method(:api) }
+
+      include_examples 'does not allow the "read_user" scope'
+    end
   end
 
   describe "GET /users/sign_up" do
diff --git a/spec/requests/api/v3/users_spec.rb b/spec/requests/api/v3/users_spec.rb
index 6d7401f9764..b2c5003c97a 100644
--- a/spec/requests/api/v3/users_spec.rb
+++ b/spec/requests/api/v3/users_spec.rb
@@ -67,6 +67,19 @@ describe API::V3::Users do
         expect(json_response.first['title']).to eq(key.title)
       end
     end
+
+    context "scopes" do
+      let(:user) { admin }
+      let(:path) { "/users/#{user.id}/keys" }
+      let(:api_call) { method(:v3_api) }
+
+      before do
+        user.keys << key
+        user.save
+      end
+
+      include_examples 'allows the "read_user" scope'
+    end
   end
 
   describe 'GET /user/:id/emails' do
@@ -312,5 +325,13 @@ describe API::V3::Users do
 
       expect(json_response['is_admin']).to be_nil
     end
+
+    context "scopes" do
+      let(:user) { admin }
+      let(:path) { '/users' }
+      let(:api_call) { method(:v3_api) }
+
+      include_examples 'does not allow the "read_user" scope'
+    end
   end
 end
diff --git a/spec/support/api/scopes/read_user_shared_examples.rb b/spec/support/api/scopes/read_user_shared_examples.rb
new file mode 100644
index 00000000000..bb5f493f3fd
--- /dev/null
+++ b/spec/support/api/scopes/read_user_shared_examples.rb
@@ -0,0 +1,33 @@
+shared_examples_for 'allows the "read_user" scope' do
+  describe 'when the requesting token has the "read_user" scope' do
+    let(:token) { create(:personal_access_token, scopes: ['read_user'], user: user) }
+
+    it 'returns a "200" response' do
+      get api_call.call(path, user, personal_access_token: token)
+
+      expect(response).to have_http_status(200)
+    end
+  end
+
+  describe 'when the requesting token does not have any required scope' do
+    let(:token) { create(:personal_access_token, scopes: ['read_registry'], user: user) }
+
+    it 'returns a "401" response' do
+      get api_call.call(path, user, personal_access_token: token)
+
+      expect(response).to have_http_status(401)
+    end
+  end
+end
+
+shared_examples_for 'does not allow the "read_user" scope' do
+  context 'when the requesting token has the "read_user" scope' do
+    let(:token) { create(:personal_access_token, scopes: ['read_user'], user: user) }
+
+    it 'returns a "401" response' do
+      post api_call.call(path, user, personal_access_token: token), attributes_for(:user, projects_limit: 3)
+
+      expect(response).to have_http_status(401)
+    end
+  end
+end
diff --git a/spec/support/api_helpers.rb b/spec/support/api_helpers.rb
index 163979a2a28..1becd302d77 100644
--- a/spec/support/api_helpers.rb
+++ b/spec/support/api_helpers.rb
@@ -34,8 +34,8 @@ module ApiHelpers
   end
 
   # Temporary helper method for simplifying V3 exclusive API specs
-  def v3_api(path, user = nil)
-    api(path, user, version: 'v3')
+  def v3_api(path, user = nil, personal_access_token: nil)
+    api(path, user, version: 'v3', personal_access_token: personal_access_token)
   end
 
   def ci_api(path, user = nil)
-- 
2.30.9