Commit 7b33d8cbcab3b0ee5789ec607455ab62130db69f

Authored by Nihad Abbasov
1 parent 0f604e62

add issues API

@@ -15,5 +15,6 @@ module Gitlab @@ -15,5 +15,6 @@ module Gitlab
15 15
16 mount Users 16 mount Users
17 mount Projects 17 mount Projects
  18 + mount Issues
18 end 19 end
19 end 20 end
lib/api/entities.rb
@@ -25,5 +25,17 @@ module Gitlab @@ -25,5 +25,17 @@ module Gitlab
25 expose :author, :using => Entities::UserBasic 25 expose :author, :using => Entities::UserBasic
26 expose :expires_at, :updated_at, :created_at 26 expose :expires_at, :updated_at, :created_at
27 end 27 end
  28 +
  29 + class Milestone < Grape::Entity
  30 + expose :id, :title, :description, :due_date, :closed, :updated_at, :created_at
  31 + end
  32 +
  33 + class Issue < Grape::Entity
  34 + expose :id, :title, :description
  35 + expose :label_list, :as => :labels
  36 + expose :milestone, :using => Entities::Milestone
  37 + expose :assignee, :author, :using => Entities::UserBasic
  38 + expose :closed, :updated_at, :created_at
  39 + end
28 end 40 end
29 end 41 end
lib/api/issues.rb 0 → 100644
@@ -0,0 +1,111 @@ @@ -0,0 +1,111 @@
  1 +module Gitlab
  2 + # Issues API
  3 + class Issues < Grape::API
  4 + before { authenticate! }
  5 +
  6 + resource :issues do
  7 + # Get currently authenticated user's issues
  8 + #
  9 + # Example Request:
  10 + # GET /issues
  11 + get do
  12 + present current_user.issues, :with => Entities::Issue
  13 + end
  14 + end
  15 +
  16 + resource :projects do
  17 + # Get a list of project issues
  18 + #
  19 + # Parameters:
  20 + # id (required) - The code name of a project
  21 + # Example Request:
  22 + # GET /projects/:id/issues
  23 + get ":id/issues" do
  24 + present user_project.issues, :with => Entities::Issue
  25 + end
  26 +
  27 + # Get a single project issue
  28 + #
  29 + # Parameters:
  30 + # id (required) - The code name of a project
  31 + # issue_id (required) - The ID of a project issue
  32 + # Example Request:
  33 + # GET /projects/:id/issues/:issue_id
  34 + get ":id/issues/:issue_id" do
  35 + @issue = user_project.issues.find(params[:issue_id])
  36 + present @issue, :with => Entities::Issue
  37 + end
  38 +
  39 + # Create a new project issue
  40 + #
  41 + # Parameters:
  42 + # id (required) - The code name of a project
  43 + # title (required) - The title of an issue
  44 + # description (optional) - The description of an issue
  45 + # assignee_id (optional) - The ID of a user to assign issue
  46 + # milestone_id (optional) - The ID of a milestone to assign issue
  47 + # labels (optional) - The labels of an issue
  48 + # Example Request:
  49 + # POST /projects/:id/issues
  50 + post ":id/issues" do
  51 + @issue = user_project.issues.new(
  52 + :title => params[:title],
  53 + :description => params[:description],
  54 + :assignee_id => params[:assignee_id],
  55 + :milestone_id => params[:milestone_id],
  56 + :label_list => params[:labels]
  57 + )
  58 + @issue.author = current_user
  59 +
  60 + if @issue.save
  61 + present @issue, :with => Entities::Issue
  62 + else
  63 + error!({'message' => '404 Not found'}, 404)
  64 + end
  65 + end
  66 +
  67 + # Update an existing issue
  68 + #
  69 + # Parameters:
  70 + # id (required) - The code name of a project
  71 + # issue_id (required) - The ID of a project issue
  72 + # title (optional) - The title of an issue
  73 + # description (optional) - The description of an issue
  74 + # assignee_id (optional) - The ID of a user to assign issue
  75 + # milestone_id (optional) - The ID of a milestone to assign issue
  76 + # labels (optional) - The labels of an issue
  77 + # closed (optional) - The state of an issue (0 = false, 1 = true)
  78 + # Example Request:
  79 + # PUT /projects/:id/issues/:issue_id
  80 + put ":id/issues/:issue_id" do
  81 + @issue = user_project.issues.find(params[:issue_id])
  82 + parameters = {
  83 + :title => (params[:title] || @issue.title),
  84 + :description => (params[:description] || @issue.description),
  85 + :assignee_id => (params[:assignee_id] || @issue.assignee_id),
  86 + :milestone_id => (params[:milestone_id] || @issue.milestone_id),
  87 + :label_list => (params[:labels] || @issue.label_list),
  88 + :closed => (params[:closed] || @issue.closed)
  89 + }
  90 +
  91 + if @issue.update_attributes(parameters)
  92 + present @issue, :with => Entities::Issue
  93 + else
  94 + error!({'message' => '404 Not found'}, 404)
  95 + end
  96 + end
  97 +
  98 + # Delete a project issue
  99 + #
  100 + # Parameters:
  101 + # id (required) - The code name of a project
  102 + # issue_id (required) - The ID of a project issue
  103 + # Example Request:
  104 + # DELETE /projects/:id/issues/:issue_id
  105 + delete ":id/issues/:issue_id" do
  106 + @issue = user_project.issues.find(params[:issue_id])
  107 + @issue.destroy
  108 + end
  109 + end
  110 + end
  111 +end
