issues.rb 6.8 KB
Newer Older
1
module API
N
Nihad Abbasov 已提交
2 3 4 5
  # Issues API
  class Issues < Grape::API
    before { authenticate! }

J
jubianchi 已提交
6
    helpers do
J
jubianchi 已提交
7
      def filter_issues_state(issues, state)
J
jubianchi 已提交
8
        case state
9 10
        when 'opened' then issues.opened
        when 'closed' then issues.closed
11
        else issues
J
jubianchi 已提交
12 13
        end
      end
J
jubianchi 已提交
14 15

      def filter_issues_labels(issues, labels)
J
jubianchi 已提交
16 17 18 19 20
        issues.includes(:labels).where('labels.title' => labels.split(','))
      end

      def filter_issues_milestone(issues, milestone)
        issues.includes(:milestone).where('milestones.title' => milestone)
J
jubianchi 已提交
21
      end
J
jubianchi 已提交
22 23
    end

N
Nihad Abbasov 已提交
24 25 26
    resource :issues do
      # Get currently authenticated user's issues
      #
J
jubianchi 已提交
27 28
      # Parameters:
      #   state (optional) - Return "opened" or "closed" issues
J
jubianchi 已提交
29
      #   labels (optional) - Comma-separated list of label names
30 31 32
      #   order_by (optional) - Return requests ordered by `created_at` or `updated_at` fields. Default is `created_at`
      #   sort (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc`
      #
J
jubianchi 已提交
33
      # Example Requests:
N
Nihad Abbasov 已提交
34
      #   GET /issues
J
jubianchi 已提交
35 36
      #   GET /issues?state=opened
      #   GET /issues?state=closed
J
jubianchi 已提交
37 38 39
      #   GET /issues?labels=foo
      #   GET /issues?labels=foo,bar
      #   GET /issues?labels=foo,bar&state=opened
N
Nihad Abbasov 已提交
40
      get do
J
jubianchi 已提交
41 42 43
        issues = current_user.issues
        issues = filter_issues_state(issues, params[:state]) unless params[:state].nil?
        issues = filter_issues_labels(issues, params[:labels]) unless params[:labels].nil?
44
        issues.reorder(issuable_order_by => issuable_sort)
J
jubianchi 已提交
45
        present paginate(issues), with: Entities::Issue
N
Nihad Abbasov 已提交
46 47 48 49 50 51 52
      end
    end

    resource :projects do
      # Get a list of project issues
      #
      # Parameters:
53
      #   id (required) - The ID of a project
54
      #   iid (optional) - Return the project issue having the given `iid`
J
jubianchi 已提交
55
      #   state (optional) - Return "opened" or "closed" issues
J
jubianchi 已提交
56
      #   labels (optional) - Comma-separated list of label names
J
jubianchi 已提交
57
      #   milestone (optional) - Milestone title
58 59
      #   order_by (optional) - Return requests ordered by `created_at` or `updated_at` fields. Default is `created_at`
      #   sort (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc`
J
jubianchi 已提交
60 61
      #
      # Example Requests:
N
Nihad Abbasov 已提交
62
      #   GET /projects/:id/issues
J
jubianchi 已提交
63 64
      #   GET /projects/:id/issues?state=opened
      #   GET /projects/:id/issues?state=closed
J
jubianchi 已提交
65 66 67
      #   GET /projects/:id/issues?labels=foo
      #   GET /projects/:id/issues?labels=foo,bar
      #   GET /projects/:id/issues?labels=foo,bar&state=opened
J
jubianchi 已提交
68 69
      #   GET /projects/:id/issues?milestone=1.0.0
      #   GET /projects/:id/issues?milestone=1.0.0&state=closed
70
      #   GET /issues?iid=42
N
Nihad Abbasov 已提交
71
      get ":id/issues" do
