##// END OF EJS Templates
remove trailing white-spaces from app/models/user.rb....
Toshi MARUYAMA -
r6387:e86f9711b9eb
parent child
Show More
@@ -5,12 +5,12
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.
@@ -19,13 +19,13 require "digest/sha1"
19
19
20 class User < Principal
20 class User < Principal
21 include Redmine::SafeAttributes
21 include Redmine::SafeAttributes
22
22
23 # Account statuses
23 # Account statuses
24 STATUS_ANONYMOUS = 0
24 STATUS_ANONYMOUS = 0
25 STATUS_ACTIVE = 1
25 STATUS_ACTIVE = 1
26 STATUS_REGISTERED = 2
26 STATUS_REGISTERED = 2
27 STATUS_LOCKED = 3
27 STATUS_LOCKED = 3
28
28
29 USER_FORMATS = {
29 USER_FORMATS = {
30 :firstname_lastname => '#{firstname} #{lastname}',
30 :firstname_lastname => '#{firstname} #{lastname}',
31 :firstname => '#{firstname}',
31 :firstname => '#{firstname}',
@@ -50,12 +50,12 class User < Principal
50 has_one :rss_token, :class_name => 'Token', :conditions => "action='feeds'"
50 has_one :rss_token, :class_name => 'Token', :conditions => "action='feeds'"
51 has_one :api_token, :class_name => 'Token', :conditions => "action='api'"
51 has_one :api_token, :class_name => 'Token', :conditions => "action='api'"
52 belongs_to :auth_source
52 belongs_to :auth_source
53
53
54 # Active non-anonymous users scope
54 # Active non-anonymous users scope
55 named_scope :active, :conditions => "#{User.table_name}.status = #{STATUS_ACTIVE}"
55 named_scope :active, :conditions => "#{User.table_name}.status = #{STATUS_ACTIVE}"
56
56
57 acts_as_customizable
57 acts_as_customizable
58
58
59 attr_accessor :password, :password_confirmation
59 attr_accessor :password, :password_confirmation
60 attr_accessor :last_before_login_on
60 attr_accessor :last_before_login_on
61 # Prevents unauthorized assignments
61 # Prevents unauthorized assignments
@@ -74,7 +74,7 class User < Principal
74 validates_inclusion_of :mail_notification, :in => MAIL_NOTIFICATION_OPTIONS.collect(&:first), :allow_blank => true
74 validates_inclusion_of :mail_notification, :in => MAIL_NOTIFICATION_OPTIONS.collect(&:first), :allow_blank => true
75
75
76 before_destroy :remove_references_before_destroy
76 before_destroy :remove_references_before_destroy
77
77
78 named_scope :in_group, lambda {|group|
78 named_scope :in_group, lambda {|group|
79 group_id = group.is_a?(Group) ? group.id : group.to_i
79 group_id = group.is_a?(Group) ? group.id : group.to_i
80 { :conditions => ["#{User.table_name}.id IN (SELECT gu.user_id FROM #{table_name_prefix}groups_users#{table_name_suffix} gu WHERE gu.group_id = ?)", group_id] }
80 { :conditions => ["#{User.table_name}.id IN (SELECT gu.user_id FROM #{table_name_prefix}groups_users#{table_name_suffix} gu WHERE gu.group_id = ?)", group_id] }
@@ -83,29 +83,29 class User < Principal
83 group_id = group.is_a?(Group) ? group.id : group.to_i
83 group_id = group.is_a?(Group) ? group.id : group.to_i
84 { :conditions => ["#{User.table_name}.id NOT IN (SELECT gu.user_id FROM #{table_name_prefix}groups_users#{table_name_suffix} gu WHERE gu.group_id = ?)", group_id] }
84 { :conditions => ["#{User.table_name}.id NOT IN (SELECT gu.user_id FROM #{table_name_prefix}groups_users#{table_name_suffix} gu WHERE gu.group_id = ?)", group_id] }
85 }
85 }
86
86
87 def before_create
87 def before_create
88 self.mail_notification = Setting.default_notification_option if self.mail_notification.blank?
88 self.mail_notification = Setting.default_notification_option if self.mail_notification.blank?
89 true
89 true
90 end
90 end
91
91
92 def before_save
92 def before_save
93 # update hashed_password if password was set
93 # update hashed_password if password was set
94 if self.password && self.auth_source_id.blank?
94 if self.password && self.auth_source_id.blank?
95 salt_password(password)
95 salt_password(password)
96 end
96 end
97 end
97 end
98
98
99 def reload(*args)
99 def reload(*args)
100 @name = nil
100 @name = nil
101 @projects_by_role = nil
101 @projects_by_role = nil
102 super
102 super
103 end
103 end
104
104
105 def mail=(arg)
105 def mail=(arg)
106 write_attribute(:mail, arg.to_s.strip)
106 write_attribute(:mail, arg.to_s.strip)
107 end
107 end
108
108
109 def identity_url=(url)
109 def identity_url=(url)
110 if url.blank?
110 if url.blank?
111 write_attribute(:identity_url, '')
111 write_attribute(:identity_url, '')
@@ -118,7 +118,7 class User < Principal
118 end
118 end
119 self.read_attribute(:identity_url)
119 self.read_attribute(:identity_url)
120 end
120 end
121
121
122 # Returns the user that matches provided login and password, or nil
122 # Returns the user that matches provided login and password, or nil
123 def self.try_to_login(login, password)
123 def self.try_to_login(login, password)
124 # Make sure no one can sign in with an empty password
124 # Make sure no one can sign in with an empty password
@@ -146,13 +146,13 class User < Principal
146 logger.info("User '#{user.login}' created from external auth source: #{user.auth_source.type} - #{user.auth_source.name}") if logger && user.auth_source
146 logger.info("User '#{user.login}' created from external auth source: #{user.auth_source.type} - #{user.auth_source.name}") if logger && user.auth_source
147 end
147 end
148 end
148 end
149 end
149 end
150 user.update_attribute(:last_login_on, Time.now) if user && !user.new_record?
150 user.update_attribute(:last_login_on, Time.now) if user && !user.new_record?
151 user
151 user
152 rescue => text
152 rescue => text
153 raise text
153 raise text
154 end
154 end
155
155
156 # Returns the user who matches the given autologin +key+ or nil
156 # Returns the user who matches the given autologin +key+ or nil
157 def self.try_to_autologin(key)
157 def self.try_to_autologin(key)
158 tokens = Token.find_all_by_action_and_value('autologin', key)
158 tokens = Token.find_all_by_action_and_value('autologin', key)
@@ -174,7 +174,7 class User < Principal
174 @name ||= eval('"' + (USER_FORMATS[Setting.user_format] || USER_FORMATS[:firstname_lastname]) + '"')
174 @name ||= eval('"' + (USER_FORMATS[Setting.user_format] || USER_FORMATS[:firstname_lastname]) + '"')
175 end
175 end
176 end
176 end
177
177
178 def active?
178 def active?
179 self.status == STATUS_ACTIVE
179 self.status == STATUS_ACTIVE
180 end
180 end
@@ -182,7 +182,7 class User < Principal
182 def registered?
182 def registered?
183 self.status == STATUS_REGISTERED
183 self.status == STATUS_REGISTERED
184 end
184 end
185
185
186 def locked?
186 def locked?
187 self.status == STATUS_LOCKED
187 self.status == STATUS_LOCKED
188 end
188 end
@@ -219,7 +219,7 class User < Principal
219 User.hash_password("#{salt}#{User.hash_password clear_password}") == hashed_password
219 User.hash_password("#{salt}#{User.hash_password clear_password}") == hashed_password
220 end
220 end
221 end
221 end
222
222
223 # Generates a random salt and computes hashed_password for +clear_password+
223 # Generates a random salt and computes hashed_password for +clear_password+
224 # The hashed password is stored in the following form: SHA1(salt + SHA1(password))
224 # The hashed password is stored in the following form: SHA1(salt + SHA1(password))
225 def salt_password(clear_password)
225 def salt_password(clear_password)
@@ -244,19 +244,19 class User < Principal
244 self.password_confirmation = password
244 self.password_confirmation = password
245 self
245 self
246 end
246 end
247
247
248 def pref
248 def pref
249 self.preference ||= UserPreference.new(:user => self)
249 self.preference ||= UserPreference.new(:user => self)
250 end
250 end
251
251
252 def time_zone
252 def time_zone
253 @time_zone ||= (self.pref.time_zone.blank? ? nil : ActiveSupport::TimeZone[self.pref.time_zone])
253 @time_zone ||= (self.pref.time_zone.blank? ? nil : ActiveSupport::TimeZone[self.pref.time_zone])
254 end
254 end
255
255
256 def wants_comments_in_reverse_order?
256 def wants_comments_in_reverse_order?
257 self.pref[:comments_sorting] == 'desc'
257 self.pref[:comments_sorting] == 'desc'
258 end
258 end
259
259
260 # Return user's RSS key (a 40 chars long string), used to access feeds
260 # Return user's RSS key (a 40 chars long string), used to access feeds
261 def rss_key
261 def rss_key
262 token = self.rss_token || Token.create(:user => self, :action => 'feeds')
262 token = self.rss_token || Token.create(:user => self, :action => 'feeds')
@@ -268,12 +268,12 class User < Principal
268 token = self.api_token || self.create_api_token(:action => 'api')
268 token = self.api_token || self.create_api_token(:action => 'api')
269 token.value
269 token.value
270 end
270 end
271
271
272 # Return an array of project ids for which the user has explicitly turned mail notifications on
272 # Return an array of project ids for which the user has explicitly turned mail notifications on
273 def notified_projects_ids
273 def notified_projects_ids
274 @notified_projects_ids ||= memberships.select {|m| m.mail_notification?}.collect(&:project_id)
274 @notified_projects_ids ||= memberships.select {|m| m.mail_notification?}.collect(&:project_id)
275 end
275 end
276
276
277 def notified_project_ids=(ids)
277 def notified_project_ids=(ids)
278 Member.update_all("mail_notification = #{connection.quoted_false}", ['user_id = ?', id])
278 Member.update_all("mail_notification = #{connection.quoted_false}", ['user_id = ?', id])
279 Member.update_all("mail_notification = #{connection.quoted_true}", ['user_id = ? AND project_id IN (?)', id, ids]) if ids && !ids.empty?
279 Member.update_all("mail_notification = #{connection.quoted_true}", ['user_id = ? AND project_id IN (?)', id, ids]) if ids && !ids.empty?
@@ -301,7 +301,7 class User < Principal
301 def self.find_by_login(login)
301 def self.find_by_login(login)
302 # force string comparison to be case sensitive on MySQL
302 # force string comparison to be case sensitive on MySQL
303 type_cast = (ActiveRecord::Base.connection.adapter_name == 'MySQL') ? 'BINARY' : ''
303 type_cast = (ActiveRecord::Base.connection.adapter_name == 'MySQL') ? 'BINARY' : ''
304
304
305 # First look for an exact match
305 # First look for an exact match
306 user = first(:conditions => ["#{type_cast} login = ?", login])
306 user = first(:conditions => ["#{type_cast} login = ?", login])
307 # Fail over to case-insensitive if none was found
307 # Fail over to case-insensitive if none was found
@@ -312,21 +312,21 class User < Principal
312 token = Token.find_by_value(key)
312 token = Token.find_by_value(key)
313 token && token.user.active? ? token.user : nil
313 token && token.user.active? ? token.user : nil
314 end
314 end
315
315
316 def self.find_by_api_key(key)
316 def self.find_by_api_key(key)
317 token = Token.find_by_action_and_value('api', key)
317 token = Token.find_by_action_and_value('api', key)
318 token && token.user.active? ? token.user : nil
318 token && token.user.active? ? token.user : nil
319 end
319 end
320
320
321 # Makes find_by_mail case-insensitive
321 # Makes find_by_mail case-insensitive
322 def self.find_by_mail(mail)
322 def self.find_by_mail(mail)
323 find(:first, :conditions => ["LOWER(mail) = ?", mail.to_s.downcase])
323 find(:first, :conditions => ["LOWER(mail) = ?", mail.to_s.downcase])
324 end
324 end
325
325
326 def to_s
326 def to_s
327 name
327 name
328 end
328 end
329
329
330 # Returns the current day according to user's time zone
330 # Returns the current day according to user's time zone
331 def today
331 def today
332 if time_zone.nil?
332 if time_zone.nil?
@@ -335,15 +335,15 class User < Principal
335 Time.now.in_time_zone(time_zone).to_date
335 Time.now.in_time_zone(time_zone).to_date
336 end
336 end
337 end
337 end
338
338
339 def logged?
339 def logged?
340 true
340 true
341 end
341 end
342
342
343 def anonymous?
343 def anonymous?
344 !logged?
344 !logged?
345 end
345 end
346
346
347 # Return user's roles for project
347 # Return user's roles for project
348 def roles_for_project(project)
348 def roles_for_project(project)
349 roles = []
349 roles = []
@@ -364,16 +364,16 class User < Principal
364 end
364 end
365 roles
365 roles
366 end
366 end
367
367
368 # Return true if the user is a member of project
368 # Return true if the user is a member of project
369 def member_of?(project)
369 def member_of?(project)
370 !roles_for_project(project).detect {|role| role.member?}.nil?
370 !roles_for_project(project).detect {|role| role.member?}.nil?
371 end
371 end
372
372
373 # Returns a hash of user's projects grouped by roles
373 # Returns a hash of user's projects grouped by roles
374 def projects_by_role
374 def projects_by_role
375 return @projects_by_role if @projects_by_role
375 return @projects_by_role if @projects_by_role
376
376
377 @projects_by_role = Hash.new {|h,k| h[k]=[]}
377 @projects_by_role = Hash.new {|h,k| h[k]=[]}
378 memberships.each do |membership|
378 memberships.each do |membership|
379 membership.roles.each do |role|
379 membership.roles.each do |role|
@@ -383,10 +383,10 class User < Principal
383 @projects_by_role.each do |role, projects|
383 @projects_by_role.each do |role, projects|
384 projects.uniq!
384 projects.uniq!
385 end
385 end
386
386
387 @projects_by_role
387 @projects_by_role
388 end
388 end
389
389
390 # Returns true if user is arg or belongs to arg
390 # Returns true if user is arg or belongs to arg
391 def is_or_belongs_to?(arg)
391 def is_or_belongs_to?(arg)
392 if arg.is_a?(User)
392 if arg.is_a?(User)
@@ -397,7 +397,7 class User < Principal
397 false
397 false
398 end
398 end
399 end
399 end
400
400
401 # Return true if the user is allowed to do the specified action on a specific context
401 # Return true if the user is allowed to do the specified action on a specific context
402 # Action can be:
402 # Action can be:
403 # * a parameter-like Hash (eg. :controller => 'projects', :action => 'edit')
403 # * a parameter-like Hash (eg. :controller => 'projects', :action => 'edit')
@@ -405,7 +405,7 class User < Principal
405 # Context can be:
405 # Context can be:
406 # * a project : returns true if user is allowed to do the specified action on this project
406 # * a project : returns true if user is allowed to do the specified action on this project
407 # * an array of projects : returns true if user is allowed on every project
407 # * an array of projects : returns true if user is allowed on every project
408 # * nil with options[:global] set : check if user has at least one role allowed for this action,
408 # * nil with options[:global] set : check if user has at least one role allowed for this action,
409 # or falls back to Non Member / Anonymous permissions depending if the user is logged
409 # or falls back to Non Member / Anonymous permissions depending if the user is logged
410 def allowed_to?(action, context, options={}, &block)
410 def allowed_to?(action, context, options={}, &block)
411 if context && context.is_a?(Project)
411 if context && context.is_a?(Project)
@@ -415,7 +415,7 class User < Principal
415 return false unless context.allows_to?(action)
415 return false unless context.allows_to?(action)
416 # Admin users are authorized for anything else
416 # Admin users are authorized for anything else
417 return true if admin?
417 return true if admin?
418
418
419 roles = roles_for_project(context)
419 roles = roles_for_project(context)
420 return false unless roles
420 return false unless roles
421 roles.detect {|role|
421 roles.detect {|role|
@@ -433,7 +433,7 class User < Principal
433 elsif options[:global]
433 elsif options[:global]
434 # Admin users are always authorized
434 # Admin users are always authorized
435 return true if admin?
435 return true if admin?
436
436
437 # authorize if user has at least one role that has this permission
437 # authorize if user has at least one role that has this permission
438 roles = memberships.collect {|m| m.roles}.flatten.uniq
438 roles = memberships.collect {|m| m.roles}.flatten.uniq
439 roles << (self.logged? ? Role.non_member : Role.anonymous)
439 roles << (self.logged? ? Role.non_member : Role.anonymous)
@@ -461,14 +461,14 class User < Principal
461 'custom_field_values',
461 'custom_field_values',
462 'custom_fields',
462 'custom_fields',
463 'identity_url'
463 'identity_url'
464
464
465 safe_attributes 'status',
465 safe_attributes 'status',
466 'auth_source_id',
466 'auth_source_id',
467 :if => lambda {|user, current_user| current_user.admin?}
467 :if => lambda {|user, current_user| current_user.admin?}
468
468
469 safe_attributes 'group_ids',
469 safe_attributes 'group_ids',
470 :if => lambda {|user, current_user| current_user.admin? && !user.new_record?}
470 :if => lambda {|user, current_user| current_user.admin? && !user.new_record?}
471
471
472 # Utility method to help check if a user should be notified about an
472 # Utility method to help check if a user should be notified about an
473 # event.
473 # event.
474 #
474 #
@@ -508,15 +508,15 class User < Principal
508 false
508 false
509 end
509 end
510 end
510 end
511
511
512 def self.current=(user)
512 def self.current=(user)
513 @current_user = user
513 @current_user = user
514 end
514 end
515
515
516 def self.current
516 def self.current
517 @current_user ||= User.anonymous
517 @current_user ||= User.anonymous
518 end
518 end
519
519
520 # Returns the anonymous user. If the anonymous user does not exist, it is created. There can be only
520 # Returns the anonymous user. If the anonymous user does not exist, it is created. There can be only
521 # one anonymous user per database.
521 # one anonymous user per database.
522 def self.anonymous
522 def self.anonymous
@@ -541,23 +541,23 class User < Principal
541 end
541 end
542 end
542 end
543 end
543 end
544
544
545 protected
545 protected
546
546
547 def validate
547 def validate
548 # Password length validation based on setting
548 # Password length validation based on setting
549 if !password.nil? && password.size < Setting.password_min_length.to_i
549 if !password.nil? && password.size < Setting.password_min_length.to_i
550 errors.add(:password, :too_short, :count => Setting.password_min_length.to_i)
550 errors.add(:password, :too_short, :count => Setting.password_min_length.to_i)
551 end
551 end
552 end
552 end
553
553
554 private
554 private
555
555
556 # Removes references that are not handled by associations
556 # Removes references that are not handled by associations
557 # Things that are not deleted are reassociated with the anonymous user
557 # Things that are not deleted are reassociated with the anonymous user
558 def remove_references_before_destroy
558 def remove_references_before_destroy
559 return if self.id.nil?
559 return if self.id.nil?
560
560
561 substitute = User.anonymous
561 substitute = User.anonymous
562 Attachment.update_all ['author_id = ?', substitute.id], ['author_id = ?', id]
562 Attachment.update_all ['author_id = ?', substitute.id], ['author_id = ?', id]
563 Comment.update_all ['author_id = ?', substitute.id], ['author_id = ?', id]
563 Comment.update_all ['author_id = ?', substitute.id], ['author_id = ?', id]
@@ -577,30 +577,30 class User < Principal
577 WikiContent.update_all ['author_id = ?', substitute.id], ['author_id = ?', id]
577 WikiContent.update_all ['author_id = ?', substitute.id], ['author_id = ?', id]
578 WikiContent::Version.update_all ['author_id = ?', substitute.id], ['author_id = ?', id]
578 WikiContent::Version.update_all ['author_id = ?', substitute.id], ['author_id = ?', id]
579 end
579 end
580
580
581 # Return password digest
581 # Return password digest
582 def self.hash_password(clear_password)
582 def self.hash_password(clear_password)
583 Digest::SHA1.hexdigest(clear_password || "")
583 Digest::SHA1.hexdigest(clear_password || "")
584 end
584 end
585
585
586 # Returns a 128bits random salt as a hex string (32 chars long)
586 # Returns a 128bits random salt as a hex string (32 chars long)
587 def self.generate_salt
587 def self.generate_salt
588 ActiveSupport::SecureRandom.hex(16)
588 ActiveSupport::SecureRandom.hex(16)
589 end
589 end
590
590
591 end
591 end
592
592
593 class AnonymousUser < User
593 class AnonymousUser < User
594
594
595 def validate_on_create
595 def validate_on_create
596 # There should be only one AnonymousUser in the database
596 # There should be only one AnonymousUser in the database
597 errors.add_to_base 'An anonymous user already exists.' if AnonymousUser.find(:first)
597 errors.add_to_base 'An anonymous user already exists.' if AnonymousUser.find(:first)
598 end
598 end
599
599
600 def available_custom_fields
600 def available_custom_fields
601 []
601 []
602 end
602 end
603
603
604 # Overrides a few properties
604 # Overrides a few properties
605 def logged?; false end
605 def logged?; false end
606 def admin; false end
606 def admin; false end
@@ -608,7 +608,7 class AnonymousUser < User
608 def mail; nil end
608 def mail; nil end
609 def time_zone; nil end
609 def time_zone; nil end
610 def rss_key; nil end
610 def rss_key; nil end
611
611
612 # Anonymous user can not be destroyed
612 # Anonymous user can not be destroyed
613 def destroy
613 def destroy
614 false
614 false
General Comments 0
You need to be logged in to leave comments. Login now