##// END OF EJS Templates
REST API for project memberships (#7420)....
Jean-Philippe Lang -
r8678:c5665276b7a4
parent child
Show More
@@ -0,0 +1,18
1 api.array :memberships, api_meta(:total_count => @member_count, :offset => @offset, :limit => @limit) do
2 @members.each do |membership|
3 api.membership do
4 api.id membership.id
5 api.project :id => membership.project.id, :name => membership.project.name
6 api.__send__ membership.principal.class.name.underscore, :id => membership.principal.id, :name => membership.principal.name
7 api.array :roles do
8 membership.member_roles.each do |member_role|
9 if member_role.role
10 attrs = {:id => member_role.role.id, :name => member_role.role.name}
11 attrs.merge!(:inherited => true) if member_role.inherited_from.present?
12 api.role attrs
13 end
14 end
15 end
16 end
17 end
18 end
@@ -0,0 +1,14
1 api.membership do
2 api.id @member.id
3 api.project :id => @member.project.id, :name => @member.project.name
4 api.__send__ @member.principal.class.name.underscore, :id => @member.principal.id, :name => @member.principal.name
5 api.array :roles do
6 @member.member_roles.each do |member_role|
7 if member_role.role
8 attrs = {:id => member_role.role.id, :name => member_role.role.name}
9 attrs.merge!(:inherited => true) if member_role.inherited_from.present?
10 api.role attrs
11 end
12 end
13 end
14 end
@@ -0,0 +1,190
1 # Redmine - project management software
2 # Copyright (C) 2006-2012 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 ApiTest::MembershipsTest < ActionController::IntegrationTest
21 fixtures :projects, :users, :roles, :members, :member_roles
22
23 def setup
24 Setting.rest_api_enabled = '1'
25 end
26
27 context "/projects/:project_id/memberships" do
28 context "GET" do
29 context "xml" do
30 should "return memberships" do
31 get '/projects/1/memberships.xml', {}, credentials('jsmith')
32
33 assert_response :success
34 assert_equal 'application/xml', @response.content_type
35 assert_tag :tag => 'memberships',
36 :attributes => {:type => 'array'},
37 :child => {
38 :tag => 'membership',
39 :child => {
40 :tag => 'id',
41 :content => '2',
42 :sibling => {
43 :tag => 'user',
44 :attributes => {:id => '3', :name => 'Dave Lopper'},
45 :sibling => {
46 :tag => 'roles',
47 :child => {
48 :tag => 'role',
49 :attributes => {:id => '2', :name => 'Developer'}
50 }
51 }
52 }
53 }
54 }
55 end
56 end
57
58 context "json" do
59 should "return memberships" do
60 get '/projects/1/memberships.json', {}, credentials('jsmith')
61
62 assert_response :success
63 assert_equal 'application/json', @response.content_type
64 json = ActiveSupport::JSON.decode(response.body)
65 assert_equal({
66 "memberships" =>
67 [{"id"=>1,
68 "project" => {"name"=>"eCookbook", "id"=>1},
69 "roles" => [{"name"=>"Manager", "id"=>1}],
70 "user" => {"name"=>"John Smith", "id"=>2}},
71 {"id"=>2,
72 "project" => {"name"=>"eCookbook", "id"=>1},
73 "roles" => [{"name"=>"Developer", "id"=>2}],
74 "user" => {"name"=>"Dave Lopper", "id"=>3}}],
75 "limit" => 25,
76 "total_count" => 2,
77 "offset" => 0},
78 json)
79 end
80 end
81 end
82
83 context "POST" do
84 context "xml" do
85 should "create membership" do
86 assert_difference 'Member.count' do
87 post '/projects/1/memberships.xml', {:membership => {:user_id => 7, :role_ids => [2,3]}}, credentials('jsmith')
88
89 assert_response :created
90 end
91 end
92
93 should "return errors on failure" do
94 assert_no_difference 'Member.count' do
95 post '/projects/1/memberships.xml', {:membership => {:role_ids => [2,3]}}, credentials('jsmith')
96
97 assert_response :unprocessable_entity
98 assert_equal 'application/xml', @response.content_type
99 assert_tag 'errors', :child => {:tag => 'error', :content => "Principal can't be blank"}
100 end
101 end
102 end
103 end
104 end
105
106 context "/memberships/:id" do
107 context "GET" do
108 context "xml" do
109 should "return the membership" do
110 get '/memberships/2.xml', {}, credentials('jsmith')
111
112 assert_response :success
113 assert_equal 'application/xml', @response.content_type
114 assert_tag :tag => 'membership',
115 :child => {
116 :tag => 'id',
117 :content => '2',
118 :sibling => {
119 :tag => 'user',
120 :attributes => {:id => '3', :name => 'Dave Lopper'},
121 :sibling => {
122 :tag => 'roles',
123 :child => {
124 :tag => 'role',
125 :attributes => {:id => '2', :name => 'Developer'}
126 }
127 }
128 }
129 }
130 end
131 end
132
133 context "json" do
134 should "return the membership" do
135 get '/memberships/2.json', {}, credentials('jsmith')
136
137 assert_response :success
138 assert_equal 'application/json', @response.content_type
139 json = ActiveSupport::JSON.decode(response.body)
140 assert_equal(
141 {"membership" => {
142 "id" => 2,
143 "project" => {"name"=>"eCookbook", "id"=>1},
144 "roles" => [{"name"=>"Developer", "id"=>2}],
145 "user" => {"name"=>"Dave Lopper", "id"=>3}}
146 },
147 json)
148 end
149 end
150 end
151
152 context "PUT" do
153 context "xml" do
154 should "update membership" do
155 assert_not_equal [1,2], Member.find(2).role_ids.sort
156 assert_no_difference 'Member.count' do
157 put '/memberships/2.xml', {:membership => {:user_id => 3, :role_ids => [1,266]}}, credentials('jsmith')
158
159 assert_response :ok
160 end
161 member = Member.find(2)
162 assert_equal [1,2], member.role_ids.sort
163 end
164 end
165 end
166
167 context "DELETE" do
168 context "xml" do
169 should "destroy membership" do
170 assert_difference 'Member.count', -1 do
171 delete '/memberships/2.xml', {}, credentials('jsmith')
172
173 assert_response :ok
174 end
175 assert_nil Member.find_by_id(2)
176 end
177
178 should "respond with 422 on failure" do
179 assert_no_difference 'Member.count' do
180 # A membership with an inherited role can't be deleted
181 Member.find(2).member_roles.first.update_attribute :inherited_from, 99
182 delete '/memberships/2.xml', {}, credentials('jsmith')
183
184 assert_response :unprocessable_entity
185 end
186 end
187 end
188 end
189 end
190 end
@@ -1,103 +1,142
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2011 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 class MembersController < ApplicationController
19 19 model_object Member
20 before_filter :find_model_object, :except => [:create, :autocomplete]
21 before_filter :find_project_from_association, :except => [:create, :autocomplete]
22 before_filter :find_project_by_project_id, :only => [:create, :autocomplete]
20 before_filter :find_model_object, :except => [:index, :create, :autocomplete]
21 before_filter :find_project_from_association, :except => [:index, :create, :autocomplete]
22 before_filter :find_project_by_project_id, :only => [:index, :create, :autocomplete]
23 23 before_filter :authorize
24 accept_api_auth :index, :show, :create, :update, :destroy
25
26 def index
27 @offset, @limit = api_offset_and_limit
28 @member_count = @project.member_principals.count
29 @member_pages = Paginator.new self, @member_count, @limit, params['page']
30 @offset ||= @member_pages.current.offset
31 @members = @project.member_principals.all(
32 :order => "#{Member.table_name}.id",
33 :limit => @limit,
34 :offset => @offset
35 )
36
37 respond_to do |format|
38 format.html { head 406 }
39 format.api
40 end
41 end
42
43 def show
44 respond_to do |format|
45 format.html { head 406 }
46 format.api
47 end
48 end
24 49
25 50 def create
26 51 members = []
27 if params[:membership] && request.post?
52 if params[:membership] && params[:membership][:user_ids]
28 53 attrs = params[:membership].dup
29 if (user_ids = attrs.delete(:user_ids))
30 user_ids.each do |user_id|
31 members << Member.new(attrs.merge(:user_id => user_id))
32 end
33 else
34 members << Member.new(attrs)
54 user_ids = attrs.delete(:user_ids)
55 user_ids.each do |user_id|
56 members << Member.new(attrs.merge(:user_id => user_id))
35 57 end
36 @project.members << members
58 else
59 members << Member.new(params[:membership])
37 60 end
61 @project.members << members
62
38 63 respond_to do |format|
39 64 if members.present? && members.all? {|m| m.valid? }
40
41 65 format.html { redirect_to :controller => 'projects', :action => 'settings', :tab => 'members', :id => @project }
42
43 66 format.js {
44 67 render(:update) {|page|
45 68 page.replace_html "tab-content-members", :partial => 'projects/settings/members'
46 69 page << 'hideOnLoad()'
47 70 members.each {|member| page.visual_effect(:highlight, "member-#{member.id}") }
48 71 }
49 72 }
73 format.api {
74 @member = members.first
75 render :action => 'show', :status => :created, :location => membership_url(@member)
76 }
50 77 else
51
52 78 format.js {
53 79 render(:update) {|page|
54 80 errors = members.collect {|m|
55 81 m.errors.full_messages
56 82 }.flatten.uniq
57 83
58 84 page.alert(l(:notice_failed_to_save_members, :errors => errors.join(', ')))
59 85 }
60 86 }
61
87 format.api { render_validation_errors(members.first) }
62 88 end
63 89 end
64 90 end
65 91
66 92 def update
67 93 if params[:membership]
68 94 @member.role_ids = params[:membership][:role_ids]
69 95 end
70 if request.put? && @member.save
71 respond_to do |format|
72 format.html { redirect_to :controller => 'projects', :action => 'settings', :tab => 'members', :id => @project }
73 format.js {
74 render(:update) {|page|
75 page.replace_html "tab-content-members", :partial => 'projects/settings/members'
76 page << 'hideOnLoad()'
77 page.visual_effect(:highlight, "member-#{@member.id}")
78 }
96 saved = @member.save
97 respond_to do |format|
98 format.html { redirect_to :controller => 'projects', :action => 'settings', :tab => 'members', :id => @project }
99 format.js {
100 render(:update) {|page|
101 page.replace_html "tab-content-members", :partial => 'projects/settings/members'
102 page << 'hideOnLoad()'
103 page.visual_effect(:highlight, "member-#{@member.id}")
79 104 }
80 end
105 }
106 format.api {
107 if saved
108 head :ok
109 else
110 render_validation_errors(@member)
111 end
112 }
81 113 end
82 114 end
83 115
84 116 def destroy
85 117 if request.delete? && @member.deletable?
86 118 @member.destroy
87 119 end
88 120 respond_to do |format|
89 121 format.html { redirect_to :controller => 'projects', :action => 'settings', :tab => 'members', :id => @project }
90 122 format.js { render(:update) {|page|
91 123 page.replace_html "tab-content-members", :partial => 'projects/settings/members'
92 124 page << 'hideOnLoad()'
93 125 }
94 126 }
127 format.api {
128 if @member.destroyed?
129 head :ok
130 else
131 head :unprocessable_entity
132 end
133 }
95 134 end
96 135 end
97 136
98 137 def autocomplete
99 138 @principals = Principal.active.like(params[:q]).find(:all, :limit => 100) - @project.principals
100 139 render :layout => false
101 140 end
102 141
103 142 end
@@ -1,415 +1,415
1 1 ActionController::Routing::Routes.draw do |map|
2 2 # Add your own custom routes here.
3 3 # The priority is based upon order of creation: first created -> highest priority.
4 4
5 5 # Here's a sample route:
6 6 # map.connect 'products/:id', :controller => 'catalog', :action => 'view'
7 7 # Keep in mind you can assign values other than :controller and :action
8 8
9 9 map.home '', :controller => 'welcome', :conditions => {:method => :get}
10 10
11 11 map.signin 'login', :controller => 'account', :action => 'login',
12 12 :conditions => {:method => [:get, :post]}
13 13 map.signout 'logout', :controller => 'account', :action => 'logout',
14 14 :conditions => {:method => :get}
15 15 map.connect 'account/register', :controller => 'account', :action => 'register',
16 16 :conditions => {:method => [:get, :post]}
17 17 map.connect 'account/lost_password', :controller => 'account', :action => 'lost_password',
18 18 :conditions => {:method => [:get, :post]}
19 19 map.connect 'account/activate', :controller => 'account', :action => 'activate',
20 20 :conditions => {:method => :get}
21 21
22 22 map.connect 'projects/:id/wiki', :controller => 'wikis',
23 23 :action => 'edit', :conditions => {:method => :post}
24 24 map.connect 'projects/:id/wiki/destroy', :controller => 'wikis',
25 25 :action => 'destroy', :conditions => {:method => [:get, :post]}
26 26
27 27 map.with_options :controller => 'messages' do |messages_routes|
28 28 messages_routes.with_options :conditions => {:method => :get} do |messages_views|
29 29 messages_views.connect 'boards/:board_id/topics/new', :action => 'new'
30 30 messages_views.connect 'boards/:board_id/topics/:id', :action => 'show'
31 31 messages_views.connect 'boards/:board_id/topics/:id/edit', :action => 'edit'
32 32 end
33 33 messages_routes.with_options :conditions => {:method => :post} do |messages_actions|
34 34 messages_actions.connect 'boards/:board_id/topics/new', :action => 'new'
35 35 messages_actions.connect 'boards/:board_id/topics/preview', :action => 'preview'
36 36 messages_actions.connect 'boards/:board_id/topics/quote/:id', :action => 'quote'
37 37 messages_actions.connect 'boards/:board_id/topics/:id/replies', :action => 'reply'
38 38 messages_actions.connect 'boards/:board_id/topics/:id/edit', :action => 'edit'
39 39 messages_actions.connect 'boards/:board_id/topics/:id/destroy', :action => 'destroy'
40 40 end
41 41 end
42 42
43 43 # Misc issue routes. TODO: move into resources
44 44 map.auto_complete_issues '/issues/auto_complete', :controller => 'auto_completes',
45 45 :action => 'issues', :conditions => { :method => :get }
46 46 # TODO: would look nicer as /issues/:id/preview
47 47 map.preview_issue '/issues/preview/:id', :controller => 'previews',
48 48 :action => 'issue'
49 49 map.issues_context_menu '/issues/context_menu',
50 50 :controller => 'context_menus', :action => 'issues'
51 51
52 52 map.issue_changes '/issues/changes', :controller => 'journals', :action => 'index'
53 53 map.quoted_issue '/issues/:id/quoted', :controller => 'journals', :action => 'new',
54 54 :id => /\d+/, :conditions => { :method => :post }
55 55
56 56 map.connect '/journals/diff/:id', :controller => 'journals', :action => 'diff',
57 57 :id => /\d+/, :conditions => { :method => :get }
58 58 map.connect '/journals/edit/:id', :controller => 'journals', :action => 'edit',
59 59 :id => /\d+/, :conditions => { :method => [:get, :post] }
60 60
61 61 map.with_options :controller => 'gantts', :action => 'show' do |gantts_routes|
62 62 gantts_routes.connect '/projects/:project_id/issues/gantt'
63 63 gantts_routes.connect '/projects/:project_id/issues/gantt.:format'
64 64 gantts_routes.connect '/issues/gantt.:format'
65 65 end
66 66
67 67 map.with_options :controller => 'calendars', :action => 'show' do |calendars_routes|
68 68 calendars_routes.connect '/projects/:project_id/issues/calendar'
69 69 calendars_routes.connect '/issues/calendar'
70 70 end
71 71
72 72 map.with_options :controller => 'reports', :conditions => {:method => :get} do |reports|
73 73 reports.connect 'projects/:id/issues/report', :action => 'issue_report'
74 74 reports.connect 'projects/:id/issues/report/:detail', :action => 'issue_report_details'
75 75 end
76 76
77 77 map.connect 'my/account', :controller => 'my', :action => 'account',
78 78 :conditions => {:method => [:get, :post]}
79 79 map.connect 'my/page', :controller => 'my', :action => 'page',
80 80 :conditions => {:method => :get}
81 81 # Redirects to my/page
82 82 map.connect 'my', :controller => 'my', :action => 'index',
83 83 :conditions => {:method => :get}
84 84 map.connect 'my/reset_rss_key', :controller => 'my', :action => 'reset_rss_key',
85 85 :conditions => {:method => :post}
86 86 map.connect 'my/reset_api_key', :controller => 'my', :action => 'reset_api_key',
87 87 :conditions => {:method => :post}
88 88 map.connect 'my/password', :controller => 'my', :action => 'password',
89 89 :conditions => {:method => [:get, :post]}
90 90 map.connect 'my/page_layout', :controller => 'my', :action => 'page_layout',
91 91 :conditions => {:method => :get}
92 92 map.connect 'my/add_block', :controller => 'my', :action => 'add_block',
93 93 :conditions => {:method => :post}
94 94 map.connect 'my/remove_block', :controller => 'my', :action => 'remove_block',
95 95 :conditions => {:method => :post}
96 96 map.connect 'my/order_blocks', :controller => 'my', :action => 'order_blocks',
97 97 :conditions => {:method => :post}
98 98
99 99 map.with_options :controller => 'users' do |users|
100 100 users.user_membership 'users/:id/memberships/:membership_id',
101 101 :action => 'edit_membership',
102 102 :conditions => {:method => :put}
103 103 users.connect 'users/:id/memberships/:membership_id',
104 104 :action => 'destroy_membership',
105 105 :conditions => {:method => :delete}
106 106 users.user_memberships 'users/:id/memberships',
107 107 :action => 'edit_membership',
108 108 :conditions => {:method => :post}
109 109 end
110 110 map.resources :users
111 111
112 112 # For nice "roadmap" in the url for the index action
113 113 map.connect 'projects/:project_id/roadmap', :controller => 'versions', :action => 'index'
114 114
115 115 map.preview_news '/news/preview', :controller => 'previews', :action => 'news'
116 116 map.connect 'news/:id/comments', :controller => 'comments',
117 117 :action => 'create', :conditions => {:method => :post}
118 118 map.connect 'news/:id/comments/:comment_id', :controller => 'comments',
119 119 :action => 'destroy', :conditions => {:method => :delete}
120 120
121 121 map.connect 'watchers/new', :controller=> 'watchers', :action => 'new',
122 122 :conditions => {:method => :get}
123 123 map.connect 'watchers', :controller=> 'watchers', :action => 'create',
124 124 :conditions => {:method => :post}
125 125 map.connect 'watchers/destroy', :controller=> 'watchers', :action => 'destroy',
126 126 :conditions => {:method => :post}
127 127 map.connect 'watchers/watch', :controller=> 'watchers', :action => 'watch',
128 128 :conditions => {:method => :post}
129 129 map.connect 'watchers/unwatch', :controller=> 'watchers', :action => 'unwatch',
130 130 :conditions => {:method => :post}
131 131 map.connect 'watchers/autocomplete_for_user', :controller=> 'watchers', :action => 'autocomplete_for_user',
132 132 :conditions => {:method => :get}
133 133
134 134 # TODO: port to be part of the resources route(s)
135 135 map.with_options :conditions => {:method => :get} do |project_views|
136 136 project_views.connect 'projects/:id/settings/:tab',
137 137 :controller => 'projects', :action => 'settings'
138 138 project_views.connect 'projects/:project_id/issues/:copy_from/copy',
139 139 :controller => 'issues', :action => 'new'
140 140 end
141 141
142 142 map.resources :projects, :member => {
143 143 :copy => [:get, :post],
144 144 :settings => :get,
145 145 :modules => :post,
146 146 :archive => :post,
147 147 :unarchive => :post
148 148 } do |project|
149 149 project.resource :enumerations, :controller => 'project_enumerations',
150 150 :only => [:update, :destroy]
151 151 # issue form update
152 152 project.issue_form 'issues/new', :controller => 'issues',
153 153 :action => 'new', :conditions => {:method => [:post, :put]}
154 154 project.resources :issues, :only => [:index, :new, :create] do |issues|
155 155 issues.resources :time_entries, :controller => 'timelog',
156 156 :collection => {:report => :get}
157 157 end
158 158
159 159 project.resources :files, :only => [:index, :new, :create]
160 160 project.resources :versions, :shallow => true,
161 161 :collection => {:close_completed => :put},
162 162 :member => {:status_by => :post}
163 163 project.resources :news, :shallow => true
164 164 project.resources :time_entries, :controller => 'timelog',
165 165 :collection => {:report => :get}
166 166 project.resources :queries, :only => [:new, :create]
167 167 project.resources :issue_categories, :shallow => true
168 168 project.resources :documents, :shallow => true, :member => {:add_attachment => :post}
169 169 project.resources :boards
170 170 project.resources :repositories, :shallow => true, :except => [:index, :show],
171 171 :member => {:committers => [:get, :post]}
172 172 project.resources :memberships, :shallow => true, :controller => 'members',
173 :only => [:create, :update, :destroy],
173 :only => [:index, :show, :create, :update, :destroy],
174 174 :collection => {:autocomplete => :get}
175 175
176 176 project.wiki_start_page 'wiki', :controller => 'wiki', :action => 'show', :conditions => {:method => :get}
177 177 project.wiki_index 'wiki/index', :controller => 'wiki', :action => 'index', :conditions => {:method => :get}
178 178 project.wiki_diff 'wiki/:id/diff/:version', :controller => 'wiki', :action => 'diff', :version => nil
179 179 project.wiki_diff 'wiki/:id/diff/:version/vs/:version_from', :controller => 'wiki', :action => 'diff'
180 180 project.wiki_annotate 'wiki/:id/annotate/:version', :controller => 'wiki', :action => 'annotate'
181 181 project.resources :wiki, :except => [:new, :create], :member => {
182 182 :rename => [:get, :post],
183 183 :history => :get,
184 184 :preview => :any,
185 185 :protect => :post,
186 186 :add_attachment => :post
187 187 }, :collection => {
188 188 :export => :get,
189 189 :date_index => :get
190 190 }
191 191 end
192 192
193 193 map.connect 'news', :controller => 'news', :action => 'index'
194 194 map.connect 'news.:format', :controller => 'news', :action => 'index'
195 195
196 196 map.resources :queries, :except => [:show]
197 197 map.resources :issues,
198 198 :collection => {:bulk_edit => [:get, :post], :bulk_update => :post} do |issues|
199 199 issues.resources :time_entries, :controller => 'timelog',
200 200 :collection => {:report => :get}
201 201 issues.resources :relations, :shallow => true,
202 202 :controller => 'issue_relations',
203 203 :only => [:index, :show, :create, :destroy]
204 204 end
205 205 # Bulk deletion
206 206 map.connect '/issues', :controller => 'issues', :action => 'destroy',
207 207 :conditions => {:method => :delete}
208 208
209 209 map.connect '/time_entries/destroy',
210 210 :controller => 'timelog', :action => 'destroy',
211 211 :conditions => { :method => :delete }
212 212 map.time_entries_context_menu '/time_entries/context_menu',
213 213 :controller => 'context_menus', :action => 'time_entries'
214 214
215 215 map.resources :time_entries, :controller => 'timelog',
216 216 :collection => {:report => :get, :bulk_edit => :get, :bulk_update => :post}
217 217
218 218 map.with_options :controller => 'activities', :action => 'index',
219 219 :conditions => {:method => :get} do |activity|
220 220 activity.connect 'projects/:id/activity'
221 221 activity.connect 'projects/:id/activity.:format'
222 222 activity.connect 'activity', :id => nil
223 223 activity.connect 'activity.:format', :id => nil
224 224 end
225 225
226 226 map.with_options :controller => 'repositories' do |repositories|
227 227 repositories.with_options :conditions => {:method => :get} do |repository_views|
228 228 repository_views.connect 'projects/:id/repository',
229 229 :action => 'show'
230 230
231 231 repository_views.connect 'projects/:id/repository/:repository_id/statistics',
232 232 :action => 'stats'
233 233 repository_views.connect 'projects/:id/repository/:repository_id/graph',
234 234 :action => 'graph'
235 235
236 236 repository_views.connect 'projects/:id/repository/statistics',
237 237 :action => 'stats'
238 238 repository_views.connect 'projects/:id/repository/graph',
239 239 :action => 'graph'
240 240
241 241 repository_views.connect 'projects/:id/repository/:repository_id/revisions',
242 242 :action => 'revisions'
243 243 repository_views.connect 'projects/:id/repository/:repository_id/revisions.:format',
244 244 :action => 'revisions'
245 245 repository_views.connect 'projects/:id/repository/:repository_id/revisions/:rev',
246 246 :action => 'revision'
247 247 repository_views.connect 'projects/:id/repository/:repository_id/revisions/:rev/issues',
248 248 :action => 'add_related_issue', :conditions => {:method => :post}
249 249 repository_views.connect 'projects/:id/repository/:repository_id/revisions/:rev/issues/:issue_id',
250 250 :action => 'remove_related_issue', :conditions => {:method => :delete}
251 251 repository_views.connect 'projects/:id/repository/:repository_id/revisions/:rev/diff',
252 252 :action => 'diff'
253 253 repository_views.connect 'projects/:id/repository/:repository_id/revisions/:rev/diff.:format',
254 254 :action => 'diff'
255 255 repository_views.connect 'projects/:id/repository/:repository_id/revisions/:rev/raw/*path',
256 256 :action => 'entry', :format => 'raw'
257 257 repository_views.connect 'projects/:id/repository/:repository_id/revisions/:rev/:action/*path',
258 258 :requirements => {
259 259 :action => /(browse|show|entry|changes|annotate|diff)/,
260 260 :rev => /[a-z0-9\.\-_]+/
261 261 }
262 262 repository_views.connect 'projects/:id/repository/:repository_id/raw/*path',
263 263 :action => 'entry', :format => 'raw'
264 264 repository_views.connect 'projects/:id/repository/:repository_id/:action/*path',
265 265 :requirements => { :action => /(browse|show|entry|changes|annotate|diff)/ }
266 266
267 267 repository_views.connect 'projects/:id/repository/revisions',
268 268 :action => 'revisions'
269 269 repository_views.connect 'projects/:id/repository/revisions.:format',
270 270 :action => 'revisions'
271 271 repository_views.connect 'projects/:id/repository/revisions/:rev',
272 272 :action => 'revision'
273 273 repository_views.connect 'projects/:id/repository/revisions/:rev/issues',
274 274 :action => 'add_related_issue', :conditions => {:method => :post}
275 275 repository_views.connect 'projects/:id/repository/revisions/:rev/issues/:issue_id',
276 276 :action => 'remove_related_issue', :conditions => {:method => :delete}
277 277 repository_views.connect 'projects/:id/repository/revisions/:rev/diff',
278 278 :action => 'diff'
279 279 repository_views.connect 'projects/:id/repository/revisions/:rev/diff.:format',
280 280 :action => 'diff'
281 281 repository_views.connect 'projects/:id/repository/revisions/:rev/raw/*path',
282 282 :action => 'entry', :format => 'raw'
283 283 repository_views.connect 'projects/:id/repository/revisions/:rev/:action/*path',
284 284 :requirements => {
285 285 :action => /(browse|show|entry|changes|annotate|diff)/,
286 286 :rev => /[a-z0-9\.\-_]+/
287 287 }
288 288 repository_views.connect 'projects/:id/repository/raw/*path',
289 289 :action => 'entry', :format => 'raw'
290 290 repository_views.connect 'projects/:id/repository/:action/*path',
291 291 :requirements => { :action => /(browse|show|entry|changes|annotate|diff)/ }
292 292
293 293 repository_views.connect 'projects/:id/repository/:repository_id',
294 294 :action => 'show'
295 295 end
296 296
297 297 repositories.connect 'projects/:id/repository/revision',
298 298 :action => 'revision',
299 299 :conditions => {:method => [:get, :post]}
300 300 end
301 301
302 302 # additional routes for having the file name at the end of url
303 303 map.connect 'attachments/:id/:filename', :controller => 'attachments',
304 304 :action => 'show', :id => /\d+/, :filename => /.*/,
305 305 :conditions => {:method => :get}
306 306 map.connect 'attachments/download/:id/:filename', :controller => 'attachments',
307 307 :action => 'download', :id => /\d+/, :filename => /.*/,
308 308 :conditions => {:method => :get}
309 309 map.connect 'attachments/download/:id', :controller => 'attachments',
310 310 :action => 'download', :id => /\d+/,
311 311 :conditions => {:method => :get}
312 312 map.resources :attachments, :only => [:show, :destroy]
313 313
314 314 map.resources :groups, :member => {:autocomplete_for_user => :get}
315 315 map.group_users 'groups/:id/users', :controller => 'groups',
316 316 :action => 'add_users', :id => /\d+/,
317 317 :conditions => {:method => :post}
318 318 map.group_user 'groups/:id/users/:user_id', :controller => 'groups',
319 319 :action => 'remove_user', :id => /\d+/,
320 320 :conditions => {:method => :delete}
321 321 map.connect 'groups/destroy_membership/:id', :controller => 'groups',
322 322 :action => 'destroy_membership', :id => /\d+/,
323 323 :conditions => {:method => :post}
324 324 map.connect 'groups/edit_membership/:id', :controller => 'groups',
325 325 :action => 'edit_membership', :id => /\d+/,
326 326 :conditions => {:method => :post}
327 327
328 328 map.resources :trackers, :except => :show
329 329 map.resources :issue_statuses, :except => :show, :collection => {:update_issue_done_ratio => :post}
330 330 map.resources :custom_fields, :except => :show
331 331 map.resources :roles, :except => :show, :collection => {:permissions => [:get, :post]}
332 332 map.resources :enumerations, :except => :show
333 333
334 334 map.connect 'search', :controller => 'search', :action => 'index', :conditions => {:method => :get}
335 335
336 336 map.connect 'mail_handler', :controller => 'mail_handler',
337 337 :action => 'index', :conditions => {:method => :post}
338 338
339 339 map.connect 'admin', :controller => 'admin', :action => 'index',
340 340 :conditions => {:method => :get}
341 341 map.connect 'admin/projects', :controller => 'admin', :action => 'projects',
342 342 :conditions => {:method => :get}
343 343 map.connect 'admin/plugins', :controller => 'admin', :action => 'plugins',
344 344 :conditions => {:method => :get}
345 345 map.connect 'admin/info', :controller => 'admin', :action => 'info',
346 346 :conditions => {:method => :get}
347 347 map.connect 'admin/test_email', :controller => 'admin', :action => 'test_email',
348 348 :conditions => {:method => :get}
349 349 map.connect 'admin/default_configuration', :controller => 'admin',
350 350 :action => 'default_configuration', :conditions => {:method => :post}
351 351
352 352 # Used by AuthSourcesControllerTest
353 353 # TODO : refactor *AuthSourcesController to remove these routes
354 354 map.connect 'auth_sources', :controller => 'auth_sources',
355 355 :action => 'index', :conditions => {:method => :get}
356 356 map.connect 'auth_sources/new', :controller => 'auth_sources',
357 357 :action => 'new', :conditions => {:method => :get}
358 358 map.connect 'auth_sources/create', :controller => 'auth_sources',
359 359 :action => 'create', :conditions => {:method => :post}
360 360 map.connect 'auth_sources/destroy/:id', :controller => 'auth_sources',
361 361 :action => 'destroy', :id => /\d+/, :conditions => {:method => :post}
362 362 map.connect 'auth_sources/test_connection/:id', :controller => 'auth_sources',
363 363 :action => 'test_connection', :conditions => {:method => :get}
364 364 map.connect 'auth_sources/edit/:id', :controller => 'auth_sources',
365 365 :action => 'edit', :id => /\d+/, :conditions => {:method => :get}
366 366 map.connect 'auth_sources/update/:id', :controller => 'auth_sources',
367 367 :action => 'update', :id => /\d+/, :conditions => {:method => :post}
368 368
369 369 map.connect 'ldap_auth_sources', :controller => 'ldap_auth_sources',
370 370 :action => 'index', :conditions => {:method => :get}
371 371 map.connect 'ldap_auth_sources/new', :controller => 'ldap_auth_sources',
372 372 :action => 'new', :conditions => {:method => :get}
373 373 map.connect 'ldap_auth_sources/create', :controller => 'ldap_auth_sources',
374 374 :action => 'create', :conditions => {:method => :post}
375 375 map.connect 'ldap_auth_sources/destroy/:id', :controller => 'ldap_auth_sources',
376 376 :action => 'destroy', :id => /\d+/, :conditions => {:method => :post}
377 377 map.connect 'ldap_auth_sources/test_connection/:id', :controller => 'ldap_auth_sources',
378 378 :action => 'test_connection', :conditions => {:method => :get}
379 379 map.connect 'ldap_auth_sources/edit/:id', :controller => 'ldap_auth_sources',
380 380 :action => 'edit', :id => /\d+/, :conditions => {:method => :get}
381 381 map.connect 'ldap_auth_sources/update/:id', :controller => 'ldap_auth_sources',
382 382 :action => 'update', :id => /\d+/, :conditions => {:method => :post}
383 383
384 384 map.connect 'workflows', :controller => 'workflows',
385 385 :action => 'index', :conditions => {:method => :get}
386 386 map.connect 'workflows/edit', :controller => 'workflows',
387 387 :action => 'edit', :conditions => {:method => [:get, :post]}
388 388 map.connect 'workflows/copy', :controller => 'workflows',
389 389 :action => 'copy', :conditions => {:method => [:get, :post]}
390 390
391 391 map.connect 'settings', :controller => 'settings',
392 392 :action => 'index', :conditions => {:method => :get}
393 393 map.connect 'settings/edit', :controller => 'settings',
394 394 :action => 'edit', :conditions => {:method => [:get, :post]}
395 395 map.connect 'settings/plugin/:id', :controller => 'settings',
396 396 :action => 'plugin', :conditions => {:method => [:get, :post]}
397 397
398 398 map.with_options :controller => 'sys' do |sys|
399 399 sys.connect 'sys/projects.:format',
400 400 :action => 'projects',
401 401 :conditions => {:method => :get}
402 402 sys.connect 'sys/projects/:id/repository.:format',
403 403 :action => 'create_project_repository',
404 404 :conditions => {:method => :post}
405 405 sys.connect 'sys/fetch_changesets',
406 406 :action => 'fetch_changesets',
407 407 :conditions => {:method => :get}
408 408 end
409 409
410 410 map.connect 'robots.txt', :controller => 'welcome',
411 411 :action => 'robots', :conditions => {:method => :get}
412 412
413 413 # Used for OpenID
414 414 map.root :controller => 'account', :action => 'login'
415 415 end
@@ -1,238 +1,238
1 1 require 'redmine/access_control'
2 2 require 'redmine/menu_manager'
3 3 require 'redmine/activity'
4 4 require 'redmine/search'
5 5 require 'redmine/custom_field_format'
6 6 require 'redmine/mime_type'
7 7 require 'redmine/core_ext'
8 8 require 'redmine/themes'
9 9 require 'redmine/hook'
10 10 require 'redmine/plugin'
11 11 require 'redmine/notifiable'
12 12 require 'redmine/wiki_formatting'
13 13 require 'redmine/scm/base'
14 14
15 15 begin
16 16 require_library_or_gem 'RMagick' unless Object.const_defined?(:Magick)
17 17 rescue LoadError
18 18 # RMagick is not available
19 19 end
20 20
21 21 if RUBY_VERSION < '1.9'
22 22 require 'faster_csv'
23 23 else
24 24 require 'csv'
25 25 FCSV = CSV
26 26 end
27 27
28 28 Redmine::Scm::Base.add "Subversion"
29 29 Redmine::Scm::Base.add "Darcs"
30 30 Redmine::Scm::Base.add "Mercurial"
31 31 Redmine::Scm::Base.add "Cvs"
32 32 Redmine::Scm::Base.add "Bazaar"
33 33 Redmine::Scm::Base.add "Git"
34 34 Redmine::Scm::Base.add "Filesystem"
35 35
36 36 Redmine::CustomFieldFormat.map do |fields|
37 37 fields.register Redmine::CustomFieldFormat.new('string', :label => :label_string, :order => 1)
38 38 fields.register Redmine::CustomFieldFormat.new('text', :label => :label_text, :order => 2)
39 39 fields.register Redmine::CustomFieldFormat.new('int', :label => :label_integer, :order => 3)
40 40 fields.register Redmine::CustomFieldFormat.new('float', :label => :label_float, :order => 4)
41 41 fields.register Redmine::CustomFieldFormat.new('list', :label => :label_list, :order => 5)
42 42 fields.register Redmine::CustomFieldFormat.new('date', :label => :label_date, :order => 6)
43 43 fields.register Redmine::CustomFieldFormat.new('bool', :label => :label_boolean, :order => 7)
44 44 fields.register Redmine::CustomFieldFormat.new('user', :label => :label_user, :only => %w(Issue TimeEntry Version Project), :edit_as => 'list', :order => 8)
45 45 fields.register Redmine::CustomFieldFormat.new('version', :label => :label_version, :only => %w(Issue TimeEntry Version Project), :edit_as => 'list', :order => 9)
46 46 end
47 47
48 48 # Permissions
49 49 Redmine::AccessControl.map do |map|
50 50 map.permission :view_project, {:projects => [:show], :activities => [:index]}, :public => true
51 51 map.permission :search_project, {:search => :index}, :public => true
52 52 map.permission :add_project, {:projects => [:new, :create]}, :require => :loggedin
53 53 map.permission :edit_project, {:projects => [:settings, :edit, :update]}, :require => :member
54 54 map.permission :select_project_modules, {:projects => :modules}, :require => :member
55 map.permission :manage_members, {:projects => :settings, :members => [:create, :update, :destroy, :autocomplete]}, :require => :member
55 map.permission :manage_members, {:projects => :settings, :members => [:index, :show, :create, :update, :destroy, :autocomplete]}, :require => :member
56 56 map.permission :manage_versions, {:projects => :settings, :versions => [:new, :create, :edit, :update, :close_completed, :destroy]}, :require => :member
57 57 map.permission :add_subprojects, {:projects => [:new, :create]}, :require => :member
58 58
59 59 map.project_module :issue_tracking do |map|
60 60 # Issue categories
61 61 map.permission :manage_categories, {:projects => :settings, :issue_categories => [:index, :show, :new, :create, :edit, :update, :destroy]}, :require => :member
62 62 # Issues
63 63 map.permission :view_issues, {:issues => [:index, :show],
64 64 :auto_complete => [:issues],
65 65 :context_menus => [:issues],
66 66 :versions => [:index, :show, :status_by],
67 67 :journals => [:index, :diff],
68 68 :queries => :index,
69 69 :reports => [:issue_report, :issue_report_details]}
70 70 map.permission :add_issues, {:issues => [:new, :create, :update_form]}
71 71 map.permission :edit_issues, {:issues => [:edit, :update, :bulk_edit, :bulk_update, :update_form], :journals => [:new]}
72 72 map.permission :manage_issue_relations, {:issue_relations => [:index, :show, :create, :destroy]}
73 73 map.permission :manage_subtasks, {}
74 74 map.permission :set_issues_private, {}
75 75 map.permission :set_own_issues_private, {}, :require => :loggedin
76 76 map.permission :add_issue_notes, {:issues => [:edit, :update], :journals => [:new]}
77 77 map.permission :edit_issue_notes, {:journals => :edit}, :require => :loggedin
78 78 map.permission :edit_own_issue_notes, {:journals => :edit}, :require => :loggedin
79 79 map.permission :move_issues, {:issues => [:bulk_edit, :bulk_update]}, :require => :loggedin
80 80 map.permission :delete_issues, {:issues => :destroy}, :require => :member
81 81 # Queries
82 82 map.permission :manage_public_queries, {:queries => [:new, :create, :edit, :update, :destroy]}, :require => :member
83 83 map.permission :save_queries, {:queries => [:new, :create, :edit, :update, :destroy]}, :require => :loggedin
84 84 # Watchers
85 85 map.permission :view_issue_watchers, {}
86 86 map.permission :add_issue_watchers, {:watchers => :new}
87 87 map.permission :delete_issue_watchers, {:watchers => :destroy}
88 88 end
89 89
90 90 map.project_module :time_tracking do |map|
91 91 map.permission :log_time, {:timelog => [:new, :create]}, :require => :loggedin
92 92 map.permission :view_time_entries, :timelog => [:index, :report, :show]
93 93 map.permission :edit_time_entries, {:timelog => [:edit, :update, :destroy, :bulk_edit, :bulk_update]}, :require => :member
94 94 map.permission :edit_own_time_entries, {:timelog => [:edit, :update, :destroy,:bulk_edit, :bulk_update]}, :require => :loggedin
95 95 map.permission :manage_project_activities, {:project_enumerations => [:update, :destroy]}, :require => :member
96 96 end
97 97
98 98 map.project_module :news do |map|
99 99 map.permission :manage_news, {:news => [:new, :create, :edit, :update, :destroy], :comments => [:destroy]}, :require => :member
100 100 map.permission :view_news, {:news => [:index, :show]}, :public => true
101 101 map.permission :comment_news, {:comments => :create}
102 102 end
103 103
104 104 map.project_module :documents do |map|
105 105 map.permission :manage_documents, {:documents => [:new, :create, :edit, :update, :destroy, :add_attachment]}, :require => :loggedin
106 106 map.permission :view_documents, :documents => [:index, :show, :download]
107 107 end
108 108
109 109 map.project_module :files do |map|
110 110 map.permission :manage_files, {:files => [:new, :create]}, :require => :loggedin
111 111 map.permission :view_files, :files => :index, :versions => :download
112 112 end
113 113
114 114 map.project_module :wiki do |map|
115 115 map.permission :manage_wiki, {:wikis => [:edit, :destroy]}, :require => :member
116 116 map.permission :rename_wiki_pages, {:wiki => :rename}, :require => :member
117 117 map.permission :delete_wiki_pages, {:wiki => :destroy}, :require => :member
118 118 map.permission :view_wiki_pages, :wiki => [:index, :show, :special, :date_index]
119 119 map.permission :export_wiki_pages, :wiki => [:export]
120 120 map.permission :view_wiki_edits, :wiki => [:history, :diff, :annotate]
121 121 map.permission :edit_wiki_pages, :wiki => [:edit, :update, :preview, :add_attachment]
122 122 map.permission :delete_wiki_pages_attachments, {}
123 123 map.permission :protect_wiki_pages, {:wiki => :protect}, :require => :member
124 124 end
125 125
126 126 map.project_module :repository do |map|
127 127 map.permission :manage_repository, {:repositories => [:new, :create, :edit, :update, :committers, :destroy]}, :require => :member
128 128 map.permission :browse_repository, :repositories => [:show, :browse, :entry, :annotate, :changes, :diff, :stats, :graph]
129 129 map.permission :view_changesets, :repositories => [:show, :revisions, :revision]
130 130 map.permission :commit_access, {}
131 131 map.permission :manage_related_issues, {:repositories => [:add_related_issue, :remove_related_issue]}
132 132 end
133 133
134 134 map.project_module :boards do |map|
135 135 map.permission :manage_boards, {:boards => [:new, :create, :edit, :update, :destroy]}, :require => :member
136 136 map.permission :view_messages, {:boards => [:index, :show], :messages => [:show]}, :public => true
137 137 map.permission :add_messages, {:messages => [:new, :reply, :quote]}
138 138 map.permission :edit_messages, {:messages => :edit}, :require => :member
139 139 map.permission :edit_own_messages, {:messages => :edit}, :require => :loggedin
140 140 map.permission :delete_messages, {:messages => :destroy}, :require => :member
141 141 map.permission :delete_own_messages, {:messages => :destroy}, :require => :loggedin
142 142 end
143 143
144 144 map.project_module :calendar do |map|
145 145 map.permission :view_calendar, :calendars => [:show, :update]
146 146 end
147 147
148 148 map.project_module :gantt do |map|
149 149 map.permission :view_gantt, :gantts => [:show, :update]
150 150 end
151 151 end
152 152
153 153 Redmine::MenuManager.map :top_menu do |menu|
154 154 menu.push :home, :home_path
155 155 menu.push :my_page, { :controller => 'my', :action => 'page' }, :if => Proc.new { User.current.logged? }
156 156 menu.push :projects, { :controller => 'projects', :action => 'index' }, :caption => :label_project_plural
157 157 menu.push :administration, { :controller => 'admin', :action => 'index' }, :if => Proc.new { User.current.admin? }, :last => true
158 158 menu.push :help, Redmine::Info.help_url, :last => true
159 159 end
160 160
161 161 Redmine::MenuManager.map :account_menu do |menu|
162 162 menu.push :login, :signin_path, :if => Proc.new { !User.current.logged? }
163 163 menu.push :register, { :controller => 'account', :action => 'register' }, :if => Proc.new { !User.current.logged? && Setting.self_registration? }
164 164 menu.push :my_account, { :controller => 'my', :action => 'account' }, :if => Proc.new { User.current.logged? }
165 165 menu.push :logout, :signout_path, :if => Proc.new { User.current.logged? }
166 166 end
167 167
168 168 Redmine::MenuManager.map :application_menu do |menu|
169 169 # Empty
170 170 end
171 171
172 172 Redmine::MenuManager.map :admin_menu do |menu|
173 173 menu.push :projects, {:controller => 'admin', :action => 'projects'}, :caption => :label_project_plural
174 174 menu.push :users, {:controller => 'users'}, :caption => :label_user_plural
175 175 menu.push :groups, {:controller => 'groups'}, :caption => :label_group_plural
176 176 menu.push :roles, {:controller => 'roles'}, :caption => :label_role_and_permissions
177 177 menu.push :trackers, {:controller => 'trackers'}, :caption => :label_tracker_plural
178 178 menu.push :issue_statuses, {:controller => 'issue_statuses'}, :caption => :label_issue_status_plural,
179 179 :html => {:class => 'issue_statuses'}
180 180 menu.push :workflows, {:controller => 'workflows', :action => 'edit'}, :caption => :label_workflow
181 181 menu.push :custom_fields, {:controller => 'custom_fields'}, :caption => :label_custom_field_plural,
182 182 :html => {:class => 'custom_fields'}
183 183 menu.push :enumerations, {:controller => 'enumerations'}
184 184 menu.push :settings, {:controller => 'settings'}
185 185 menu.push :ldap_authentication, {:controller => 'ldap_auth_sources', :action => 'index'},
186 186 :html => {:class => 'server_authentication'}
187 187 menu.push :plugins, {:controller => 'admin', :action => 'plugins'}, :last => true
188 188 menu.push :info, {:controller => 'admin', :action => 'info'}, :caption => :label_information_plural, :last => true
189 189 end
190 190
191 191 Redmine::MenuManager.map :project_menu do |menu|
192 192 menu.push :overview, { :controller => 'projects', :action => 'show' }
193 193 menu.push :activity, { :controller => 'activities', :action => 'index' }
194 194 menu.push :roadmap, { :controller => 'versions', :action => 'index' }, :param => :project_id,
195 195 :if => Proc.new { |p| p.shared_versions.any? }
196 196 menu.push :issues, { :controller => 'issues', :action => 'index' }, :param => :project_id, :caption => :label_issue_plural
197 197 menu.push :new_issue, { :controller => 'issues', :action => 'new' }, :param => :project_id, :caption => :label_issue_new,
198 198 :html => { :accesskey => Redmine::AccessKeys.key_for(:new_issue) }
199 199 menu.push :gantt, { :controller => 'gantts', :action => 'show' }, :param => :project_id, :caption => :label_gantt
200 200 menu.push :calendar, { :controller => 'calendars', :action => 'show' }, :param => :project_id, :caption => :label_calendar
201 201 menu.push :news, { :controller => 'news', :action => 'index' }, :param => :project_id, :caption => :label_news_plural
202 202 menu.push :documents, { :controller => 'documents', :action => 'index' }, :param => :project_id, :caption => :label_document_plural
203 203 menu.push :wiki, { :controller => 'wiki', :action => 'show', :id => nil }, :param => :project_id,
204 204 :if => Proc.new { |p| p.wiki && !p.wiki.new_record? }
205 205 menu.push :boards, { :controller => 'boards', :action => 'index', :id => nil }, :param => :project_id,
206 206 :if => Proc.new { |p| p.boards.any? }, :caption => :label_board_plural
207 207 menu.push :files, { :controller => 'files', :action => 'index' }, :caption => :label_file_plural, :param => :project_id
208 208 menu.push :repository, { :controller => 'repositories', :action => 'show' },
209 209 :if => Proc.new { |p| p.repository && !p.repository.new_record? }
210 210 menu.push :settings, { :controller => 'projects', :action => 'settings' }, :last => true
211 211 end
212 212
213 213 Redmine::Activity.map do |activity|
214 214 activity.register :issues, :class_name => %w(Issue Journal)
215 215 activity.register :changesets
216 216 activity.register :news
217 217 activity.register :documents, :class_name => %w(Document Attachment)
218 218 activity.register :files, :class_name => 'Attachment'
219 219 activity.register :wiki_edits, :class_name => 'WikiContent::Version', :default => false
220 220 activity.register :messages, :default => false
221 221 activity.register :time_entries, :default => false
222 222 end
223 223
224 224 Redmine::Search.map do |search|
225 225 search.register :issues
226 226 search.register :news
227 227 search.register :documents
228 228 search.register :changesets
229 229 search.register :wiki_pages
230 230 search.register :messages
231 231 search.register :projects
232 232 end
233 233
234 234 Redmine::WikiFormatting.map do |format|
235 235 format.register :textile, Redmine::WikiFormatting::Textile::Formatter, Redmine::WikiFormatting::Textile::Helper
236 236 end
237 237
238 238 ActionView::Template.register_template_handler :rsb, Redmine::Views::ApiTemplateHandler
@@ -1,39 +1,59
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2011 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 require File.expand_path('../../../test_helper', __FILE__)
19 19
20 20 class RoutingMembersTest < ActionController::IntegrationTest
21 21 def test_members
22 22 assert_routing(
23 { :method => 'get', :path => "/projects/5234/memberships.xml" },
24 { :controller => 'members', :action => 'index', :project_id => '5234', :format => 'xml' }
25 )
26 assert_routing(
27 { :method => 'get', :path => "/memberships/5234.xml" },
28 { :controller => 'members', :action => 'show', :id => '5234', :format => 'xml' }
29 )
30 assert_routing(
23 31 { :method => 'post', :path => "/projects/5234/memberships" },
24 32 { :controller => 'members', :action => 'create', :project_id => '5234' }
25 33 )
26 34 assert_routing(
35 { :method => 'post', :path => "/projects/5234/memberships.xml" },
36 { :controller => 'members', :action => 'create', :project_id => '5234', :format => 'xml' }
37 )
38 assert_routing(
27 39 { :method => 'put', :path => "/memberships/5234" },
28 40 { :controller => 'members', :action => 'update', :id => '5234' }
29 41 )
30 42 assert_routing(
43 { :method => 'put', :path => "/memberships/5234.xml" },
44 { :controller => 'members', :action => 'update', :id => '5234', :format => 'xml' }
45 )
46 assert_routing(
31 47 { :method => 'delete', :path => "/memberships/5234" },
32 48 { :controller => 'members', :action => 'destroy', :id => '5234' }
33 49 )
34 50 assert_routing(
51 { :method => 'delete', :path => "/memberships/5234.xml" },
52 { :controller => 'members', :action => 'destroy', :id => '5234', :format => 'xml' }
53 )
54 assert_routing(
35 55 { :method => 'get', :path => "/projects/5234/memberships/autocomplete" },
36 56 { :controller => 'members', :action => 'autocomplete', :project_id => '5234' }
37 57 )
38 58 end
39 59 end
General Comments 0
You need to be logged in to leave comments. Login now