From f411772e3395f569da893dd1fc0fd666dcbb5caa Mon Sep 17 00:00:00 2001
From: Matt Humphrey <matt@tomatto.co.uk>
Date: Tue, 5 Mar 2013 21:23:29 +0000
Subject: [PATCH] Project deploy keys API

---
 doc/api/projects.md                | 79 ++++++++++++++++++++++++++++++
 lib/api/projects.rb                | 43 ++++++++++++++++
 spec/requests/api/projects_spec.rb | 57 +++++++++++++++++++++
 3 files changed, 179 insertions(+)

diff --git a/doc/api/projects.md b/doc/api/projects.md
index ed9690f09a2..e599ed49c43 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -274,3 +274,82 @@ Parameters:
 + `hook_id` (required) - The ID of hook to delete
 
 Will return status `200 OK` on success, or `404 Not found` on fail.
+
+
+## List deploy keys
+
+Get a list of a project's deploy keys.
+
+```
+GET /projects/:id/keys
+```
+
+```json
+[
+  {
+    "id": 1,
+    "title" : "Public key"
+    "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4
+      596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4
+      soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=",
+  },
+  {
+    "id": 3,
+    "title" : "Another Public key"
+    "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4
+      596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4
+      soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0="
+  }
+]
+```
+
+## Single deploy key
+
+Get a single key.
+
+```
+GET /projects/:id/keys/:key_id
+```
+
+Parameters:
+
++ `id` (required) - The ID of an deploy key
+
+```json
+{
+  "id": 1,
+  "title" : "Public key"
+  "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4
+      596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4
+      soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0="
+}
+```
+## Add deploy key
+
+Create new deploy key for a project
+
+```
+POST /projects/:id/keys
+```
+
+Parameters:
+
++ `title` (required) - new deploy key's title
++ `key` (required) - new deploy key
+
+Will return created key with status `201 Created` on success, or `404 Not
+found` on fail.
+
+## Delete deploy key
+
+Delete a deploy key from a project
+
+```
+DELETE /projects/:id/keys/:key_id
+```
+
+Parameters:
+
++ `id` (required) - Deploy key ID
+
+Will return `200 OK` on success, or `404 Not Found` on fail.
\ No newline at end of file
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index 8f57e5ac79f..763f90015dd 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -424,6 +424,49 @@ module Gitlab
         present tree.data
       end
 
+      # Get a specific project's keys
+      #
+      # Example Request:
+      #   GET /projects/:id/keys
+      get ":id/keys" do
+        present user_project.deploy_keys, with: Entities::SSHKey
+      end
+
+      # Get single key owned by currently authenticated user
+      #
+      # Example Request:
+      #   GET /projects/:id/keys/:id
+      get ":id/keys/:key_id" do
+        key = user_project.deploy_keys.find params[:key_id]
+        present key, with: Entities::SSHKey
+      end
+
+      # Add new ssh key to currently authenticated user
+      #
+      # Parameters:
+      #   key (required) - New SSH Key
+      #   title (required) - New SSH Key's title
+      # Example Request:
+      #   POST /projects/:id/keys
+      post ":id/keys" do
+        attrs = attributes_for_keys [:title, :key]
+        key = user_project.deploy_keys.new attrs
+        if key.save
+          present key, with: Entities::SSHKey
+        else
+          not_found!
+        end
+      end
+
+      # Delete existed ssh key of currently authenticated user
+      #
+      # Example Request:
+      #   DELETE /projects/:id/keys/:id
+      delete ":id/keys/:key_id" do
+        key = user_project.deploy_keys.find params[:key_id]
+        key.delete
+      end
+
     end
   end
 end
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index d410885bd22..422ccbf6f68 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -11,6 +11,8 @@ describe Gitlab::API do
   let!(:snippet) { create(:snippet, author: user, project: project, title: 'example') }
   let!(:users_project) { create(:users_project, user: user, project: project, project_access: UsersProject::MASTER) }
   let!(:users_project2) { create(:users_project, user: user3, project: project, project_access: UsersProject::DEVELOPER) }
+  let(:key) { create(:key, project: project) }
+
   before { project.team << [user, :reporter] }
 
   describe "GET /projects" do
@@ -380,4 +382,59 @@ describe Gitlab::API do
       response.status.should == 404
     end
   end
+
+  describe "GET /projects/:id/keys" do
+    it "should return array of ssh keys" do
+      project.deploy_keys << key
+      project.save
+      get api("/projects/#{project.id}/keys", user)
+      response.status.should == 200
+      json_response.should be_an Array
+      json_response.first['title'].should == key.title
+    end
+  end
+
+  describe "GET /projects/:id/keys/:key_id" do
+    it "should return a single key" do
+      project.deploy_keys << key
+      project.save
+      get api("/projects/#{project.id}/keys/#{key.id}", user)
+      response.status.should == 200
+      json_response['title'].should == key.title
+    end
+
+    it "should return 404 Not Found with invalid ID" do
+      get api("/projects/#{project.id}/keys/404", user)
+      response.status.should == 404
+    end
+  end
+
+  describe "POST /projects/:id/keys" do
+    it "should not create an invalid ssh key" do
+      post api("/projects/#{project.id}/keys", user), { title: "invalid key" }
+      response.status.should == 404
+    end
+
+    it "should create new ssh key" do
+      key_attrs = attributes_for :key
+      expect {
+        post api("/projects/#{project.id}/keys", user), key_attrs
+      }.to change{ project.deploy_keys.count }.by(1)
+    end
+  end
+
+  describe "DELETE /projects/:id/keys/:key_id" do
+    it "should delete existing key" do
+      project.deploy_keys << key
+      project.save
+      expect {
+        delete api("/projects/#{project.id}/keys/#{key.id}", user)
+      }.to change{ project.deploy_keys.count }.by(-1)
+    end
+
+    it "should return 404 Not Found with invalid ID" do
+      delete api("/projects/#{project.id}/keys/404", user)
+      response.status.should == 404
+    end
+  end
 end
-- 
GitLab