XML REST API for Projects (#296).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@3313 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
parent
64f4b50139
commit
68a4cd38f5
|
@ -22,6 +22,7 @@ class ApplicationController < ActionController::Base
|
|||
include Redmine::I18n
|
||||
|
||||
layout 'base'
|
||||
exempt_from_layout 'builder'
|
||||
|
||||
# Remove broken cookie after upgrade from 0.8.x (#4292)
|
||||
# See https://rails.lighthouseapp.com/projects/8994/tickets/3360
|
||||
|
|
|
@ -53,6 +53,9 @@ class ProjectsController < ApplicationController
|
|||
format.html {
|
||||
@projects = Project.visible.find(:all, :order => 'lft')
|
||||
}
|
||||
format.xml {
|
||||
@projects = Project.visible.find(:all, :order => 'lft')
|
||||
}
|
||||
format.atom {
|
||||
projects = Project.visible.find(:all, :order => 'created_on DESC',
|
||||
:limit => Setting.feeds_limit.to_i)
|
||||
|
@ -81,8 +84,18 @@ class ProjectsController < ApplicationController
|
|||
m = Member.new(:user => User.current, :roles => [r])
|
||||
@project.members << m
|
||||
end
|
||||
flash[:notice] = l(:notice_successful_create)
|
||||
redirect_to :controller => 'projects', :action => 'settings', :id => @project
|
||||
respond_to do |format|
|
||||
format.html {
|
||||
flash[:notice] = l(:notice_successful_create)
|
||||
redirect_to :controller => 'projects', :action => 'settings', :id => @project
|
||||
}
|
||||
format.xml { head :created, :location => url_for(:controller => 'projects', :action => 'show', :id => @project.id) }
|
||||
end
|
||||
else
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.xml { render :xml => @project.errors, :status => :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -147,6 +160,11 @@ class ProjectsController < ApplicationController
|
|||
:conditions => cond).to_f
|
||||
end
|
||||
@key = User.current.rss_key
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.xml
|
||||
end
|
||||
end
|
||||
|
||||
def settings
|
||||
|
@ -160,15 +178,26 @@ class ProjectsController < ApplicationController
|
|||
|
||||
# Edit @project
|
||||
def edit
|
||||
if request.post?
|
||||
if request.get?
|
||||
else
|
||||
@project.attributes = params[:project]
|
||||
if validate_parent_id && @project.save
|
||||
@project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id')
|
||||
flash[:notice] = l(:notice_successful_update)
|
||||
redirect_to :action => 'settings', :id => @project
|
||||
respond_to do |format|
|
||||
format.html {
|
||||
flash[:notice] = l(:notice_successful_update)
|
||||
redirect_to :action => 'settings', :id => @project
|
||||
}
|
||||
format.xml { head :ok }
|
||||
end
|
||||
else
|
||||
settings
|
||||
render :action => 'settings'
|
||||
respond_to do |format|
|
||||
format.html {
|
||||
settings
|
||||
render :action => 'settings'
|
||||
}
|
||||
format.xml { render :xml => @project.errors, :status => :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -195,9 +224,16 @@ class ProjectsController < ApplicationController
|
|||
# Delete @project
|
||||
def destroy
|
||||
@project_to_destroy = @project
|
||||
if request.post? and params[:confirm]
|
||||
@project_to_destroy.destroy
|
||||
redirect_to :controller => 'admin', :action => 'projects'
|
||||
if request.get?
|
||||
# display confirmation view
|
||||
else
|
||||
if params[:format] == 'xml' || params[:confirm]
|
||||
@project_to_destroy.destroy
|
||||
respond_to do |format|
|
||||
format.html { redirect_to :controller => 'admin', :action => 'projects' }
|
||||
format.xml { head :ok }
|
||||
end
|
||||
end
|
||||
end
|
||||
# hide project in layout
|
||||
@project = nil
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
xml.instruct!
|
||||
xml.projects :type => 'array' do
|
||||
@projects.each do |project|
|
||||
xml.project :id => project.id do
|
||||
xml.name project.name
|
||||
xml.identifier project.identifier
|
||||
xml.description project.description
|
||||
xml.parent(:id => project.parent_id, :name => project.parent.name) unless project.parent.nil?
|
||||
xml.custom_fields do
|
||||
project.custom_field_values.each do |custom_value|
|
||||
xml.custom_field custom_value.value, :id => custom_value.custom_field_id, :name => custom_value.custom_field.name
|
||||
end
|
||||
end unless project.custom_field_values.empty?
|
||||
xml.created_on project.created_on
|
||||
xml.updated_on project.updated_on
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,16 @@
|
|||
xml.instruct!
|
||||
xml.project :id => @project.id do
|
||||
xml.name @project.name
|
||||
xml.identifier @project.identifier
|
||||
xml.description @project.description
|
||||
xml.homepage @project.homepage
|
||||
|
||||
xml.custom_fields do
|
||||
@project.custom_field_values.each do |custom_value|
|
||||
xml.custom_field custom_value.value, :id => custom_value.custom_field_id, :name => custom_value.custom_field.name
|
||||
end
|
||||
end unless @project.custom_field_values.empty?
|
||||
|
||||
xml.created_on @project.created_on
|
||||
xml.updated_on @project.updated_on
|
||||
end
|
|
@ -186,6 +186,7 @@ ActionController::Routing::Routes.draw do |map|
|
|||
project_views.connect 'projects.:format', :action => 'index'
|
||||
project_views.connect 'projects/new', :action => 'add'
|
||||
project_views.connect 'projects/:id', :action => 'show'
|
||||
project_views.connect 'projects/:id.:format', :action => 'show'
|
||||
project_views.connect 'projects/:id/:action', :action => /roadmap|destroy|settings/
|
||||
project_views.connect 'projects/:id/files', :action => 'list_files'
|
||||
project_views.connect 'projects/:id/files/new', :action => 'add_file'
|
||||
|
@ -204,6 +205,7 @@ ActionController::Routing::Routes.draw do |map|
|
|||
projects.with_options :conditions => {:method => :post} do |project_actions|
|
||||
project_actions.connect 'projects/new', :action => 'add'
|
||||
project_actions.connect 'projects', :action => 'add'
|
||||
project_actions.connect 'projects.:format', :action => 'add', :format => /xml/
|
||||
project_actions.connect 'projects/:id/:action', :action => /destroy|archive|unarchive/
|
||||
project_actions.connect 'projects/:id/files/new', :action => 'add_file'
|
||||
project_actions.connect 'projects/:id/versions/new', :action => 'add_version'
|
||||
|
@ -211,7 +213,12 @@ ActionController::Routing::Routes.draw do |map|
|
|||
project_actions.connect 'projects/:id/activities/save', :action => 'save_activities'
|
||||
end
|
||||
|
||||
projects.with_options :conditions => {:method => :put} do |project_actions|
|
||||
project_actions.conditions 'projects/:id.:format', :action => 'edit', :format => /xml/
|
||||
end
|
||||
|
||||
projects.with_options :conditions => {:method => :delete} do |project_actions|
|
||||
project_actions.conditions 'projects/:id.:format', :action => 'destroy', :format => /xml/
|
||||
project_actions.conditions 'projects/:id/reset_activities', :action => 'reset_activities'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -44,7 +44,7 @@ custom_fields_003:
|
|||
- Alpha
|
||||
- Planning
|
||||
id: 3
|
||||
is_required: true
|
||||
is_required: false
|
||||
field_format: list
|
||||
default_value: ""
|
||||
editable: true
|
||||
|
|
|
@ -0,0 +1,134 @@
|
|||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2010 Jean-Philippe Lang
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require "#{File.dirname(__FILE__)}/../test_helper"
|
||||
|
||||
class ProjectsApiTest < ActionController::IntegrationTest
|
||||
fixtures :projects, :versions, :users, :roles, :members, :member_roles, :issues, :journals, :journal_details,
|
||||
:trackers, :projects_trackers, :issue_statuses, :enabled_modules, :enumerations, :boards, :messages,
|
||||
:attachments, :custom_fields, :custom_values, :time_entries
|
||||
|
||||
def setup
|
||||
Setting.rest_api_enabled = '1'
|
||||
end
|
||||
|
||||
def test_index_routing
|
||||
assert_routing(
|
||||
{:method => :get, :path => '/projects.xml'},
|
||||
:controller => 'projects', :action => 'index', :format => 'xml'
|
||||
)
|
||||
end
|
||||
|
||||
def test_index
|
||||
get '/projects.xml'
|
||||
assert_response :success
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
end
|
||||
|
||||
def test_show_routing
|
||||
assert_routing(
|
||||
{:method => :get, :path => '/projects/1.xml'},
|
||||
:controller => 'projects', :action => 'show', :id => '1', :format => 'xml'
|
||||
)
|
||||
end
|
||||
|
||||
def test_show
|
||||
get '/projects/1.xml'
|
||||
assert_response :success
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
end
|
||||
|
||||
def test_create_routing
|
||||
assert_routing(
|
||||
{:method => :post, :path => '/projects.xml'},
|
||||
:controller => 'projects', :action => 'add', :format => 'xml'
|
||||
)
|
||||
end
|
||||
|
||||
def test_create
|
||||
attributes = {:name => 'API test', :identifier => 'api-test'}
|
||||
assert_difference 'Project.count' do
|
||||
post '/projects.xml', {:project => attributes}, :authorization => credentials('admin')
|
||||
end
|
||||
assert_response :created
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
project = Project.first(:order => 'id DESC')
|
||||
attributes.each do |attribute, value|
|
||||
assert_equal value, project.send(attribute)
|
||||
end
|
||||
end
|
||||
|
||||
def test_create_failure
|
||||
attributes = {:name => 'API test'}
|
||||
assert_no_difference 'Project.count' do
|
||||
post '/projects.xml', {:project => attributes}, :authorization => credentials('admin')
|
||||
end
|
||||
assert_response :unprocessable_entity
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
assert_tag :errors, :child => {:tag => 'error', :content => "Identifier can't be blank"}
|
||||
end
|
||||
|
||||
def test_update_routing
|
||||
assert_routing(
|
||||
{:method => :put, :path => '/projects/1.xml'},
|
||||
:controller => 'projects', :action => 'edit', :id => '1', :format => 'xml'
|
||||
)
|
||||
end
|
||||
|
||||
def test_update
|
||||
attributes = {:name => 'API update'}
|
||||
assert_no_difference 'Project.count' do
|
||||
put '/projects/1.xml', {:project => attributes}, :authorization => credentials('jsmith')
|
||||
end
|
||||
assert_response :ok
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
project = Project.find(1)
|
||||
attributes.each do |attribute, value|
|
||||
assert_equal value, project.send(attribute)
|
||||
end
|
||||
end
|
||||
|
||||
def test_update_failure
|
||||
attributes = {:name => ''}
|
||||
assert_no_difference 'Project.count' do
|
||||
put '/projects/1.xml', {:project => attributes}, :authorization => credentials('jsmith')
|
||||
end
|
||||
assert_response :unprocessable_entity
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
assert_tag :errors, :child => {:tag => 'error', :content => "Name can't be blank"}
|
||||
end
|
||||
|
||||
def test_destroy_routing
|
||||
assert_routing(
|
||||
{:method => :delete, :path => '/projects/1.xml'},
|
||||
:controller => 'projects', :action => 'destroy', :id => '1', :format => 'xml'
|
||||
)
|
||||
end
|
||||
|
||||
def test_destroy
|
||||
assert_difference 'Project.count', -1 do
|
||||
delete '/projects/2.xml', {}, :authorization => credentials('admin')
|
||||
end
|
||||
assert_response :ok
|
||||
assert_equal 'application/xml', @response.content_type
|
||||
assert_nil Project.find_by_id(2)
|
||||
end
|
||||
|
||||
def credentials(user, password=nil)
|
||||
ActionController::HttpAuthentication::Basic.encode_credentials(user, password || user)
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue