# encoding: utf-8
# 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
#before_filter :update_system
# skip_before_filter :verify_authenticity_token,
# :if => Proc.new { |c| c.request.format == 'application/json' }
layout 'base'
# 这行代码的作用:所有表单和 Ajax 请求中都会包含安全权标
# 非 GET 请求中没有 CSRF 权标就会调用这个方法
protect_from_forgery
def handle_unverified_request
super
if session [ :user_id ] . blank?
redirect_to signin_url ( :back_url = > request . original_url )
else
raise ( ActionController :: InvalidAuthenticityToken )
end
# cookies.delete(autologin_cookie_name)
end
before_filter :session_expiration , :user_setup , :check_if_login_required , :set_localization
before_filter :user_agent
# 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
helper_method :admin_or_business?
# 云启训练场( EduCoder) 个人版 产品编码( appId) 9200108
# 产品名称 计费类型 套餐编码
# 云启训练场( EduCoder) 个人版 固定包月 9200108001
# 固定包月 9200108002
# 固定包月 9200108003
# ---------------------------------------------------
# 产品名称 计费类型 套餐编码
# 云启训练场( EduCoder) ) 院校版 包月+按license 9200109001
# 包月+按license 9200109002
# 云启训练场( EduCoder) ) 院校版 产品编码( appId) 9200109
# 如果不是Ecloud过来的用户, 则不改变用户的使用状态及权限, 按现有模式即可
def ecloud_auth
euser = EcloudUser . where ( " userid =? and opttype not in(3, 5) " , User . current . id ) . first
if euser . present? # 开通过业务
# 获取用户的套餐信息
e_services = euser . ecloud_services . where ( " opttype != 1 " ) . order ( " ecloud_services.code desc " )
# 如果用户开通过服务
if e_services . present?
if e_services . count > 1 # 说明有重复开通过业务
# 开通多业务的话, 以最大的套餐排序, 如果最大套餐还可以用, 则直接返回true, 如果最大套餐不能用, 则轮询返回, 直到找到可用的套餐
e_services . each do | e_service |
# 使用期限内套餐才有效
ecloud_services_auth ( e_service . code , e_service . begintime , e_service . endtime )
end
else
# 先看套餐,再看时间区间
e_service = e_services . first
ecloud_services_auth ( e_service . code , e_service . begintime , e_service . endtime )
end
else
false # 没开通过服务,或者服务被禁用则不允许访问
end
end
end
# 根据业务确定权限
def ecloud_services_auth code , begintime , endtime
# 如果当前实训不在实训课堂等级体系中,则不允许访问
subject_id = @shixun . stage_shixuns . map ( & :subject_id )
if subject_id . blank?
render_403
end
subject_level = Subject . find ( subject_id ) . subject_level_system . try ( :level )
# 当前时间转毫秒
current_time = DateTime . now . strftime ( '%Q' ) . to_i
if current_time - begintime > 0 && endtime - current_time > 0
case code
when " 9200108001 "
subject_level . to_i == 1 ? true : false
when " 9200108002 "
subject_level . to_i == 2 ? true : false
when " 9200108003 "
subject_level . to_i == 3 ? true : false
when " 9200109001 " # 企业用户
subject_level . to_i < 3 ? true : false
when " 9200109002 " # 企业用户
subject_level . to_i < = 3 ? true : false
end
else
false
end
end
def ec_public_auth major_school
unless User . current . admin? || major_school . template_major || major_school . school . users . where ( :id = > User . current . id ) . count > 0 ||
major_school . ec_major_school_users . where ( :user_id = > User . current . id ) . count > 0 ||
EcCourseUser . where ( :user_id = > User . current . id , :ec_course_id = > EcCourse . where ( :ec_year_id = > major_school . ec_years . pluck ( :id ) ) . pluck ( :id ) ) . count > 0
render_403
else
true
end
end
def user_agent
logger . info " HTTP_USER_AGENT #{ request . env [ " HTTP_USER_AGENT " ] } "
end
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
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
#logger.info(" Current user: " + (User.current.logged? ? "#{User.current.login} (id=#{User.current.id})" : "anonymous")) if logger
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 set_autologin_cookie ( user )
token = Token . get_or_create_permanent_login_token ( user )
cookie_options = {
:value = > token . value ,
:expires = > 1 . month . from_now ,
:path = > ( Redmine :: Configuration [ 'autologin_cookie_path' ] || '/' ) ,
:secure = > ( Redmine :: Configuration [ 'autologin_cookie_secure' ] ? true : false ) ,
:httponly = > true
}
if Redmine :: Configuration [ 'cookie_domain' ] . present?
cookie_options = cookie_options . merge ( domain : Redmine :: Configuration [ 'cookie_domain' ] )
end
cookies [ autologin_cookie_name ] = cookie_options
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 ] )
elsif session [ :wechat_openid ]
uw = UserWechat . find_by_openid ( session [ :wechat_openid ] )
user = uw . user if uw
elsif params [ :authToken ]
user = Token . find_by_value ( params [ :authToken ] ) . user
#set_autologin_cookie(user)
#start_user_session(user)
session [ :user_id ] = user . id
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 |
user = User . try_to_login ( username , password ) [ 0 ] || User . find_by_api_key ( username )
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
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
Rails . logger . info ( " # # auth_login1 end " )
end
# 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
def logged_user_by_apptoken
#从手机端传来apptoken则将当前登陆用户变为对应的用户
if params [ :apptoken ]
token = ApiKey . where ( access_token : params [ :apptoken ] ) . first
if token . expired?
return
end
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
# Logs out current user
def logout_user
if User . current . logged?
if Redmine :: Configuration [ 'cookie_domain' ] . present?
logger . info ( " # # # # # # # # # # # # # # # # # # # # # # # # # #{ Redmine :: Configuration [ 'cookie_domain' ] } " )
cookies . delete ( autologin_cookie_name , domain : Redmine :: Configuration [ 'cookie_domain' ] )
else
cookies . delete autologin_cookie_name
end
# Token.delete_all(["user_id = ? AND action = ?", User.current.id, 'autologin'])
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
if User . current . logged?
if User . current . last_login_on && User . current . last_login_on . strftime ( '%Y-%m-%d' ) < Time . now . strftime ( '%Y-%m-%d' )
User . current . update_column ( :last_login_on , Time . now )
end
return true
end
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
logger . info ( " # # # # # # # # # login?: #{ User . current . logged? } " )
logger . info ( " # # # # # # # # # get?: #{ request . get? } " )
if ! User . current . logged?
# Extract only the basic url parameters on non-GET requests
if request . get?
url = request . original_url
else
url = url_for ( :controller = > params [ :controller ] , :action = > params [ :action ] , :id = > params [ :id ] , :project_id = > params [ :project_id ] )
end
respond_to do | format |
format . html { redirect_to signin_url ( :back_url = > url ) }
format . atom { redirect_to signin_url }
format . xml { head :unauthorized , 'WWW-Authenticate' = > 'Basic realm="Redmine API"' }
format . js { redirect_to signin_url ( :back_url = > url ) }
format . json { redirect_to signin_url ( :back_url = > url ) }
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 require_business
unless ( User . current . business? || User . current . admin? )
render_403
end
end
def admin_or_business?
User . current . business? || User . current . admin?
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 )
#modify by NWB
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
def authorize1 ( ctrl = params [ :controller ] , action = params [ :action ] , token = params [ :token ] , global = false )
if ( ! User . current . logged? && ! token . nil? )
User . current = try_to_autologin1
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
def auth_login1 ( token = params [ :token ] )
Rails . logger . info ( " # # auth_login1 start " )
if ( ! User . current . logged? && ! token . nil? )
User . current = try_to_autologin1
end
end
def authorize_allowed ( ctrl = params [ :controller ] , action = params [ :action ] , global = false )
#modify by NWB
if @project
if ctrl == " repositories " && action == " show " && @project . hidden_repo
allowed = User . current . admin? || ( User . current . member_of? ( @project ) && ! ( role_of_members_in_project ( @project . id , User . current . id ) == " Reporter " ) )
else
allowed = User . current . allowed_to? ( { :controller = > ctrl , :action = > action } , @project || @projects , :global = > global )
end
elsif @course
allowed = User . current . allowed_to? ( { :controller = > ctrl , :action = > action } , @course || @courses , :global = > global )
else
# allowed = User.current.allowed_to?({:controller => ctrl, :action => action}, @project || @projects, :global => global)
allowed = true
end
allowed
end
def authorize_attachment_download ( ctrl = params [ :controller ] , action = params [ :action ] , global = false )
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
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
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 )
elsif @contest
allowed = User . current . member_of_contest? ( @contest )
end
when " contest "
return true
when " Course "
if @attachment . get_status_by_attach ( User . current . id ) == 2
return true
else
allowed = User . current . allowed_to? ( :course_attachments_download , @course , :global = > false )
end
else
return true
end
if allowed || ( params [ :type ] && params [ :type ] == " wechat " )
true
else
if @project && @project . archived?
render_403 :message = > :notice_not_authorized_archived_project
else
deny_access
end
end
end
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
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
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
# 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
@project = Project . find ( params [ :id ] )
rescue ActiveRecord :: RecordNotFound
render_404
end
# Find project of id params[:project_id]
def find_project_by_project_id
if params [ :project_id ]
@project = Project . find ( params [ :project_id ] )
elsif params [ :shixun_id ]
@shixun = Shixun . find_by_identifier ( params [ :shixun_id ] )
elsif params [ :course_id ]
@course = Course . find ( params [ :course_id ] )
elsif params [ :org_subfield_id ]
@org_subfield = OrgSubfield . find ( params [ :org_subfield_id ] )
elsif params [ :contest_id ]
@contest = Contest . find ( params [ :contest_id ] )
end
rescue ActiveRecord :: RecordNotFound
render_404
end
def find_contest_by_contest_id
@contest = Contest . find ( params [ :contest_id ] )
rescue ActiveRecord :: RecordNotFound
render_404
end
#<23> <> <EFBFBD> course_id<69> <64> project
def find_project_by_course_id
@bid = Bid . find params [ :course_id ]
@project = @bid . courses [ 0 ]
rescue ActiveRecord :: RecordNotFound
render_404
end
# 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
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
# Finds and sets @project based on @object.project
def find_project_from_association
render_404 unless @object . present?
@project = @object . project
if @project == nil && @object . has_attribute? ( 'course_id' )
@course = @object . course
if @course . nil? && @object . has_attribute? ( 'contest_id' )
@contest = @object . contest
end
end
end
def find_contest_from_association
render_404 unless @object . present?
@contest = @object . contest
end
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
#added by nwb
#<23> <> ȡ<EFBFBD> γ <EFBFBD>
def find_course
@course = Course . find ( params [ :id ] )
rescue ActiveRecord :: RecordNotFound
render_404
end
# 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
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
def redirect_back_or_default ( default , options = { } )
back_url = params [ :back_url ] . to_s
if back_url . present?
begin
uri = URI . parse ( back_url )
logger . warn ( " -----back URL #{ uri } " )
# 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) } )
# back_url = back_url.gsub(%r{\/users\/(\w+)},"/users/"+default.to_s) if default.is_a?(:User)
redirect_to ( back_url )
return
end
rescue URI :: InvalidURIError
logger . warn ( " Could not redirect to invalid URL #{ back_url } " )
#redirect to default
end
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 = { } )
if User . current . id == 2
redirect_to signin_url
return
end
@project = nil
render_error ( { :message = > :notice_not_authorized , :status = > 403 } . merge ( options ) , 'common/403' )
#render :template => 'common/403'
return false
end
def render_404 ( options = { } )
if User . current . id == 2
redirect_to signin_url
return
end
render_error ( { :message = > :notice_file_not_found , :status = > 404 } . merge ( options ) , 'common/404' )
#render :template => 'common/404'
return false
end
# Renders an error response
def render_error ( arg , template = 'common/error' )
arg = { :message = > arg } unless arg . is_a? ( Hash )
@message = arg [ :message ]
@lay = arg [ :layout ]
@message = l ( @message ) if @message . is_a? ( Symbol )
@status = arg [ :status ] || 500
respond_to do | format |
format . html {
if @lay
render :template = > template , :layout = > @lay , :status = > @status
else
render :template = > template , :layout = > use_layout , :status = > @status
end
}
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
request . xhr? ? false : 'users_base'
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
Rails . logger . info ( " # # invalid_authenticity_token " )
#render_error "Invalid form authenticity token."
redirect_to signin_path ( :login = > true )
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 issue_ratio_change done_ratio , status_id
if done_ratio == 100 || status_id == 3
" 已完成 "
else
done_ratio . to_s + " % "
end
end
def issue_priority_change priority_id
case priority_id
when 1
" 低 "
when 2
" 正常 "
when 3
" 高 "
when 4
" 紧急 "
when 5
" 立即 "
end
end
def issue_status_change status_id
case status_id
when 1
" 新增 "
when 2
" 正在解决 "
when 3
" 已解决 "
when 4
" 反馈 "
when 5
" 关闭 "
when 6
" 拒绝 "
end
end
def issue_tracker_change tracker_id
case tracker_id
when 1
" 缺陷 "
when 2
" 功能 "
when 3
" 支持 "
when 4
" 任务 "
when 5
" 周报 "
end
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 )
request . env [ 'HTTP_USER_AGENT' ] =~ %r{ MSIE|Trident|Edge } ? ERB :: Util . url_encode ( name ) : name
end
def api_request?
return false if params [ :controller ] == 'at'
%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
## 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
@obj_count = obj . count
@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 ( @obj_pages . offset )
elsif obj . kind_of? Array
obj [ @obj_pages . offset , @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
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
# gitlab分页定制
def paginateHelperForGitlab obj , pre_size = 15
@obj_count = obj . count
@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 ( @obj_pages . offset )
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
#查找首页相关信息
def find_first_page
@first_page = FirstPage . find_by_page_type ( 'project' )
if @first_page . nil?
@first_page = FirstPage . new
@first_page . page_type = 'project'
@first_page . description = " "
@first_page . save ( )
end
@show_course = @first_page . show_course
@show_contest = @first_page . show_contest
end
# def find_web_footer
# @organizer = WebFooterOranizer.first
# @companies = WebFooterCompany.all
# end
def password_authentication
user , last_login_on = User . try_to_login ( params [ :user_name ] , params [ :password ] )
successful_authentication ( user , last_login_on )
end
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
def user_unlogged_check
if ! User . current . logged?
redirect_to signin_url
return false
end
true
end
def update_system
redirect_to " https://www.educoder.net/update.html " if Time . now > Time . new ( 2019 , 4 , 23 ) &&
Time . now < Time . new ( 2019 , 4 , 23 , 2 )
end
# 获取Oauth Client
def get_client ( site )
client_id = Redmine :: Configuration [ 'client_id' ]
client_secret = Redmine :: Configuration [ 'client_secret' ]
OAuth2 :: Client . new ( client_id , client_secret , site : site )
end
def handle_openi_request
site = Redmine :: Configuration [ 'openi_domain' ]
root_url = Redmine :: Configuration [ 'educoder_domain' ]
get_code_url = " /oauth/get_code "
original_url = request . original_url
client = get_client ( site )
redirect_uri = " #{ root_url } #{ get_code_url } "
authorize_url = client . auth_code . authorize_url ( redirect_uri : redirect_uri )
authorize_url = authorize_url + " &gen_code=true&state=1&original_url= #{ original_url } "
redirect_to authorize_url
end
def user_login_and_from_openi?
url = request . referer . nil? ? Redmine :: Configuration [ 'educoder_domain' ] : request . referer
flag = URI ( url ) . host == URI ( Redmine :: Configuration [ 'openi_domain' ] ) . host && ! current_user . logged?
logger . info " ----------------------- request referer: #{ request . referer } ------------------------- "
logger . info " ----------------------- url after processed: #{ url } ------------------------- "
logger . info " ----------------------- host: #{ URI ( url ) . host } -------------------------- "
logger . info " ----------------------- handle_flag: #{ flag } ------------------------- "
flag
end
end