Commit afee5303ff3a31d4b3eca82e19c7a326f2c86659
Exists in
master
and in
4 other branches
Merge pull request #3149 from m4tthumphrey/api-deploy-keys
Added methods to manage project deploy keys via API
Showing
3 changed files
with
179 additions
and
0 deletions
Show diff stats
doc/api/projects.md
@@ -274,3 +274,82 @@ Parameters: | @@ -274,3 +274,82 @@ Parameters: | ||
274 | + `hook_id` (required) - The ID of hook to delete | 274 | + `hook_id` (required) - The ID of hook to delete |
275 | 275 | ||
276 | Will return status `200 OK` on success, or `404 Not found` on fail. | 276 | Will return status `200 OK` on success, or `404 Not found` on fail. |
277 | + | ||
278 | + | ||
279 | +## List deploy keys | ||
280 | + | ||
281 | +Get a list of a project's deploy keys. | ||
282 | + | ||
283 | +``` | ||
284 | +GET /projects/:id/keys | ||
285 | +``` | ||
286 | + | ||
287 | +```json | ||
288 | +[ | ||
289 | + { | ||
290 | + "id": 1, | ||
291 | + "title" : "Public key" | ||
292 | + "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4 | ||
293 | + 596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4 | ||
294 | + soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=", | ||
295 | + }, | ||
296 | + { | ||
297 | + "id": 3, | ||
298 | + "title" : "Another Public key" | ||
299 | + "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4 | ||
300 | + 596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4 | ||
301 | + soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=" | ||
302 | + } | ||
303 | +] | ||
304 | +``` | ||
305 | + | ||
306 | +## Single deploy key | ||
307 | + | ||
308 | +Get a single key. | ||
309 | + | ||
310 | +``` | ||
311 | +GET /projects/:id/keys/:key_id | ||
312 | +``` | ||
313 | + | ||
314 | +Parameters: | ||
315 | + | ||
316 | ++ `id` (required) - The ID of an deploy key | ||
317 | + | ||
318 | +```json | ||
319 | +{ | ||
320 | + "id": 1, | ||
321 | + "title" : "Public key" | ||
322 | + "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4 | ||
323 | + 596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4 | ||
324 | + soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=" | ||
325 | +} | ||
326 | +``` | ||
327 | +## Add deploy key | ||
328 | + | ||
329 | +Create new deploy key for a project | ||
330 | + | ||
331 | +``` | ||
332 | +POST /projects/:id/keys | ||
333 | +``` | ||
334 | + | ||
335 | +Parameters: | ||
336 | + | ||
337 | ++ `title` (required) - new deploy key's title | ||
338 | ++ `key` (required) - new deploy key | ||
339 | + | ||
340 | +Will return created key with status `201 Created` on success, or `404 Not | ||
341 | +found` on fail. | ||
342 | + | ||
343 | +## Delete deploy key | ||
344 | + | ||
345 | +Delete a deploy key from a project | ||
346 | + | ||
347 | +``` | ||
348 | +DELETE /projects/:id/keys/:key_id | ||
349 | +``` | ||
350 | + | ||
351 | +Parameters: | ||
352 | + | ||
353 | ++ `id` (required) - Deploy key ID | ||
354 | + | ||
355 | +Will return `200 OK` on success, or `404 Not Found` on fail. | ||
277 | \ No newline at end of file | 356 | \ No newline at end of file |
lib/api/projects.rb
@@ -424,6 +424,49 @@ module Gitlab | @@ -424,6 +424,49 @@ module Gitlab | ||
424 | present tree.data | 424 | present tree.data |
425 | end | 425 | end |
426 | 426 | ||
427 | + # Get a specific project's keys | ||
428 | + # | ||
429 | + # Example Request: | ||
430 | + # GET /projects/:id/keys | ||
431 | + get ":id/keys" do | ||
432 | + present user_project.deploy_keys, with: Entities::SSHKey | ||
433 | + end | ||
434 | + | ||
435 | + # Get single key owned by currently authenticated user | ||
436 | + # | ||
437 | + # Example Request: | ||
438 | + # GET /projects/:id/keys/:id | ||
439 | + get ":id/keys/:key_id" do | ||
440 | + key = user_project.deploy_keys.find params[:key_id] | ||
441 | + present key, with: Entities::SSHKey | ||
442 | + end | ||
443 | + | ||
444 | + # Add new ssh key to currently authenticated user | ||
445 | + # | ||
446 | + # Parameters: | ||
447 | + # key (required) - New SSH Key | ||
448 | + # title (required) - New SSH Key's title | ||
449 | + # Example Request: | ||
450 | + # POST /projects/:id/keys | ||
451 | + post ":id/keys" do | ||
452 | + attrs = attributes_for_keys [:title, :key] | ||
453 | + key = user_project.deploy_keys.new attrs | ||
454 | + if key.save | ||
455 | + present key, with: Entities::SSHKey | ||
456 | + else | ||
457 | + not_found! | ||
458 | + end | ||
459 | + end | ||
460 | + | ||
461 | + # Delete existed ssh key of currently authenticated user | ||
462 | + # | ||
463 | + # Example Request: | ||
464 | + # DELETE /projects/:id/keys/:id | ||
465 | + delete ":id/keys/:key_id" do | ||
466 | + key = user_project.deploy_keys.find params[:key_id] | ||
467 | + key.delete | ||
468 | + end | ||
469 | + | ||
427 | end | 470 | end |
428 | end | 471 | end |
429 | end | 472 | end |
spec/requests/api/projects_spec.rb
@@ -11,6 +11,8 @@ describe Gitlab::API do | @@ -11,6 +11,8 @@ describe Gitlab::API do | ||
11 | let!(:snippet) { create(:snippet, author: user, project: project, title: 'example') } | 11 | let!(:snippet) { create(:snippet, author: user, project: project, title: 'example') } |
12 | let!(:users_project) { create(:users_project, user: user, project: project, project_access: UsersProject::MASTER) } | 12 | let!(:users_project) { create(:users_project, user: user, project: project, project_access: UsersProject::MASTER) } |
13 | let!(:users_project2) { create(:users_project, user: user3, project: project, project_access: UsersProject::DEVELOPER) } | 13 | let!(:users_project2) { create(:users_project, user: user3, project: project, project_access: UsersProject::DEVELOPER) } |
14 | + let(:key) { create(:key, project: project) } | ||
15 | + | ||
14 | before { project.team << [user, :reporter] } | 16 | before { project.team << [user, :reporter] } |
15 | 17 | ||
16 | describe "GET /projects" do | 18 | describe "GET /projects" do |
@@ -380,4 +382,59 @@ describe Gitlab::API do | @@ -380,4 +382,59 @@ describe Gitlab::API do | ||
380 | response.status.should == 404 | 382 | response.status.should == 404 |
381 | end | 383 | end |
382 | end | 384 | end |
385 | + | ||
386 | + describe "GET /projects/:id/keys" do | ||
387 | + it "should return array of ssh keys" do | ||
388 | + project.deploy_keys << key | ||
389 | + project.save | ||
390 | + get api("/projects/#{project.id}/keys", user) | ||
391 | + response.status.should == 200 | ||
392 | + json_response.should be_an Array | ||
393 | + json_response.first['title'].should == key.title | ||
394 | + end | ||
395 | + end | ||
396 | + | ||
397 | + describe "GET /projects/:id/keys/:key_id" do | ||
398 | + it "should return a single key" do | ||
399 | + project.deploy_keys << key | ||
400 | + project.save | ||
401 | + get api("/projects/#{project.id}/keys/#{key.id}", user) | ||
402 | + response.status.should == 200 | ||
403 | + json_response['title'].should == key.title | ||
404 | + end | ||
405 | + | ||
406 | + it "should return 404 Not Found with invalid ID" do | ||
407 | + get api("/projects/#{project.id}/keys/404", user) | ||
408 | + response.status.should == 404 | ||
409 | + end | ||
410 | + end | ||
411 | + | ||
412 | + describe "POST /projects/:id/keys" do | ||
413 | + it "should not create an invalid ssh key" do | ||
414 | + post api("/projects/#{project.id}/keys", user), { title: "invalid key" } | ||
415 | + response.status.should == 404 | ||
416 | + end | ||
417 | + | ||
418 | + it "should create new ssh key" do | ||
419 | + key_attrs = attributes_for :key | ||
420 | + expect { | ||
421 | + post api("/projects/#{project.id}/keys", user), key_attrs | ||
422 | + }.to change{ project.deploy_keys.count }.by(1) | ||
423 | + end | ||
424 | + end | ||
425 | + | ||
426 | + describe "DELETE /projects/:id/keys/:key_id" do | ||
427 | + it "should delete existing key" do | ||
428 | + project.deploy_keys << key | ||
429 | + project.save | ||
430 | + expect { | ||
431 | + delete api("/projects/#{project.id}/keys/#{key.id}", user) | ||
432 | + }.to change{ project.deploy_keys.count }.by(-1) | ||
433 | + end | ||
434 | + | ||
435 | + it "should return 404 Not Found with invalid ID" do | ||
436 | + delete api("/projects/#{project.id}/keys/404", user) | ||
437 | + response.status.should == 404 | ||
438 | + end | ||
439 | + end | ||
383 | end | 440 | end |