Project

General

Profile

Patch #19116 » 0001-REST-API-add-files-REST-API_v3.patch

Jake Kemme, 2016-07-22 19:07

View differences:

app/controllers/files_controller.rb
20 20

  
21 21
  before_action :find_project_by_project_id
22 22
  before_action :authorize
23
  accept_api_auth :index, :create
23 24

  
25
  helper :attachments 
24 26
  helper :sort
25 27
  include SortHelper
26 28

  
......
35 37
                     references(:attachments).reorder(sort_clause).find(@project.id)]
36 38
    @containers += @project.versions.includes(:attachments).
37 39
                    references(:attachments).reorder(sort_clause).to_a.sort.reverse
38
    render :layout => !request.xhr?
40
    respond_to do |format|
41
      format.html { render :layout => !request.xhr? }
42
      format.api
43
    end
39 44
  end
40 45

  
41 46
  def new
......
43 48
  end
44 49

  
45 50
  def create
46
    container = (params[:version_id].blank? ? @project : @project.versions.find_by_id(params[:version_id]))
47
    attachments = Attachment.attach_files(container, params[:attachments])
51
    version_id = params[:version_id] || (params[:file] && params[:file][:version_id])
52
    container = version_id.blank? ? @project : @project.versions.find_by_id(version_id)
53
    attachments = Attachment.attach_files(container, (params[:attachments] || (params[:file] && params[:file][:token] && params)))
48 54
    render_attachment_warning_if_needed(container)
49 55

  
50 56
    if attachments[:files].present?
51 57
      if Setting.notified_events.include?('file_added')
52 58
        Mailer.attachments_added(attachments[:files]).deliver
53 59
      end
54
      flash[:notice] = l(:label_file_added)
55
      redirect_to project_files_path(@project)
60
      respond_to do |format|
61
        format.html {
62
          flash[:notice] = l(:label_file_added)
63
          redirect_to project_files_path(@project) }
64
        format.api { render_api_ok }
65
      end
56 66
    else
57
      flash.now[:error] = l(:label_attachment) + " " + l('activerecord.errors.messages.invalid')
58
      new
59
      render :action => 'new'
67
      respond_to do |format|
68
        format.html {
69
          flash.now[:error] = l(:label_attachment) + " " + l('activerecord.errors.messages.invalid')
70
          new
71
          render :action => 'new' }
72
        format.api { render :status => :bad_request }
73
      end
60 74
    end
61 75
  end
62 76
end
app/helpers/attachments_helper.rb
51 51
    end
52 52
  end
53 53

  
54
  def render_api_attachment(attachment, api)
54
  def render_api_attachment(attachment, api, options={})
55 55
    api.attachment do
56 56
      api.id attachment.id
57 57
      api.filename attachment.filename
......
64 64
      end
65 65
      api.author(:id => attachment.author.id, :name => attachment.author.name) if attachment.author
66 66
      api.created_on attachment.created_on
67
      options.each { |key, value| eval("api.#{key} value") }
67 68
    end
68 69
  end
69 70
end
test/integration/api_test/api_routing_test.rb
32 32
    should_route 'GET /enumerations/issue_priorities' => 'enumerations#index', :type => 'issue_priorities'
33 33
  end
34 34

  
35
  def test_files
36
    should_route 'GET /projects/foo/files' => 'files#index', :project_id => 'foo'
37
    should_route 'POST /projects/foo/files' => 'files#create', :project_id => 'foo'
38
  end
39

  
35 40
  def test_groups
36 41
    should_route 'GET /groups' => 'groups#index'
37 42
    should_route 'POST /groups' => 'groups#create'
test/integration/api_test/files_test.rb
1
# Redmine - project management software
2
# Copyright (C) 2006-2015  Jean-Philippe Lang
3
#
4
# This program is free software; you can redistribute it and/or
5
# modify it under the terms of the GNU General Public License
6
# as published by the Free Software Foundation; either version 2
7
# of the License, or (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17

  
18
require File.expand_path('../../../test_helper', __FILE__)
19

  
20
class Redmine::ApiTest::FilesTest < Redmine::ApiTest::Base
21
  fixtures :projects,