spec/api/issues_spec.rb 0 → 100644
@@ -0,0 +1,71 @@ @@ -0,0 +1,71 @@
  1 +require 'spec_helper'
  2 +
  3 +describe Gitlab::API do
  4 + let(:user) { Factory :user }
  5 + let!(:project) { Factory :project, :owner => user }
  6 + let!(:issue) { Factory :issue, :author => user, :assignee => user, :project => project }
  7 + before { project.add_access(user, :read) }
  8 +
  9 + describe "GET /issues" do
  10 + it "should return authentication error" do
  11 + get "#{api_prefix}/issues"
  12 + response.status.should == 401
  13 + end
  14 +
  15 + describe "authenticated GET /issues" do
  16 + it "should return an array of issues" do
  17 + get "#{api_prefix}/issues?private_token=#{user.private_token}"
  18 + response.status.should == 200
  19 + json_response.should be_an Array
  20 + json_response.first['title'].should == issue.title
  21 + end
  22 + end
  23 + end
  24 +
  25 + describe "GET /projects/:id/issues" do
  26 + it "should return project issues" do
  27 + get "#{api_prefix}/projects/#{project.code}/issues?private_token=#{user.private_token}"
  28 + response.status.should == 200
  29 + json_response.should be_an Array
  30 + json_response.first['title'].should == issue.title
  31 + end
  32 + end
  33 +
  34 + describe "GET /projects/:id/issues/:issue_id" do
  35 + it "should return a project issue by id" do
  36 + get "#{api_prefix}/projects/#{project.code}/issues/#{issue.id}?private_token=#{user.private_token}"
  37 + response.status.should == 200
  38 + json_response['title'].should == issue.title
  39 + end
  40 + end
  41 +
  42 + describe "POST /projects/:id/issues" do
  43 + it "should create a new project issue" do
  44 + post "#{api_prefix}/projects/#{project.code}/issues?private_token=#{user.private_token}",
  45 + :title => 'new issue', :labels => 'label, label2'
  46 + response.status.should == 201
  47 + json_response['title'].should == 'new issue'
  48 + json_response['description'].should be_nil
  49 + json_response['labels'].should == ['label', 'label2']
  50 + end
  51 + end
  52 +
  53 + describe "PUT /projects/:id/issues/:issue_id" do
  54 + it "should update a project issue" do
  55 + put "#{api_prefix}/projects/#{project.code}/issues/#{issue.id}?private_token=#{user.private_token}",
  56 + :title => 'updated title', :labels => 'label2', :closed => 1
  57 + response.status.should == 200
  58 + json_response['title'].should == 'updated title'
  59 + json_response['labels'].should == ['label2']
  60 + json_response['closed'].should be_true
  61 + end
  62 + end
  63 +
  64 + describe "DELETE /projects/:id/issues/:issue_id" do
  65 + it "should delete a project issue" do
  66 + expect {
  67 + delete "#{api_prefix}/projects/#{project.code}/issues/#{issue.id}?private_token=#{user.private_token}"
  68 + }.to change { Issue.count }.by(-1)
  69 + end
  70 + end
  71 +end