Commit 7c7e9b13e724c622929ee62f4daf632d3c5b707f

Authored by Dmitriy Zaporozhets
2 parents eed1b52f c83af0df

Merge pull request #1478 from AlexDenisov/ssh_keys_api

SSH Keys API implemented
doc/api/README.md
@@ -34,3 +34,4 @@ When listing resources you can pass the following parameters: @@ -34,3 +34,4 @@ When listing resources you can pass the following parameters:
34 + [Snippets](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/snippets.md) 34 + [Snippets](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/snippets.md)
35 + [Issues](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/issues.md) 35 + [Issues](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/issues.md)
36 + [Milestones](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/milestones.md) 36 + [Milestones](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/milestones.md)
  37 ++ [SSH Keys](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/keys.md)
doc/api/keys.md 0 → 100644
@@ -0,0 +1,79 @@ @@ -0,0 +1,79 @@
  1 +## List keys
  2 +
  3 +Get a list of currently authenticated user's keys.
  4 +
  5 +```
  6 +GET /keys
  7 +```
  8 +
  9 +```json
  10 +[
  11 + {
  12 + "id": 1,
  13 + "title" : "Public key"
  14 + "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4
  15 + 596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4
  16 + soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=",
  17 + },
  18 + {
  19 + "id": 3,
  20 + "title" : "Another Public key"
  21 + "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4
  22 + 596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4
  23 + soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0="
  24 + }
  25 +]
  26 +```
  27 +
  28 +## Single key
  29 +
  30 +Get a single key.
  31 +
  32 +```
  33 +GET /keys/:id
  34 +```
  35 +
  36 +Parameters:
  37 +
  38 ++ `id` (required) - The ID of a key
  39 +
  40 +```json
  41 +{
  42 + "id": 1,
  43 + "title" : "Public key"
  44 + "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4
  45 + 596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4
  46 + soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0="
  47 + }
  48 +```
  49 +## Add key
  50 +
  51 +Create new key owned by currently authenticated user
  52 +
  53 +```
  54 +POST /keys
  55 +```
  56 +
  57 +Parameters:
  58 +
  59 ++ `title` (required) - new SSH Key
  60 ++ `key` (optional) - new SSH key's title
  61 +
  62 +Will return created key with status `201 Created` on success, or `404 Not
  63 +found` on fail.
  64 +
  65 +## Delete key
  66 +
  67 +Delete key owned by currently authenticated user
  68 +
  69 +```
  70 +DELETE /keys/:id
  71 +```
  72 +
  73 +Parameters:
  74 +
  75 ++ `id` (required) - key ID
  76 +
  77 +Will return `200 OK` on success, or `404 Not Found` on fail.
  78 +
  79 +
@@ -17,5 +17,6 @@ module Gitlab @@ -17,5 +17,6 @@ module Gitlab
17 mount Projects 17 mount Projects
18 mount Issues 18 mount Issues
19 mount Milestones 19 mount Milestones
  20 + mount Keys
20 end 21 end
21 end 22 end
lib/api/entities.rb
@@ -48,5 +48,11 @@ module Gitlab @@ -48,5 +48,11 @@ module Gitlab
48 expose :assignee, :author, using: Entities::UserBasic 48 expose :assignee, :author, using: Entities::UserBasic
49 expose :closed, :updated_at, :created_at 49 expose :closed, :updated_at, :created_at
50 end 50 end
  51 +
  52 + class Key < Grape::Entity
  53 + expose :id,
  54 + :title,
  55 + :key
  56 + end
51 end 57 end
52 end 58 end
lib/api/keys.rb 0 → 100644
@@ -0,0 +1,50 @@ @@ -0,0 +1,50 @@
  1 +module Gitlab
  2 + # Keys API
  3 + class Keys < Grape::API
  4 + before { authenticate! }
  5 + resource :keys do
  6 + # Get currently authenticated user's keys
  7 + #
  8 + # Example Request:
  9 + # GET /keys
  10 + get do
  11 + present current_user.keys, with: Entities::Key
  12 + end
  13 + # Get single key owned by currently authenticated user
  14 + #
  15 + # Example Request:
  16 + # GET /keys/:id
  17 + get "/:id" do
  18 + key = current_user.keys.find params[:id]
  19 + present key, with: Entities::Key
  20 + end
  21 + # Add new ssh key to currently authenticated user
  22 + #
  23 + # Parameters:
  24 + # key (required) - New SSH Key
  25 + # title (required) - New SSH Key's title
  26 + # Example Request:
  27 + # POST /keys
  28 + post do
  29 + attrs = attributes_for_keys [:title, :key]
  30 + key = current_user.keys.new attrs
  31 + if key.save
  32 + present key, with: Entities::Key
  33 + else
  34 + not_found!
  35 + end
  36 + end
  37 + # Delete existed ssh key of currently authenticated user
  38 + #
  39 + # Parameters:
  40 + # id (required) - SSH Key ID
  41 + # Example Request:
  42 + # DELETE /keys/:id
  43 + delete "/:id" do
  44 + key = current_user.keys.find params[:id]
  45 + key.delete
  46 + end
  47 + end
  48 + end
  49 +end
  50 +
spec/requests/api/ssh_keys_spec.rb 0 → 100644
@@ -0,0 +1,73 @@ @@ -0,0 +1,73 @@
  1 +require 'spec_helper'
  2 +
  3 +describe Gitlab::Keys do
  4 + include ApiHelpers
  5 + let(:user) {
  6 + user = Factory.create :user
  7 + user.reset_authentication_token!
  8 + user
  9 + }
  10 + let(:key) { Factory.create :key, { user: user}}
  11 +
  12 + describe "GET /keys" do
  13 + context "when unauthenticated" do
  14 + it "should return authentication error" do
  15 + get api("/keys")
  16 + response.status.should == 401
  17 + end
  18 + end
  19 + context "when authenticated" do
  20 + it "should return array of ssh keys" do
  21 + user.keys << key
  22 + user.save
  23 + get api("/keys", user)
  24 + response.status.should == 200
  25 + json_response.should be_an Array
  26 + json_response.first["title"].should == key.title
  27 + end
  28 + end
  29 + end
  30 +
  31 + describe "GET /keys/:id" do
  32 + it "should returm single key" do
  33 + user.keys << key
  34 + user.save
  35 + get api("/keys/#{key.id}", user)
  36 + response.status.should == 200
  37 + json_response["title"].should == key.title
  38 + end
  39 + it "should return 404 Not Found within invalid ID" do
  40 + get api("/keys/42", user)
  41 + response.status.should == 404
  42 + end
  43 + end
  44 +
  45 + describe "POST /keys" do
  46 + it "should not create invalid ssh key" do
  47 + post api("/keys", user), { title: "invalid key" }
  48 + response.status.should == 404
  49 + end
  50 + it "should create ssh key" do
  51 + key_attrs = Factory.attributes :key
  52 + expect {
  53 + post api("/keys", user), key_attrs
  54 + }.to change{ user.keys.count }.by(1)
  55 + end
  56 + end
  57 +
  58 + describe "DELETE /keys/:id" do
  59 + it "should delete existed key" do
  60 + user.keys << key
  61 + user.save
  62 + expect {
  63 + delete api("/keys/#{key.id}", user)
  64 + }.to change{user.keys.count}.by(-1)
  65 + end
  66 + it "should return 404 Not Found within invalid ID" do
  67 + delete api("/keys/42", user)
  68 + response.status.should == 404
  69 + end
  70 + end
  71 +
  72 +end
  73 +