##// END OF EJS Templates
Fixed: login filter providing incorrect back_url for Redmine installed in sub-directory (#1900)....
Jean-Philippe Lang -
r1888:7afdb01f0065
parent child
Show More
@@ -1,225 +1,225
1 1 # redMine - project management software
2 2 # Copyright (C) 2006-2007 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 require 'uri'
19 19
20 20 class ApplicationController < ActionController::Base
21 21 layout 'base'
22 22
23 23 before_filter :user_setup, :check_if_login_required, :set_localization
24 24 filter_parameter_logging :password
25 25
26 26 include Redmine::MenuManager::MenuController
27 27 helper Redmine::MenuManager::MenuHelper
28 28
29 29 REDMINE_SUPPORTED_SCM.each do |scm|
30 30 require_dependency "repository/#{scm.underscore}"
31 31 end
32 32
33 33 def current_role
34 34 @current_role ||= User.current.role_for_project(@project)
35 35 end
36 36
37 37 def user_setup
38 38 # Check the settings cache for each request
39 39 Setting.check_cache
40 40 # Find the current user
41 41 User.current = find_current_user
42 42 end
43 43
44 44 # Returns the current user or nil if no user is logged in
45 45 def find_current_user
46 46 if session[:user_id]
47 47 # existing session
48 48 (User.find_active(session[:user_id]) rescue nil)
49 49 elsif cookies[:autologin] && Setting.autologin?
50 50 # auto-login feature
51 51 User.find_by_autologin_key(cookies[:autologin])
52 52 elsif params[:key] && accept_key_auth_actions.include?(params[:action])
53 53 # RSS key authentication
54 54 User.find_by_rss_key(params[:key])
55 55 end
56 56 end
57 57
58 58 # check if login is globally required to access the application
59 59 def check_if_login_required
60 60 # no check needed if user is already logged in
61 61 return true if User.current.logged?
62 62 require_login if Setting.login_required?
63 63 end
64 64
65 65 def set_localization
66 66 User.current.language = nil unless User.current.logged?
67 67 lang = begin
68 68 if !User.current.language.blank? && GLoc.valid_language?(User.current.language)
69 69 User.current.language
70 70 elsif request.env['HTTP_ACCEPT_LANGUAGE']
71 71 accept_lang = parse_qvalues(request.env['HTTP_ACCEPT_LANGUAGE']).first.downcase
72 72 if !accept_lang.blank? && (GLoc.valid_language?(accept_lang) || GLoc.valid_language?(accept_lang = accept_lang.split('-').first))
73 73 User.current.language = accept_lang
74 74 end
75 75 end
76 76 rescue
77 77 nil
78 78 end || Setting.default_language
79 79 set_language_if_valid(lang)
80 80 end
81 81
82 82 def require_login
83 83 if !User.current.logged?
84 redirect_to :controller => "account", :action => "login", :back_url => request.request_uri
84 redirect_to :controller => "account", :action => "login", :back_url => (request.relative_url_root + request.request_uri)
85 85 return false
86 86 end
87 87 true
88 88 end
89 89
90 90 def require_admin
91 91 return unless require_login
92 92 if !User.current.admin?
93 93 render_403
94 94 return false
95 95 end
96 96 true
97 97 end
98 98
99 99 def deny_access
100 100 User.current.logged? ? render_403 : require_login
101 101 end
102 102
103 103 # Authorize the user for the requested action
104 104 def authorize(ctrl = params[:controller], action = params[:action])
105 105 allowed = User.current.allowed_to?({:controller => ctrl, :action => action}, @project)
106 106 allowed ? true : deny_access
107 107 end
108 108
109 109 # make sure that the user is a member of the project (or admin) if project is private
110 110 # used as a before_filter for actions that do not require any particular permission on the project
111 111 def check_project_privacy
112 112 if @project && @project.active?
113 113 if @project.is_public? || User.current.member_of?(@project) || User.current.admin?
114 114 true
115 115 else
116 116 User.current.logged? ? render_403 : require_login
117 117 end
118 118 else
119 119 @project = nil
120 120 render_404
121 121 false
122 122 end
123 123 end
124 124
125 125 def redirect_back_or_default(default)
126 126 back_url = params[:back_url]
127 127 if !back_url.blank?
128 128 uri = URI.parse(back_url)
129 129 # do not redirect user to another host
130 130 if uri.relative? || (uri.host == request.host)
131 131 redirect_to(back_url) and return
132 132 end
133 133 end
134 134 redirect_to default
135 135 end
136 136
137 137 def render_403
138 138 @project = nil
139 139 render :template => "common/403", :layout => !request.xhr?, :status => 403
140 140 return false
141 141 end
142 142
143 143 def render_404
144 144 render :template => "common/404", :layout => !request.xhr?, :status => 404
145 145 return false
146 146 end
147 147
148 148 def render_error(msg)
149 149 flash.now[:error] = msg
150 150 render :nothing => true, :layout => !request.xhr?, :status => 500
151 151 end
152 152
153 153 def render_feed(items, options={})
154 154 @items = items || []
155 155 @items.sort! {|x,y| y.event_datetime <=> x.event_datetime }
156 156 @items = @items.slice(0, Setting.feeds_limit.to_i)
157 157 @title = options[:title] || Setting.app_title
158 158 render :template => "common/feed.atom.rxml", :layout => false, :content_type => 'application/atom+xml'
159 159 end
160 160
161 161 def self.accept_key_auth(*actions)
162 162 actions = actions.flatten.map(&:to_s)
163 163 write_inheritable_attribute('accept_key_auth_actions', actions)
164 164 end
165 165
166 166 def accept_key_auth_actions
167 167 self.class.read_inheritable_attribute('accept_key_auth_actions') || []
168 168 end
169 169
170 170 # TODO: move to model
171 171 def attach_files(obj, attachments)
172 172 attached = []
173 173 if attachments && attachments.is_a?(Hash)
174 174 attachments.each_value do |attachment|
175 175 file = attachment['file']
176 176 next unless file && file.size > 0
177 177 a = Attachment.create(:container => obj,
178 178 :file => file,
179 179 :description => attachment['description'].to_s.strip,
180 180 :author => User.current)
181 181 attached << a unless a.new_record?
182 182 end
183 183 end
184 184 attached
185 185 end
186 186
187 187 # Returns the number of objects that should be displayed
188 188 # on the paginated list
189 189 def per_page_option
190 190 per_page = nil
191 191 if params[:per_page] && Setting.per_page_options_array.include?(params[:per_page].to_s.to_i)
192 192 per_page = params[:per_page].to_s.to_i
193 193 session[:per_page] = per_page
194 194 elsif session[:per_page]
195 195 per_page = session[:per_page]
196 196 else
197 197 per_page = Setting.per_page_options_array.first || 25
198 198 end
199 199 per_page
200 200 end
201 201
202 202 # qvalues http header parser
203 203 # code taken from webrick
204 204 def parse_qvalues(value)
205 205 tmp = []
206 206 if value
207 207 parts = value.split(/,\s*/)
208 208 parts.each {|part|
209 209 if m = %r{^([^\s,]+?)(?:;\s*q=(\d+(?:\.\d+)?))?$}.match(part)
210 210 val = m[1]
211 211 q = (m[2] or 1).to_f
212 212 tmp.push([val, q])
213 213 end
214 214 }
215 215 tmp = tmp.sort_by{|val, q| -q}
216 216 tmp.collect!{|val, q| val}
217 217 end
218 218 return tmp
219 219 end
220 220
221 221 # Returns a string that can be used as filename value in Content-Disposition header
222 222 def filename_for_content_disposition(name)
223 223 request.env['HTTP_USER_AGENT'] =~ %r{MSIE} ? ERB::Util.url_encode(name) : name
224 224 end
225 225 end
General Comments 0
You need to be logged in to leave comments. Login now