22
           :users,
23
           :members,
24
           :roles,
25
           :member_roles,
26
           :enabled_modules,
27
           :attachments,
28
           :versions
29

  
30
  test "GET /projects/:project_id/files.xml should return the list of uploaded files" do
31
    get '/projects/1/files.xml', {}, credentials('jsmith')
32
    assert_response :success
33
    assert_select 'files attachment id', :text => '8'
34
  end
35

  
36
  test "POST /projects/:project_id/files.json should create a file" do
37
    set_tmp_attachments_directory
38
    post '/uploads.xml', 'File content', {"CONTENT_TYPE" => 'application/octet-stream'}.merge(credentials('jsmith'))
39
    token = Attachment.last.token
40
    payload = <<-JSON
41
{ "file": {
42
    "token": "#{token}"
43
  }
44
}
45
    JSON
46
    post '/projects/1/files.json', payload, {"CONTENT_TYPE" => 'application/json'}.merge(credentials('jsmith'))
47
    assert_response :success
48
    assert_equal 1, Attachment.last.container_id
49
    assert_equal "Project", Attachment.last.container_type
50
  end
51

  
52
  test "POST /projects/:project_id/files.xml should create a file" do
53
    set_tmp_attachments_directory
54
    post '/uploads.xml', 'File content', {"CONTENT_TYPE" => 'application/octet-stream'}.merge(credentials('jsmith'))
55
    token = Attachment.last.token
56
    payload = <<-XML
57
<file>
58
  <token>#{token}</token>
59
</file>
60
    XML
61
    post '/projects/1/files.xml', payload, {"CONTENT_TYPE" => 'application/xml'}.merge(credentials('jsmith'))
62
    assert_response :success
63
    assert_equal 1, Attachment.last.container_id
64
    assert_equal "Project", Attachment.last.container_type
65
  end
66

  
67
  test "POST /projects/:project_id/files.json should refuse requests without the :token parameter" do
68
    payload = <<-JSON
69
{ "file": {
70
    "filename": "project_file.zip",
71
  }
72
}
73
    JSON
74
    post '/projects/1/files.json', payload, {"CONTENT_TYPE" => 'application/json'}.merge(credentials('jsmith'))
75
    assert_response :bad_request
76
  end
77

  
78
  test "POST /projects/:project_id/files.json should accept :filename, :description, :content_type as optional parameters" do
79
    set_tmp_attachments_directory
80
    post '/uploads.xml', 'File content', {"CONTENT_TYPE" => 'application/octet-stream'}.merge(credentials('jsmith'))
81
    token = Attachment.last.token
82
    payload = <<-JSON
83
{ "file": {
84
    "filename": "New filename",
85
    "description": "New description",
86
    "content_type": "application/txt",
87
    "token": "#{token}"
88
  }
89
}
90
    JSON
91
    post '/projects/1/files.json', payload, {"CONTENT_TYPE" => 'application/json'}.merge(credentials('jsmith'))
92
    assert_response :success
93
    assert_equal "New filename", Attachment.last.filename
94
    assert_equal "New description", Attachment.last.description
95
    assert_equal "application/txt", Attachment.last.content_type
96
  end
97

  
98
  test "POST /projects/:project_id/files.json should accept :version_id to attach the files to a version" do
99
    set_tmp_attachments_directory
100
    post '/uploads.xml', 'File content', {"CONTENT_TYPE" => 'application/octet-stream'}.merge(credentials('jsmith'))
101
    token = Attachment.last.token
102
    payload = <<-JSON
103
{ "file": {
104
    "version_id": 3,
105
    "filename": "New filename",
106
    "description": "New description",
107
    "token": "#{token}"
108
  }
109
}
110
    JSON
111
    post '/projects/1/files.json', payload, {"CONTENT_TYPE" => 'application/json'}.merge(credentials('jsmith'))
112
    assert_equal 3, Attachment.last.container_id
113
    assert_equal "Version", Attachment.last.container_type
114
  end
115
end
(3-3/3)