J
jubianchi 已提交
72 73 74
        issues = user_project.issues
        issues = filter_issues_state(issues, params[:state]) unless params[:state].nil?
        issues = filter_issues_labels(issues, params[:labels]) unless params[:labels].nil?
75
        issues = filter_by_iid(issues, params[:iid]) unless params[:iid].nil?
76

J
jubianchi 已提交
77 78 79
        unless params[:milestone].nil?
          issues = filter_issues_milestone(issues, params[:milestone])
        end
J
jubianchi 已提交
80

81
        issues.reorder(issuable_order_by => issuable_sort)
J
jubianchi 已提交
82
        present paginate(issues), with: Entities::Issue
N
Nihad Abbasov 已提交
83 84 85 86 87
      end

      # Get a single project issue
      #
      # Parameters:
88
      #   id (required) - The ID of a project
N
Nihad Abbasov 已提交
89 90 91 92 93
      #   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])
94
        present @issue, with: Entities::Issue
N
Nihad Abbasov 已提交
95 96 97 98 99
      end

      # Create a new project issue
      #
      # Parameters:
100
      #   id (required) - The ID of a project
N
Nihad Abbasov 已提交
101 102 103 104 105 106 107 108
      #   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
109 110
        required_attributes! [:title]
        attrs = attributes_for_keys [:title, :description, :assignee_id, :milestone_id]
111

112
        # Validate label names in advance
113 114
        if (errors = validate_label_params(params)).any?
          render_api_error!({ labels: errors }, 400)
115 116
        end

117 118 119
        issue = ::Issues::CreateService.new(user_project, current_user, attrs).execute

        if issue.valid?
120 121
          # Find or create labels and attach to issue. Labels are valid because
          # we already checked its name, so there can't be an error here
122
          if params[:labels].present?
123
            issue.add_labels_by_names(params[:labels].split(','))
124 125
          end

126 127
          present issue, with: Entities::Issue
        else
J
jubianchi 已提交
128
          render_validation_error!(issue)
N
Nihad Abbasov 已提交
129 130 131 132 133 134
        end
      end

      # Update an existing issue
      #
      # Parameters:
135
      #   id (required) - The ID of a project
N
Nihad Abbasov 已提交
136 137 138 139 140 141
      #   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
142
      #   state_event (optional) - The state event of an issue (close|reopen)
N
Nihad Abbasov 已提交
143 144 145
      # Example Request:
      #   PUT /projects/:id/issues/:issue_id
      put ":id/issues/:issue_id" do
146 147 148 149
        issue = user_project.issues.find(params[:issue_id])
        authorize! :modify_issue, issue
        attrs = attributes_for_keys [:title, :description, :assignee_id, :milestone_id, :state_event]

150
        # Validate label names in advance
151 152
        if (errors = validate_label_params(params)).any?
          render_api_error!({ labels: errors }, 400)
153 154
        end

155
        issue = ::Issues::UpdateService.new(user_project, current_user, attrs).execute(issue)
156

157
        if issue.valid?
158 159
          # Find or create labels and attach to issue. Labels are valid because
          # we already checked its name, so there can't be an error here
160 161
          unless params[:labels].nil?
            issue.remove_labels
162 163
            # Create and add labels to the new created issue
            issue.add_labels_by_names(params[:labels].split(','))
164 165
          end

166 167
          present issue, with: Entities::Issue
        else
J
jubianchi 已提交
168
          render_validation_error!(issue)
N
Nihad Abbasov 已提交
169 170 171
        end
      end

172
      # Delete a project issue (deprecated)
N
Nihad Abbasov 已提交
173 174
      #
      # Parameters:
175
      #   id (required) - The ID of a project
N
Nihad Abbasov 已提交
176 177 178 179
      #   issue_id (required) - The ID of a project issue
      # Example Request:
      #   DELETE /projects/:id/issues/:issue_id
      delete ":id/issues/:issue_id" do
180
        not_allowed!
N
Nihad Abbasov 已提交
181 182 183 184
      end
    end
  end
end