diff options
-rw-r--r-- | config/routes.rb | 1 | ||||
-rw-r--r-- | doc/api/notes.md | 10 | ||||
-rw-r--r-- | doc/api/projects.md | 7 | ||||
-rw-r--r-- | lib/api.rb | 13 | ||||
-rw-r--r-- | lib/api/merge_requests.rb | 22 | ||||
-rw-r--r-- | lib/api/milestones.rb | 16 | ||||
-rw-r--r-- | lib/api/notes.rb | 2 | ||||
-rw-r--r-- | lib/api/projects.rb | 6 | ||||
-rw-r--r-- | spec/requests/api/merge_requests_spec.rb | 40 | ||||
-rw-r--r-- | spec/requests/api/milestones_spec.rb | 24 | ||||
-rw-r--r-- | spec/requests/api/notes_spec.rb | 30 | ||||
-rw-r--r-- | spec/requests/api/projects_spec.rb | 17 |
12 files changed, 180 insertions, 8 deletions
diff --git a/config/routes.rb b/config/routes.rb index d6432b86007..ddf284f1fe5 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -8,6 +8,7 @@ Gitlab::Application.routes.draw do # API require 'api' + Gitlab::API.logger Rails.logger mount Gitlab::API => '/api' constraint = lambda { |request| request.env["warden"].authenticate? and request.env['warden'].user.admin? } diff --git a/doc/api/notes.md b/doc/api/notes.md index a4ba2826076..eef4b63fcaf 100644 --- a/doc/api/notes.md +++ b/doc/api/notes.md @@ -89,7 +89,7 @@ Parameters: Get an issue note. ``` -GET /projects/:id/issues/:issue_id/:notes/:note_id +GET /projects/:id/issues/:issue_id/notes/:note_id ``` Parameters: @@ -103,7 +103,7 @@ Parameters: Get a snippet note. ``` -GET /projects/:id/issues/:snippet_id/:notes/:note_id +GET /projects/:id/issues/:snippet_id/notes/:note_id ``` Parameters: @@ -127,7 +127,7 @@ Parameters: + `id` (required) - The ID of a project + `body` (required) - The content of a note -Will return created note with status `201 Created` on success, or `404 Not found` on fail. +Will return created note with status `201 Created` on success, `400 Bad Request` if the body attribute is missing or `404 Not found` on fail. ### New issue note @@ -144,7 +144,7 @@ Parameters: + `issue_id` (required) - The ID of an issue + `body` (required) - The content of a note -Will return created note with status `201 Created` on success, or `404 Not found` on fail. +Will return created note with status `201 Created` on success, `400 Bad Request` if the body attribute is missing or `404 Not found` on fail. ### New snippet note @@ -160,4 +160,4 @@ Parameters: + `snippet_id` (required) - The ID of an snippet + `body` (required) - The content of a note -Will return created note with status `201 Created` on success, or `404 Not found` on fail. +Will return created note with status `201 Created` on success, `400 Bad Request` if the body attribute is missing or `404 Not found` on fail. diff --git a/doc/api/projects.md b/doc/api/projects.md index 82bb0c0d561..03731427703 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -197,7 +197,10 @@ Parameters: + `id` (required) - The ID of a project + `user_id` (required) - The ID of a team member -Status code `200` will be returned on success. +Status code `200 OK` will be returned on success. This method is idempotent and call be called multiple +times with the same parameters. Revoking team membership for a user who is not currently a team member is +considered success. Please note that the returned JSON currently differs slightly. Thus you should not +rely on the returned JSON structure. ## List project hooks @@ -221,7 +224,7 @@ Get hook for project GET /projects/:id/hooks/:hook_id ``` -Parameters: +Parameters:ยง + `id` (required) - The ID of a project + `hook_id` (required) - The ID of a project hook diff --git a/lib/api.rb b/lib/api.rb index d9dce7c70cc..ffd980ca7e0 100644 --- a/lib/api.rb +++ b/lib/api.rb @@ -8,6 +8,19 @@ module Gitlab rack_response({'message' => '404 Not found'}.to_json, 404) end + rescue_from :all do |exception| + # lifted from https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb#L60 + # why is this not wrapped in something reusable? + trace = exception.backtrace + + message = "\n#{exception.class} (#{exception.message}):\n" + message << exception.annoted_source_code.to_s if exception.respond_to?(:annoted_source_code) + message << " " << trace.join("\n ") + + API.logger.add Logger::FATAL, message + rack_response({'message' => '500 Internal Server Error'}, 500) + end + format :json error_format :json helpers APIHelpers diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb index 470cd1e1c2d..a0ca3026acb 100644 --- a/lib/api/merge_requests.rb +++ b/lib/api/merge_requests.rb @@ -5,6 +5,23 @@ module Gitlab resource :projects do + helpers do + # If an error occurred this helper method provides an appropriate status code + # + # Parameters: + # merge_request_errors (required) - The errors collection of MR + # + def handle_merge_request_error(merge_request_errors) + if merge_request_errors[:target_branch].any? + error!(merge_request_errors[:target_branch], 400) + elsif merge_request_errors[:source_branch].any? + error!(merge_request_errors[:source_branch], 400) + elsif merge_request_errors[:base].any? + error!(merge_request_errors[:base], 422) + end + end + end + # List merge requests # # Parameters: @@ -60,6 +77,7 @@ module Gitlab merge_request.reload_code present merge_request, with: Entities::MergeRequest else + handle_merge_request_error(merge_request.errors) not_found! end end @@ -88,6 +106,7 @@ module Gitlab merge_request.mark_as_unchecked present merge_request, with: Entities::MergeRequest else + handle_merge_request_error(merge_request.errors) not_found! end end @@ -109,6 +128,9 @@ module Gitlab if note.save present note, with: Entities::MRNote else + if note.errors[:note].any? + error!(note.errors[:note], 400) + end not_found! end end diff --git a/lib/api/milestones.rb b/lib/api/milestones.rb index 6aca9d01b09..1f7d0876120 100644 --- a/lib/api/milestones.rb +++ b/lib/api/milestones.rb @@ -4,6 +4,20 @@ module Gitlab before { authenticate! } resource :projects do + + helpers do + # If an error occurs this helper method handles error codes for a given milestone + # + # Parameters: + # milestone_errors (required) - The erros collection of a milestone + # + def handle_milestone_errors(milestone_errors) + if milestone_errors[:title].any? + error!(milestone_errors[:title], 400) + end + end + end + # Get a list of project milestones # # Parameters: @@ -47,6 +61,7 @@ module Gitlab if @milestone.save present @milestone, with: Entities::Milestone else + handle_milestone_errors(@milestone.errors) not_found! end end @@ -70,6 +85,7 @@ module Gitlab if @milestone.update_attributes attrs present @milestone, with: Entities::Milestone else + handle_milestone_errors(@milestone.errors) not_found! end end diff --git a/lib/api/notes.rb b/lib/api/notes.rb index 70344d6e381..47dead9dfae 100644 --- a/lib/api/notes.rb +++ b/lib/api/notes.rb @@ -43,6 +43,8 @@ module Gitlab if @note.save present @note, with: Entities::Note else + # :note is exposed as :body, but :note is set on error + error!(@note.errors[:note], 400) if @note.errors[:note].any? not_found! end end diff --git a/lib/api/projects.rb b/lib/api/projects.rb index a16243aa822..47ab4e1aab0 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -132,7 +132,11 @@ module Gitlab delete ":id/members/:user_id" do authorize! :admin_project, user_project users_project = user_project.users_projects.find_by_user_id params[:user_id] - users_project.destroy + unless users_project.nil? + users_project.destroy + else + {:message => "Access revoked", :id => params[:user_id].to_i} + end end # Get project hooks diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb index 5da54154a81..4e7a84dfb47 100644 --- a/spec/requests/api/merge_requests_spec.rb +++ b/spec/requests/api/merge_requests_spec.rb @@ -41,6 +41,24 @@ describe Gitlab::API do response.status.should == 201 json_response['title'].should == 'Test merge_request' end + + it "should return 422 when source_branch equals target_branch" do + post api("/projects/#{project.id}/merge_requests", user), + title: "Test merge_request", source_branch: "master", target_branch: "master", author: user + response.status.should == 422 + end + + it "should return 400 when source_branch is missing" do + post api("/projects/#{project.id}/merge_requests", user), + title: "Test merge_request", target_branch: "master", author: user + response.status.should == 400 + end + + it "should return 400 when target_branch is missing" do + post api("/projects/#{project.id}/merge_requests", user), + title: "Test merge_request", source_branch: "stable", author: user + response.status.should == 400 + end end describe "PUT /projects/:id/merge_request/:merge_request_id" do @@ -49,6 +67,18 @@ describe Gitlab::API do response.status.should == 200 json_response['title'].should == 'New title' end + + it "should return 422 when source_branch and target_branch are renamed the same" do + put api("/projects/#{project.id}/merge_request/#{merge_request.id}", user), + source_branch: "master", target_branch: "master" + response.status.should == 422 + end + + it "should return merge_request with renamed target_branch" do + put api("/projects/#{project.id}/merge_request/#{merge_request.id}", user), target_branch: "test" + response.status.should == 200 + json_response['target_branch'].should == 'test' + end end describe "POST /projects/:id/merge_request/:merge_request_id/comments" do @@ -57,6 +87,16 @@ describe Gitlab::API do response.status.should == 201 json_response['note'].should == 'My comment' end + + it "should return 400 if note is missing" do + post api("/projects/#{project.id}/merge_request/#{merge_request.id}/comments", user) + response.status.should == 400 + end + + it "should return 404 if note is attached to non existent merge request" do + post api("/projects/#{project.id}/merge_request/111/comments", user), note: "My comment" + response.status.should == 404 + end end end diff --git a/spec/requests/api/milestones_spec.rb b/spec/requests/api/milestones_spec.rb index 80696671462..3cab63557a9 100644 --- a/spec/requests/api/milestones_spec.rb +++ b/spec/requests/api/milestones_spec.rb @@ -24,6 +24,11 @@ describe Gitlab::API do response.status.should == 200 json_response['title'].should == milestone.title end + + it "should return a 404 error if milestone id not found" do + get api("/projects/#{project.id}/milestones/1234", user) + response.status.should == 404 + end end describe "POST /projects/:id/milestones" do @@ -34,6 +39,19 @@ describe Gitlab::API do json_response['title'].should == 'new milestone' json_response['description'].should be_nil end + + it "should create a new project milestone with description and due date" do + post api("/projects/#{project.id}/milestones", user), + title: 'new milestone', description: 'release', due_date: '2013-03-02' + response.status.should == 201 + json_response['description'].should == 'release' + json_response['due_date'].should == '2013-03-02' + end + + it "should return a 400 error if title is missing" do + post api("/projects/#{project.id}/milestones", user) + response.status.should == 400 + end end describe "PUT /projects/:id/milestones/:milestone_id" do @@ -43,5 +61,11 @@ describe Gitlab::API do response.status.should == 200 json_response['title'].should == 'updated title' end + + it "should return a 404 error if milestone is not found" do + put api("/projects/#{project.id}/milestones/1234", user), + title: 'updated title' + response.status.should == 404 + end end end diff --git a/spec/requests/api/notes_spec.rb b/spec/requests/api/notes_spec.rb index ee99d85df4d..d382d7d9294 100644 --- a/spec/requests/api/notes_spec.rb +++ b/spec/requests/api/notes_spec.rb @@ -38,6 +38,11 @@ describe Gitlab::API do response.status.should == 200 json_response['body'].should == wall_note.note end + + it "should return a 404 error if note not found" do + get api("/projects/#{project.id}/notes/123", user) + response.status.should == 404 + end end describe "POST /projects/:id/notes" do @@ -46,6 +51,11 @@ describe Gitlab::API do response.status.should == 201 json_response['body'].should == 'hi!' end + + it "should return a 400 error if body is missing" do + post api("/projects/#{project.id}/notes", user) + response.status.should == 400 + end end describe "GET /projects/:id/noteable/:noteable_id/notes" do @@ -56,6 +66,11 @@ describe Gitlab::API do json_response.should be_an Array json_response.first['body'].should == issue_note.note end + + it "should return a 404 error when issue id not found" do + get api("/projects/#{project.id}/issues/123/notes", user) + response.status.should == 404 + end end context "when noteable is a Snippet" do @@ -65,6 +80,11 @@ describe Gitlab::API do json_response.should be_an Array json_response.first['body'].should == snippet_note.note end + + it "should return a 404 error when snippet id not found" do + get api("/projects/#{project.id}/snippets/42/notes", user) + response.status.should == 404 + end end context "when noteable is a Merge Request" do @@ -84,6 +104,11 @@ describe Gitlab::API do response.status.should == 200 json_response['body'].should == issue_note.note end + + it "should return a 404 error if issue note not found" do + get api("/projects/#{project.id}/issues/#{issue.id}/notes/123", user) + response.status.should == 404 + end end context "when noteable is a Snippet" do @@ -92,6 +117,11 @@ describe Gitlab::API do response.status.should == 200 json_response['body'].should == snippet_note.note end + + it "should return a 404 error if snippet note not found" do + get api("/projects/#{project.id}/snippets/#{snippet.id}/notes/123", user) + response.status.should == 404 + end end end diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index d932fd9e74d..2682629e7db 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -89,6 +89,12 @@ describe Gitlab::API do response.status.should == 404 json_response['message'].should == '404 Not Found' end + + it "should return a 404 error if user is not a member" do + other_user = create(:user) + get api("/projects/#{project.id}", other_user) + response.status.should == 404 + end end describe "GET /projects/:id/repository/branches" do @@ -190,6 +196,17 @@ describe Gitlab::API do end end + describe "DELETE /projects/:id/members/:user_id" do + it "should return 200 OK when the user was not member" do + expect { + delete api("/projects/#{project.id}/members/1000000", user) + }.to change { UsersProject.count }.by(0) + response.status.should == 200 + json_response['message'].should == "Access revoked" + json_response['id'].should == 1000000 + end + end + describe "GET /projects/:id/hooks" do it "should return project hooks" do get api("/projects/#{project.id}/hooks", user) |