##// END OF EJS Templates
Makes User.find_by_mail case-insensitive (password reminder #2322, repo users mapping)....
Jean-Philippe Lang -
r2120:72d0843c1fef
parent child
Show More
@@ -1,289 +1,294
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? }
57 validates_uniqueness_of :mail, :if => Proc.new { |user| !user.mail.blank? }
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 # Returns the user that matches provided login and password, or nil
83 # Returns the user that matches provided login and password, or nil
84 def self.try_to_login(login, password)
84 def self.try_to_login(login, password)
85 # Make sure no one can sign in with an empty password
85 # Make sure no one can sign in with an empty password
86 return nil if password.to_s.empty?
86 return nil if password.to_s.empty?
87 user = find(:first, :conditions => ["login=?", login])
87 user = find(:first, :conditions => ["login=?", login])
88 if user
88 if user
89 # user is already in local database
89 # user is already in local database
90 return nil if !user.active?
90 return nil if !user.active?
91 if user.auth_source
91 if user.auth_source
92 # user has an external authentication method
92 # user has an external authentication method
93 return nil unless user.auth_source.authenticate(login, password)
93 return nil unless user.auth_source.authenticate(login, password)
94 else
94 else
95 # authentication with local password
95 # authentication with local password
96 return nil unless User.hash_password(password) == user.hashed_password
96 return nil unless User.hash_password(password) == user.hashed_password
97 end
97 end
98 else
98 else
99 # user is not yet registered, try to authenticate with available sources
99 # user is not yet registered, try to authenticate with available sources
100 attrs = AuthSource.authenticate(login, password)
100 attrs = AuthSource.authenticate(login, password)
101 if attrs
101 if attrs
102 user = new(*attrs)
102 user = new(*attrs)
103 user.login = login
103 user.login = login
104 user.language = Setting.default_language
104 user.language = Setting.default_language
105 if user.save
105 if user.save
106 user.reload
106 user.reload
107 logger.info("User '#{user.login}' created from the LDAP") if logger
107 logger.info("User '#{user.login}' created from the LDAP") if logger
108 end
108 end
109 end
109 end
110 end
110 end
111 user.update_attribute(:last_login_on, Time.now) if user && !user.new_record?
111 user.update_attribute(:last_login_on, Time.now) if user && !user.new_record?
112 user
112 user
113 rescue => text
113 rescue => text
114 raise text
114 raise text
115 end
115 end
116
116
117 # Return user's full name for display
117 # Return user's full name for display
118 def name(formatter = nil)
118 def name(formatter = nil)
119 if formatter
119 if formatter
120 eval('"' + (USER_FORMATS[formatter] || USER_FORMATS[:firstname_lastname]) + '"')
120 eval('"' + (USER_FORMATS[formatter] || USER_FORMATS[:firstname_lastname]) + '"')
121 else
121 else
122 @name ||= eval('"' + (USER_FORMATS[Setting.user_format] || USER_FORMATS[:firstname_lastname]) + '"')
122 @name ||= eval('"' + (USER_FORMATS[Setting.user_format] || USER_FORMATS[:firstname_lastname]) + '"')
123 end
123 end
124 end
124 end
125
125
126 def active?
126 def active?
127 self.status == STATUS_ACTIVE
127 self.status == STATUS_ACTIVE
128 end
128 end
129
129
130 def registered?
130 def registered?
131 self.status == STATUS_REGISTERED
131 self.status == STATUS_REGISTERED
132 end
132 end
133
133
134 def locked?
134 def locked?
135 self.status == STATUS_LOCKED
135 self.status == STATUS_LOCKED
136 end
136 end
137
137
138 def check_password?(clear_password)
138 def check_password?(clear_password)
139 User.hash_password(clear_password) == self.hashed_password
139 User.hash_password(clear_password) == self.hashed_password
140 end
140 end
141
141
142 def pref
142 def pref
143 self.preference ||= UserPreference.new(:user => self)
143 self.preference ||= UserPreference.new(:user => self)
144 end
144 end
145
145
146 def time_zone
146 def time_zone
147 @time_zone ||= (self.pref.time_zone.blank? ? nil : TimeZone[self.pref.time_zone])
147 @time_zone ||= (self.pref.time_zone.blank? ? nil : TimeZone[self.pref.time_zone])
148 end
148 end
149
149
150 def wants_comments_in_reverse_order?
150 def wants_comments_in_reverse_order?
151 self.pref[:comments_sorting] == 'desc'
151 self.pref[:comments_sorting] == 'desc'
152 end
152 end
153
153
154 # Return user's RSS key (a 40 chars long string), used to access feeds
154 # Return user's RSS key (a 40 chars long string), used to access feeds
155 def rss_key
155 def rss_key
156 token = self.rss_token || Token.create(:user => self, :action => 'feeds')
156 token = self.rss_token || Token.create(:user => self, :action => 'feeds')
157 token.value
157 token.value
158 end
158 end
159
159
160 # Return an array of project ids for which the user has explicitly turned mail notifications on
160 # Return an array of project ids for which the user has explicitly turned mail notifications on
161 def notified_projects_ids
161 def notified_projects_ids
162 @notified_projects_ids ||= memberships.select {|m| m.mail_notification?}.collect(&:project_id)
162 @notified_projects_ids ||= memberships.select {|m| m.mail_notification?}.collect(&:project_id)
163 end
163 end
164
164
165 def notified_project_ids=(ids)
165 def notified_project_ids=(ids)
166 Member.update_all("mail_notification = #{connection.quoted_false}", ['user_id = ?', id])
166 Member.update_all("mail_notification = #{connection.quoted_false}", ['user_id = ?', id])
167 Member.update_all("mail_notification = #{connection.quoted_true}", ['user_id = ? AND project_id IN (?)', id, ids]) if ids && !ids.empty?
167 Member.update_all("mail_notification = #{connection.quoted_true}", ['user_id = ? AND project_id IN (?)', id, ids]) if ids && !ids.empty?
168 @notified_projects_ids = nil
168 @notified_projects_ids = nil
169 notified_projects_ids
169 notified_projects_ids
170 end
170 end
171
171
172 def self.find_by_rss_key(key)
172 def self.find_by_rss_key(key)
173 token = Token.find_by_value(key)
173 token = Token.find_by_value(key)
174 token && token.user.active? ? token.user : nil
174 token && token.user.active? ? token.user : nil
175 end
175 end
176
176
177 def self.find_by_autologin_key(key)
177 def self.find_by_autologin_key(key)
178 token = Token.find_by_action_and_value('autologin', key)
178 token = Token.find_by_action_and_value('autologin', key)
179 token && (token.created_on > Setting.autologin.to_i.day.ago) && token.user.active? ? token.user : nil
179 token && (token.created_on > Setting.autologin.to_i.day.ago) && token.user.active? ? token.user : nil
180 end
180 end
181
181
182 # Makes find_by_mail case-insensitive
183 def self.find_by_mail(mail)
184 find(:first, :conditions => ["LOWER(mail) = ?", mail.to_s.downcase])
185 end
186
182 # Sort users by their display names
187 # Sort users by their display names
183 def <=>(user)
188 def <=>(user)
184 self.to_s.downcase <=> user.to_s.downcase
189 self.to_s.downcase <=> user.to_s.downcase
185 end
190 end
186
191
187 def to_s
192 def to_s
188 name
193 name
189 end
194 end
190
195
191 def logged?
196 def logged?
192 true
197 true
193 end
198 end
194
199
195 def anonymous?
200 def anonymous?
196 !logged?
201 !logged?
197 end
202 end
198
203
199 # Return user's role for project
204 # Return user's role for project
200 def role_for_project(project)
205 def role_for_project(project)
201 # No role on archived projects
206 # No role on archived projects
202 return nil unless project && project.active?
207 return nil unless project && project.active?
203 if logged?
208 if logged?
204 # Find project membership
209 # Find project membership
205 membership = memberships.detect {|m| m.project_id == project.id}
210 membership = memberships.detect {|m| m.project_id == project.id}
206 if membership
211 if membership
207 membership.role
212 membership.role
208 else
213 else
209 @role_non_member ||= Role.non_member
214 @role_non_member ||= Role.non_member
210 end
215 end
211 else
216 else
212 @role_anonymous ||= Role.anonymous
217 @role_anonymous ||= Role.anonymous
213 end
218 end
214 end
219 end
215
220
216 # Return true if the user is a member of project
221 # Return true if the user is a member of project
217 def member_of?(project)
222 def member_of?(project)
218 role_for_project(project).member?
223 role_for_project(project).member?
219 end
224 end
220
225
221 # Return true if the user is allowed to do the specified action on project
226 # Return true if the user is allowed to do the specified action on project
222 # action can be:
227 # action can be:
223 # * a parameter-like Hash (eg. :controller => 'projects', :action => 'edit')
228 # * a parameter-like Hash (eg. :controller => 'projects', :action => 'edit')
224 # * a permission Symbol (eg. :edit_project)
229 # * a permission Symbol (eg. :edit_project)
225 def allowed_to?(action, project, options={})
230 def allowed_to?(action, project, options={})
226 if project
231 if project
227 # No action allowed on archived projects
232 # No action allowed on archived projects
228 return false unless project.active?
233 return false unless project.active?
229 # No action allowed on disabled modules
234 # No action allowed on disabled modules
230 return false unless project.allows_to?(action)
235 return false unless project.allows_to?(action)
231 # Admin users are authorized for anything else
236 # Admin users are authorized for anything else
232 return true if admin?
237 return true if admin?
233
238
234 role = role_for_project(project)
239 role = role_for_project(project)
235 return false unless role
240 return false unless role
236 role.allowed_to?(action) && (project.is_public? || role.member?)
241 role.allowed_to?(action) && (project.is_public? || role.member?)
237
242
238 elsif options[:global]
243 elsif options[:global]
239 # authorize if user has at least one role that has this permission
244 # authorize if user has at least one role that has this permission
240 roles = memberships.collect {|m| m.role}.uniq
245 roles = memberships.collect {|m| m.role}.uniq
241 roles.detect {|r| r.allowed_to?(action)} || (self.logged? ? Role.non_member.allowed_to?(action) : Role.anonymous.allowed_to?(action))
246 roles.detect {|r| r.allowed_to?(action)} || (self.logged? ? Role.non_member.allowed_to?(action) : Role.anonymous.allowed_to?(action))
242 else
247 else
243 false
248 false
244 end
249 end
245 end
250 end
246
251
247 def self.current=(user)
252 def self.current=(user)
248 @current_user = user
253 @current_user = user
249 end
254 end
250
255
251 def self.current
256 def self.current
252 @current_user ||= User.anonymous
257 @current_user ||= User.anonymous
253 end
258 end
254
259
255 def self.anonymous
260 def self.anonymous
256 anonymous_user = AnonymousUser.find(:first)
261 anonymous_user = AnonymousUser.find(:first)
257 if anonymous_user.nil?
262 if anonymous_user.nil?
258 anonymous_user = AnonymousUser.create(:lastname => 'Anonymous', :firstname => '', :mail => '', :login => '', :status => 0)
263 anonymous_user = AnonymousUser.create(:lastname => 'Anonymous', :firstname => '', :mail => '', :login => '', :status => 0)
259 raise 'Unable to create the anonymous user.' if anonymous_user.new_record?
264 raise 'Unable to create the anonymous user.' if anonymous_user.new_record?
260 end
265 end
261 anonymous_user
266 anonymous_user
262 end
267 end
263
268
264 private
269 private
265 # Return password digest
270 # Return password digest
266 def self.hash_password(clear_password)
271 def self.hash_password(clear_password)
267 Digest::SHA1.hexdigest(clear_password || "")
272 Digest::SHA1.hexdigest(clear_password || "")
268 end
273 end
269 end
274 end
270
275
271 class AnonymousUser < User
276 class AnonymousUser < User
272
277
273 def validate_on_create
278 def validate_on_create
274 # There should be only one AnonymousUser in the database
279 # There should be only one AnonymousUser in the database
275 errors.add_to_base 'An anonymous user already exists.' if AnonymousUser.find(:first)
280 errors.add_to_base 'An anonymous user already exists.' if AnonymousUser.find(:first)
276 end
281 end
277
282
278 def available_custom_fields
283 def available_custom_fields
279 []
284 []
280 end
285 end
281
286
282 # Overrides a few properties
287 # Overrides a few properties
283 def logged?; false end
288 def logged?; false end
284 def admin; false end
289 def admin; false end
285 def name; 'Anonymous' end
290 def name; 'Anonymous' end
286 def mail; nil end
291 def mail; nil end
287 def time_zone; nil end
292 def time_zone; nil end
288 def rss_key; nil end
293 def rss_key; nil end
289 end
294 end
@@ -1,153 +1,153
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 "account/login"
32 assert_redirected_to "account/login"
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_lost_password
40 def test_lost_password
41 Token.delete_all
41 Token.delete_all
42
42
43 get "account/lost_password"
43 get "account/lost_password"
44 assert_response :success
44 assert_response :success
45 assert_template "account/lost_password"
45 assert_template "account/lost_password"
46
46
47 post "account/lost_password", :mail => 'jsmith@somenet.foo'
47 post "account/lost_password", :mail => 'jSmith@somenet.foo'
48 assert_redirected_to "account/login"
48 assert_redirected_to "account/login"
49
49
50 token = Token.find(:first)
50 token = Token.find(:first)
51 assert_equal 'recovery', token.action
51 assert_equal 'recovery', token.action
52 assert_equal 'jsmith@somenet.foo', token.user.mail
52 assert_equal 'jsmith@somenet.foo', token.user.mail
53 assert !token.expired?
53 assert !token.expired?
54
54
55 get "account/lost_password", :token => token.value
55 get "account/lost_password", :token => token.value
56 assert_response :success
56 assert_response :success
57 assert_template "account/password_recovery"
57 assert_template "account/password_recovery"
58
58
59 post "account/lost_password", :token => token.value, :new_password => 'newpass', :new_password_confirmation => 'newpass'
59 post "account/lost_password", :token => token.value, :new_password => 'newpass', :new_password_confirmation => 'newpass'
60 assert_redirected_to "account/login"
60 assert_redirected_to "account/login"
61 assert_equal 'Password was successfully updated.', flash[:notice]
61 assert_equal 'Password was successfully updated.', flash[:notice]
62
62
63 log_user('jsmith', 'newpass')
63 log_user('jsmith', 'newpass')
64 assert_equal 0, Token.count
64 assert_equal 0, Token.count
65 end
65 end
66
66
67 def test_register_with_automatic_activation
67 def test_register_with_automatic_activation
68 Setting.self_registration = '3'
68 Setting.self_registration = '3'
69
69
70 get 'account/register'
70 get 'account/register'
71 assert_response :success
71 assert_response :success
72 assert_template 'account/register'
72 assert_template 'account/register'
73
73
74 post 'account/register', :user => {:login => "newuser", :language => "en", :firstname => "New", :lastname => "User", :mail => "newuser@foo.bar"},
74 post 'account/register', :user => {:login => "newuser", :language => "en", :firstname => "New", :lastname => "User", :mail => "newuser@foo.bar"},
75 :password => "newpass", :password_confirmation => "newpass"
75 :password => "newpass", :password_confirmation => "newpass"
76 assert_redirected_to 'my/account'
76 assert_redirected_to 'my/account'
77 follow_redirect!
77 follow_redirect!
78 assert_response :success
78 assert_response :success
79 assert_template 'my/account'
79 assert_template 'my/account'
80
80
81 assert User.find_by_login('newuser').active?
81 assert User.find_by_login('newuser').active?
82 end
82 end
83
83
84 def test_register_with_manual_activation
84 def test_register_with_manual_activation
85 Setting.self_registration = '2'
85 Setting.self_registration = '2'
86
86
87 post 'account/register', :user => {:login => "newuser", :language => "en", :firstname => "New", :lastname => "User", :mail => "newuser@foo.bar"},
87 post 'account/register', :user => {:login => "newuser", :language => "en", :firstname => "New", :lastname => "User", :mail => "newuser@foo.bar"},
88 :password => "newpass", :password_confirmation => "newpass"
88 :password => "newpass", :password_confirmation => "newpass"
89 assert_redirected_to 'account/login'
89 assert_redirected_to 'account/login'
90 assert !User.find_by_login('newuser').active?
90 assert !User.find_by_login('newuser').active?
91 end
91 end
92
92
93 def test_register_with_email_activation
93 def test_register_with_email_activation
94 Setting.self_registration = '1'
94 Setting.self_registration = '1'
95 Token.delete_all
95 Token.delete_all
96
96
97 post 'account/register', :user => {:login => "newuser", :language => "en", :firstname => "New", :lastname => "User", :mail => "newuser@foo.bar"},
97 post 'account/register', :user => {:login => "newuser", :language => "en", :firstname => "New", :lastname => "User", :mail => "newuser@foo.bar"},
98 :password => "newpass", :password_confirmation => "newpass"
98 :password => "newpass", :password_confirmation => "newpass"
99 assert_redirected_to 'account/login'
99 assert_redirected_to 'account/login'
100 assert !User.find_by_login('newuser').active?
100 assert !User.find_by_login('newuser').active?
101
101
102 token = Token.find(:first)
102 token = Token.find(:first)
103 assert_equal 'register', token.action
103 assert_equal 'register', token.action
104 assert_equal 'newuser@foo.bar', token.user.mail
104 assert_equal 'newuser@foo.bar', token.user.mail
105 assert !token.expired?
105 assert !token.expired?
106
106
107 get 'account/activate', :token => token.value
107 get 'account/activate', :token => token.value
108 assert_redirected_to 'account/login'
108 assert_redirected_to 'account/login'
109 log_user('newuser', 'newpass')
109 log_user('newuser', 'newpass')
110 end
110 end
111
111
112 if Object.const_defined?(:Mocha)
112 if Object.const_defined?(:Mocha)
113
113
114 def test_onthefly_registration
114 def test_onthefly_registration
115 # disable registration
115 # disable registration
116 Setting.self_registration = '0'
116 Setting.self_registration = '0'
117 AuthSource.expects(:authenticate).returns([:login => 'foo', :firstname => 'Foo', :lastname => 'Smith', :mail => 'foo@bar.com', :auth_source_id => 66])
117 AuthSource.expects(:authenticate).returns([:login => 'foo', :firstname => 'Foo', :lastname => 'Smith', :mail => 'foo@bar.com', :auth_source_id => 66])
118
118
119 post 'account/login', :username => 'foo', :password => 'bar'
119 post 'account/login', :username => 'foo', :password => 'bar'
120 assert_redirected_to 'my/page'
120 assert_redirected_to 'my/page'
121
121
122 user = User.find_by_login('foo')
122 user = User.find_by_login('foo')
123 assert user.is_a?(User)
123 assert user.is_a?(User)
124 assert_equal 66, user.auth_source_id
124 assert_equal 66, user.auth_source_id
125 assert user.hashed_password.blank?
125 assert user.hashed_password.blank?
126 end
126 end
127
127
128 def test_onthefly_registration_with_invalid_attributes
128 def test_onthefly_registration_with_invalid_attributes
129 # disable registration
129 # disable registration
130 Setting.self_registration = '0'
130 Setting.self_registration = '0'
131 AuthSource.expects(:authenticate).returns([:login => 'foo', :lastname => 'Smith', :auth_source_id => 66])
131 AuthSource.expects(:authenticate).returns([:login => 'foo', :lastname => 'Smith', :auth_source_id => 66])
132
132
133 post 'account/login', :username => 'foo', :password => 'bar'
133 post 'account/login', :username => 'foo', :password => 'bar'
134 assert_response :success
134 assert_response :success
135 assert_template 'account/register'
135 assert_template 'account/register'
136 assert_tag :input, :attributes => { :name => 'user[firstname]', :value => '' }
136 assert_tag :input, :attributes => { :name => 'user[firstname]', :value => '' }
137 assert_tag :input, :attributes => { :name => 'user[lastname]', :value => 'Smith' }
137 assert_tag :input, :attributes => { :name => 'user[lastname]', :value => 'Smith' }
138 assert_no_tag :input, :attributes => { :name => 'user[login]' }
138 assert_no_tag :input, :attributes => { :name => 'user[login]' }
139 assert_no_tag :input, :attributes => { :name => 'user[password]' }
139 assert_no_tag :input, :attributes => { :name => 'user[password]' }
140
140
141 post 'account/register', :user => {:firstname => 'Foo', :lastname => 'Smith', :mail => 'foo@bar.com'}
141 post 'account/register', :user => {:firstname => 'Foo', :lastname => 'Smith', :mail => 'foo@bar.com'}
142 assert_redirected_to 'my/account'
142 assert_redirected_to 'my/account'
143
143
144 user = User.find_by_login('foo')
144 user = User.find_by_login('foo')
145 assert user.is_a?(User)
145 assert user.is_a?(User)
146 assert_equal 66, user.auth_source_id
146 assert_equal 66, user.auth_source_id
147 assert user.hashed_password.blank?
147 assert user.hashed_password.blank?
148 end
148 end
149
149
150 else
150 else
151 puts 'Mocha is missing. Skipping tests.'
151 puts 'Mocha is missing. Skipping tests.'
152 end
152 end
153 end
153 end
@@ -1,161 +1,167
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006 Jean-Philippe Lang
2 # Copyright (C) 2006 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 class UserTest < Test::Unit::TestCase
20 class UserTest < Test::Unit::TestCase
21 fixtures :users, :members, :projects
21 fixtures :users, :members, :projects
22
22
23 def setup
23 def setup
24 @admin = User.find(1)
24 @admin = User.find(1)
25 @jsmith = User.find(2)
25 @jsmith = User.find(2)
26 @dlopper = User.find(3)
26 @dlopper = User.find(3)
27 end
27 end
28
28
29 def test_truth
29 def test_truth
30 assert_kind_of User, @jsmith
30 assert_kind_of User, @jsmith
31 end
31 end
32
32
33 def test_create
33 def test_create
34 user = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
34 user = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
35
35
36 user.login = "jsmith"
36 user.login = "jsmith"
37 user.password, user.password_confirmation = "password", "password"
37 user.password, user.password_confirmation = "password", "password"
38 # login uniqueness
38 # login uniqueness
39 assert !user.save
39 assert !user.save
40 assert_equal 1, user.errors.count
40 assert_equal 1, user.errors.count
41
41
42 user.login = "newuser"
42 user.login = "newuser"
43 user.password, user.password_confirmation = "passwd", "password"
43 user.password, user.password_confirmation = "passwd", "password"
44 # password confirmation
44 # password confirmation
45 assert !user.save
45 assert !user.save
46 assert_equal 1, user.errors.count
46 assert_equal 1, user.errors.count
47
47
48 user.password, user.password_confirmation = "password", "password"
48 user.password, user.password_confirmation = "password", "password"
49 assert user.save
49 assert user.save
50 end
50 end
51
51
52 def test_update
52 def test_update
53 assert_equal "admin", @admin.login
53 assert_equal "admin", @admin.login
54 @admin.login = "john"
54 @admin.login = "john"
55 assert @admin.save, @admin.errors.full_messages.join("; ")
55 assert @admin.save, @admin.errors.full_messages.join("; ")
56 @admin.reload
56 @admin.reload
57 assert_equal "john", @admin.login
57 assert_equal "john", @admin.login
58 end
58 end
59
59
60 def test_destroy
60 def test_destroy
61 User.find(2).destroy
61 User.find(2).destroy
62 assert_nil User.find_by_id(2)
62 assert_nil User.find_by_id(2)
63 assert Member.find_all_by_user_id(2).empty?
63 assert Member.find_all_by_user_id(2).empty?
64 end
64 end
65
65
66 def test_validate
66 def test_validate
67 @admin.login = ""
67 @admin.login = ""
68 assert !@admin.save
68 assert !@admin.save
69 assert_equal 1, @admin.errors.count
69 assert_equal 1, @admin.errors.count
70 end
70 end
71
71
72 def test_password
72 def test_password
73 user = User.try_to_login("admin", "admin")
73 user = User.try_to_login("admin", "admin")
74 assert_kind_of User, user
74 assert_kind_of User, user
75 assert_equal "admin", user.login
75 assert_equal "admin", user.login
76 user.password = "hello"
76 user.password = "hello"
77 assert user.save
77 assert user.save
78
78
79 user = User.try_to_login("admin", "hello")
79 user = User.try_to_login("admin", "hello")
80 assert_kind_of User, user
80 assert_kind_of User, user
81 assert_equal "admin", user.login
81 assert_equal "admin", user.login
82 assert_equal User.hash_password("hello"), user.hashed_password
82 assert_equal User.hash_password("hello"), user.hashed_password
83 end
83 end
84
84
85 def test_name_format
85 def test_name_format
86 assert_equal 'Smith, John', @jsmith.name(:lastname_coma_firstname)
86 assert_equal 'Smith, John', @jsmith.name(:lastname_coma_firstname)
87 Setting.user_format = :firstname_lastname
87 Setting.user_format = :firstname_lastname
88 assert_equal 'John Smith', @jsmith.reload.name
88 assert_equal 'John Smith', @jsmith.reload.name
89 Setting.user_format = :username
89 Setting.user_format = :username
90 assert_equal 'jsmith', @jsmith.reload.name
90 assert_equal 'jsmith', @jsmith.reload.name
91 end
91 end
92
92
93 def test_lock
93 def test_lock
94 user = User.try_to_login("jsmith", "jsmith")
94 user = User.try_to_login("jsmith", "jsmith")
95 assert_equal @jsmith, user
95 assert_equal @jsmith, user
96
96
97 @jsmith.status = User::STATUS_LOCKED
97 @jsmith.status = User::STATUS_LOCKED
98 assert @jsmith.save
98 assert @jsmith.save
99
99
100 user = User.try_to_login("jsmith", "jsmith")
100 user = User.try_to_login("jsmith", "jsmith")
101 assert_equal nil, user
101 assert_equal nil, user
102 end
102 end
103
103
104 def test_create_anonymous
104 def test_create_anonymous
105 AnonymousUser.delete_all
105 AnonymousUser.delete_all
106 anon = User.anonymous
106 anon = User.anonymous
107 assert !anon.new_record?
107 assert !anon.new_record?
108 assert_kind_of AnonymousUser, anon
108 assert_kind_of AnonymousUser, anon
109 end
109 end
110
110
111 def test_rss_key
111 def test_rss_key
112 assert_nil @jsmith.rss_token
112 assert_nil @jsmith.rss_token
113 key = @jsmith.rss_key
113 key = @jsmith.rss_key
114 assert_equal 40, key.length
114 assert_equal 40, key.length
115
115
116 @jsmith.reload
116 @jsmith.reload
117 assert_equal key, @jsmith.rss_key
117 assert_equal key, @jsmith.rss_key
118 end
118 end
119
119
120 def test_role_for_project
120 def test_role_for_project
121 # user with a role
121 # user with a role
122 role = @jsmith.role_for_project(Project.find(1))
122 role = @jsmith.role_for_project(Project.find(1))
123 assert_kind_of Role, role
123 assert_kind_of Role, role
124 assert_equal "Manager", role.name
124 assert_equal "Manager", role.name
125
125
126 # user with no role
126 # user with no role
127 assert !@dlopper.role_for_project(Project.find(2)).member?
127 assert !@dlopper.role_for_project(Project.find(2)).member?
128 end
128 end
129
129
130 def test_mail_notification_all
130 def test_mail_notification_all
131 @jsmith.mail_notification = true
131 @jsmith.mail_notification = true
132 @jsmith.notified_project_ids = []
132 @jsmith.notified_project_ids = []
133 @jsmith.save
133 @jsmith.save
134 @jsmith.reload
134 @jsmith.reload
135 assert @jsmith.projects.first.recipients.include?(@jsmith.mail)
135 assert @jsmith.projects.first.recipients.include?(@jsmith.mail)
136 end
136 end
137
137
138 def test_mail_notification_selected
138 def test_mail_notification_selected
139 @jsmith.mail_notification = false
139 @jsmith.mail_notification = false
140 @jsmith.notified_project_ids = [1]
140 @jsmith.notified_project_ids = [1]
141 @jsmith.save
141 @jsmith.save
142 @jsmith.reload
142 @jsmith.reload
143 assert Project.find(1).recipients.include?(@jsmith.mail)
143 assert Project.find(1).recipients.include?(@jsmith.mail)
144 end
144 end
145
145
146 def test_mail_notification_none
146 def test_mail_notification_none
147 @jsmith.mail_notification = false
147 @jsmith.mail_notification = false
148 @jsmith.notified_project_ids = []
148 @jsmith.notified_project_ids = []
149 @jsmith.save
149 @jsmith.save
150 @jsmith.reload
150 @jsmith.reload
151 assert !@jsmith.projects.first.recipients.include?(@jsmith.mail)
151 assert !@jsmith.projects.first.recipients.include?(@jsmith.mail)
152 end
152 end
153
153
154 def test_comments_sorting_preference
154 def test_comments_sorting_preference
155 assert !@jsmith.wants_comments_in_reverse_order?
155 assert !@jsmith.wants_comments_in_reverse_order?
156 @jsmith.pref.comments_sorting = 'asc'
156 @jsmith.pref.comments_sorting = 'asc'
157 assert !@jsmith.wants_comments_in_reverse_order?
157 assert !@jsmith.wants_comments_in_reverse_order?
158 @jsmith.pref.comments_sorting = 'desc'
158 @jsmith.pref.comments_sorting = 'desc'
159 assert @jsmith.wants_comments_in_reverse_order?
159 assert @jsmith.wants_comments_in_reverse_order?
160 end
160 end
161
162 def test_find_by_mail_should_be_case_insensitive
163 u = User.find_by_mail('JSmith@somenet.foo')
164 assert_not_nil u
165 assert_equal 'jsmith@somenet.foo', u.mail
166 end
161 end
167 end
General Comments 0
You need to be logged in to leave comments. Login now