diff --git a/doc/api/README.md b/doc/api/README.md index 93919b42..9741072c 100644 --- a/doc/api/README.md +++ b/doc/api/README.md @@ -34,3 +34,4 @@ When listing resources you can pass the following parameters: + [Snippets](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/snippets.md) + [Issues](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/issues.md) + [Milestones](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/milestones.md) ++ [SSH Keys](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/keys.md) diff --git a/doc/api/keys.md b/doc/api/keys.md new file mode 100644 index 00000000..8106eb8a --- /dev/null +++ b/doc/api/keys.md @@ -0,0 +1,79 @@ +## List keys + +Get a list of currently authenticated user's keys. + +``` +GET /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 key + +Get a single key. + +``` +GET /keys/:id +``` + +Parameters: + ++ `id` (required) - The ID of a key + +```json +{ + "id": 1, + "title" : "Public key" + "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4 + 596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4 + soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=" + } +``` +## Add key + +Create new key owned by currently authenticated user + +``` +POST /keys +``` + +Parameters: + ++ `title` (required) - new SSH Key ++ `key` (optional) - new SSH key's title + +Will return created key with status `201 Created` on success, or `404 Not +found` on fail. + +## Delete key + +Delete key owned by currently authenticated user + +``` +DELETE /keys/:id +``` + +Parameters: + ++ `id` (required) - key ID + +Will return `200 OK` on success, or `404 Not Found` on fail. + + diff --git a/lib/api.rb b/lib/api.rb index be04701c..37e03849 100644 --- a/lib/api.rb +++ b/lib/api.rb @@ -17,5 +17,6 @@ module Gitlab mount Projects mount Issues mount Milestones + mount Keys end end diff --git a/lib/api/entities.rb b/lib/api/entities.rb index b50d683f..13a48e12 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -48,5 +48,11 @@ module Gitlab expose :assignee, :author, using: Entities::UserBasic expose :closed, :updated_at, :created_at end + + class Key < Grape::Entity + expose :id, + :title, + :key + end end end diff --git a/lib/api/keys.rb b/lib/api/keys.rb new file mode 100644 index 00000000..4c302727 --- /dev/null +++ b/lib/api/keys.rb @@ -0,0 +1,50 @@ +module Gitlab + # Keys API + class Keys < Grape::API + before { authenticate! } + resource :keys do + # Get currently authenticated user's keys + # + # Example Request: + # GET /keys + get do + present current_user.keys, with: Entities::Key + end + # Get single key owned by currently authenticated user + # + # Example Request: + # GET /keys/:id + get "/:id" do + key = current_user.keys.find params[:id] + present key, with: Entities::Key + 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 /keys + post do + attrs = attributes_for_keys [:title, :key] + key = current_user.keys.new attrs + if key.save + present key, with: Entities::Key + else + not_found! + end + end + # Delete existed ssh key of currently authenticated user + # + # Parameters: + # id (required) - SSH Key ID + # Example Request: + # DELETE /keys/:id + delete "/:id" do + key = current_user.keys.find params[:id] + key.delete + end + end + end +end + diff --git a/spec/requests/api/ssh_keys_spec.rb b/spec/requests/api/ssh_keys_spec.rb new file mode 100644 index 00000000..7fb8c920 --- /dev/null +++ b/spec/requests/api/ssh_keys_spec.rb @@ -0,0 +1,73 @@ +require 'spec_helper' + +describe Gitlab::Keys do + include ApiHelpers + let(:user) { + user = Factory.create :user + user.reset_authentication_token! + user + } + let(:key) { Factory.create :key, { user: user}} + + describe "GET /keys" do + context "when unauthenticated" do + it "should return authentication error" do + get api("/keys") + response.status.should == 401 + end + end + context "when authenticated" do + it "should return array of ssh keys" do + user.keys << key + user.save + get api("/keys", user) + response.status.should == 200 + json_response.should be_an Array + json_response.first["title"].should == key.title + end + end + end + + describe "GET /keys/:id" do + it "should returm single key" do + user.keys << key + user.save + get api("/keys/#{key.id}", user) + response.status.should == 200 + json_response["title"].should == key.title + end + it "should return 404 Not Found within invalid ID" do + get api("/keys/42", user) + response.status.should == 404 + end + end + + describe "POST /keys" do + it "should not create invalid ssh key" do + post api("/keys", user), { title: "invalid key" } + response.status.should == 404 + end + it "should create ssh key" do + key_attrs = Factory.attributes :key + expect { + post api("/keys", user), key_attrs + }.to change{ user.keys.count }.by(1) + end + end + + describe "DELETE /keys/:id" do + it "should delete existed key" do + user.keys << key + user.save + expect { + delete api("/keys/#{key.id}", user) + }.to change{user.keys.count}.by(-1) + end + it "should return 404 Not Found within invalid ID" do + delete api("/keys/42", user) + response.status.should == 404 + end + end + +end +