Redmine 4.1.1
This commit is contained in:
parent
33e7b881a5
commit
3d976f1b3b
1593 changed files with 36180 additions and 19489 deletions
|
@ -1,5 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# Redmine - project management software
|
||||
# Copyright (C) 2006-2017 Jean-Philippe Lang
|
||||
# Copyright (C) 2006-2019 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
|
||||
|
@ -18,14 +20,17 @@
|
|||
require 'uri'
|
||||
require 'cgi'
|
||||
|
||||
class Unauthorized < Exception; end
|
||||
class Unauthorized < StandardError; end
|
||||
|
||||
class ApplicationController < ActionController::Base
|
||||
include Redmine::I18n
|
||||
include Redmine::Pagination
|
||||
include Redmine::Hook::Helper
|
||||
include RoutesHelper
|
||||
include AvatarsHelper
|
||||
|
||||
helper :routes
|
||||
helper :avatars
|
||||
|
||||
class_attribute :accept_api_auth_actions
|
||||
class_attribute :accept_rss_auth_actions
|
||||
|
@ -52,6 +57,7 @@ class ApplicationController < ActionController::Base
|
|||
end
|
||||
|
||||
before_action :session_expiration, :user_setup, :check_if_login_required, :set_localization, :check_password_change
|
||||
after_action :record_project_usage
|
||||
|
||||
rescue_from ::Unauthorized, :with => :deny_access
|
||||
rescue_from ::ActionView::MissingTemplate, :with => :missing_template
|
||||
|
@ -112,7 +118,7 @@ class ApplicationController < ActionController::Base
|
|||
if (key = api_key_from_request)
|
||||
# Use API key
|
||||
user = User.find_by_api_key(key)
|
||||
elsif request.authorization.to_s =~ /\ABasic /i
|
||||
elsif /\ABasic /i.match?(request.authorization.to_s)
|
||||
# HTTP Basic, either username/password or API key/random
|
||||
authenticate_with_http_basic do |username, password|
|
||||
user = User.try_to_login(username, password) || User.find_by_api_key(username)
|
||||
|
@ -229,9 +235,14 @@ class ApplicationController < ActionController::Base
|
|||
format.any(:atom, :pdf, :csv) {
|
||||
redirect_to signin_path(:back_url => url)
|
||||
}
|
||||
format.xml { head :unauthorized, 'WWW-Authenticate' => 'Basic realm="Redmine API"' }
|
||||
format.api {
|
||||
if Setting.rest_api_enabled? && accept_api_auth?
|
||||
head(:unauthorized, 'WWW-Authenticate' => 'Basic realm="Redmine API"')
|
||||
else
|
||||
head(:forbidden)
|
||||
end
|
||||
}
|
||||
format.js { head :unauthorized, 'WWW-Authenticate' => 'Basic realm="Redmine API"' }
|
||||
format.json { head :unauthorized, 'WWW-Authenticate' => 'Basic realm="Redmine API"' }
|
||||
format.any { head :unauthorized }
|
||||
end
|
||||
return false
|
||||
|
@ -259,7 +270,11 @@ class ApplicationController < ActionController::Base
|
|||
true
|
||||
else
|
||||
if @project && @project.archived?
|
||||
@archived_project = @project
|
||||
render_403 :message => :notice_not_authorized_archived_project
|
||||
elsif @project && !@project.allows_to?(:controller => ctrl, :action => action)
|
||||
# Project module is disabled
|
||||
render_403
|
||||
else
|
||||
deny_access
|
||||
end
|
||||
|
@ -272,27 +287,31 @@ class ApplicationController < ActionController::Base
|
|||
end
|
||||
|
||||
# Find project of id params[:id]
|
||||
def find_project
|
||||
@project = Project.find(params[:id])
|
||||
def find_project(project_id=params[:id])
|
||||
@project = Project.find(project_id)
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render_404
|
||||
end
|
||||
|
||||
# Find project of id params[:project_id]
|
||||
def find_project_by_project_id
|
||||
@project = Project.find(params[:project_id])
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render_404
|
||||
find_project(params[:project_id])
|
||||
end
|
||||
|
||||
# Find project of id params[:id] if present
|
||||
def find_optional_project_by_id
|
||||
if params[:id].present?
|
||||
find_project(params[:id])
|
||||
end
|
||||
end
|
||||
|
||||
# Find a project based on params[:project_id]
|
||||
# TODO: some subclasses override this, see about merging their logic
|
||||
# and authorize the user for the requested action
|
||||
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
|
||||
if params[:project_id].present?
|
||||
find_project(params[:project_id])
|
||||
end
|
||||
authorize_global
|
||||
end
|
||||
|
||||
# Finds and sets @project based on @object.project
|
||||
|
@ -385,18 +404,30 @@ class ApplicationController < ActionController::Base
|
|||
end
|
||||
end
|
||||
|
||||
def record_project_usage
|
||||
if @project && @project.id && User.current.logged? && User.current.allowed_to?(:view_project, @project)
|
||||
Redmine::ProjectJumpBox.new(User.current).project_used(@project)
|
||||
end
|
||||
true
|
||||
end
|
||||
|
||||
def back_url
|
||||
url = params[:back_url]
|
||||
if url.nil? && referer = request.env['HTTP_REFERER']
|
||||
url = CGI.unescape(referer.to_s)
|
||||
# URLs that contains the utf8=[checkmark] parameter added by Rails are
|
||||
# parsed as invalid by URI.parse so the redirect to the back URL would
|
||||
# not be accepted (ApplicationController#validate_back_url would return
|
||||
# false)
|
||||
url.gsub!(/(\?|&)utf8=\u2713&?/, '\1')
|
||||
end
|
||||
url
|
||||
end
|
||||
helper_method :back_url
|
||||
|
||||
def redirect_back_or_default(default, options={})
|
||||
back_url = params[:back_url].to_s
|
||||
if back_url.present? && valid_url = validate_back_url(back_url)
|
||||
redirect_to(valid_url)
|
||||
if back_url = validate_back_url(params[:back_url].to_s)
|
||||
redirect_to(back_url)
|
||||
return
|
||||
elsif options[:referer]
|
||||
redirect_to_referer_or default
|
||||
|
@ -409,6 +440,8 @@ class ApplicationController < ActionController::Base
|
|||
# Returns a validated URL string if back_url is a valid url for redirection,
|
||||
# otherwise false
|
||||
def validate_back_url(back_url)
|
||||
return false if back_url.blank?
|
||||
|
||||
if CGI.unescape(back_url).include?('..')
|
||||
return false
|
||||
end
|
||||
|
@ -431,11 +464,11 @@ class ApplicationController < ActionController::Base
|
|||
path = uri.to_s
|
||||
# Ensure that the remaining URL starts with a slash, followed by a
|
||||
# non-slash character or the end
|
||||
if path !~ %r{\A/([^/]|\z)}
|
||||
if !%r{\A/([^/]|\z)}.match?(path)
|
||||
return false
|
||||
end
|
||||
|
||||
if path.match(%r{/(login|account/register|account/lost_password)})
|
||||
if %r{/(login|account/register|account/lost_password)}.match?(path)
|
||||
return false
|
||||
end
|
||||
|
||||
|
@ -446,11 +479,13 @@ class ApplicationController < ActionController::Base
|
|||
return path
|
||||
end
|
||||
private :validate_back_url
|
||||
helper_method :validate_back_url
|
||||
|
||||
def valid_back_url?(back_url)
|
||||
!!validate_back_url(back_url)
|
||||
end
|
||||
private :valid_back_url?
|
||||
helper_method :valid_back_url?
|
||||
|
||||
# Redirects to the request referer if present, redirects to args or call block otherwise.
|
||||
def redirect_to_referer_or(*args, &block)
|
||||
|
@ -460,7 +495,7 @@ class ApplicationController < ActionController::Base
|
|||
if args.any?
|
||||
redirect_to *args
|
||||
elsif block_given?
|
||||
block.call
|
||||
yield
|
||||
else
|
||||
raise "#redirect_to_referer_or takes arguments or a block"
|
||||
end
|
||||
|
@ -495,8 +530,8 @@ class ApplicationController < ActionController::Base
|
|||
end
|
||||
|
||||
# Handler for ActionView::MissingTemplate exception
|
||||
def missing_template
|
||||
logger.warn "Missing template, responding with 404"
|
||||
def missing_template(exception)
|
||||
logger.warn "Missing template, responding with 404: #{exception}"
|
||||
@project = nil
|
||||
render_404
|
||||
end
|
||||
|
@ -616,7 +651,7 @@ class ApplicationController < ActionController::Base
|
|||
|
||||
# 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
|
||||
%r{(MSIE|Trident|Edge)}.match?(request.env['HTTP_USER_AGENT']) ? ERB::Util.url_encode(name) : name
|
||||
end
|
||||
|
||||
def api_request?
|
||||
|
@ -649,9 +684,9 @@ class ApplicationController < ActionController::Base
|
|||
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 successful updates or deletions via the API
|
||||
# Renders a 204 response for successful updates or deletions via the API
|
||||
def render_api_ok
|
||||
render_api_head :ok
|
||||
render_api_head :no_content
|
||||
end
|
||||
|
||||
# Renders a head API response
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue