2013-10-30 20:56:24 +08:00
# Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require 'uri'
require 'cgi'
class Unauthorized < Exception ; end
class ApplicationController < ActionController :: Base
include Redmine :: I18n
include Redmine :: Pagination
include RoutesHelper
helper :routes
#added by william
helper :watchers
class_attribute :accept_api_auth_actions
class_attribute :accept_rss_auth_actions
class_attribute :model_object
layout 'base'
protect_from_forgery
def handle_unverified_request
super
2015-10-21 17:13:07 +08:00
raise ( ActionController :: InvalidAuthenticityToken )
# cookies.delete(autologin_cookie_name)
2013-10-30 20:56:24 +08:00
end
2014-07-30 15:26:55 +08:00
before_filter :find_first_page
2014-10-13 17:38:59 +08:00
before_filter :find_web_footer
2013-10-30 20:56:24 +08:00
before_filter :session_expiration , :user_setup , :check_if_login_required , :set_localization
2013-11-28 09:36:46 +08:00
before_filter :user_agent
2013-10-30 20:56:24 +08:00
rescue_from ActionController :: InvalidAuthenticityToken , :with = > :invalid_authenticity_token
rescue_from :: Unauthorized , :with = > :deny_access
rescue_from :: ActionView :: MissingTemplate , :with = > :missing_template
include Redmine :: Search :: Controller
include Redmine :: MenuManager :: MenuController
helper Redmine :: MenuManager :: MenuHelper
2013-11-28 09:36:46 +08:00
def user_agent
logger . info " HTTP_USER_AGENT #{ request . env [ " HTTP_USER_AGENT " ] } "
end
2013-10-30 20:56:24 +08:00
def session_expiration
if session [ :user_id ]
if session_expired? && ! try_to_autologin
reset_session
flash [ :error ] = l ( :error_session_expired )
redirect_to signin_url
else
session [ :atime ] = Time . now . utc . to_i
end
end
end
2013-11-28 09:36:46 +08:00
2013-10-30 20:56:24 +08:00
def session_expired?
if Setting . session_lifetime?
unless session [ :ctime ] && ( Time . now . utc . to_i - session [ :ctime ] . to_i < = Setting . session_lifetime . to_i * 60 )
return true
end
end
if Setting . session_timeout?
unless session [ :atime ] && ( Time . now . utc . to_i - session [ :atime ] . to_i < = Setting . session_timeout . to_i * 60 )
return true
end
end
false
end
def start_user_session ( user )
session [ :user_id ] = user . id
session [ :ctime ] = Time . now . utc . to_i
session [ :atime ] = Time . now . utc . to_i
end
def user_setup
# Check the settings cache for each request
Setting . check_cache
# Find the current user
User . current = find_current_user
2014-06-30 17:26:11 +08:00
#logger.info(" Current user: " + (User.current.logged? ? "#{User.current.login} (id=#{User.current.id})" : "anonymous")) if logger
2013-10-30 20:56:24 +08:00
end
# Returns the current user or nil if no user is logged in
# and starts a session if needed
def current_user
find_current_user
end
def find_current_user
user = nil
unless api_request?
if session [ :user_id ]
# existing session
user = ( User . active . find ( session [ :user_id ] ) rescue nil )
elsif autologin_user = try_to_autologin
user = autologin_user
elsif params [ :format ] == 'atom' && params [ :key ] && request . get? && accept_rss_auth?
# RSS key authentication does not start a session
user = User . find_by_rss_key ( params [ :key ] )
end
end
if user . nil? && Setting . rest_api_enabled? && accept_api_auth?
if ( key = api_key_from_request )
# Use API key
user = User . find_by_api_key ( key )
else
# HTTP Basic, either username/password or API key/random
authenticate_with_http_basic do | username , password |
2014-11-21 19:11:40 +08:00
user = User . try_to_login ( username , password ) [ 0 ] || User . find_by_api_key ( username )
2013-10-30 20:56:24 +08:00
end
end
# Switch user if requested by an admin user
if user && user . admin? && ( username = api_switch_user_from_request )
su = User . find_by_login ( username )
if su && su . active?
logger . info ( " User switched by: #{ user . login } (id= #{ user . id } ) " ) if logger
user = su
else
render_error :message = > 'Invalid X-Redmine-Switch-User header' , :status = > 412
end
end
end
user
end
def autologin_cookie_name
Redmine :: Configuration [ 'autologin_cookie_name' ] . presence || 'autologin'
end
def try_to_autologin
if cookies [ autologin_cookie_name ] && Setting . autologin?
# auto-login feature starts a new session
user = User . try_to_autologin ( cookies [ autologin_cookie_name ] )
if user
reset_session
start_user_session ( user )
end
user
end
end
2015-01-15 18:48:19 +08:00
2015-05-05 11:45:58 +08:00
def try_to_autologin1
user = User . try_to_autologin ( params [ :token ] )
if user
logout_user if User . current . id != user . id
start_user_session ( user )
end
user
2015-01-15 18:48:19 +08:00
end
2015-05-05 11:45:58 +08:00
2013-10-30 20:56:24 +08:00
# Sets the logged in user
def logged_user = ( user )
reset_session
if user && user . is_a? ( User )
User . current = user
start_user_session ( user )
else
User . current = User . anonymous
end
end
2015-03-09 17:28:17 +08:00
def logged_user_by_apptoken
#从手机端传来apptoken则将当前登陆用户变为对应的用户
if params [ :apptoken ]
token = ApiKey . where ( access_token : params [ :apptoken ] ) . first
2015-03-10 14:41:36 +08:00
if token . expired?
return
end
2015-03-09 17:28:17 +08:00
if token && ! token . expired?
@current_user = User . find ( token . user_id )
end
unless @current_user . nil?
self . logged_user = @current_user
if @current_user
@current_user . update_column ( :last_login_on , Time . now )
end
end
end
end
2013-10-30 20:56:24 +08:00
# Logs out current user
def logout_user
if User . current . logged?
2015-05-28 12:23:56 +08:00
if Redmine :: Configuration [ 'cookie_domain' ] . present?
cookies . delete ( autologin_cookie_name , domain : Redmine :: Configuration [ 'cookie_domain' ] )
else
cookies . delete autologin_cookie_name
end
2015-05-05 11:45:58 +08:00
# Token.delete_all(["user_id = ? AND action = ?", User.current.id, 'autologin'])
2013-10-30 20:56:24 +08:00
self . logged_user = nil
end
end
# check if login is globally required to access the application
def check_if_login_required
# no check needed if user is already logged in
return true if User . current . logged?
require_login if Setting . login_required?
end
def set_localization
lang = nil
if User . current . logged?
lang = find_language ( User . current . language )
end
if lang . nil? && request . env [ 'HTTP_ACCEPT_LANGUAGE' ]
accept_lang = parse_qvalues ( request . env [ 'HTTP_ACCEPT_LANGUAGE' ] ) . first
if ! accept_lang . blank?
accept_lang = accept_lang . downcase
lang = find_language ( accept_lang ) || find_language ( accept_lang . split ( '-' ) . first )
end
end
lang || = Setting . default_language
set_language_if_valid ( lang )
end
def require_login
if ! User . current . logged?
# 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
respond_to do | format |
2014-10-15 09:54:54 +08:00
format . html { redirect_to signin_url }
format . atom { redirect_to signin_url }
2013-10-30 20:56:24 +08:00
format . xml { head :unauthorized , 'WWW-Authenticate' = > 'Basic realm="Redmine API"' }
format . js { head :unauthorized , 'WWW-Authenticate' = > 'Basic realm="Redmine API"' }
format . json { head :unauthorized , 'WWW-Authenticate' = > 'Basic realm="Redmine API"' }
end
return false
end
true
end
def require_admin
return unless require_login
if ! User . current . admin?
render_403
return false
end
true
end
def deny_access
User . current . logged? ? render_403 : require_login
end
# Authorize the user for the requested action
def authorize ( ctrl = params [ :controller ] , action = params [ :action ] , global = false )
2014-06-11 11:31:35 +08:00
#modify by NWB
2014-12-22 01:29:53 +08:00
allowed = authorize_allowed ( params [ :controller ] , params [ :action ] , global )
2014-06-11 11:31:35 +08:00
2013-10-30 20:56:24 +08:00
if allowed
true
else
if @project && @project . archived?
render_403 :message = > :notice_not_authorized_archived_project
else
deny_access
end
end
end
2015-01-15 18:48:19 +08:00
def authorize1 ( ctrl = params [ :controller ] , action = params [ :action ] , token = params [ :token ] , global = false )
2015-01-14 16:08:56 +08:00
2015-01-15 18:48:19 +08:00
if ( ! User . current . logged? && ! token . nil? )
User . current = try_to_autologin1
2015-01-13 18:24:14 +08:00
end
allowed = authorize_allowed ( params [ :controller ] , params [ :action ] , global )
if allowed
true
else
if @project && @project . archived?
render_403 :message = > :notice_not_authorized_archived_project
else
deny_access
end
end
end
2015-01-17 11:18:24 +08:00
def auth_login1 ( token = params [ :token ] )
if ( ! User . current . logged? && ! token . nil? )
2013-10-30 20:56:24 +08:00
2015-01-17 11:18:24 +08:00
User . current = try_to_autologin1
end
end
2014-12-22 01:29:53 +08:00
def authorize_allowed ( ctrl = params [ :controller ] , action = params [ :action ] , global = false )
#modify by NWB
if @project
allowed = User . current . allowed_to? ( { :controller = > ctrl , :action = > action } , @project || @projects , :global = > global )
elsif @course
allowed = User . current . allowed_to? ( { :controller = > ctrl , :action = > action } , @course || @courses , :global = > global )
else
2016-01-22 16:10:05 +08:00
# allowed = User.current.allowed_to?({:controller => ctrl, :action => action}, @project || @projects, :global => global)
allowed = true
2014-12-22 01:29:53 +08:00
end
allowed
end
2014-09-28 11:31:12 +08:00
def authorize_attachment_download ( ctrl = params [ :controller ] , action = params [ :action ] , global = false )
2015-01-14 16:08:56 +08:00
2014-10-15 17:26:58 +08:00
case @attachment . container_type
when " Memo "
allowed = User . current . allowed_to? ( :memos_attachments_download , nil , :global = > true )
when " Message "
if @project
allowed = User . current . allowed_to? ( :projects_attachments_download , @project , :global = > false )
elsif @course
allowed = User . current . allowed_to? ( :course_attachments_download , @course , :global = > false )
end
when " contest "
return true
2014-11-22 10:06:56 +08:00
when " Course "
allowed = User . current . allowed_to? ( :course_attachments_download , @course , :global = > false )
2014-10-15 17:26:58 +08:00
else
return true
2014-09-28 11:31:12 +08:00
end
if allowed
true
else
if @project && @project . archived?
render_403 :message = > :notice_not_authorized_archived_project
else
deny_access
end
end
end
2015-01-15 18:48:19 +08:00
def authorize_attachment_download1 ( ctrl = params [ :controller ] , action = params [ :action ] , token = params [ :token ] , global = false )
if ( ! User . current . logged? && ! token . nil? )
User . current = try_to_autologin1
2015-01-14 16:08:56 +08:00
end
case @attachment . container_type
when " Memo "
allowed = User . current . allowed_to? ( :memos_attachments_download , nil , :global = > true )
when " Message "
if @project
allowed = User . current . allowed_to? ( :projects_attachments_download , @project , :global = > false )
elsif @course
allowed = User . current . allowed_to? ( :course_attachments_download , @course , :global = > false )
end
when " contest "
return true
when " Course "
allowed = User . current . allowed_to? ( :course_attachments_download , @course , :global = > false )
else
return true
end
if allowed
true
else
if @project && @project . archived?
render_403 :message = > :notice_not_authorized_archived_project
else
deny_access
end
end
end
2014-06-06 13:56:48 +08:00
def authorize_course ( ctrl = params [ :controller ] , action = params [ :action ] , global = false )
allowed = User . current . allowed_to? ( { :controller = > ctrl , :action = > action } , @course || @course , :global = > global )
if allowed
true
else
2015-10-26 13:26:49 +08:00
if params [ :action ] == 'show'
#更新申请结果反馈消息的状态
messages = CourseMessage . where ( " course_message_type =? and course_id =? and user_id =? and viewed =? " , 'CourseRequestDealResult' , @course . id , User . current . id , false )
messages . update_all ( :viewed = > true )
end
2014-06-06 13:56:48 +08:00
if @course && @course . archived?
render_403 :message = > :notice_not_authorized_archived_project
else
deny_access
end
end
end
def authorize_course_global ( ctrl = params [ :controller ] , action = params [ :action ] , global = true )
authorize_course ( ctrl , action , global )
end
2013-10-30 20:56:24 +08:00
# 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
# Find project of id params[:id]
def find_project
2014-12-10 16:26:39 +08:00
@project = Project . find ( params [ :id ] )
2013-10-30 20:56:24 +08:00
rescue ActiveRecord :: RecordNotFound
render_404
end
# Find project of id params[:project_id]
def find_project_by_project_id
2014-06-09 14:23:31 +08:00
if params [ :project_id ]
@project = Project . find ( params [ :project_id ] )
elsif params [ :course_id ]
@course = Course . find ( params [ :course_id ] )
2015-12-11 16:30:50 +08:00
elsif params [ :org_subfield_id ]
@org_subfield = OrgSubfield . find ( params [ :org_subfield_id ] )
2014-06-09 14:23:31 +08:00
end
2013-10-30 20:56:24 +08:00
rescue ActiveRecord :: RecordNotFound
2014-06-09 14:23:31 +08:00
render_404
2013-10-30 20:56:24 +08:00
end
2014-05-30 20:32:37 +08:00
def find_contest_by_contest_id
@contest = Contest . find ( params [ :contest_id ] )
rescue ActiveRecord :: RecordNotFound
render_404
end
2014-06-30 17:26:11 +08:00
#<23> <> <EFBFBD> course_id<69> <64> project
2014-06-05 17:39:48 +08:00
def find_project_by_course_id
@bid = Bid . find params [ :course_id ]
@project = @bid . courses [ 0 ]
rescue ActiveRecord :: RecordNotFound
render_404
end
2013-10-30 20:56:24 +08:00
# 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
2014-05-30 20:32:37 +08:00
def find_optional_contest
@contest = Contest . find ( params [ :contest_id ] ) unless params [ :contest_id ] . blank?
allowed = User . current . allowed_to? ( { :controller = > params [ :controller ] , :action = > params [ :action ] } , @contest , :global = > true )
allowed ? true : deny_access
rescue ActiveRecord :: RecordNotFound
render_404
end
2013-10-30 20:56:24 +08:00
# Finds and sets @project based on @object.project
def find_project_from_association
render_404 unless @object . present?
@project = @object . project
2014-06-12 16:01:38 +08:00
if @project == nil && @object . has_attribute? ( 'course_id' )
@course = @object . course
end
2013-10-30 20:56:24 +08:00
end
2014-05-30 20:32:37 +08:00
def find_contest_from_association
2014-06-05 14:58:24 +08:00
render_404 unless @object . present?
2014-05-30 20:32:37 +08:00
2014-06-05 14:58:24 +08:00
@contest = @object . contest
2014-05-30 20:32:37 +08:00
end
2013-10-30 20:56:24 +08:00
def find_model_object
model = self . class . 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
2014-06-12 09:20:39 +08:00
#added by nwb
2014-06-30 17:26:11 +08:00
#<23> <> ȡ<EFBFBD> γ <EFBFBD>
2014-06-05 10:33:32 +08:00
def find_course
@course = Course . find ( params [ :id ] )
rescue ActiveRecord :: RecordNotFound
render_404
end
2014-06-06 16:03:47 +08:00
# def find_model_object_contest
# model = self.class.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
2014-05-30 20:32:37 +08:00
2013-10-30 20:56:24 +08:00
def self . model_object ( model )
self . model_object = model
end
# Find the issue whose id is the :id parameter
# Raises a Unauthorized exception if the issue is not visible
def find_issue
# Issue.visible.find(...) can not be used to redirect user to the login form
# if the issue actually exists but requires authentication
@issue = Issue . find ( params [ :id ] )
raise Unauthorized unless @issue . visible?
@project = @issue . project
rescue ActiveRecord :: RecordNotFound
render_404
end
# Find issues with a single :id param or :ids array param
# Raises a Unauthorized exception if one of the issues is not visible
def find_issues
@issues = Issue . find_all_by_id ( params [ :id ] || params [ :ids ] )
raise ActiveRecord :: RecordNotFound if @issues . empty?
raise Unauthorized unless @issues . all? ( & :visible? )
@projects = @issues . collect ( & :project ) . compact . uniq
@project = @projects . first if @projects . size == 1
rescue ActiveRecord :: RecordNotFound
render_404
end
def find_attachments
if ( attachments = params [ :attachments ] ) . present?
att = attachments . values . collect do | attachment |
Attachment . find_by_token ( attachment [ :token ] ) if attachment [ :token ] . present?
end
att . compact!
end
@attachments = att || [ ]
end
# 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
if @project && ! @project . archived?
if @project . visible?
true
else
deny_access
end
else
@project = nil
render_404
false
end
end
def back_url
url = params [ :back_url ]
if url . nil? && referer = request . env [ 'HTTP_REFERER' ]
url = CGI . unescape ( referer . to_s )
end
url
end
2014-04-08 14:53:11 +08:00
def redirect_back_or_default ( default , options = { } )
2015-08-29 15:07:47 +08:00
back_url = '' #params[:back_url].to_s
2013-10-30 20:56:24 +08:00
if back_url . present?
begin
uri = URI . parse ( back_url )
# do not redirect user to another host or to the login or register page
2014-04-08 14:53:11 +08:00
if ( uri . relative? || ( uri . host == request . host ) ) && ! uri . path . match ( %r{ /(login|account/register) } )
2015-08-29 17:03:31 +08:00
back_url = back_url . gsub ( %r{ \ /users \ /( \ d+) } , " /users/ " + default . id . to_s ) if default . is_a? ( :User )
2013-10-30 20:56:24 +08:00
redirect_to ( back_url )
return
end
rescue URI :: InvalidURIError
logger . warn ( " Could not redirect to invalid URL #{ back_url } " )
# redirect to default
end
2014-04-08 14:53:11 +08:00
elsif options [ :referer ]
redirect_to_referer_or default
return
2013-10-30 20:56:24 +08:00
end
redirect_to default
false
end
# Redirects to the request referer if present, redirects to args or call block otherwise.
def redirect_to_referer_or ( * args , & block )
redirect_to :back
rescue :: ActionController :: RedirectBackError
if args . any?
redirect_to * args
elsif block_given?
block . call
else
raise " # redirect_to_referer_or takes arguments or a block "
end
end
def render_403 ( options = { } )
@project = nil
2014-10-22 14:53:54 +08:00
render_error ( { :message = > :notice_not_authorized , :status = > 403 } . merge ( options ) , 'common/403' )
#render :template => 'common/403'
2013-10-30 20:56:24 +08:00
return false
end
def render_404 ( options = { } )
2014-10-22 14:53:54 +08:00
render_error ( { :message = > :notice_file_not_found , :status = > 404 } . merge ( options ) , 'common/404' )
#render :template => 'common/404'
2013-10-30 20:56:24 +08:00
return false
end
# Renders an error response
2014-10-22 14:53:54 +08:00
def render_error ( arg , template = 'common/error' )
2013-10-30 20:56:24 +08:00
arg = { :message = > arg } unless arg . is_a? ( Hash )
@message = arg [ :message ]
2014-07-25 11:08:16 +08:00
@lay = arg [ :layout ]
2013-10-30 20:56:24 +08:00
@message = l ( @message ) if @message . is_a? ( Symbol )
@status = arg [ :status ] || 500
respond_to do | format |
format . html {
2014-07-25 11:08:16 +08:00
if @lay
2014-10-22 14:53:54 +08:00
render :template = > template , :layout = > @lay , :status = > @status
2014-07-25 11:08:16 +08:00
else
2014-10-22 14:53:54 +08:00
render :template = > template , :layout = > use_layout , :status = > @status
2014-07-25 11:08:16 +08:00
end
2013-10-30 20:56:24 +08:00
}
format . any { head @status }
end
end
# Handler for ActionView::MissingTemplate exception
def missing_template
logger . warn " Missing template, responding with 404 "
@project = nil
render_404
end
# Filter for actions that provide an API response
# but have no HTML representation for non admin users
def require_admin_or_api_request
return true if api_request?
if User . current . admin?
true
elsif User . current . logged?
render_error ( :status = > 406 )
else
deny_access
end
end
# 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
2014-08-01 16:01:16 +08:00
request . xhr? ? false : 'users_base'
2013-10-30 20:56:24 +08:00
end
def invalid_authenticity_token
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
2015-11-06 16:34:37 +08:00
#render_error "Invalid form authenticity token."
redirect_to signin_path ( :login = > true )
2013-10-30 20:56:24 +08:00
end
def render_feed ( items , options = { } )
@items = items || [ ]
@items . sort! { | x , y | y . event_datetime < = > x . event_datetime }
@items = @items . slice ( 0 , Setting . feeds_limit . to_i )
@title = options [ :title ] || Setting . app_title
render :template = > " common/feed " , :formats = > [ :atom ] , :layout = > false ,
:content_type = > 'application/atom+xml'
end
def self . accept_rss_auth ( * actions )
if actions . any?
self . accept_rss_auth_actions = actions
else
self . accept_rss_auth_actions || [ ]
end
end
def accept_rss_auth? ( action = action_name )
self . class . accept_rss_auth . include? ( action . to_sym )
end
def self . accept_api_auth ( * actions )
if actions . any?
self . accept_api_auth_actions = actions
else
self . accept_api_auth_actions || [ ]
end
end
def accept_api_auth? ( action = action_name )
self . class . accept_api_auth . include? ( action . to_sym )
end
# 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
# Returns offset and limit used to retrieve objects
# for an API response based on offset, limit and page parameters
def api_offset_and_limit ( options = params )
if options [ :offset ] . present?
offset = options [ :offset ] . to_i
if offset < 0
offset = 0
end
end
limit = options [ :limit ] . to_i
if limit < 1
limit = 25
elsif limit > 100
limit = 100
end
if offset . nil? && options [ :page ] . present?
offset = ( options [ :page ] . to_i - 1 ) * limit
offset = 0 if offset < 0
offset || = 0
end
[ offset , limit ]
end
# 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
rescue
nil
end
# Returns a string that can be used as filename value in Content-Disposition header
def filename_for_content_disposition ( name )
2015-10-13 16:29:25 +08:00
request . env [ 'HTTP_USER_AGENT' ] =~ %r{ MSIE|Trident } ? ERB :: Util . url_encode ( name ) : name
2013-10-30 20:56:24 +08:00
end
def api_request?
2016-01-29 21:15:23 +08:00
return false if params [ :controller ] == 'at'
2013-10-30 20:56:24 +08:00
%w( xml json ) . include? params [ :format ]
end
# Returns the API key present in the request
def api_key_from_request
if params [ :key ] . present?
params [ :key ] . to_s
elsif request . headers [ " X-Redmine-API-Key " ] . present?
request . headers [ " X-Redmine-API-Key " ] . to_s
end
end
# Returns the API 'switch user' value if present
def api_switch_user_from_request
request . headers [ " X-Redmine-Switch-User " ] . to_s . presence
end
# 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
# 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
# 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
# Renders a 200 response for successfull updates or deletions via the API
def render_api_ok
render_api_head :ok
end
# Renders a head API response
def render_api_head ( status )
# #head would return a response body with one space
render :text = > '' , :status = > status , :layout = > nil
end
# Renders API response on validation failure
def render_validation_errors ( objects )
if objects . is_a? ( Array )
@error_messages = objects . map { | object | object . errors . full_messages } . flatten
else
@error_messages = objects . errors . full_messages
end
render :template = > 'common/error_messages.api' , :status = > :unprocessable_entity , :layout = > nil
end
# Overrides #_include_layout? so that #render with no arguments
# doesn't use the layout for api requests
def _include_layout? ( * args )
api_request? ? false : super
end
2013-12-02 17:27:15 +08:00
## Please added code in html.
# <div class="pagination"><%= pagination_links_full @obj_pages, @obj_count, :per_page_links => false %></div>
def paginateHelper obj , pre_size = 20
2013-12-20 21:39:33 +08:00
@obj_count = obj . count
@obj_pages = Paginator . new @obj_count , pre_size , params [ 'page' ]
2013-12-02 17:27:15 +08:00
if obj . kind_of? ActiveRecord :: Base or obj . kind_of? ActiveRecord :: Relation
2014-01-15 14:28:36 +08:00
obj . limit ( @obj_pages . per_page ) . offset ( @obj_pages . offset )
2013-12-02 17:27:15 +08:00
elsif obj . kind_of? Array
2013-12-20 11:10:40 +08:00
obj [ @obj_pages . offset , @obj_pages . per_page ]
2013-12-02 17:27:15 +08:00
else
logger . error " [ApplicationController] Error : application_controller # paginateHelper ===> unknow category: #{ obj . class } "
2013-12-21 10:15:41 +08:00
raise RuntimeError , 'unknow type, Please input you type into this helper.'
2013-12-02 17:27:15 +08:00
end
end
2014-07-30 15:26:55 +08:00
2014-12-29 16:57:31 +08:00
def paginateHelper_for_members obj , pre_size = 10
@obj_count = StudentsForCourse . find_by_sql ( " select count(id) as mem_count from students_for_courses where course_id = #{ @course . id } " ) [ 0 ] [ :mem_count ] . to_s . to_i
@obj_pages = Paginator . new @obj_count , pre_size , params [ 'page' ]
if obj . kind_of? ActiveRecord :: Base or obj . kind_of? ActiveRecord :: Relation
obj . limit ( @obj_pages . per_page ) . offset ( 0 )
elsif obj . kind_of? Array
obj [ 0 , @obj_pages . per_page ]
else
logger . error " [ApplicationController] Error : application_controller # paginateHelper ===> unknow category: #{ obj . class } "
raise RuntimeError , 'unknow type, Please input you type into this helper.'
end
end
2014-12-26 14:50:14 +08:00
2014-07-30 15:26:55 +08:00
#查找首页相关信息
def find_first_page
2014-10-16 11:09:45 +08:00
@first_page = FirstPage . find_by_page_type ( 'project' )
2014-08-15 14:30:01 +08:00
if @first_page . nil?
@first_page = FirstPage . new
@first_page . page_type = 'project'
@first_page . description = " "
@first_page . save ( )
end
2014-07-30 15:26:55 +08:00
@show_course = @first_page . show_course
@show_contest = @first_page . show_contest
end
2014-10-13 17:38:59 +08:00
def find_web_footer
2014-10-17 15:02:09 +08:00
@organizer = WebFooterOranizer . first
2014-10-15 09:23:12 +08:00
@companies = WebFooterCompany . all
2014-10-13 17:38:59 +08:00
end
2015-01-13 18:24:14 +08:00
def password_authentication
user , last_login_on = User . try_to_login ( params [ :user_name ] , params [ :password ] )
successful_authentication ( user , last_login_on )
end
2015-01-15 18:48:19 +08:00
2015-01-13 18:24:14 +08:00
def successful_authentication ( user , last_login_on )
logger . info " Successful authentication for ' #{ user . login } ' from #{ request . remote_ip } at #{ Time . now . utc } "
# Valid user
self . logged_user = user
# generate a key and set cookie if autologin
if params [ :autologin ] && Setting . autologin?
set_autologin_cookie ( user )
end
call_hook ( :controller_account_success_authentication_after , { :user = > user } )
end
2015-04-23 17:42:03 +08:00
2013-10-30 20:56:24 +08:00
end