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 | 274 | + `hook_id` (required) - The ID of hook to delete |
| 275 | 275 | |
| 276 | 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 | 356 | \ No newline at end of file | ... | ... |
lib/api/projects.rb
| ... | ... | @@ -424,6 +424,49 @@ module Gitlab |
| 424 | 424 | present tree.data |
| 425 | 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 | 470 | end |
| 428 | 471 | end |
| 429 | 472 | end | ... | ... |
spec/requests/api/projects_spec.rb
| ... | ... | @@ -11,6 +11,8 @@ describe Gitlab::API do |
| 11 | 11 | let!(:snippet) { create(:snippet, author: user, project: project, title: 'example') } |
| 12 | 12 | let!(:users_project) { create(:users_project, user: user, project: project, project_access: UsersProject::MASTER) } |
| 13 | 13 | let!(:users_project2) { create(:users_project, user: user3, project: project, project_access: UsersProject::DEVELOPER) } |
| 14 | + let(:key) { create(:key, project: project) } | |
| 15 | + | |
| 14 | 16 | before { project.team << [user, :reporter] } |
| 15 | 17 | |
| 16 | 18 | describe "GET /projects" do |
| ... | ... | @@ -380,4 +382,59 @@ describe Gitlab::API do |
| 380 | 382 | response.status.should == 404 |
| 381 | 383 | end |
| 382 | 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 | 440 | end | ... | ... |