From 05e792b4c492e04aaa7e301432f71e01d63c02bc Mon Sep 17 00:00:00 2001
From: Timm Friebe <thekid@thekid.de>
Date: Tue, 15 Apr 2014 16:39:46 +0200
Subject: [PATCH] Implement GET /users/:uid/keys for admin users Complements
 POST operation added in gitlabhq/gitlabhq#3146

Implement DELETE /users/:uid/keys/:id for admin users

Fix "Line is too long. [83/80]"

Use single quotes as advised

Use single quotes as advised

Use single quotes as advised

Fix missing space around { and }

Fix typo in documentation

Only catch  ActiveRecord::RecordNotFound, let other exceptions propagate

Raise a "404 Not found" if key to be deleted cannot be found
As requested by @jvanbaarsen in https://github.com/gitlabhq/gitlabhq/pull/6781#discussion_r11735114

Remove tab
Unconfigured vim on this box, grrrr./
---
 Gemfile.lock                    |  4 +--
 doc/api/users.md                | 27 +++++++++++++++
 lib/api/users.rb                | 39 +++++++++++++++++++++
 spec/requests/api/users_spec.rb | 61 +++++++++++++++++++++++++++++++++
 4 files changed, 129 insertions(+), 2 deletions(-)

diff --git a/Gemfile.lock b/Gemfile.lock
index 7682540eba0..155e03e5456 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -644,7 +644,7 @@ DEPENDENCIES
   simplecov
   sinatra
   six
-  slack-notifier (~> 0.2.0)
+  slack-notifier (~> 0.3.2)
   slim
   spinach-rails
   spring (= 1.1.1)
@@ -662,4 +662,4 @@ DEPENDENCIES
   unicorn (~> 4.6.3)
   unicorn-worker-killer
   version_sorter
-  webmock
\ No newline at end of file
+  webmock
diff --git a/doc/api/users.md b/doc/api/users.md
index 2d5dedb3a39..2b927c30777 100644
--- a/doc/api/users.md
+++ b/doc/api/users.md
@@ -220,6 +220,18 @@ Parameters:
 
 + **none**
 
+## List SSH keys for user
+
+Get a list of a specified user's SSH keys. Available only for admin
+
+```
+GET /users/:uid/keys
+```
+
+Parameters:
+
++ `uid` (required) - id of specified user
+
 
 ## Single SSH key
 
@@ -286,3 +298,18 @@ Parameters:
 
 + `id` (required) - SSH key ID
 
+## Delete SSH key
+
+Deletes key owned by a specified user. Available only for admin.
+
+```
+DELETE /users/:uid/keys/:id
+```
+
+Parameters:
+
++ `uid` (required) - id of specified user
++ `id` (required) - SSH key ID
+
+Will return `200 Ok` on success, or `404 Not found` if either user or key cannot be found.
+
diff --git a/lib/api/users.rb b/lib/api/users.rb
index ae808b6272b..6ed2740c333 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -113,6 +113,45 @@ module API
         end
       end
 
+      # Get ssh keys of a specified user. Only available to admin users.
+      #
+      # Parameters:
+      # uid (required) - The ID of a user
+      # Example Request:
+      # GET /users/:uid/keys
+      get ':uid/keys' do
+        authenticated_as_admin!
+        user = User.find_by(id: params[:uid])
+        if user
+          present user.keys, with: Entities::SSHKey
+        else
+          not_found!
+        end
+      end
+
+      # Delete existing ssh key of a specified user. Only available to admin
+      # users.
+      #
+      # Parameters:
+      #   uid (required) - The ID of a user
+      #   id (required) - SSH Key ID
+      # Example Request:
+      #   DELETE /users/:uid/keys/:id
+      delete ':uid/keys/:id' do
+        authenticated_as_admin!
+        user = User.find_by(id: params[:uid])
+        if user
+          begin
+            key = user.keys.find params[:id]
+            key.destroy
+          rescue ActiveRecord::RecordNotFound
+            not_found!
+          end
+        else
+          not_found!
+        end
+      end
+
       # Delete user. Available only for admin
       #
       # Example Request:
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index 86610c47513..a6d300b099b 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -242,6 +242,67 @@ describe API::API, api: true  do
     end
   end
 
+  describe 'GET /user/:uid/keys' do
+    before { admin }
+
+    context 'when unauthenticated' do
+      it 'should return authentication error' do
+        get api("/users/#{user.id}/keys")
+        response.status.should == 401
+      end
+    end
+
+    context 'when authenticated' do
+      it 'should return 404 for non-existing user' do
+        get api('/users/999999/keys', admin)
+        response.status.should == 404
+      end
+
+      it 'should return array of ssh keys' do
+        user.keys << key
+        user.save
+        get api("/users/#{user.id}/keys", admin)
+        response.status.should == 200
+        json_response.should be_an Array
+        json_response.first['title'].should == key.title
+      end
+    end
+  end
+
+  describe 'DELETE /user/:uid/keys/:id' do
+    before { admin }
+
+    context 'when unauthenticated' do
+      it 'should return authentication error' do
+        delete api("/users/#{user.id}/keys/42")
+        response.status.should == 401
+      end
+    end
+
+    context 'when authenticated' do
+      it 'should delete existing key' do
+        user.keys << key
+        user.save
+        expect {
+          delete api("/users/#{user.id}/keys/#{key.id}", admin)
+        }.to change { user.keys.count }.by(-1)
+        response.status.should == 200
+      end
+
+      it 'should return 404 error if user not found' do
+        user.keys << key
+        user.save
+        delete api("/users/999999/keys/#{key.id}", admin)
+        response.status.should == 404
+      end
+
+      it 'should return 404 error if key not foud' do
+        delete api("/users/#{user.id}/keys/42", admin)
+        response.status.should == 404
+      end
+    end
+  end
+
   describe "DELETE /users/:id" do
     before { admin }
 
-- 
GitLab