##// END OF EJS Templates
Dry Users API responders....
Dry Users API responders. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4454 e93f8b46-1217-0410-a6f0-8f06a7374b81

File last commit:

r4338:96ce0f017cfe
r4340:ea59d93dc82d
Show More
application_controller.rb
417 lines | 13.4 KiB | text/x-ruby | RubyLexer
/ app / controllers / application_controller.rb
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 # redMine - project management software
# Copyright (C) 2006-2007 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.
Jean-Philippe Lang
Redirect user to the previous page after logging in (#1679)....
r1686 require 'uri'
Jean-Philippe Lang
Unescape back_url param before calling redirect_to....
r1891 require 'cgi'
Jean-Philippe Lang
Redirect user to the previous page after logging in (#1679)....
r1686
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 class ApplicationController < ActionController::Base
Jean-Philippe Lang
Merged Rails 2.2 branch. Redmine now requires Rails 2.2.2....
r2430 include Redmine::I18n
Eric Davis
Upgraded to Rails 2.3.4 (#3597)...
r2773
Jean-Philippe Lang
Moves @layout 'base'@ to ApplicationController....
r1726 layout 'base'
Jean-Philippe Lang
Adds a builder-like template system for rendering xml and json API responses....
r4338 exempt_from_layout 'builder', 'apit'
Jean-Philippe Lang
Moves @layout 'base'@ to ApplicationController....
r1726
Jean-Philippe Lang
Remove broken cookies after upgrade from 0.8.x to prevent an error from Rails (#4292)....
r2979 # Remove broken cookie after upgrade from 0.8.x (#4292)
# See https://rails.lighthouseapp.com/projects/8994/tickets/3360
# TODO: remove it when Rails is fixed
before_filter :delete_broken_cookies
def delete_broken_cookies
if cookies['_redmine_session'] && cookies['_redmine_session'] !~ /--/
cookies.delete '_redmine_session'
Jean-Philippe Lang
Removes "xxx and return" calls (#4446)....
r3071 redirect_to home_path
return false
Jean-Philippe Lang
Remove broken cookies after upgrade from 0.8.x to prevent an error from Rails (#4292)....
r2979 end
end
Jean-Philippe Lang
Merged 0.6 branch into trunk....
r663 before_filter :user_setup, :check_if_login_required, :set_localization
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 filter_parameter_logging :password
Eric Davis
Protect controllers from potential CSRF attacks. #4216...
r2937 protect_from_forgery
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330
Jean-Philippe Lang
Display an error when authenticity token is invalid....
r2980 rescue_from ActionController::InvalidAuthenticityToken, :with => :invalid_authenticity_token
Jean-Philippe Lang
Contextual quick search (#3263)....
r2829 include Redmine::Search::Controller
Jean-Philippe Lang
Highlight the current item of the main menu....
r1062 include Redmine::MenuManager::MenuController
helper Redmine::MenuManager::MenuHelper
Eric Davis
Converted the REDMINE_SUPPORTED_SCM constant to a class...
r3326 Redmine::Scm::Base.all.each do |scm|
Jean-Philippe Lang
Applied this fix http://dev.rubyonrails.org/ticket/4967 to solve namespaced models dependencies problem....
r558 require_dependency "repository/#{scm.underscore}"
end
Jean-Philippe Lang
Remove broken cookies after upgrade from 0.8.x to prevent an error from Rails (#4292)....
r2979
Jean-Philippe Lang
Merged 0.6 branch into trunk....
r663 def user_setup
Jean-Philippe Lang
Moved current user management to a dedicated method for modularity....
r1016 # Check the settings cache for each request
Jean-Philippe Lang
Added cache for application settings (Setting model)....
r674 Setting.check_cache
Jean-Philippe Lang
Moved current user management to a dedicated method for modularity....
r1016 # Find the current user
Jean-Philippe Lang
Do not start user session when accessing atom feed with token-based authentication....
r2679 User.current = find_current_user
Jean-Philippe Lang
Moved current user management to a dedicated method for modularity....
r1016 end
# Returns the current user or nil if no user is logged in
Jean-Philippe Lang
Do not start user session when accessing atom feed with token-based authentication....
r2679 # and starts a session if needed
Jean-Philippe Lang
Moved current user management to a dedicated method for modularity....
r1016 def find_current_user
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 if session[:user_id]
Jean-Philippe Lang
Merged 0.6 branch into trunk....
r663 # existing session
Jean-Philippe Lang
Replaces User.find_active with a named scope....
r2077 (User.active.find(session[:user_id]) rescue nil)
Jean-Philippe Lang
Merged 0.6 branch into trunk....
r663 elsif cookies[:autologin] && Setting.autologin?
Jean-Philippe Lang
Do not start user session when accessing atom feed with token-based authentication....
r2679 # auto-login feature starts a new session
user = User.try_to_autologin(cookies[:autologin])
session[:user_id] = user.id if user
user
elsif params[:format] == 'atom' && params[:key] && accept_key_auth_actions.include?(params[:action])
# RSS key authentication does not start a session
Jean-Philippe Lang
Moved current user management to a dedicated method for modularity....
r1016 User.find_by_rss_key(params[:key])
Jean-Philippe Lang
XML REST API for issues that provides CRUD operations for Issues (#1214)....
r3196 elsif Setting.rest_api_enabled? && ['xml', 'json'].include?(params[:format])
if params[:key].present? && accept_key_auth_actions.include?(params[:action])
Eric Davis
Added support for HTTP Basic access to the API. (#3920)...
r3105 # Use API key
User.find_by_api_key(params[:key])
else
# HTTP Basic, either username/password or API key/random
authenticate_with_http_basic do |username, password|
User.try_to_login(username, password) || User.find_by_api_key(username)
end
end
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 end
end
Eric Davis
Added support for HTTP Basic access to the API. (#3920)...
r3105
Jean-Philippe Lang
Fixed: When logging in via an autologin cookie the user's last_login_on should be updated (#2820)....
r2460 # Sets the logged in user
def logged_user=(user)
Jean-Philippe Lang
Reset session on login/logout (#4248)....
r2966 reset_session
Jean-Philippe Lang
Fixed: When logging in via an autologin cookie the user's last_login_on should be updated (#2820)....
r2460 if user && user.is_a?(User)
User.current = user
session[:user_id] = user.id
else
User.current = User.anonymous
end
end
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 # check if login is globally required to access the application
def check_if_login_required
Jean-Philippe Lang
Added autologin feature (disabled by default)....
r511 # no check needed if user is already logged in
Jean-Philippe Lang
Merged 0.6 branch into trunk....
r663 return true if User.current.logged?
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 require_login if Setting.login_required?
end
def set_localization
Jean-Philippe Lang
Merged Rails 2.2 branch. Redmine now requires Rails 2.2.2....
r2430 lang = nil
if User.current.logged?
lang = find_language(User.current.language)
end
if lang.nil? && request.env['HTTP_ACCEPT_LANGUAGE']
Jean-Philippe Lang
Fixed: 500 internal error when browsing any Redmine page in Epiphany (#5401)....
r3588 accept_lang = parse_qvalues(request.env['HTTP_ACCEPT_LANGUAGE']).first
Jean-Philippe Lang
Merged Rails 2.2 branch. Redmine now requires Rails 2.2.2....
r2430 if !accept_lang.blank?
Jean-Philippe Lang
Fixed: 500 internal error when browsing any Redmine page in Epiphany (#5401)....
r3588 accept_lang = accept_lang.downcase
Jean-Philippe Lang
Merged Rails 2.2 branch. Redmine now requires Rails 2.2.2....
r2430 lang = find_language(accept_lang) || find_language(accept_lang.split('-').first)
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 end
Jean-Philippe Lang
Merged Rails 2.2 branch. Redmine now requires Rails 2.2.2....
r2430 end
lang ||= Setting.default_language
set_language_if_valid(lang)
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 end
def require_login
Jean-Philippe Lang
Merged 0.6 branch into trunk....
r663 if !User.current.logged?
Eric Davis
Fix 500 errors with a POST request that requires a login. #4216...
r2936 # Extract only the basic url parameters on non-GET requests
if request.get?
url = url_for(params)
else
url = url_for(:controller => params[:controller], :action => params[:action], :id => params[:id], :project_id => params[:project_id])
end
Eric Davis
Allow authenticating with an API token via XML or JSON. (#3920)...
r3104 respond_to do |format|
format.html { redirect_to :controller => "account", :action => "login", :back_url => url }
Eric Davis
Added support for HTTP Basic access to the API. (#3920)...
r3105 format.atom { redirect_to :controller => "account", :action => "login", :back_url => url }
Jean-Philippe Lang
Fixed: API 401 response does not include WWW-Authenticate header (#5322)....
r3565 format.xml { head :unauthorized, 'WWW-Authenticate' => 'Basic realm="Redmine API"' }
Eric Davis
Allow js formatted responses....
r3713 format.js { head :unauthorized, 'WWW-Authenticate' => 'Basic realm="Redmine API"' }
Jean-Philippe Lang
Fixed: API 401 response does not include WWW-Authenticate header (#5322)....
r3565 format.json { head :unauthorized, 'WWW-Authenticate' => 'Basic realm="Redmine API"' }
Eric Davis
Allow authenticating with an API token via XML or JSON. (#3920)...
r3104 end
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 return false
end
true
end
def require_admin
return unless require_login
Jean-Philippe Lang
Merged 0.6 branch into trunk....
r663 if !User.current.admin?
Jean-Philippe Lang
A 403 error page is now displayed (instead of a blank page) when trying to access a protected page....
r492 render_403
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 return false
end
true
end
Jean-Philippe Lang
Adds cross-project time reports support (#994)....
r1777
def deny_access
User.current.logged? ? render_403 : require_login
end
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330
Jean-Philippe Lang
Merged 0.6 branch into trunk....
r663 # Authorize the user for the requested action
Jean-Philippe Lang
Ability to allow non-admin users to create projects (#1007)....
r2651 def authorize(ctrl = params[:controller], action = params[:action], global = false)
Jean-Baptiste Barth
Added ability to delete issues from different projects through contextual menu (#5332)...
r4122 allowed = User.current.allowed_to?({:controller => ctrl, :action => action}, @project || @projects, :global => global)
Jean-Philippe Lang
Improved error message when trying to access an archived project (#2995)....
r4171 if allowed
true
else
if @project && @project.archived?
render_403 :message => :notice_not_authorized_archived_project
else
deny_access
end
end
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 end
Jean-Philippe Lang
Ability to allow non-admin users to create projects (#1007)....
r2651
# Authorize the user for the requested action outside a project
def authorize_global(ctrl = params[:controller], action = params[:action], global = true)
authorize(ctrl, action, global)
end
Eric Davis
Refactor: Pull up several #find_project methods to ApplicationController...
r3256
# Find project of id params[:id]
def find_project
@project = Project.find(params[:id])
rescue ActiveRecord::RecordNotFound
render_404
end
Eric Davis
Refactor: Split the find_object methods to prep for a larger refactoring....
r3477
Eric Davis
Refactor: convert ProjectEnumerations to a resource on a project....
r3961 # Find project of id params[:project_id]
def find_project_by_project_id
@project = Project.find(params[:project_id])
rescue ActiveRecord::RecordNotFound
render_404
end
Eric Davis
Refactor: Pull up #find_optional_project to ApplicationController....
r3602 # Find a project based on params[:project_id]
# TODO: some subclasses override this, see about merging their logic
def find_optional_project
@project = Project.find(params[:project_id]) unless params[:project_id].blank?
allowed = User.current.allowed_to?({:controller => params[:controller], :action => params[:action]}, @project, :global => true)
allowed ? true : deny_access
rescue ActiveRecord::RecordNotFound
render_404
end
Eric Davis
Refactor: Split the find_object methods to prep for a larger refactoring....
r3477 # Finds and sets @project based on @object.project
def find_project_from_association
render_404 unless @object.present?
@project = @object.project
rescue ActiveRecord::RecordNotFound
render_404
end
Eric Davis
Refactor: Change the different find_object filters to share a common method....
r3483 def find_model_object
model = self.class.read_inheritable_attribute('model_object')
if model
@object = model.find(params[:id])
self.instance_variable_set('@' + controller_name.singularize, @object) if @object
end
rescue ActiveRecord::RecordNotFound
render_404
end
def self.model_object(model)
write_inheritable_attribute('model_object', model)
end
Eric Davis
Refactor: Pull up method to ApplicationController....
r3824
# Filter for bulk issue operations
def find_issues
@issues = Issue.find_all_by_id(params[:id] || params[:ids])
raise ActiveRecord::RecordNotFound if @issues.empty?
Jean-Baptiste Barth
Splitted #find_issues filter in ApplicationController to #find_issues and #check_project_uniqueness (#5332)...
r4114 @projects = @issues.collect(&:project).compact.uniq
@project = @projects.first if @projects.size == 1
rescue ActiveRecord::RecordNotFound
render_404
end
# Check if project is unique before bulk operations
def check_project_uniqueness
unless @project
Eric Davis
Refactor: Pull up method to ApplicationController....
r3824 # TODO: let users bulk edit/move/destroy issues from different projects
render_error 'Can not bulk edit/move/destroy issues from different projects'
return false
end
end
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 # make sure that the user is a member of the project (or admin) if project is private
# used as a before_filter for actions that do not require any particular permission on the project
def check_project_privacy
Jean-Philippe Lang
Fixes #820: invalid project id causes a NoMethodError in SearchController (Angel Dobbs-Sciortino)....
r1223 if @project && @project.active?
if @project.is_public? || User.current.member_of?(@project) || User.current.admin?
true
else
User.current.logged? ? render_403 : require_login
end
else
Jean-Philippe Lang
Added the ability to archive projects:...
r546 @project = nil
render_404
Jean-Philippe Lang
Fixes #820: invalid project id causes a NoMethodError in SearchController (Angel Dobbs-Sciortino)....
r1223 false
Jean-Philippe Lang
Added the ability to archive projects:...
r546 end
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 end
Eric Davis
Refactor: extract back_url method to ApplicationController....
r3798 def back_url
params[:back_url] || request.env['HTTP_REFERER']
end
Jean-Philippe Lang
v0.2.0...
r5 def redirect_back_or_default(default)
Jean-Philippe Lang
Unescape back_url param before calling redirect_to....
r1891 back_url = CGI.unescape(params[:back_url].to_s)
Jean-Philippe Lang
Redirect user to the previous page after logging in (#1679)....
r1686 if !back_url.blank?
Jean-Philippe Lang
Rescue back_url param parsing on redirect....
r2124 begin
uri = URI.parse(back_url)
# do not redirect user to another host or to the login or register page
if (uri.relative? || (uri.host == request.host)) && !uri.path.match(%r{/(login|account/register)})
Jean-Philippe Lang
Removes "xxx and return" calls (#4446)....
r3071 redirect_to(back_url)
return
Jean-Philippe Lang
Rescue back_url param parsing on redirect....
r2124 end
rescue URI::InvalidURIError
# redirect to default
Jean-Philippe Lang
Redirect user to the previous page after logging in (#1679)....
r1686 end
Jean-Philippe Lang
v0.2.0...
r5 end
Jean-Philippe Lang
Redirect user to the previous page after logging in (#1679)....
r1686 redirect_to default
Jean-Philippe Lang
v0.2.0...
r5 end
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330
Jean-Philippe Lang
Improved error message when trying to access an archived project (#2995)....
r4171 def render_403(options={})
Jean-Philippe Lang
A 403 error page is now displayed (instead of a blank page) when trying to access a protected page....
r492 @project = nil
Jean-Philippe Lang
Refactor: merged error rendering methods....
r4172 render_error({:message => :notice_not_authorized, :status => 403}.merge(options))
Jean-Philippe Lang
A 403 error page is now displayed (instead of a blank page) when trying to access a protected page....
r492 return false
end
Jean-Philippe Lang
Refactor: merged error rendering methods....
r4172 def render_404(options={})
render_error({:message => :notice_file_not_found, :status => 404}.merge(options))
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 return false
end
Jean-Philippe Lang
Merged 0.6 branch into trunk....
r663
Jean-Philippe Lang
Refactor: merged error rendering methods....
r4172 # Renders an error response
def render_error(arg)
arg = {:message => arg} unless arg.is_a?(Hash)
@message = arg[:message]
@message = l(@message) if @message.is_a?(Symbol)
@status = arg[:status] || 500
Jean-Philippe Lang
XML REST API for issues that provides CRUD operations for Issues (#1214)....
r3196 respond_to do |format|
Jean-Philippe Lang
Refactor: merged error rendering methods....
r4172 format.html {
render :template => 'common/error', :layout => use_layout, :status => @status
Jean-Philippe Lang
XML REST API for issues that provides CRUD operations for Issues (#1214)....
r3196 }
Jean-Philippe Lang
Refactor: merged error rendering methods....
r4172 format.atom { head @status }
format.xml { head @status }
format.js { head @status }
format.json { head @status }
Jean-Philippe Lang
XML REST API for issues that provides CRUD operations for Issues (#1214)....
r3196 end
Jean-Philippe Lang
Show explicit error message when the scm command failed (eg. when svn binary is not available)....
r1080 end
Eric Davis
Use the base layout for all 403, 404, and 500 pages. #6172...
r3835
# Picks which layout to use based on the request
#
# @return [boolean, string] name of the layout to use or false for no layout
def use_layout
request.xhr? ? false : 'base'
end
Jean-Philippe Lang
Show explicit error message when the scm command failed (eg. when svn binary is not available)....
r1080
Jean-Philippe Lang
Display an error when authenticity token is invalid....
r2980 def invalid_authenticity_token
Jean-Philippe Lang
Adds a log message when an API call raises an InvalidAuthenticityToken error....
r3218 if api_request?
logger.error "Form authenticity token is missing or is invalid. API calls must include a proper Content-type header (text/xml or text/json)."
end
Jean-Philippe Lang
Display an error when authenticity token is invalid....
r2980 render_error "Invalid form authenticity token."
end
Jean-Philippe Lang
Added atom feed on the new cross-project issue list....
r675 def render_feed(items, options={})
@items = items || []
@items.sort! {|x,y| y.event_datetime <=> x.event_datetime }
Jean-Philippe Lang
Fixed: Feed content limit setting has no effect (closes #954)....
r1295 @items = @items.slice(0, Setting.feeds_limit.to_i)
Jean-Philippe Lang
Merged 0.6 branch into trunk....
r663 @title = options[:title] || Setting.app_title
render :template => "common/feed.atom.rxml", :layout => false, :content_type => 'application/atom+xml'
end
def self.accept_key_auth(*actions)
actions = actions.flatten.map(&:to_s)
write_inheritable_attribute('accept_key_auth_actions', actions)
end
def accept_key_auth_actions
self.class.read_inheritable_attribute('accept_key_auth_actions') || []
end
Jean-Philippe Lang
Added ApplicationController#attach_files as a common method to attach files in all actions....
r977
Jean-Philippe Lang
New setting added to specify how many objects should be displayed on most paginated lists....
r1013 # Returns the number of objects that should be displayed
# on the paginated list
def per_page_option
per_page = nil
if params[:per_page] && Setting.per_page_options_array.include?(params[:per_page].to_s.to_i)
per_page = params[:per_page].to_s.to_i
session[:per_page] = per_page
elsif session[:per_page]
per_page = session[:per_page]
else
per_page = Setting.per_page_options_array.first || 25
end
per_page
end
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 # qvalues http header parser
# code taken from webrick
def parse_qvalues(value)
tmp = []
if value
parts = value.split(/,\s*/)
parts.each {|part|
if m = %r{^([^\s,]+?)(?:;\s*q=(\d+(?:\.\d+)?))?$}.match(part)
val = m[1]
q = (m[2] or 1).to_f
tmp.push([val, q])
end
}
tmp = tmp.sort_by{|val, q| -q}
tmp.collect!{|val, q| val}
end
return tmp
Jean-Philippe Lang
Merged Rails 2.2 branch. Redmine now requires Rails 2.2.2....
r2430 rescue
nil
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 end
Jean-Philippe Lang
Non-ascii attachement filename fix for IE....
r1039
# Returns a string that can be used as filename value in Content-Disposition header
def filename_for_content_disposition(name)
request.env['HTTP_USER_AGENT'] =~ %r{MSIE} ? ERB::Util.url_encode(name) : name
end
Jean-Philippe Lang
Adds a log message when an API call raises an InvalidAuthenticityToken error....
r3218
def api_request?
%w(xml json).include? params[:format]
end
Eric Davis
Refactor: Decouple failed attachments and the flash messages...
r3414
# Renders a warning flash if obj has unsaved attachments
def render_attachment_warning_if_needed(obj)
flash[:warning] = l(:warning_attachments_not_saved, obj.unsaved_attachments.size) if obj.unsaved_attachments.present?
end
Eric Davis
Refactor: pull #query_statement_invalid up to ApplicationController....
r3582
Eric Davis
Refactor: pull up method to ApplicationController....
r3826 # Sets the `flash` notice or error based the number of issues that did not save
#
# @param [Array, Issue] issues all of the saved and unsaved Issues
# @param [Array, Integer] unsaved_issue_ids the issue ids that were not saved
def set_flash_from_bulk_issue_save(issues, unsaved_issue_ids)
if unsaved_issue_ids.empty?
flash[:notice] = l(:notice_successful_update) unless issues.empty?
else
flash[:error] = l(:notice_failed_to_save_issues,
:count => unsaved_issue_ids.size,
:total => issues.size,
:ids => '#' + unsaved_issue_ids.join(', #'))
end
end
Eric Davis
Refactor: pull #query_statement_invalid up to ApplicationController....
r3582 # Rescues an invalid query statement. Just in case...
def query_statement_invalid(exception)
logger.error "Query::StatementInvalid: #{exception.message}" if logger
session.delete(:query)
sort_clear if respond_to?(:sort_clear)
render_error "An error occurred while executing the query and has been logged. Please report this error to your Redmine administrator."
end
Eric Davis
Added JSON support to the issues API. #1214...
r3652 # Converts the errors on an ActiveRecord object into a common JSON format
def object_errors_to_json(object)
object.errors.collect do |attribute, error|
{ attribute => error }
end.to_json
end
Jean-Philippe Lang
Merged 0.6 branch into trunk....
r663 end