summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNihad Abbasov <narkoz.2008@gmail.com>2012-07-24 05:19:51 -0700
committerNihad Abbasov <narkoz.2008@gmail.com>2012-07-24 05:19:51 -0700
commit7b33d8cbcab3b0ee5789ec607455ab62130db69f (patch)
treeface779cd41b36844c010dcd367d366fd9c4b29d
parent0f604e62fb453f2359ebc0438fe7dfaff8e55d10 (diff)
downloadgitlab-ce-7b33d8cbcab3b0ee5789ec607455ab62130db69f.tar.gz
add issues API
-rw-r--r--lib/api.rb1
-rw-r--r--lib/api/entities.rb12
-rw-r--r--lib/api/issues.rb111
-rw-r--r--spec/api/issues_spec.rb71
4 files changed, 195 insertions, 0 deletions
diff --git a/lib/api.rb b/lib/api.rb
index e24e0a78f71..6a8a3d651c0 100644
--- a/lib/api.rb
+++ b/lib/api.rb
@@ -15,5 +15,6 @@ module Gitlab
mount Users
mount Projects
+ mount Issues
end
end
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index f57545ff2f5..e5095f7189e 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -25,5 +25,17 @@ module Gitlab
expose :author, :using => Entities::UserBasic
expose :expires_at, :updated_at, :created_at
end
+
+ class Milestone < Grape::Entity
+ expose :id, :title, :description, :due_date, :closed, :updated_at, :created_at
+ end
+
+ class Issue < Grape::Entity
+ expose :id, :title, :description
+ expose :label_list, :as => :labels
+ expose :milestone, :using => Entities::Milestone
+ expose :assignee, :author, :using => Entities::UserBasic
+ expose :closed, :updated_at, :created_at
+ end
end
end
diff --git a/lib/api/issues.rb b/lib/api/issues.rb
new file mode 100644
index 00000000000..2b6a1ac269d
--- /dev/null
+++ b/lib/api/issues.rb
@@ -0,0 +1,111 @@
+module Gitlab
+ # Issues API
+ class Issues < Grape::API
+ before { authenticate! }
+
+ resource :issues do
+ # Get currently authenticated user's issues
+ #
+ # Example Request:
+ # GET /issues
+ get do
+ present current_user.issues, :with => Entities::Issue
+ end
+ end
+
+ resource :projects do
+ # Get a list of project issues
+ #
+ # Parameters:
+ # id (required) - The code name of a project
+ # Example Request:
+ # GET /projects/:id/issues
+ get ":id/issues" do
+ present user_project.issues, :with => Entities::Issue
+ end
+
+ # Get a single project issue
+ #
+ # Parameters:
+ # id (required) - The code name of a project
+ # issue_id (required) - The ID of a project issue
+ # Example Request:
+ # GET /projects/:id/issues/:issue_id
+ get ":id/issues/:issue_id" do
+ @issue = user_project.issues.find(params[:issue_id])
+ present @issue, :with => Entities::Issue
+ end
+
+ # Create a new project issue
+ #
+ # Parameters:
+ # id (required) - The code name of a project
+ # title (required) - The title of an issue
+ # description (optional) - The description of an issue
+ # assignee_id (optional) - The ID of a user to assign issue
+ # milestone_id (optional) - The ID of a milestone to assign issue
+ # labels (optional) - The labels of an issue
+ # Example Request:
+ # POST /projects/:id/issues
+ post ":id/issues" do
+ @issue = user_project.issues.new(
+ :title => params[:title],
+ :description => params[:description],
+ :assignee_id => params[:assignee_id],
+ :milestone_id => params[:milestone_id],
+ :label_list => params[:labels]
+ )
+ @issue.author = current_user
+
+ if @issue.save
+ present @issue, :with => Entities::Issue
+ else
+ error!({'message' => '404 Not found'}, 404)
+ end
+ end
+
+ # Update an existing issue
+ #
+ # Parameters:
+ # id (required) - The code name of a project
+ # issue_id (required) - The ID of a project issue
+ # title (optional) - The title of an issue
+ # description (optional) - The description of an issue
+ # assignee_id (optional) - The ID of a user to assign issue
+ # milestone_id (optional) - The ID of a milestone to assign issue
+ # labels (optional) - The labels of an issue
+ # closed (optional) - The state of an issue (0 = false, 1 = true)
+ # Example Request:
+ # PUT /projects/:id/issues/:issue_id
+ put ":id/issues/:issue_id" do
+ @issue = user_project.issues.find(params[:issue_id])
+ parameters = {
+ :title => (params[:title] || @issue.title),
+ :description => (params[:description] || @issue.description),
+ :assignee_id => (params[:assignee_id] || @issue.assignee_id),
+ :milestone_id => (params[:milestone_id] || @issue.milestone_id),
+ :label_list => (params[:labels] || @issue.label_list),
+ :closed => (params[:closed] || @issue.closed)
+ }
+
+ if @issue.update_attributes(parameters)
+ present @issue, :with => Entities::Issue
+ else
+ error!({'message' => '404 Not found'}, 404)
+ end
+ end
+
+ # Delete a project issue
+ #
+ # Parameters:
+ # id (required) - The code name of a project
+ # issue_id (required) - The ID of a project issue
+ # Example Request:
+ # DELETE /projects/:id/issues/:issue_id
+ delete ":id/issues/:issue_id" do
+ @issue = user_project.issues.find(params[:issue_id])
+ @issue.destroy
+ end
+ end
+ end
+end
diff --git a/spec/api/issues_spec.rb b/spec/api/issues_spec.rb
new file mode 100644
index 00000000000..d81a07e214b
--- /dev/null
+++ b/spec/api/issues_spec.rb
@@ -0,0 +1,71 @@
+require 'spec_helper'
+
+describe Gitlab::API do
+ let(:user) { Factory :user }
+ let!(:project) { Factory :project, :owner => user }
+ let!(:issue) { Factory :issue, :author => user, :assignee => user, :project => project }
+ before { project.add_access(user, :read) }
+
+ describe "GET /issues" do
+ it "should return authentication error" do
+ get "#{api_prefix}/issues"
+ response.status.should == 401
+ end
+
+ describe "authenticated GET /issues" do
+ it "should return an array of issues" do
+ get "#{api_prefix}/issues?private_token=#{user.private_token}"
+ response.status.should == 200
+ json_response.should be_an Array
+ json_response.first['title'].should == issue.title
+ end
+ end
+ end
+
+ describe "GET /projects/:id/issues" do
+ it "should return project issues" do
+ get "#{api_prefix}/projects/#{project.code}/issues?private_token=#{user.private_token}"
+ response.status.should == 200
+ json_response.should be_an Array
+ json_response.first['title'].should == issue.title
+ end
+ end
+
+ describe "GET /projects/:id/issues/:issue_id" do
+ it "should return a project issue by id" do
+ get "#{api_prefix}/projects/#{project.code}/issues/#{issue.id}?private_token=#{user.private_token}"
+ response.status.should == 200
+ json_response['title'].should == issue.title
+ end
+ end
+
+ describe "POST /projects/:id/issues" do
+ it "should create a new project issue" do
+ post "#{api_prefix}/projects/#{project.code}/issues?private_token=#{user.private_token}",
+ :title => 'new issue', :labels => 'label, label2'
+ response.status.should == 201
+ json_response['title'].should == 'new issue'
+ json_response['description'].should be_nil
+ json_response['labels'].should == ['label', 'label2']
+ end
+ end
+
+ describe "PUT /projects/:id/issues/:issue_id" do
+ it "should update a project issue" do
+ put "#{api_prefix}/projects/#{project.code}/issues/#{issue.id}?private_token=#{user.private_token}",
+ :title => 'updated title', :labels => 'label2', :closed => 1
+ response.status.should == 200
+ json_response['title'].should == 'updated title'
+ json_response['labels'].should == ['label2']
+ json_response['closed'].should be_true
+ end
+ end
+
+ describe "DELETE /projects/:id/issues/:issue_id" do
+ it "should delete a project issue" do
+ expect {
+ delete "#{api_prefix}/projects/#{project.code}/issues/#{issue.id}?private_token=#{user.private_token}"
+ }.to change { Issue.count }.by(-1)
+ end
+ end
+end