##// END OF EJS Templates
Fixed: When logging in via an autologin cookie the user's last_login_on should be updated (#2820)....
Jean-Philippe Lang -
r2460:21eb3c089d08
parent child
Show More
@@ -1,286 +1,277
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2008 Jean-Philippe Lang
2 # Copyright (C) 2006-2008 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 class AccountController < ApplicationController
18 class AccountController < ApplicationController
19 helper :custom_fields
19 helper :custom_fields
20 include CustomFieldsHelper
20 include CustomFieldsHelper
21
21
22 # prevents login action to be filtered by check_if_login_required application scope filter
22 # prevents login action to be filtered by check_if_login_required application scope filter
23 skip_before_filter :check_if_login_required, :only => [:login, :lost_password, :register, :activate]
23 skip_before_filter :check_if_login_required, :only => [:login, :lost_password, :register, :activate]
24
24
25 # Show user's account
25 # Show user's account
26 def show
26 def show
27 @user = User.active.find(params[:id])
27 @user = User.active.find(params[:id])
28 @custom_values = @user.custom_values
28 @custom_values = @user.custom_values
29
29
30 # show only public projects and private projects that the logged in user is also a member of
30 # show only public projects and private projects that the logged in user is also a member of
31 @memberships = @user.memberships.select do |membership|
31 @memberships = @user.memberships.select do |membership|
32 membership.project.is_public? || (User.current.member_of?(membership.project))
32 membership.project.is_public? || (User.current.member_of?(membership.project))
33 end
33 end
34
34
35 events = Redmine::Activity::Fetcher.new(User.current, :author => @user).events(nil, nil, :limit => 10)
35 events = Redmine::Activity::Fetcher.new(User.current, :author => @user).events(nil, nil, :limit => 10)
36 @events_by_day = events.group_by(&:event_date)
36 @events_by_day = events.group_by(&:event_date)
37
37
38 rescue ActiveRecord::RecordNotFound
38 rescue ActiveRecord::RecordNotFound
39 render_404
39 render_404
40 end
40 end
41
41
42 # Login request and validation
42 # Login request and validation
43 def login
43 def login
44 if request.get?
44 if request.get?
45 # Logout user
45 # Logout user
46 self.logged_user = nil
46 self.logged_user = nil
47 else
47 else
48 # Authenticate user
48 # Authenticate user
49 if Setting.openid? && using_open_id?
49 if Setting.openid? && using_open_id?
50 open_id_authenticate(params[:openid_url])
50 open_id_authenticate(params[:openid_url])
51 else
51 else
52 password_authentication
52 password_authentication
53 end
53 end
54 end
54 end
55 end
55 end
56
56
57 # Log out current user and redirect to welcome page
57 # Log out current user and redirect to welcome page
58 def logout
58 def logout
59 cookies.delete :autologin
59 cookies.delete :autologin
60 Token.delete_all(["user_id = ? AND action = ?", User.current.id, 'autologin']) if User.current.logged?
60 Token.delete_all(["user_id = ? AND action = ?", User.current.id, 'autologin']) if User.current.logged?
61 self.logged_user = nil
61 self.logged_user = nil
62 redirect_to home_url
62 redirect_to home_url
63 end
63 end
64
64
65 # Enable user to choose a new password
65 # Enable user to choose a new password
66 def lost_password
66 def lost_password
67 redirect_to(home_url) && return unless Setting.lost_password?
67 redirect_to(home_url) && return unless Setting.lost_password?
68 if params[:token]
68 if params[:token]
69 @token = Token.find_by_action_and_value("recovery", params[:token])
69 @token = Token.find_by_action_and_value("recovery", params[:token])
70 redirect_to(home_url) && return unless @token and !@token.expired?
70 redirect_to(home_url) && return unless @token and !@token.expired?
71 @user = @token.user
71 @user = @token.user
72 if request.post?
72 if request.post?
73 @user.password, @user.password_confirmation = params[:new_password], params[:new_password_confirmation]
73 @user.password, @user.password_confirmation = params[:new_password], params[:new_password_confirmation]
74 if @user.save
74 if @user.save
75 @token.destroy
75 @token.destroy
76 flash[:notice] = l(:notice_account_password_updated)
76 flash[:notice] = l(:notice_account_password_updated)
77 redirect_to :action => 'login'
77 redirect_to :action => 'login'
78 return
78 return
79 end
79 end
80 end
80 end
81 render :template => "account/password_recovery"
81 render :template => "account/password_recovery"
82 return
82 return
83 else
83 else
84 if request.post?
84 if request.post?
85 user = User.find_by_mail(params[:mail])
85 user = User.find_by_mail(params[:mail])
86 # user not found in db
86 # user not found in db
87 flash.now[:error] = l(:notice_account_unknown_email) and return unless user
87 flash.now[:error] = l(:notice_account_unknown_email) and return unless user
88 # user uses an external authentification
88 # user uses an external authentification
89 flash.now[:error] = l(:notice_can_t_change_password) and return if user.auth_source_id
89 flash.now[:error] = l(:notice_can_t_change_password) and return if user.auth_source_id
90 # create a new token for password recovery
90 # create a new token for password recovery
91 token = Token.new(:user => user, :action => "recovery")
91 token = Token.new(:user => user, :action => "recovery")
92 if token.save
92 if token.save
93 Mailer.deliver_lost_password(token)
93 Mailer.deliver_lost_password(token)
94 flash[:notice] = l(:notice_account_lost_email_sent)
94 flash[:notice] = l(:notice_account_lost_email_sent)
95 redirect_to :action => 'login'
95 redirect_to :action => 'login'
96 return
96 return
97 end
97 end
98 end
98 end
99 end
99 end
100 end
100 end
101
101
102 # User self-registration
102 # User self-registration
103 def register
103 def register
104 redirect_to(home_url) && return unless Setting.self_registration? || session[:auth_source_registration]
104 redirect_to(home_url) && return unless Setting.self_registration? || session[:auth_source_registration]
105 if request.get?
105 if request.get?
106 session[:auth_source_registration] = nil
106 session[:auth_source_registration] = nil
107 @user = User.new(:language => Setting.default_language)
107 @user = User.new(:language => Setting.default_language)
108 else
108 else
109 @user = User.new(params[:user])
109 @user = User.new(params[:user])
110 @user.admin = false
110 @user.admin = false
111 @user.status = User::STATUS_REGISTERED
111 @user.status = User::STATUS_REGISTERED
112 if session[:auth_source_registration]
112 if session[:auth_source_registration]
113 @user.status = User::STATUS_ACTIVE
113 @user.status = User::STATUS_ACTIVE
114 @user.login = session[:auth_source_registration][:login]
114 @user.login = session[:auth_source_registration][:login]
115 @user.auth_source_id = session[:auth_source_registration][:auth_source_id]
115 @user.auth_source_id = session[:auth_source_registration][:auth_source_id]
116 if @user.save
116 if @user.save
117 session[:auth_source_registration] = nil
117 session[:auth_source_registration] = nil
118 self.logged_user = @user
118 self.logged_user = @user
119 flash[:notice] = l(:notice_account_activated)
119 flash[:notice] = l(:notice_account_activated)
120 redirect_to :controller => 'my', :action => 'account'
120 redirect_to :controller => 'my', :action => 'account'
121 end
121 end
122 else
122 else
123 @user.login = params[:user][:login]
123 @user.login = params[:user][:login]
124 @user.password, @user.password_confirmation = params[:password], params[:password_confirmation]
124 @user.password, @user.password_confirmation = params[:password], params[:password_confirmation]
125
125
126 case Setting.self_registration
126 case Setting.self_registration
127 when '1'
127 when '1'
128 register_by_email_activation(@user)
128 register_by_email_activation(@user)
129 when '3'
129 when '3'
130 register_automatically(@user)
130 register_automatically(@user)
131 else
131 else
132 register_manually_by_administrator(@user)
132 register_manually_by_administrator(@user)
133 end
133 end
134 end
134 end
135 end
135 end
136 end
136 end
137
137
138 # Token based account activation
138 # Token based account activation
139 def activate
139 def activate
140 redirect_to(home_url) && return unless Setting.self_registration? && params[:token]
140 redirect_to(home_url) && return unless Setting.self_registration? && params[:token]
141 token = Token.find_by_action_and_value('register', params[:token])
141 token = Token.find_by_action_and_value('register', params[:token])
142 redirect_to(home_url) && return unless token and !token.expired?
142 redirect_to(home_url) && return unless token and !token.expired?
143 user = token.user
143 user = token.user
144 redirect_to(home_url) && return unless user.status == User::STATUS_REGISTERED
144 redirect_to(home_url) && return unless user.status == User::STATUS_REGISTERED
145 user.status = User::STATUS_ACTIVE
145 user.status = User::STATUS_ACTIVE
146 if user.save
146 if user.save
147 token.destroy
147 token.destroy
148 flash[:notice] = l(:notice_account_activated)
148 flash[:notice] = l(:notice_account_activated)
149 end
149 end
150 redirect_to :action => 'login'
150 redirect_to :action => 'login'
151 end
151 end
152
152
153 private
153 private
154 def logged_user=(user)
154
155 if user && user.is_a?(User)
156 User.current = user
157 session[:user_id] = user.id
158 else
159 User.current = User.anonymous
160 session[:user_id] = nil
161 end
162 end
163
164 def password_authentication
155 def password_authentication
165 user = User.try_to_login(params[:username], params[:password])
156 user = User.try_to_login(params[:username], params[:password])
166 if user.nil?
157 if user.nil?
167 # Invalid credentials
158 # Invalid credentials
168 flash.now[:error] = l(:notice_account_invalid_creditentials)
159 flash.now[:error] = l(:notice_account_invalid_creditentials)
169 elsif user.new_record?
160 elsif user.new_record?
170 # Onthefly creation failed, display the registration form to fill/fix attributes
161 # Onthefly creation failed, display the registration form to fill/fix attributes
171 @user = user
162 @user = user
172 session[:auth_source_registration] = {:login => user.login, :auth_source_id => user.auth_source_id }
163 session[:auth_source_registration] = {:login => user.login, :auth_source_id => user.auth_source_id }
173 render :action => 'register'
164 render :action => 'register'
174 else
165 else
175 # Valid user
166 # Valid user
176 successful_authentication(user)
167 successful_authentication(user)
177 end
168 end
178 end
169 end
179
170
180
171
181 def open_id_authenticate(openid_url)
172 def open_id_authenticate(openid_url)
182 authenticate_with_open_id(openid_url, :required => [:nickname, :fullname, :email], :return_to => signin_url) do |result, identity_url, registration|
173 authenticate_with_open_id(openid_url, :required => [:nickname, :fullname, :email], :return_to => signin_url) do |result, identity_url, registration|
183 if result.successful?
174 if result.successful?
184 user = User.find_or_initialize_by_identity_url(identity_url)
175 user = User.find_or_initialize_by_identity_url(identity_url)
185 if user.new_record?
176 if user.new_record?
186 # Self-registration off
177 # Self-registration off
187 redirect_to(home_url) && return unless Setting.self_registration?
178 redirect_to(home_url) && return unless Setting.self_registration?
188
179
189 # Create on the fly
180 # Create on the fly
190 user.login = registration['nickname'] unless registration['nickname'].nil?
181 user.login = registration['nickname'] unless registration['nickname'].nil?
191 user.mail = registration['email'] unless registration['email'].nil?
182 user.mail = registration['email'] unless registration['email'].nil?
192 user.firstname, user.lastname = registration['fullname'].split(' ') unless registration['fullname'].nil?
183 user.firstname, user.lastname = registration['fullname'].split(' ') unless registration['fullname'].nil?
193 user.random_password
184 user.random_password
194 user.status = User::STATUS_REGISTERED
185 user.status = User::STATUS_REGISTERED
195
186
196 case Setting.self_registration
187 case Setting.self_registration
197 when '1'
188 when '1'
198 register_by_email_activation(user) do
189 register_by_email_activation(user) do
199 onthefly_creation_failed(user)
190 onthefly_creation_failed(user)
200 end
191 end
201 when '3'
192 when '3'
202 register_automatically(user) do
193 register_automatically(user) do
203 onthefly_creation_failed(user)
194 onthefly_creation_failed(user)
204 end
195 end
205 else
196 else
206 register_manually_by_administrator(user) do
197 register_manually_by_administrator(user) do
207 onthefly_creation_failed(user)
198 onthefly_creation_failed(user)
208 end
199 end
209 end
200 end
210 else
201 else
211 # Existing record
202 # Existing record
212 if user.active?
203 if user.active?
213 successful_authentication(user)
204 successful_authentication(user)
214 else
205 else
215 account_pending
206 account_pending
216 end
207 end
217 end
208 end
218 end
209 end
219 end
210 end
220 end
211 end
221
212
222 def successful_authentication(user)
213 def successful_authentication(user)
223 # Valid user
214 # Valid user
224 self.logged_user = user
215 self.logged_user = user
225 # generate a key and set cookie if autologin
216 # generate a key and set cookie if autologin
226 if params[:autologin] && Setting.autologin?
217 if params[:autologin] && Setting.autologin?
227 token = Token.create(:user => user, :action => 'autologin')
218 token = Token.create(:user => user, :action => 'autologin')
228 cookies[:autologin] = { :value => token.value, :expires => 1.year.from_now }
219 cookies[:autologin] = { :value => token.value, :expires => 1.year.from_now }
229 end
220 end
230 redirect_back_or_default :controller => 'my', :action => 'page'
221 redirect_back_or_default :controller => 'my', :action => 'page'
231 end
222 end
232
223
233 # Onthefly creation failed, display the registration form to fill/fix attributes
224 # Onthefly creation failed, display the registration form to fill/fix attributes
234 def onthefly_creation_failed(user, auth_source_options = { })
225 def onthefly_creation_failed(user, auth_source_options = { })
235 @user = user
226 @user = user
236 session[:auth_source_registration] = auth_source_options unless auth_source_options.empty?
227 session[:auth_source_registration] = auth_source_options unless auth_source_options.empty?
237 render :action => 'register'
228 render :action => 'register'
238 end
229 end
239
230
240 # Register a user for email activation.
231 # Register a user for email activation.
241 #
232 #
242 # Pass a block for behavior when a user fails to save
233 # Pass a block for behavior when a user fails to save
243 def register_by_email_activation(user, &block)
234 def register_by_email_activation(user, &block)
244 token = Token.new(:user => user, :action => "register")
235 token = Token.new(:user => user, :action => "register")
245 if user.save and token.save
236 if user.save and token.save
246 Mailer.deliver_register(token)
237 Mailer.deliver_register(token)
247 flash[:notice] = l(:notice_account_register_done)
238 flash[:notice] = l(:notice_account_register_done)
248 redirect_to :action => 'login'
239 redirect_to :action => 'login'
249 else
240 else
250 yield if block_given?
241 yield if block_given?
251 end
242 end
252 end
243 end
253
244
254 # Automatically register a user
245 # Automatically register a user
255 #
246 #
256 # Pass a block for behavior when a user fails to save
247 # Pass a block for behavior when a user fails to save
257 def register_automatically(user, &block)
248 def register_automatically(user, &block)
258 # Automatic activation
249 # Automatic activation
259 user.status = User::STATUS_ACTIVE
250 user.status = User::STATUS_ACTIVE
260 if user.save
251 if user.save
261 self.logged_user = user
252 self.logged_user = user
262 flash[:notice] = l(:notice_account_activated)
253 flash[:notice] = l(:notice_account_activated)
263 redirect_to :controller => 'my', :action => 'account'
254 redirect_to :controller => 'my', :action => 'account'
264 else
255 else
265 yield if block_given?
256 yield if block_given?
266 end
257 end
267 end
258 end
268
259
269 # Manual activation by the administrator
260 # Manual activation by the administrator
270 #
261 #
271 # Pass a block for behavior when a user fails to save
262 # Pass a block for behavior when a user fails to save
272 def register_manually_by_administrator(user, &block)
263 def register_manually_by_administrator(user, &block)
273 if user.save
264 if user.save
274 # Sends an email to the administrators
265 # Sends an email to the administrators
275 Mailer.deliver_account_activation_request(user)
266 Mailer.deliver_account_activation_request(user)
276 account_pending
267 account_pending
277 else
268 else
278 yield if block_given?
269 yield if block_given?
279 end
270 end
280 end
271 end
281
272
282 def account_pending
273 def account_pending
283 flash[:notice] = l(:notice_account_pending)
274 flash[:notice] = l(:notice_account_pending)
284 redirect_to :action => 'login'
275 redirect_to :action => 'login'
285 end
276 end
286 end
277 end
@@ -1,241 +1,252
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require 'uri'
18 require 'uri'
19 require 'cgi'
19 require 'cgi'
20
20
21 class ApplicationController < ActionController::Base
21 class ApplicationController < ActionController::Base
22 include Redmine::I18n
22 include Redmine::I18n
23
23
24 # In case the cookie store secret changes
24 # In case the cookie store secret changes
25 rescue_from CGI::Session::CookieStore::TamperedWithCookie do |exception|
25 rescue_from CGI::Session::CookieStore::TamperedWithCookie do |exception|
26 render :text => 'Your session was invalid and has been reset. Please, reload this page.', :status => 500
26 render :text => 'Your session was invalid and has been reset. Please, reload this page.', :status => 500
27 end
27 end
28
28
29 layout 'base'
29 layout 'base'
30
30
31 before_filter :user_setup, :check_if_login_required, :set_localization
31 before_filter :user_setup, :check_if_login_required, :set_localization
32 filter_parameter_logging :password
32 filter_parameter_logging :password
33
33
34 include Redmine::MenuManager::MenuController
34 include Redmine::MenuManager::MenuController
35 helper Redmine::MenuManager::MenuHelper
35 helper Redmine::MenuManager::MenuHelper
36
36
37 REDMINE_SUPPORTED_SCM.each do |scm|
37 REDMINE_SUPPORTED_SCM.each do |scm|
38 require_dependency "repository/#{scm.underscore}"
38 require_dependency "repository/#{scm.underscore}"
39 end
39 end
40
40
41 def current_role
41 def current_role
42 @current_role ||= User.current.role_for_project(@project)
42 @current_role ||= User.current.role_for_project(@project)
43 end
43 end
44
44
45 def user_setup
45 def user_setup
46 # Check the settings cache for each request
46 # Check the settings cache for each request
47 Setting.check_cache
47 Setting.check_cache
48 # Find the current user
48 # Find the current user
49 User.current = find_current_user
49 self.logged_user = find_current_user
50 end
50 end
51
51
52 # Returns the current user or nil if no user is logged in
52 # Returns the current user or nil if no user is logged in
53 def find_current_user
53 def find_current_user
54 if session[:user_id]
54 if session[:user_id]
55 # existing session
55 # existing session
56 (User.active.find(session[:user_id]) rescue nil)
56 (User.active.find(session[:user_id]) rescue nil)
57 elsif cookies[:autologin] && Setting.autologin?
57 elsif cookies[:autologin] && Setting.autologin?
58 # auto-login feature
58 # auto-login feature
59 User.find_by_autologin_key(cookies[:autologin])
59 User.try_to_autologin(cookies[:autologin])
60 elsif params[:key] && accept_key_auth_actions.include?(params[:action])
60 elsif params[:key] && accept_key_auth_actions.include?(params[:action])
61 # RSS key authentication
61 # RSS key authentication
62 User.find_by_rss_key(params[:key])
62 User.find_by_rss_key(params[:key])
63 end
63 end
64 end
64 end
65
65
66 # Sets the logged in user
67 def logged_user=(user)
68 if user && user.is_a?(User)
69 User.current = user
70 session[:user_id] = user.id
71 else
72 User.current = User.anonymous
73 session[:user_id] = nil
74 end
75 end
76
66 # check if login is globally required to access the application
77 # check if login is globally required to access the application
67 def check_if_login_required
78 def check_if_login_required
68 # no check needed if user is already logged in
79 # no check needed if user is already logged in
69 return true if User.current.logged?
80 return true if User.current.logged?
70 require_login if Setting.login_required?
81 require_login if Setting.login_required?
71 end
82 end
72
83
73 def set_localization
84 def set_localization
74 lang = nil
85 lang = nil
75 if User.current.logged?
86 if User.current.logged?
76 lang = find_language(User.current.language)
87 lang = find_language(User.current.language)
77 end
88 end
78 if lang.nil? && request.env['HTTP_ACCEPT_LANGUAGE']
89 if lang.nil? && request.env['HTTP_ACCEPT_LANGUAGE']
79 accept_lang = parse_qvalues(request.env['HTTP_ACCEPT_LANGUAGE']).first.downcase
90 accept_lang = parse_qvalues(request.env['HTTP_ACCEPT_LANGUAGE']).first.downcase
80 if !accept_lang.blank?
91 if !accept_lang.blank?
81 lang = find_language(accept_lang) || find_language(accept_lang.split('-').first)
92 lang = find_language(accept_lang) || find_language(accept_lang.split('-').first)
82 end
93 end
83 end
94 end
84 lang ||= Setting.default_language
95 lang ||= Setting.default_language
85 set_language_if_valid(lang)
96 set_language_if_valid(lang)
86 end
97 end
87
98
88 def require_login
99 def require_login
89 if !User.current.logged?
100 if !User.current.logged?
90 redirect_to :controller => "account", :action => "login", :back_url => url_for(params)
101 redirect_to :controller => "account", :action => "login", :back_url => url_for(params)
91 return false
102 return false
92 end
103 end
93 true
104 true
94 end
105 end
95
106
96 def require_admin
107 def require_admin
97 return unless require_login
108 return unless require_login
98 if !User.current.admin?
109 if !User.current.admin?
99 render_403
110 render_403
100 return false
111 return false
101 end
112 end
102 true
113 true
103 end
114 end
104
115
105 def deny_access
116 def deny_access
106 User.current.logged? ? render_403 : require_login
117 User.current.logged? ? render_403 : require_login
107 end
118 end
108
119
109 # Authorize the user for the requested action
120 # Authorize the user for the requested action
110 def authorize(ctrl = params[:controller], action = params[:action])
121 def authorize(ctrl = params[:controller], action = params[:action])
111 allowed = User.current.allowed_to?({:controller => ctrl, :action => action}, @project)
122 allowed = User.current.allowed_to?({:controller => ctrl, :action => action}, @project)
112 allowed ? true : deny_access
123 allowed ? true : deny_access
113 end
124 end
114
125
115 # make sure that the user is a member of the project (or admin) if project is private
126 # make sure that the user is a member of the project (or admin) if project is private
116 # used as a before_filter for actions that do not require any particular permission on the project
127 # used as a before_filter for actions that do not require any particular permission on the project
117 def check_project_privacy
128 def check_project_privacy
118 if @project && @project.active?
129 if @project && @project.active?
119 if @project.is_public? || User.current.member_of?(@project) || User.current.admin?
130 if @project.is_public? || User.current.member_of?(@project) || User.current.admin?
120 true
131 true
121 else
132 else
122 User.current.logged? ? render_403 : require_login
133 User.current.logged? ? render_403 : require_login
123 end
134 end
124 else
135 else
125 @project = nil
136 @project = nil
126 render_404
137 render_404
127 false
138 false
128 end
139 end
129 end
140 end
130
141
131 def redirect_back_or_default(default)
142 def redirect_back_or_default(default)
132 back_url = CGI.unescape(params[:back_url].to_s)
143 back_url = CGI.unescape(params[:back_url].to_s)
133 if !back_url.blank?
144 if !back_url.blank?
134 begin
145 begin
135 uri = URI.parse(back_url)
146 uri = URI.parse(back_url)
136 # do not redirect user to another host or to the login or register page
147 # do not redirect user to another host or to the login or register page
137 if (uri.relative? || (uri.host == request.host)) && !uri.path.match(%r{/(login|account/register)})
148 if (uri.relative? || (uri.host == request.host)) && !uri.path.match(%r{/(login|account/register)})
138 redirect_to(back_url) and return
149 redirect_to(back_url) and return
139 end
150 end
140 rescue URI::InvalidURIError
151 rescue URI::InvalidURIError
141 # redirect to default
152 # redirect to default
142 end
153 end
143 end
154 end
144 redirect_to default
155 redirect_to default
145 end
156 end
146
157
147 def render_403
158 def render_403
148 @project = nil
159 @project = nil
149 render :template => "common/403", :layout => !request.xhr?, :status => 403
160 render :template => "common/403", :layout => !request.xhr?, :status => 403
150 return false
161 return false
151 end
162 end
152
163
153 def render_404
164 def render_404
154 render :template => "common/404", :layout => !request.xhr?, :status => 404
165 render :template => "common/404", :layout => !request.xhr?, :status => 404
155 return false
166 return false
156 end
167 end
157
168
158 def render_error(msg)
169 def render_error(msg)
159 flash.now[:error] = msg
170 flash.now[:error] = msg
160 render :text => '', :layout => !request.xhr?, :status => 500
171 render :text => '', :layout => !request.xhr?, :status => 500
161 end
172 end
162
173
163 def render_feed(items, options={})
174 def render_feed(items, options={})
164 @items = items || []
175 @items = items || []
165 @items.sort! {|x,y| y.event_datetime <=> x.event_datetime }
176 @items.sort! {|x,y| y.event_datetime <=> x.event_datetime }
166 @items = @items.slice(0, Setting.feeds_limit.to_i)
177 @items = @items.slice(0, Setting.feeds_limit.to_i)
167 @title = options[:title] || Setting.app_title
178 @title = options[:title] || Setting.app_title
168 render :template => "common/feed.atom.rxml", :layout => false, :content_type => 'application/atom+xml'
179 render :template => "common/feed.atom.rxml", :layout => false, :content_type => 'application/atom+xml'
169 end
180 end
170
181
171 def self.accept_key_auth(*actions)
182 def self.accept_key_auth(*actions)
172 actions = actions.flatten.map(&:to_s)
183 actions = actions.flatten.map(&:to_s)
173 write_inheritable_attribute('accept_key_auth_actions', actions)
184 write_inheritable_attribute('accept_key_auth_actions', actions)
174 end
185 end
175
186
176 def accept_key_auth_actions
187 def accept_key_auth_actions
177 self.class.read_inheritable_attribute('accept_key_auth_actions') || []
188 self.class.read_inheritable_attribute('accept_key_auth_actions') || []
178 end
189 end
179
190
180 # TODO: move to model
191 # TODO: move to model
181 def attach_files(obj, attachments)
192 def attach_files(obj, attachments)
182 attached = []
193 attached = []
183 unsaved = []
194 unsaved = []
184 if attachments && attachments.is_a?(Hash)
195 if attachments && attachments.is_a?(Hash)
185 attachments.each_value do |attachment|
196 attachments.each_value do |attachment|
186 file = attachment['file']
197 file = attachment['file']
187 next unless file && file.size > 0
198 next unless file && file.size > 0
188 a = Attachment.create(:container => obj,
199 a = Attachment.create(:container => obj,
189 :file => file,
200 :file => file,
190 :description => attachment['description'].to_s.strip,
201 :description => attachment['description'].to_s.strip,
191 :author => User.current)
202 :author => User.current)
192 a.new_record? ? (unsaved << a) : (attached << a)
203 a.new_record? ? (unsaved << a) : (attached << a)
193 end
204 end
194 if unsaved.any?
205 if unsaved.any?
195 flash[:warning] = l(:warning_attachments_not_saved, unsaved.size)
206 flash[:warning] = l(:warning_attachments_not_saved, unsaved.size)
196 end
207 end
197 end
208 end
198 attached
209 attached
199 end
210 end
200
211
201 # Returns the number of objects that should be displayed
212 # Returns the number of objects that should be displayed
202 # on the paginated list
213 # on the paginated list
203 def per_page_option
214 def per_page_option
204 per_page = nil
215 per_page = nil
205 if params[:per_page] && Setting.per_page_options_array.include?(params[:per_page].to_s.to_i)
216 if params[:per_page] && Setting.per_page_options_array.include?(params[:per_page].to_s.to_i)
206 per_page = params[:per_page].to_s.to_i
217 per_page = params[:per_page].to_s.to_i
207 session[:per_page] = per_page
218 session[:per_page] = per_page
208 elsif session[:per_page]
219 elsif session[:per_page]
209 per_page = session[:per_page]
220 per_page = session[:per_page]
210 else
221 else
211 per_page = Setting.per_page_options_array.first || 25
222 per_page = Setting.per_page_options_array.first || 25
212 end
223 end
213 per_page
224 per_page
214 end
225 end
215
226
216 # qvalues http header parser
227 # qvalues http header parser
217 # code taken from webrick
228 # code taken from webrick
218 def parse_qvalues(value)
229 def parse_qvalues(value)
219 tmp = []
230 tmp = []
220 if value
231 if value
221 parts = value.split(/,\s*/)
232 parts = value.split(/,\s*/)
222 parts.each {|part|
233 parts.each {|part|
223 if m = %r{^([^\s,]+?)(?:;\s*q=(\d+(?:\.\d+)?))?$}.match(part)
234 if m = %r{^([^\s,]+?)(?:;\s*q=(\d+(?:\.\d+)?))?$}.match(part)
224 val = m[1]
235 val = m[1]
225 q = (m[2] or 1).to_f
236 q = (m[2] or 1).to_f
226 tmp.push([val, q])
237 tmp.push([val, q])
227 end
238 end
228 }
239 }
229 tmp = tmp.sort_by{|val, q| -q}
240 tmp = tmp.sort_by{|val, q| -q}
230 tmp.collect!{|val, q| val}
241 tmp.collect!{|val, q| val}
231 end
242 end
232 return tmp
243 return tmp
233 rescue
244 rescue
234 nil
245 nil
235 end
246 end
236
247
237 # Returns a string that can be used as filename value in Content-Disposition header
248 # Returns a string that can be used as filename value in Content-Disposition header
238 def filename_for_content_disposition(name)
249 def filename_for_content_disposition(name)
239 request.env['HTTP_USER_AGENT'] =~ %r{MSIE} ? ERB::Util.url_encode(name) : name
250 request.env['HTTP_USER_AGENT'] =~ %r{MSIE} ? ERB::Util.url_encode(name) : name
240 end
251 end
241 end
252 end
@@ -1,319 +1,323
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require "digest/sha1"
18 require "digest/sha1"
19
19
20 class User < ActiveRecord::Base
20 class User < ActiveRecord::Base
21
21
22 # Account statuses
22 # Account statuses
23 STATUS_ANONYMOUS = 0
23 STATUS_ANONYMOUS = 0
24 STATUS_ACTIVE = 1
24 STATUS_ACTIVE = 1
25 STATUS_REGISTERED = 2
25 STATUS_REGISTERED = 2
26 STATUS_LOCKED = 3
26 STATUS_LOCKED = 3
27
27
28 USER_FORMATS = {
28 USER_FORMATS = {
29 :firstname_lastname => '#{firstname} #{lastname}',
29 :firstname_lastname => '#{firstname} #{lastname}',
30 :firstname => '#{firstname}',
30 :firstname => '#{firstname}',
31 :lastname_firstname => '#{lastname} #{firstname}',
31 :lastname_firstname => '#{lastname} #{firstname}',
32 :lastname_coma_firstname => '#{lastname}, #{firstname}',
32 :lastname_coma_firstname => '#{lastname}, #{firstname}',
33 :username => '#{login}'
33 :username => '#{login}'
34 }
34 }
35
35
36 has_many :memberships, :class_name => 'Member', :include => [ :project, :role ], :conditions => "#{Project.table_name}.status=#{Project::STATUS_ACTIVE}", :order => "#{Project.table_name}.name"
36 has_many :memberships, :class_name => 'Member', :include => [ :project, :role ], :conditions => "#{Project.table_name}.status=#{Project::STATUS_ACTIVE}", :order => "#{Project.table_name}.name"
37 has_many :members, :dependent => :delete_all
37 has_many :members, :dependent => :delete_all
38 has_many :projects, :through => :memberships
38 has_many :projects, :through => :memberships
39 has_many :issue_categories, :foreign_key => 'assigned_to_id', :dependent => :nullify
39 has_many :issue_categories, :foreign_key => 'assigned_to_id', :dependent => :nullify
40 has_many :changesets, :dependent => :nullify
40 has_many :changesets, :dependent => :nullify
41 has_one :preference, :dependent => :destroy, :class_name => 'UserPreference'
41 has_one :preference, :dependent => :destroy, :class_name => 'UserPreference'
42 has_one :rss_token, :dependent => :destroy, :class_name => 'Token', :conditions => "action='feeds'"
42 has_one :rss_token, :dependent => :destroy, :class_name => 'Token', :conditions => "action='feeds'"
43 belongs_to :auth_source
43 belongs_to :auth_source
44
44
45 # Active non-anonymous users scope
45 # Active non-anonymous users scope
46 named_scope :active, :conditions => "#{User.table_name}.status = #{STATUS_ACTIVE}"
46 named_scope :active, :conditions => "#{User.table_name}.status = #{STATUS_ACTIVE}"
47
47
48 acts_as_customizable
48 acts_as_customizable
49
49
50 attr_accessor :password, :password_confirmation
50 attr_accessor :password, :password_confirmation
51 attr_accessor :last_before_login_on
51 attr_accessor :last_before_login_on
52 # Prevents unauthorized assignments
52 # Prevents unauthorized assignments
53 attr_protected :login, :admin, :password, :password_confirmation, :hashed_password
53 attr_protected :login, :admin, :password, :password_confirmation, :hashed_password
54
54
55 validates_presence_of :login, :firstname, :lastname, :mail, :if => Proc.new { |user| !user.is_a?(AnonymousUser) }
55 validates_presence_of :login, :firstname, :lastname, :mail, :if => Proc.new { |user| !user.is_a?(AnonymousUser) }
56 validates_uniqueness_of :login, :if => Proc.new { |user| !user.login.blank? }
56 validates_uniqueness_of :login, :if => Proc.new { |user| !user.login.blank? }
57 validates_uniqueness_of :mail, :if => Proc.new { |user| !user.mail.blank? }, :case_sensitive => false
57 validates_uniqueness_of :mail, :if => Proc.new { |user| !user.mail.blank? }, :case_sensitive => false
58 # Login must contain lettres, numbers, underscores only
58 # Login must contain lettres, numbers, underscores only
59 validates_format_of :login, :with => /^[a-z0-9_\-@\.]*$/i
59 validates_format_of :login, :with => /^[a-z0-9_\-@\.]*$/i
60 validates_length_of :login, :maximum => 30
60 validates_length_of :login, :maximum => 30
61 validates_format_of :firstname, :lastname, :with => /^[\w\s\'\-\.]*$/i
61 validates_format_of :firstname, :lastname, :with => /^[\w\s\'\-\.]*$/i
62 validates_length_of :firstname, :lastname, :maximum => 30
62 validates_length_of :firstname, :lastname, :maximum => 30
63 validates_format_of :mail, :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i, :allow_nil => true
63 validates_format_of :mail, :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i, :allow_nil => true
64 validates_length_of :mail, :maximum => 60, :allow_nil => true
64 validates_length_of :mail, :maximum => 60, :allow_nil => true
65 validates_length_of :password, :minimum => 4, :allow_nil => true
65 validates_length_of :password, :minimum => 4, :allow_nil => true
66 validates_confirmation_of :password, :allow_nil => true
66 validates_confirmation_of :password, :allow_nil => true
67
67
68 def before_create
68 def before_create
69 self.mail_notification = false
69 self.mail_notification = false
70 true
70 true
71 end
71 end
72
72
73 def before_save
73 def before_save
74 # update hashed_password if password was set
74 # update hashed_password if password was set
75 self.hashed_password = User.hash_password(self.password) if self.password
75 self.hashed_password = User.hash_password(self.password) if self.password
76 end
76 end
77
77
78 def reload(*args)
78 def reload(*args)
79 @name = nil
79 @name = nil
80 super
80 super
81 end
81 end
82
82
83 def identity_url=(url)
83 def identity_url=(url)
84 if url.blank?
84 if url.blank?
85 write_attribute(:identity_url, '')
85 write_attribute(:identity_url, '')
86 else
86 else
87 begin
87 begin
88 write_attribute(:identity_url, OpenIdAuthentication.normalize_identifier(url))
88 write_attribute(:identity_url, OpenIdAuthentication.normalize_identifier(url))
89 rescue OpenIdAuthentication::InvalidOpenId
89 rescue OpenIdAuthentication::InvalidOpenId
90 # Invlaid url, don't save
90 # Invlaid url, don't save
91 end
91 end
92 end
92 end
93 self.read_attribute(:identity_url)
93 self.read_attribute(:identity_url)
94 end
94 end
95
95
96 # Returns the user that matches provided login and password, or nil
96 # Returns the user that matches provided login and password, or nil
97 def self.try_to_login(login, password)
97 def self.try_to_login(login, password)
98 # Make sure no one can sign in with an empty password
98 # Make sure no one can sign in with an empty password
99 return nil if password.to_s.empty?
99 return nil if password.to_s.empty?
100 user = find(:first, :conditions => ["login=?", login])
100 user = find(:first, :conditions => ["login=?", login])
101 if user
101 if user
102 # user is already in local database
102 # user is already in local database
103 return nil if !user.active?
103 return nil if !user.active?
104 if user.auth_source
104 if user.auth_source
105 # user has an external authentication method
105 # user has an external authentication method
106 return nil unless user.auth_source.authenticate(login, password)
106 return nil unless user.auth_source.authenticate(login, password)
107 else
107 else
108 # authentication with local password
108 # authentication with local password
109 return nil unless User.hash_password(password) == user.hashed_password
109 return nil unless User.hash_password(password) == user.hashed_password
110 end
110 end
111 else
111 else
112 # user is not yet registered, try to authenticate with available sources
112 # user is not yet registered, try to authenticate with available sources
113 attrs = AuthSource.authenticate(login, password)
113 attrs = AuthSource.authenticate(login, password)
114 if attrs
114 if attrs
115 user = new(*attrs)
115 user = new(*attrs)
116 user.login = login
116 user.login = login
117 user.language = Setting.default_language
117 user.language = Setting.default_language
118 if user.save
118 if user.save
119 user.reload
119 user.reload
120 logger.info("User '#{user.login}' created from the LDAP") if logger
120 logger.info("User '#{user.login}' created from the LDAP") if logger
121 end
121 end
122 end
122 end
123 end
123 end
124 user.update_attribute(:last_login_on, Time.now) if user && !user.new_record?
124 user.update_attribute(:last_login_on, Time.now) if user && !user.new_record?
125 user
125 user
126 rescue => text
126 rescue => text
127 raise text
127 raise text
128 end
128 end
129
130 # Returns the user who matches the given autologin +key+ or nil
131 def self.try_to_autologin(key)
132 token = Token.find_by_action_and_value('autologin', key)
133 if token && (token.created_on > Setting.autologin.to_i.day.ago) && token.user && token.user.active?
134 token.user.update_attribute(:last_login_on, Time.now)
135 token.user
136 end
137 end
129
138
130 # Return user's full name for display
139 # Return user's full name for display
131 def name(formatter = nil)
140 def name(formatter = nil)
132 if formatter
141 if formatter
133 eval('"' + (USER_FORMATS[formatter] || USER_FORMATS[:firstname_lastname]) + '"')
142 eval('"' + (USER_FORMATS[formatter] || USER_FORMATS[:firstname_lastname]) + '"')
134 else
143 else
135 @name ||= eval('"' + (USER_FORMATS[Setting.user_format] || USER_FORMATS[:firstname_lastname]) + '"')
144 @name ||= eval('"' + (USER_FORMATS[Setting.user_format] || USER_FORMATS[:firstname_lastname]) + '"')
136 end
145 end
137 end
146 end
138
147
139 def active?
148 def active?
140 self.status == STATUS_ACTIVE
149 self.status == STATUS_ACTIVE
141 end
150 end
142
151
143 def registered?
152 def registered?
144 self.status == STATUS_REGISTERED
153 self.status == STATUS_REGISTERED
145 end
154 end
146
155
147 def locked?
156 def locked?
148 self.status == STATUS_LOCKED
157 self.status == STATUS_LOCKED
149 end
158 end
150
159
151 def check_password?(clear_password)
160 def check_password?(clear_password)
152 User.hash_password(clear_password) == self.hashed_password
161 User.hash_password(clear_password) == self.hashed_password
153 end
162 end
154
163
155 # Generate and set a random password. Useful for automated user creation
164 # Generate and set a random password. Useful for automated user creation
156 # Based on Token#generate_token_value
165 # Based on Token#generate_token_value
157 #
166 #
158 def random_password
167 def random_password
159 chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
168 chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
160 password = ''
169 password = ''
161 40.times { |i| password << chars[rand(chars.size-1)] }
170 40.times { |i| password << chars[rand(chars.size-1)] }
162 self.password = password
171 self.password = password
163 self.password_confirmation = password
172 self.password_confirmation = password
164 self
173 self
165 end
174 end
166
175
167 def pref
176 def pref
168 self.preference ||= UserPreference.new(:user => self)
177 self.preference ||= UserPreference.new(:user => self)
169 end
178 end
170
179
171 def time_zone
180 def time_zone
172 @time_zone ||= (self.pref.time_zone.blank? ? nil : ActiveSupport::TimeZone[self.pref.time_zone])
181 @time_zone ||= (self.pref.time_zone.blank? ? nil : ActiveSupport::TimeZone[self.pref.time_zone])
173 end
182 end
174
183
175 def wants_comments_in_reverse_order?
184 def wants_comments_in_reverse_order?
176 self.pref[:comments_sorting] == 'desc'
185 self.pref[:comments_sorting] == 'desc'
177 end
186 end
178
187
179 # Return user's RSS key (a 40 chars long string), used to access feeds
188 # Return user's RSS key (a 40 chars long string), used to access feeds
180 def rss_key
189 def rss_key
181 token = self.rss_token || Token.create(:user => self, :action => 'feeds')
190 token = self.rss_token || Token.create(:user => self, :action => 'feeds')
182 token.value
191 token.value
183 end
192 end
184
193
185 # Return an array of project ids for which the user has explicitly turned mail notifications on
194 # Return an array of project ids for which the user has explicitly turned mail notifications on
186 def notified_projects_ids
195 def notified_projects_ids
187 @notified_projects_ids ||= memberships.select {|m| m.mail_notification?}.collect(&:project_id)
196 @notified_projects_ids ||= memberships.select {|m| m.mail_notification?}.collect(&:project_id)
188 end
197 end
189
198
190 def notified_project_ids=(ids)
199 def notified_project_ids=(ids)
191 Member.update_all("mail_notification = #{connection.quoted_false}", ['user_id = ?', id])
200 Member.update_all("mail_notification = #{connection.quoted_false}", ['user_id = ?', id])
192 Member.update_all("mail_notification = #{connection.quoted_true}", ['user_id = ? AND project_id IN (?)', id, ids]) if ids && !ids.empty?
201 Member.update_all("mail_notification = #{connection.quoted_true}", ['user_id = ? AND project_id IN (?)', id, ids]) if ids && !ids.empty?
193 @notified_projects_ids = nil
202 @notified_projects_ids = nil
194 notified_projects_ids
203 notified_projects_ids
195 end
204 end
196
205
197 def self.find_by_rss_key(key)
206 def self.find_by_rss_key(key)
198 token = Token.find_by_value(key)
207 token = Token.find_by_value(key)
199 token && token.user.active? ? token.user : nil
208 token && token.user.active? ? token.user : nil
200 end
209 end
201
210
202 def self.find_by_autologin_key(key)
203 token = Token.find_by_action_and_value('autologin', key)
204 token && (token.created_on > Setting.autologin.to_i.day.ago) && token.user.active? ? token.user : nil
205 end
206
207 # Makes find_by_mail case-insensitive
211 # Makes find_by_mail case-insensitive
208 def self.find_by_mail(mail)
212 def self.find_by_mail(mail)
209 find(:first, :conditions => ["LOWER(mail) = ?", mail.to_s.downcase])
213 find(:first, :conditions => ["LOWER(mail) = ?", mail.to_s.downcase])
210 end
214 end
211
215
212 # Sort users by their display names
216 # Sort users by their display names
213 def <=>(user)
217 def <=>(user)
214 self.to_s.downcase <=> user.to_s.downcase
218 self.to_s.downcase <=> user.to_s.downcase
215 end
219 end
216
220
217 def to_s
221 def to_s
218 name
222 name
219 end
223 end
220
224
221 def logged?
225 def logged?
222 true
226 true
223 end
227 end
224
228
225 def anonymous?
229 def anonymous?
226 !logged?
230 !logged?
227 end
231 end
228
232
229 # Return user's role for project
233 # Return user's role for project
230 def role_for_project(project)
234 def role_for_project(project)
231 # No role on archived projects
235 # No role on archived projects
232 return nil unless project && project.active?
236 return nil unless project && project.active?
233 if logged?
237 if logged?
234 # Find project membership
238 # Find project membership
235 membership = memberships.detect {|m| m.project_id == project.id}
239 membership = memberships.detect {|m| m.project_id == project.id}
236 if membership
240 if membership
237 membership.role
241 membership.role
238 else
242 else
239 @role_non_member ||= Role.non_member
243 @role_non_member ||= Role.non_member
240 end
244 end
241 else
245 else
242 @role_anonymous ||= Role.anonymous
246 @role_anonymous ||= Role.anonymous
243 end
247 end
244 end
248 end
245
249
246 # Return true if the user is a member of project
250 # Return true if the user is a member of project
247 def member_of?(project)
251 def member_of?(project)
248 role_for_project(project).member?
252 role_for_project(project).member?
249 end
253 end
250
254
251 # Return true if the user is allowed to do the specified action on project
255 # Return true if the user is allowed to do the specified action on project
252 # action can be:
256 # action can be:
253 # * a parameter-like Hash (eg. :controller => 'projects', :action => 'edit')
257 # * a parameter-like Hash (eg. :controller => 'projects', :action => 'edit')
254 # * a permission Symbol (eg. :edit_project)
258 # * a permission Symbol (eg. :edit_project)
255 def allowed_to?(action, project, options={})
259 def allowed_to?(action, project, options={})
256 if project
260 if project
257 # No action allowed on archived projects
261 # No action allowed on archived projects
258 return false unless project.active?
262 return false unless project.active?
259 # No action allowed on disabled modules
263 # No action allowed on disabled modules
260 return false unless project.allows_to?(action)
264 return false unless project.allows_to?(action)
261 # Admin users are authorized for anything else
265 # Admin users are authorized for anything else
262 return true if admin?
266 return true if admin?
263
267
264 role = role_for_project(project)
268 role = role_for_project(project)
265 return false unless role
269 return false unless role
266 role.allowed_to?(action) && (project.is_public? || role.member?)
270 role.allowed_to?(action) && (project.is_public? || role.member?)
267
271
268 elsif options[:global]
272 elsif options[:global]
269 # authorize if user has at least one role that has this permission
273 # authorize if user has at least one role that has this permission
270 roles = memberships.collect {|m| m.role}.uniq
274 roles = memberships.collect {|m| m.role}.uniq
271 roles.detect {|r| r.allowed_to?(action)} || (self.logged? ? Role.non_member.allowed_to?(action) : Role.anonymous.allowed_to?(action))
275 roles.detect {|r| r.allowed_to?(action)} || (self.logged? ? Role.non_member.allowed_to?(action) : Role.anonymous.allowed_to?(action))
272 else
276 else
273 false
277 false
274 end
278 end
275 end
279 end
276
280
277 def self.current=(user)
281 def self.current=(user)
278 @current_user = user
282 @current_user = user
279 end
283 end
280
284
281 def self.current
285 def self.current
282 @current_user ||= User.anonymous
286 @current_user ||= User.anonymous
283 end
287 end
284
288
285 def self.anonymous
289 def self.anonymous
286 anonymous_user = AnonymousUser.find(:first)
290 anonymous_user = AnonymousUser.find(:first)
287 if anonymous_user.nil?
291 if anonymous_user.nil?
288 anonymous_user = AnonymousUser.create(:lastname => 'Anonymous', :firstname => '', :mail => '', :login => '', :status => 0)
292 anonymous_user = AnonymousUser.create(:lastname => 'Anonymous', :firstname => '', :mail => '', :login => '', :status => 0)
289 raise 'Unable to create the anonymous user.' if anonymous_user.new_record?
293 raise 'Unable to create the anonymous user.' if anonymous_user.new_record?
290 end
294 end
291 anonymous_user
295 anonymous_user
292 end
296 end
293
297
294 private
298 private
295 # Return password digest
299 # Return password digest
296 def self.hash_password(clear_password)
300 def self.hash_password(clear_password)
297 Digest::SHA1.hexdigest(clear_password || "")
301 Digest::SHA1.hexdigest(clear_password || "")
298 end
302 end
299 end
303 end
300
304
301 class AnonymousUser < User
305 class AnonymousUser < User
302
306
303 def validate_on_create
307 def validate_on_create
304 # There should be only one AnonymousUser in the database
308 # There should be only one AnonymousUser in the database
305 errors.add_to_base 'An anonymous user already exists.' if AnonymousUser.find(:first)
309 errors.add_to_base 'An anonymous user already exists.' if AnonymousUser.find(:first)
306 end
310 end
307
311
308 def available_custom_fields
312 def available_custom_fields
309 []
313 []
310 end
314 end
311
315
312 # Overrides a few properties
316 # Overrides a few properties
313 def logged?; false end
317 def logged?; false end
314 def admin; false end
318 def admin; false end
315 def name; 'Anonymous' end
319 def name; 'Anonymous' end
316 def mail; nil end
320 def mail; nil end
317 def time_zone; nil end
321 def time_zone; nil end
318 def rss_key; nil end
322 def rss_key; nil end
319 end
323 end
@@ -1,181 +1,169
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require File.dirname(__FILE__) + '/../test_helper'
18 require File.dirname(__FILE__) + '/../test_helper'
19 require 'account_controller'
19 require 'account_controller'
20
20
21 # Re-raise errors caught by the controller.
21 # Re-raise errors caught by the controller.
22 class AccountController; def rescue_action(e) raise e end; end
22 class AccountController; def rescue_action(e) raise e end; end
23
23
24 class AccountControllerTest < Test::Unit::TestCase
24 class AccountControllerTest < Test::Unit::TestCase
25 fixtures :users, :roles
25 fixtures :users, :roles
26
26
27 def setup
27 def setup
28 @controller = AccountController.new
28 @controller = AccountController.new
29 @request = ActionController::TestRequest.new
29 @request = ActionController::TestRequest.new
30 @response = ActionController::TestResponse.new
30 @response = ActionController::TestResponse.new
31 User.current = nil
31 User.current = nil
32 end
32 end
33
33
34 def test_show
34 def test_show
35 get :show, :id => 2
35 get :show, :id => 2
36 assert_response :success
36 assert_response :success
37 assert_template 'show'
37 assert_template 'show'
38 assert_not_nil assigns(:user)
38 assert_not_nil assigns(:user)
39 end
39 end
40
40
41 def test_show_inactive
41 def test_show_inactive
42 get :show, :id => 5
42 get :show, :id => 5
43 assert_response 404
43 assert_response 404
44 assert_nil assigns(:user)
44 assert_nil assigns(:user)
45 end
45 end
46
46
47 def test_login_should_redirect_to_back_url_param
47 def test_login_should_redirect_to_back_url_param
48 # request.uri is "test.host" in test environment
48 # request.uri is "test.host" in test environment
49 post :login, :username => 'jsmith', :password => 'jsmith', :back_url => 'http%3A%2F%2Ftest.host%2Fissues%2Fshow%2F1'
49 post :login, :username => 'jsmith', :password => 'jsmith', :back_url => 'http%3A%2F%2Ftest.host%2Fissues%2Fshow%2F1'
50 assert_redirected_to '/issues/show/1'
50 assert_redirected_to '/issues/show/1'
51 end
51 end
52
52
53 def test_login_should_not_redirect_to_another_host
53 def test_login_should_not_redirect_to_another_host
54 post :login, :username => 'jsmith', :password => 'jsmith', :back_url => 'http%3A%2F%2Ftest.foo%2Ffake'
54 post :login, :username => 'jsmith', :password => 'jsmith', :back_url => 'http%3A%2F%2Ftest.foo%2Ffake'
55 assert_redirected_to '/my/page'
55 assert_redirected_to '/my/page'
56 end
56 end
57
57
58 def test_login_with_wrong_password
58 def test_login_with_wrong_password
59 post :login, :username => 'admin', :password => 'bad'
59 post :login, :username => 'admin', :password => 'bad'
60 assert_response :success
60 assert_response :success
61 assert_template 'login'
61 assert_template 'login'
62 assert_tag 'div',
62 assert_tag 'div',
63 :attributes => { :class => "flash error" },
63 :attributes => { :class => "flash error" },
64 :content => /Invalid user or password/
64 :content => /Invalid user or password/
65 end
65 end
66
66
67 if Object.const_defined?(:OpenID)
67 if Object.const_defined?(:OpenID)
68
68
69 def test_login_with_openid_for_existing_user
69 def test_login_with_openid_for_existing_user
70 Setting.self_registration = '3'
70 Setting.self_registration = '3'
71 Setting.openid = '1'
71 Setting.openid = '1'
72 existing_user = User.new(:firstname => 'Cool',
72 existing_user = User.new(:firstname => 'Cool',
73 :lastname => 'User',
73 :lastname => 'User',
74 :mail => 'user@somedomain.com',
74 :mail => 'user@somedomain.com',
75 :identity_url => 'http://openid.example.com/good_user')
75 :identity_url => 'http://openid.example.com/good_user')
76 existing_user.login = 'cool_user'
76 existing_user.login = 'cool_user'
77 assert existing_user.save!
77 assert existing_user.save!
78
78
79 post :login, :openid_url => existing_user.identity_url
79 post :login, :openid_url => existing_user.identity_url
80 assert_redirected_to 'my/page'
80 assert_redirected_to 'my/page'
81 end
81 end
82
82
83 def test_login_with_openid_for_existing_non_active_user
83 def test_login_with_openid_for_existing_non_active_user
84 Setting.self_registration = '2'
84 Setting.self_registration = '2'
85 Setting.openid = '1'
85 Setting.openid = '1'
86 existing_user = User.new(:firstname => 'Cool',
86 existing_user = User.new(:firstname => 'Cool',
87 :lastname => 'User',
87 :lastname => 'User',
88 :mail => 'user@somedomain.com',
88 :mail => 'user@somedomain.com',
89 :identity_url => 'http://openid.example.com/good_user',
89 :identity_url => 'http://openid.example.com/good_user',
90 :status => User::STATUS_REGISTERED)
90 :status => User::STATUS_REGISTERED)
91 existing_user.login = 'cool_user'
91 existing_user.login = 'cool_user'
92 assert existing_user.save!
92 assert existing_user.save!
93
93
94 post :login, :openid_url => existing_user.identity_url
94 post :login, :openid_url => existing_user.identity_url
95 assert_redirected_to 'login'
95 assert_redirected_to 'login'
96 end
96 end
97
97
98 def test_login_with_openid_with_new_user_created
98 def test_login_with_openid_with_new_user_created
99 Setting.self_registration = '3'
99 Setting.self_registration = '3'
100 Setting.openid = '1'
100 Setting.openid = '1'
101 post :login, :openid_url => 'http://openid.example.com/good_user'
101 post :login, :openid_url => 'http://openid.example.com/good_user'
102 assert_redirected_to 'my/account'
102 assert_redirected_to 'my/account'
103 user = User.find_by_login('cool_user')
103 user = User.find_by_login('cool_user')
104 assert user
104 assert user
105 assert_equal 'Cool', user.firstname
105 assert_equal 'Cool', user.firstname
106 assert_equal 'User', user.lastname
106 assert_equal 'User', user.lastname
107 end
107 end
108
108
109 def test_login_with_openid_with_new_user_and_self_registration_off
109 def test_login_with_openid_with_new_user_and_self_registration_off
110 Setting.self_registration = '0'
110 Setting.self_registration = '0'
111 Setting.openid = '1'
111 Setting.openid = '1'
112 post :login, :openid_url => 'http://openid.example.com/good_user'
112 post :login, :openid_url => 'http://openid.example.com/good_user'
113 assert_redirected_to home_url
113 assert_redirected_to home_url
114 user = User.find_by_login('cool_user')
114 user = User.find_by_login('cool_user')
115 assert ! user
115 assert ! user
116 end
116 end
117
117
118 def test_login_with_openid_with_new_user_created_with_email_activation_should_have_a_token
118 def test_login_with_openid_with_new_user_created_with_email_activation_should_have_a_token
119 Setting.self_registration = '1'
119 Setting.self_registration = '1'
120 Setting.openid = '1'
120 Setting.openid = '1'
121 post :login, :openid_url => 'http://openid.example.com/good_user'
121 post :login, :openid_url => 'http://openid.example.com/good_user'
122 assert_redirected_to 'login'
122 assert_redirected_to 'login'
123 user = User.find_by_login('cool_user')
123 user = User.find_by_login('cool_user')
124 assert user
124 assert user
125
125
126 token = Token.find_by_user_id_and_action(user.id, 'register')
126 token = Token.find_by_user_id_and_action(user.id, 'register')
127 assert token
127 assert token
128 end
128 end
129
129
130 def test_login_with_openid_with_new_user_created_with_manual_activation
130 def test_login_with_openid_with_new_user_created_with_manual_activation
131 Setting.self_registration = '2'
131 Setting.self_registration = '2'
132 Setting.openid = '1'
132 Setting.openid = '1'
133 post :login, :openid_url => 'http://openid.example.com/good_user'
133 post :login, :openid_url => 'http://openid.example.com/good_user'
134 assert_redirected_to 'login'
134 assert_redirected_to 'login'
135 user = User.find_by_login('cool_user')
135 user = User.find_by_login('cool_user')
136 assert user
136 assert user
137 assert_equal User::STATUS_REGISTERED, user.status
137 assert_equal User::STATUS_REGISTERED, user.status
138 end
138 end
139
139
140 def test_login_with_openid_with_new_user_with_conflict_should_register
140 def test_login_with_openid_with_new_user_with_conflict_should_register
141 Setting.self_registration = '3'
141 Setting.self_registration = '3'
142 Setting.openid = '1'
142 Setting.openid = '1'
143 existing_user = User.new(:firstname => 'Cool', :lastname => 'User', :mail => 'user@somedomain.com')
143 existing_user = User.new(:firstname => 'Cool', :lastname => 'User', :mail => 'user@somedomain.com')
144 existing_user.login = 'cool_user'
144 existing_user.login = 'cool_user'
145 assert existing_user.save!
145 assert existing_user.save!
146
146
147 post :login, :openid_url => 'http://openid.example.com/good_user'
147 post :login, :openid_url => 'http://openid.example.com/good_user'
148 assert_response :success
148 assert_response :success
149 assert_template 'register'
149 assert_template 'register'
150 assert assigns(:user)
150 assert assigns(:user)
151 assert_equal 'http://openid.example.com/good_user', assigns(:user)[:identity_url]
151 assert_equal 'http://openid.example.com/good_user', assigns(:user)[:identity_url]
152 end
152 end
153
153
154 def test_setting_openid_should_return_true_when_set_to_true
154 def test_setting_openid_should_return_true_when_set_to_true
155 Setting.openid = '1'
155 Setting.openid = '1'
156 assert_equal true, Setting.openid?
156 assert_equal true, Setting.openid?
157 end
157 end
158
158
159 else
159 else
160 puts "Skipping openid tests."
160 puts "Skipping openid tests."
161 end
161 end
162
162
163
164 def test_autologin
165 Setting.autologin = "7"
166 Token.delete_all
167 post :login, :username => 'admin', :password => 'admin', :autologin => 1
168 assert_redirected_to 'my/page'
169 token = Token.find :first
170 assert_not_nil token
171 assert_equal User.find_by_login('admin'), token.user
172 assert_equal 'autologin', token.action
173 end
174
175 def test_logout
163 def test_logout
176 @request.session[:user_id] = 2
164 @request.session[:user_id] = 2
177 get :logout
165 get :logout
178 assert_redirected_to ''
166 assert_redirected_to ''
179 assert_nil @request.session[:user_id]
167 assert_nil @request.session[:user_id]
180 end
168 end
181 end
169 end
@@ -1,153 +1,185
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require "#{File.dirname(__FILE__)}/../test_helper"
18 require "#{File.dirname(__FILE__)}/../test_helper"
19
19
20 begin
20 begin
21 require 'mocha'
21 require 'mocha'
22 rescue
22 rescue
23 # Won't run some tests
23 # Won't run some tests
24 end
24 end
25
25
26 class AccountTest < ActionController::IntegrationTest
26 class AccountTest < ActionController::IntegrationTest
27 fixtures :users
27 fixtures :users
28
28
29 # Replace this with your real tests.
29 # Replace this with your real tests.
30 def test_login
30 def test_login
31 get "my/page"
31 get "my/page"
32 assert_redirected_to "/login?back_url=http%3A%2F%2Fwww.example.com%2Fmy%2Fpage"
32 assert_redirected_to "/login?back_url=http%3A%2F%2Fwww.example.com%2Fmy%2Fpage"
33 log_user('jsmith', 'jsmith')
33 log_user('jsmith', 'jsmith')
34
34
35 get "my/account"
35 get "my/account"
36 assert_response :success
36 assert_response :success
37 assert_template "my/account"
37 assert_template "my/account"
38 end
38 end
39
39
40 def test_autologin
41 user = User.find(1)
42 Setting.autologin = "7"
43 Token.delete_all
44
45 # User logs in with 'autologin' checked
46 post '/login', :username => user.login, :password => 'admin', :autologin => 1
47 assert_redirected_to 'my/page'
48 token = Token.find :first
49 assert_not_nil token
50 assert_equal user, token.user
51 assert_equal 'autologin', token.action
52 assert_equal user.id, session[:user_id]
53 assert_equal token.value, cookies['autologin']
54
55 # Session is cleared
56 reset!
57 User.current = nil
58 # Clears user's last login timestamp
59 user.update_attribute :last_login_on, nil
60 assert_nil user.reload.last_login_on
61
62 # User comes back with his autologin cookie
63 cookies[:autologin] = token.value
64 get '/my/page'
65 assert_response :success
66 assert_template 'my/page'
67 assert_equal user.id, session[:user_id]
68 assert_not_nil user.reload.last_login_on
69 assert user.last_login_on > 2.second.ago
70 end
71
40 def test_lost_password
72 def test_lost_password
41 Token.delete_all
73 Token.delete_all
42
74
43 get "account/lost_password"
75 get "account/lost_password"
44 assert_response :success
76 assert_response :success
45 assert_template "account/lost_password"
77 assert_template "account/lost_password"
46
78
47 post "account/lost_password", :mail => 'jSmith@somenet.foo'
79 post "account/lost_password", :mail => 'jSmith@somenet.foo'
48 assert_redirected_to "/login"
80 assert_redirected_to "/login"
49
81
50 token = Token.find(:first)
82 token = Token.find(:first)
51 assert_equal 'recovery', token.action
83 assert_equal 'recovery', token.action
52 assert_equal 'jsmith@somenet.foo', token.user.mail
84 assert_equal 'jsmith@somenet.foo', token.user.mail
53 assert !token.expired?
85 assert !token.expired?
54
86
55 get "account/lost_password", :token => token.value
87 get "account/lost_password", :token => token.value
56 assert_response :success
88 assert_response :success
57 assert_template "account/password_recovery"
89 assert_template "account/password_recovery"
58
90
59 post "account/lost_password", :token => token.value, :new_password => 'newpass', :new_password_confirmation => 'newpass'
91 post "account/lost_password", :token => token.value, :new_password => 'newpass', :new_password_confirmation => 'newpass'
60 assert_redirected_to "/login"
92 assert_redirected_to "/login"
61 assert_equal 'Password was successfully updated.', flash[:notice]
93 assert_equal 'Password was successfully updated.', flash[:notice]
62
94
63 log_user('jsmith', 'newpass')
95 log_user('jsmith', 'newpass')
64 assert_equal 0, Token.count
96 assert_equal 0, Token.count
65 end
97 end
66
98
67 def test_register_with_automatic_activation
99 def test_register_with_automatic_activation
68 Setting.self_registration = '3'
100 Setting.self_registration = '3'
69
101
70 get 'account/register'
102 get 'account/register'
71 assert_response :success
103 assert_response :success
72 assert_template 'account/register'
104 assert_template 'account/register'
73
105
74 post 'account/register', :user => {:login => "newuser", :language => "en", :firstname => "New", :lastname => "User", :mail => "newuser@foo.bar"},
106 post 'account/register', :user => {:login => "newuser", :language => "en", :firstname => "New", :lastname => "User", :mail => "newuser@foo.bar"},
75 :password => "newpass", :password_confirmation => "newpass"
107 :password => "newpass", :password_confirmation => "newpass"
76 assert_redirected_to 'my/account'
108 assert_redirected_to 'my/account'
77 follow_redirect!
109 follow_redirect!
78 assert_response :success
110 assert_response :success
79 assert_template 'my/account'
111 assert_template 'my/account'
80
112
81 assert User.find_by_login('newuser').active?
113 assert User.find_by_login('newuser').active?
82 end
114 end
83
115
84 def test_register_with_manual_activation
116 def test_register_with_manual_activation
85 Setting.self_registration = '2'
117 Setting.self_registration = '2'
86
118
87 post 'account/register', :user => {:login => "newuser", :language => "en", :firstname => "New", :lastname => "User", :mail => "newuser@foo.bar"},
119 post 'account/register', :user => {:login => "newuser", :language => "en", :firstname => "New", :lastname => "User", :mail => "newuser@foo.bar"},
88 :password => "newpass", :password_confirmation => "newpass"
120 :password => "newpass", :password_confirmation => "newpass"
89 assert_redirected_to '/login'
121 assert_redirected_to '/login'
90 assert !User.find_by_login('newuser').active?
122 assert !User.find_by_login('newuser').active?
91 end
123 end
92
124
93 def test_register_with_email_activation
125 def test_register_with_email_activation
94 Setting.self_registration = '1'
126 Setting.self_registration = '1'
95 Token.delete_all
127 Token.delete_all
96
128
97 post 'account/register', :user => {:login => "newuser", :language => "en", :firstname => "New", :lastname => "User", :mail => "newuser@foo.bar"},
129 post 'account/register', :user => {:login => "newuser", :language => "en", :firstname => "New", :lastname => "User", :mail => "newuser@foo.bar"},
98 :password => "newpass", :password_confirmation => "newpass"
130 :password => "newpass", :password_confirmation => "newpass"
99 assert_redirected_to '/login'
131 assert_redirected_to '/login'
100 assert !User.find_by_login('newuser').active?
132 assert !User.find_by_login('newuser').active?
101
133
102 token = Token.find(:first)
134 token = Token.find(:first)
103 assert_equal 'register', token.action
135 assert_equal 'register', token.action
104 assert_equal 'newuser@foo.bar', token.user.mail
136 assert_equal 'newuser@foo.bar', token.user.mail
105 assert !token.expired?
137 assert !token.expired?
106
138
107 get 'account/activate', :token => token.value
139 get 'account/activate', :token => token.value
108 assert_redirected_to '/login'
140 assert_redirected_to '/login'
109 log_user('newuser', 'newpass')
141 log_user('newuser', 'newpass')
110 end
142 end
111
143
112 if Object.const_defined?(:Mocha)
144 if Object.const_defined?(:Mocha)
113
145
114 def test_onthefly_registration
146 def test_onthefly_registration
115 # disable registration
147 # disable registration
116 Setting.self_registration = '0'
148 Setting.self_registration = '0'
117 AuthSource.expects(:authenticate).returns([:login => 'foo', :firstname => 'Foo', :lastname => 'Smith', :mail => 'foo@bar.com', :auth_source_id => 66])
149 AuthSource.expects(:authenticate).returns([:login => 'foo', :firstname => 'Foo', :lastname => 'Smith', :mail => 'foo@bar.com', :auth_source_id => 66])
118
150
119 post 'account/login', :username => 'foo', :password => 'bar'
151 post 'account/login', :username => 'foo', :password => 'bar'
120 assert_redirected_to 'my/page'
152 assert_redirected_to 'my/page'
121
153
122 user = User.find_by_login('foo')
154 user = User.find_by_login('foo')
123 assert user.is_a?(User)
155 assert user.is_a?(User)
124 assert_equal 66, user.auth_source_id
156 assert_equal 66, user.auth_source_id
125 assert user.hashed_password.blank?
157 assert user.hashed_password.blank?
126 end
158 end
127
159
128 def test_onthefly_registration_with_invalid_attributes
160 def test_onthefly_registration_with_invalid_attributes
129 # disable registration
161 # disable registration
130 Setting.self_registration = '0'
162 Setting.self_registration = '0'
131 AuthSource.expects(:authenticate).returns([:login => 'foo', :lastname => 'Smith', :auth_source_id => 66])
163 AuthSource.expects(:authenticate).returns([:login => 'foo', :lastname => 'Smith', :auth_source_id => 66])
132
164
133 post 'account/login', :username => 'foo', :password => 'bar'
165 post 'account/login', :username => 'foo', :password => 'bar'
134 assert_response :success
166 assert_response :success
135 assert_template 'account/register'
167 assert_template 'account/register'
136 assert_tag :input, :attributes => { :name => 'user[firstname]', :value => '' }
168 assert_tag :input, :attributes => { :name => 'user[firstname]', :value => '' }
137 assert_tag :input, :attributes => { :name => 'user[lastname]', :value => 'Smith' }
169 assert_tag :input, :attributes => { :name => 'user[lastname]', :value => 'Smith' }
138 assert_no_tag :input, :attributes => { :name => 'user[login]' }
170 assert_no_tag :input, :attributes => { :name => 'user[login]' }
139 assert_no_tag :input, :attributes => { :name => 'user[password]' }
171 assert_no_tag :input, :attributes => { :name => 'user[password]' }
140
172
141 post 'account/register', :user => {:firstname => 'Foo', :lastname => 'Smith', :mail => 'foo@bar.com'}
173 post 'account/register', :user => {:firstname => 'Foo', :lastname => 'Smith', :mail => 'foo@bar.com'}
142 assert_redirected_to '/my/account'
174 assert_redirected_to '/my/account'
143
175
144 user = User.find_by_login('foo')
176 user = User.find_by_login('foo')
145 assert user.is_a?(User)
177 assert user.is_a?(User)
146 assert_equal 66, user.auth_source_id
178 assert_equal 66, user.auth_source_id
147 assert user.hashed_password.blank?
179 assert user.hashed_password.blank?
148 end
180 end
149
181
150 else
182 else
151 puts 'Mocha is missing. Skipping tests.'
183 puts 'Mocha is missing. Skipping tests.'
152 end
184 end
153 end
185 end
General Comments 0
You need to be logged in to leave comments. Login now