Project

General

Profile

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

Lucile Quirion, 2015-02-19 17:07

View differences:

app/controllers/files_controller.rb
20 20

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

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

  
27 29
  def index
......
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
44

  
39 45
  end
40 46

  
41 47
  def new
......
43 49
  end
44 50

  
45 51
  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])
52
    version_id = params[:version_id] || (params[:file] && params[:file][:version_id])
53
    container = version_id.blank? ? @project : @project.versions.find_by_id(version_id)
54
    attachments = Attachment.attach_files(container, (params[:attachments] || (params[:file] && params[:file][:token] && params)))
48 55
    render_attachment_warning_if_needed(container)
49 56

  
50 57
    if !attachments.empty? && !attachments[:files].blank? && Setting.notified_events.include?('file_added')
51 58
      Mailer.attachments_added(attachments[:files]).deliver
52 59
    end
53
    redirect_to project_files_path(@project)
60

  
61
    respond_to do |format|
62
      format.html { redirect_to project_files_path(@project) }
63
      format.api { if attachments.empty?
64
                     render :status => :bad_request
65
                   else
66
                     render_api_ok
67
                   end }
68
    end
54 69
  end
55 70
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
app/views/files/index.api.rsb
1
api.array :files do
2
  @containers.each do |container|
3
    next if container.attachments.empty?
4
    if container.is_a?(Version)
5
      version_id = container.name
6
    end
7

  
8
    container.attachments.each do |file|
9
      render_api_attachment(file, api, { version_id: version_id, digest: file.digest, downloads: file.downloads } )
10
    end
11
  end
12
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
(2-2/3)