@@ -0,0 +1,14 | |||
|
1 | api.array :files do | |
|
2 | @containers.each do |container| | |
|
3 | container.attachments.each do |attachment| | |
|
4 | api.file do | |
|
5 | render_api_attachment_attributes(attachment, api) | |
|
6 | if container.is_a?(Version) | |
|
7 | api.version :id => container.id, :name => container.name | |
|
8 | end | |
|
9 | api.digest attachment.digest | |
|
10 | api.downloads attachment.downloads | |
|
11 | end | |
|
12 | end | |
|
13 | end | |
|
14 | end |
@@ -0,0 +1,115 | |||
|
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>file>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 |
@@ -20,7 +20,9 class FilesController < ApplicationController | |||
|
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,7 +37,10 class FilesController < ApplicationController | |||
|
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,20 +48,29 class FilesController < ApplicationController | |||
|
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 |
|
60 | respond_to do |format| | |
|
61 | format.html { | |
|
54 | 62 | flash[:notice] = l(:label_file_added) |
|
55 | redirect_to project_files_path(@project) | |
|
63 | redirect_to project_files_path(@project) } | |
|
64 | format.api { render_api_ok } | |
|
65 | end | |
|
56 | 66 | else |
|
67 | respond_to do |format| | |
|
68 | format.html { | |
|
57 | 69 | flash.now[:error] = l(:label_attachment) + " " + l('activerecord.errors.messages.invalid') |
|
58 | 70 | new |
|
59 | render :action => 'new' | |
|
71 | render :action => 'new' } | |
|
72 | format.api { render :status => :bad_request } | |
|
73 | end | |
|
60 | 74 | end |
|
61 | 75 | end |
|
62 | 76 | end |
@@ -51,8 +51,14 module AttachmentsHelper | |||
|
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 | render_api_attachment_attributes(attachment, api) | |
|
57 | options.each { |key, value| eval("api.#{key} value") } | |
|
58 | end | |
|
59 | end | |
|
60 | ||
|
61 | def render_api_attachment_attributes(attachment, api) | |
|
56 | 62 |
|
|
57 | 63 |
|
|
58 | 64 |
|
@@ -62,8 +68,9 module AttachmentsHelper | |||
|
62 | 68 |
|
|
63 | 69 |
|
|
64 | 70 |
|
|
65 | api.author(:id => attachment.author.id, :name => attachment.author.name) if attachment.author | |
|
66 | api.created_on attachment.created_on | |
|
71 | if attachment.author | |
|
72 | api.author(:id => attachment.author.id, :name => attachment.author.name) | |
|
67 | 73 | end |
|
74 | api.created_on attachment.created_on | |
|
68 | 75 | end |
|
69 | 76 | end |
@@ -34,6 +34,11 class Redmine::ApiTest::ApiRoutingTest < Redmine::ApiTest::Routing | |||
|
34 | 34 | should_route 'GET /enumerations/issue_priorities' => 'enumerations#index', :type => 'issue_priorities' |
|
35 | 35 | end |
|
36 | 36 | |
|
37 | def test_files | |
|
38 | should_route 'GET /projects/foo/files' => 'files#index', :project_id => 'foo' | |
|
39 | should_route 'POST /projects/foo/files' => 'files#create', :project_id => 'foo' | |
|
40 | end | |
|
41 | ||
|
37 | 42 | def test_groups |
|
38 | 43 | should_route 'GET /groups' => 'groups#index' |
|
39 | 44 | should_route 'POST /groups' => 'groups#create' |
General Comments 0
You need to be logged in to leave comments.
Login now