Mercurial > hg > soundsoftware-site
comparison app/controllers/application_controller.rb @ 442:753f1380d6bc cannam
Merge from branch "redmine-1.2"
author | Chris Cannam |
---|---|
date | Mon, 06 Jun 2011 14:41:04 +0100 |
parents | 73ff0e6a11b1 cbce1fd3b1b7 |
children | 350acce374a2 |
comparison
equal
deleted
inserted
replaced
252:adc8466df404 | 442:753f1380d6bc |
---|---|
1 # redMine - project management software | 1 # Redmine - project management software |
2 # Copyright (C) 2006-2007 Jean-Philippe Lang | 2 # Copyright (C) 2006-2011 Jean-Philippe Lang |
3 # | 3 # |
4 # This program is free software; you can redistribute it and/or | 4 # This program is free software; you can redistribute it and/or |
5 # modify it under the terms of the GNU General Public License | 5 # modify it under the terms of the GNU General Public License |
6 # as published by the Free Software Foundation; either version 2 | 6 # as published by the Free Software Foundation; either version 2 |
7 # of the License, or (at your option) any later version. | 7 # of the License, or (at your option) any later version. |
8 # | 8 # |
9 # This program is distributed in the hope that it will be useful, | 9 # This program is distributed in the hope that it will be useful, |
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 # GNU General Public License for more details. | 12 # GNU General Public License for more details. |
13 # | 13 # |
14 # You should have received a copy of the GNU General Public License | 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 | 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. | 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
17 | 17 |
18 require 'uri' | 18 require 'uri' |
21 class ApplicationController < ActionController::Base | 21 class ApplicationController < ActionController::Base |
22 include Redmine::I18n | 22 include Redmine::I18n |
23 | 23 |
24 layout 'base' | 24 layout 'base' |
25 exempt_from_layout 'builder', 'rsb' | 25 exempt_from_layout 'builder', 'rsb' |
26 | 26 |
27 # Remove broken cookie after upgrade from 0.8.x (#4292) | 27 # Remove broken cookie after upgrade from 0.8.x (#4292) |
28 # See https://rails.lighthouseapp.com/projects/8994/tickets/3360 | 28 # See https://rails.lighthouseapp.com/projects/8994/tickets/3360 |
29 # TODO: remove it when Rails is fixed | 29 # TODO: remove it when Rails is fixed |
30 before_filter :delete_broken_cookies | 30 before_filter :delete_broken_cookies |
31 def delete_broken_cookies | 31 def delete_broken_cookies |
32 if cookies['_redmine_session'] && cookies['_redmine_session'] !~ /--/ | 32 if cookies['_redmine_session'] && cookies['_redmine_session'] !~ /--/ |
33 cookies.delete '_redmine_session' | 33 cookies.delete '_redmine_session' |
34 redirect_to home_path | 34 redirect_to home_path |
35 return false | 35 return false |
36 end | 36 end |
37 end | 37 end |
38 | 38 |
39 before_filter :user_setup, :check_if_login_required, :set_localization | 39 before_filter :user_setup, :check_if_login_required, :set_localization |
40 filter_parameter_logging :password | 40 filter_parameter_logging :password |
41 protect_from_forgery | 41 protect_from_forgery |
42 | 42 |
43 rescue_from ActionController::InvalidAuthenticityToken, :with => :invalid_authenticity_token | 43 rescue_from ActionController::InvalidAuthenticityToken, :with => :invalid_authenticity_token |
44 | 44 |
45 include Redmine::Search::Controller | 45 include Redmine::Search::Controller |
46 include Redmine::MenuManager::MenuController | 46 include Redmine::MenuManager::MenuController |
47 helper Redmine::MenuManager::MenuHelper | 47 helper Redmine::MenuManager::MenuHelper |
48 | 48 |
49 Redmine::Scm::Base.all.each do |scm| | 49 Redmine::Scm::Base.all.each do |scm| |
50 require_dependency "repository/#{scm.underscore}" | 50 require_dependency "repository/#{scm.underscore}" |
51 end | 51 end |
52 | 52 |
53 def user_setup | 53 def user_setup |
54 # Check the settings cache for each request | 54 # Check the settings cache for each request |
55 Setting.check_cache | 55 Setting.check_cache |
56 # Find the current user | 56 # Find the current user |
57 User.current = find_current_user | 57 User.current = find_current_user |
58 end | 58 end |
59 | 59 |
60 # Returns the current user or nil if no user is logged in | 60 # Returns the current user or nil if no user is logged in |
61 # and starts a session if needed | 61 # and starts a session if needed |
62 def find_current_user | 62 def find_current_user |
63 if session[:user_id] | 63 if session[:user_id] |
64 # existing session | 64 # existing session |
92 session[:user_id] = user.id | 92 session[:user_id] = user.id |
93 else | 93 else |
94 User.current = User.anonymous | 94 User.current = User.anonymous |
95 end | 95 end |
96 end | 96 end |
97 | 97 |
98 # check if login is globally required to access the application | 98 # check if login is globally required to access the application |
99 def check_if_login_required | 99 def check_if_login_required |
100 # no check needed if user is already logged in | 100 # no check needed if user is already logged in |
101 return true if User.current.logged? | 101 return true if User.current.logged? |
102 require_login if Setting.login_required? | 102 require_login if Setting.login_required? |
103 end | 103 end |
104 | 104 |
105 def set_localization | 105 def set_localization |
106 lang = nil | 106 lang = nil |
107 if User.current.logged? | 107 if User.current.logged? |
108 lang = find_language(User.current.language) | 108 lang = find_language(User.current.language) |
109 end | 109 end |
115 end | 115 end |
116 end | 116 end |
117 lang ||= Setting.default_language | 117 lang ||= Setting.default_language |
118 set_language_if_valid(lang) | 118 set_language_if_valid(lang) |
119 end | 119 end |
120 | 120 |
121 def require_login | 121 def require_login |
122 if !User.current.logged? | 122 if !User.current.logged? |
123 # Extract only the basic url parameters on non-GET requests | 123 # Extract only the basic url parameters on non-GET requests |
124 if request.get? | 124 if request.get? |
125 url = url_for(params) | 125 url = url_for(params) |
144 render_403 | 144 render_403 |
145 return false | 145 return false |
146 end | 146 end |
147 true | 147 true |
148 end | 148 end |
149 | 149 |
150 def deny_access | 150 def deny_access |
151 User.current.logged? ? render_403 : require_login | 151 User.current.logged? ? render_403 : require_login |
152 end | 152 end |
153 | 153 |
154 # Authorize the user for the requested action | 154 # Authorize the user for the requested action |
195 end | 195 end |
196 | 196 |
197 # Finds and sets @project based on @object.project | 197 # Finds and sets @project based on @object.project |
198 def find_project_from_association | 198 def find_project_from_association |
199 render_404 unless @object.present? | 199 render_404 unless @object.present? |
200 | 200 |
201 @project = @object.project | 201 @project = @object.project |
202 rescue ActiveRecord::RecordNotFound | 202 rescue ActiveRecord::RecordNotFound |
203 render_404 | 203 render_404 |
204 end | 204 end |
205 | 205 |
219 | 219 |
220 # Filter for bulk issue operations | 220 # Filter for bulk issue operations |
221 def find_issues | 221 def find_issues |
222 @issues = Issue.find_all_by_id(params[:id] || params[:ids]) | 222 @issues = Issue.find_all_by_id(params[:id] || params[:ids]) |
223 raise ActiveRecord::RecordNotFound if @issues.empty? | 223 raise ActiveRecord::RecordNotFound if @issues.empty? |
224 if @issues.detect {|issue| !issue.visible?} | |
225 deny_access | |
226 return | |
227 end | |
224 @projects = @issues.collect(&:project).compact.uniq | 228 @projects = @issues.collect(&:project).compact.uniq |
225 @project = @projects.first if @projects.size == 1 | 229 @project = @projects.first if @projects.size == 1 |
226 rescue ActiveRecord::RecordNotFound | 230 rescue ActiveRecord::RecordNotFound |
227 render_404 | 231 render_404 |
228 end | 232 end |
229 | 233 |
230 # Check if project is unique before bulk operations | 234 # Check if project is unique before bulk operations |
231 def check_project_uniqueness | 235 def check_project_uniqueness |
232 unless @project | 236 unless @project |
233 # TODO: let users bulk edit/move/destroy issues from different projects | 237 # TODO: let users bulk edit/move/destroy issues from different projects |
234 render_error 'Can not bulk edit/move/destroy issues from different projects' | 238 render_error 'Can not bulk edit/move/destroy issues from different projects' |
235 return false | 239 return false |
236 end | 240 end |
237 end | 241 end |
238 | 242 |
239 # make sure that the user is a member of the project (or admin) if project is private | 243 # make sure that the user is a member of the project (or admin) if project is private |
240 # used as a before_filter for actions that do not require any particular permission on the project | 244 # used as a before_filter for actions that do not require any particular permission on the project |
241 def check_project_privacy | 245 def check_project_privacy |
242 if @project && @project.active? | 246 if @project && @project.active? |
243 if @project.is_public? || User.current.member_of?(@project) || User.current.admin? | 247 if @project.is_public? || User.current.member_of?(@project) || User.current.admin? |
275 rescue URI::InvalidURIError | 279 rescue URI::InvalidURIError |
276 # redirect to default | 280 # redirect to default |
277 end | 281 end |
278 end | 282 end |
279 redirect_to default | 283 redirect_to default |
280 end | 284 false |
281 | 285 end |
286 | |
282 def render_403(options={}) | 287 def render_403(options={}) |
283 @project = nil | 288 @project = nil |
284 render_error({:message => :notice_not_authorized, :status => 403}.merge(options)) | 289 render_error({:message => :notice_not_authorized, :status => 403}.merge(options)) |
285 return false | 290 return false |
286 end | 291 end |
287 | 292 |
288 def render_404(options={}) | 293 def render_404(options={}) |
289 render_error({:message => :notice_file_not_found, :status => 404}.merge(options)) | 294 render_error({:message => :notice_file_not_found, :status => 404}.merge(options)) |
290 return false | 295 return false |
291 end | 296 end |
292 | 297 |
293 # Renders an error response | 298 # Renders an error response |
294 def render_error(arg) | 299 def render_error(arg) |
295 arg = {:message => arg} unless arg.is_a?(Hash) | 300 arg = {:message => arg} unless arg.is_a?(Hash) |
296 | 301 |
297 @message = arg[:message] | 302 @message = arg[:message] |
298 @message = l(@message) if @message.is_a?(Symbol) | 303 @message = l(@message) if @message.is_a?(Symbol) |
299 @status = arg[:status] || 500 | 304 @status = arg[:status] || 500 |
300 | 305 |
301 respond_to do |format| | 306 respond_to do |format| |
302 format.html { | 307 format.html { |
303 render :template => 'common/error', :layout => use_layout, :status => @status | 308 render :template => 'common/error', :layout => use_layout, :status => @status |
304 } | 309 } |
305 format.atom { head @status } | 310 format.atom { head @status } |
313 # | 318 # |
314 # @return [boolean, string] name of the layout to use or false for no layout | 319 # @return [boolean, string] name of the layout to use or false for no layout |
315 def use_layout | 320 def use_layout |
316 request.xhr? ? false : 'base' | 321 request.xhr? ? false : 'base' |
317 end | 322 end |
318 | 323 |
319 def invalid_authenticity_token | 324 def invalid_authenticity_token |
320 if api_request? | 325 if api_request? |
321 logger.error "Form authenticity token is missing or is invalid. API calls must include a proper Content-type header (text/xml or text/json)." | 326 logger.error "Form authenticity token is missing or is invalid. API calls must include a proper Content-type header (text/xml or text/json)." |
322 end | 327 end |
323 render_error "Invalid form authenticity token. Perhaps your session has timed out; try reloading the form and entering your details again." | 328 render_error "Invalid form authenticity token. Perhaps your session has timed out; try reloading the form and entering your details again." |
324 end | 329 end |
325 | 330 |
326 def render_feed(items, options={}) | 331 def render_feed(items, options={}) |
327 @items = items || [] | 332 @items = items || [] |
328 @items.sort! {|x,y| y.event_datetime <=> x.event_datetime } | 333 @items.sort! {|x,y| y.event_datetime <=> x.event_datetime } |
329 @items = @items.slice(0, Setting.feeds_limit.to_i) | 334 @items = @items.slice(0, Setting.feeds_limit.to_i) |
330 @title = options[:title] || Setting.app_title | 335 @title = options[:title] || Setting.app_title |
331 render :template => "common/feed.atom.rxml", :layout => false, :content_type => 'application/atom+xml' | 336 render :template => "common/feed.atom.rxml", :layout => false, :content_type => 'application/atom+xml' |
332 end | 337 end |
333 | 338 |
334 def self.accept_key_auth(*actions) | 339 def self.accept_key_auth(*actions) |
335 actions = actions.flatten.map(&:to_s) | 340 actions = actions.flatten.map(&:to_s) |
336 write_inheritable_attribute('accept_key_auth_actions', actions) | 341 write_inheritable_attribute('accept_key_auth_actions', actions) |
337 end | 342 end |
338 | 343 |
339 def accept_key_auth_actions | 344 def accept_key_auth_actions |
340 self.class.read_inheritable_attribute('accept_key_auth_actions') || [] | 345 self.class.read_inheritable_attribute('accept_key_auth_actions') || [] |
341 end | 346 end |
342 | 347 |
343 # Returns the number of objects that should be displayed | 348 # Returns the number of objects that should be displayed |
344 # on the paginated list | 349 # on the paginated list |
345 def per_page_option | 350 def per_page_option |
346 per_page = nil | 351 per_page = nil |
347 if params[:per_page] && Setting.per_page_options_array.include?(params[:per_page].to_s.to_i) | 352 if params[:per_page] && Setting.per_page_options_array.include?(params[:per_page].to_s.to_i) |
373 if offset.nil? && options[:page].present? | 378 if offset.nil? && options[:page].present? |
374 offset = (options[:page].to_i - 1) * limit | 379 offset = (options[:page].to_i - 1) * limit |
375 offset = 0 if offset < 0 | 380 offset = 0 if offset < 0 |
376 end | 381 end |
377 offset ||= 0 | 382 offset ||= 0 |
378 | 383 |
379 [offset, limit] | 384 [offset, limit] |
380 end | 385 end |
381 | 386 |
382 # qvalues http header parser | 387 # qvalues http header parser |
383 # code taken from webrick | 388 # code taken from webrick |
384 def parse_qvalues(value) | 389 def parse_qvalues(value) |
385 tmp = [] | 390 tmp = [] |
386 if value | 391 if value |
397 end | 402 end |
398 return tmp | 403 return tmp |
399 rescue | 404 rescue |
400 nil | 405 nil |
401 end | 406 end |
402 | 407 |
403 # Returns a string that can be used as filename value in Content-Disposition header | 408 # Returns a string that can be used as filename value in Content-Disposition header |
404 def filename_for_content_disposition(name) | 409 def filename_for_content_disposition(name) |
405 request.env['HTTP_USER_AGENT'] =~ %r{MSIE} ? ERB::Util.url_encode(name) : name | 410 request.env['HTTP_USER_AGENT'] =~ %r{MSIE} ? ERB::Util.url_encode(name) : name |
406 end | 411 end |
407 | 412 |
408 def api_request? | 413 def api_request? |
409 %w(xml json).include? params[:format] | 414 %w(xml json).include? params[:format] |
410 end | 415 end |
411 | 416 |
412 # Returns the API key present in the request | 417 # Returns the API key present in the request |
413 def api_key_from_request | 418 def api_key_from_request |
414 if params[:key].present? | 419 if params[:key].present? |
415 params[:key] | 420 params[:key] |
416 elsif request.headers["X-Redmine-API-Key"].present? | 421 elsif request.headers["X-Redmine-API-Key"].present? |
463 raise "Unknown format #{params[:format]} in #render_validation_errors" | 468 raise "Unknown format #{params[:format]} in #render_validation_errors" |
464 end | 469 end |
465 ) | 470 ) |
466 render options | 471 render options |
467 end | 472 end |
468 | 473 |
469 # Overrides #default_template so that the api template | 474 # Overrides #default_template so that the api template |
470 # is used automatically if it exists | 475 # is used automatically if it exists |
471 def default_template(action_name = self.action_name) | 476 def default_template(action_name = self.action_name) |
472 if api_request? | 477 if api_request? |
473 begin | 478 begin |
477 # fallback to the default behaviour | 482 # fallback to the default behaviour |
478 end | 483 end |
479 end | 484 end |
480 super | 485 super |
481 end | 486 end |
482 | 487 |
483 # Overrides #pick_layout so that #render with no arguments | 488 # Overrides #pick_layout so that #render with no arguments |
484 # doesn't use the layout for api requests | 489 # doesn't use the layout for api requests |
485 def pick_layout(*args) | 490 def pick_layout(*args) |
486 api_request? ? nil : super | 491 api_request? ? nil : super |
487 end | 492 end |