##// END OF EJS Templates
tagged version 0.8.1...
tagged version 0.8.1 git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/tags/0.8.1@2471 e93f8b46-1217-0410-a6f0-8f06a7374b81

File last commit:

r2144:7389b4bed0ca
r2410:ed6151b4d2ff 0.8.1
Show More
user.rb
294 lines | 9.3 KiB | text/x-ruby | RubyLexer
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 # redMine - project management software
# Copyright (C) 2006-2007 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require "digest/sha1"
class User < ActiveRecord::Base
Jean-Philippe Lang
Better error message and AR errors in log for failed LDAP on-the-fly user creation (closes #932, #1042)....
r1330
Jean-Philippe Lang
User's projects alphabetically sorted in the Projects drop down menu....
r535 # Account statuses
Jean-Philippe Lang
Anonymous users can now be allowed to create, edit, comment issues, comment news and post messages in the forums....
r906 STATUS_ANONYMOUS = 0
Jean-Philippe Lang
User's projects alphabetically sorted in the Projects drop down menu....
r535 STATUS_ACTIVE = 1
STATUS_REGISTERED = 2
STATUS_LOCKED = 3
Jean-Philippe Lang
User display format is now configurable in administration settings....
r1089
USER_FORMATS = {
:firstname_lastname => '#{firstname} #{lastname}',
:firstname => '#{firstname}',
:lastname_firstname => '#{lastname} #{firstname}',
:lastname_coma_firstname => '#{lastname}, #{firstname}',
:username => '#{login}'
}
Jean-Philippe Lang
User's projects alphabetically sorted in the Projects drop down menu....
r535
Jean-Philippe Lang
Fixed: invalid SQL query on User#destroy (#1781)....
r1754 has_many :memberships, :class_name => 'Member', :include => [ :project, :role ], :conditions => "#{Project.table_name}.status=#{Project::STATUS_ACTIVE}", :order => "#{Project.table_name}.name"
has_many :members, :dependent => :delete_all
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 has_many :projects, :through => :memberships
Jean-Philippe Lang
Each category can now be associated to a user, so that new issues in that category are automatically assigned to that user....
r574 has_many :issue_categories, :foreign_key => 'assigned_to_id', :dependent => :nullify
Jean-Philippe Lang
Maps repository users to Redmine users (#1383)....
r2004 has_many :changesets, :dependent => :nullify
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 has_one :preference, :dependent => :destroy, :class_name => 'UserPreference'
Jean-Philippe Lang
Merged 0.6 branch into trunk....
r663 has_one :rss_token, :dependent => :destroy, :class_name => 'Token', :conditions => "action='feeds'"
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 belongs_to :auth_source
Jean-Philippe Lang
Replaces User.find_active with a named scope....
r2077 # Active non-anonymous users scope
named_scope :active, :conditions => "#{User.table_name}.status = #{STATUS_ACTIVE}"
Jean-Philippe Lang
Custom fields refactoring: most of code moved from controllers to models (using new module ActsAsCustomizable)....
r1578 acts_as_customizable
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 attr_accessor :password, :password_confirmation
attr_accessor :last_before_login_on
# Prevents unauthorized assignments
attr_protected :login, :admin, :password, :password_confirmation, :hashed_password
Jean-Philippe Lang
Anonymous users can now be allowed to create, edit, comment issues, comment news and post messages in the forums....
r906 validates_presence_of :login, :firstname, :lastname, :mail, :if => Proc.new { |user| !user.is_a?(AnonymousUser) }
Jean-Philippe Lang
Prevent 'has already been taken' error messages for user login and email if these fields are left empty....
r1029 validates_uniqueness_of :login, :if => Proc.new { |user| !user.login.blank? }
validates_uniqueness_of :mail, :if => Proc.new { |user| !user.mail.blank? }
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 # Login must contain lettres, numbers, underscores only
Jean-Philippe Lang
Anonymous users can now be allowed to create, edit, comment issues, comment news and post messages in the forums....
r906 validates_format_of :login, :with => /^[a-z0-9_\-@\.]*$/i
Jean-Philippe Lang
Added some attributes length validations....
r397 validates_length_of :login, :maximum => 30
Jean-Philippe Lang
Allow dot in firstnames and lastnames (closes #1426)....
r1547 validates_format_of :firstname, :lastname, :with => /^[\w\s\'\-\.]*$/i
Jean-Philippe Lang
Added some attributes length validations....
r397 validates_length_of :firstname, :lastname, :maximum => 30
Jean-Philippe Lang
Anonymous users can now be allowed to create, edit, comment issues, comment news and post messages in the forums....
r906 validates_format_of :mail, :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i, :allow_nil => true
validates_length_of :mail, :maximum => 60, :allow_nil => true
Jean-Philippe Lang
Removed the 12 characters limit on passwords....
r914 validates_length_of :password, :minimum => 4, :allow_nil => true
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 validates_confirmation_of :password, :allow_nil => true
Jean-Philippe Lang
More flexible mail notifications settings at user level. A user has now 3 options:...
r842 def before_create
self.mail_notification = false
true
end
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 def before_save
# update hashed_password if password was set
self.hashed_password = User.hash_password(self.password) if self.password
end
Jean-Philippe Lang
Sort users by their display names so that user dropdown lists are sorted alphabetically (#2015)....
r2008
def reload(*args)
@name = nil
super
end
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330
# Returns the user that matches provided login and password, or nil
def self.try_to_login(login, password)
Jean-Philippe Lang
Prevent LDAP authentication with empty password related problems....
r1217 # Make sure no one can sign in with an empty password
return nil if password.to_s.empty?
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 user = find(:first, :conditions => ["login=?", login])
if user
# user is already in local database
return nil if !user.active?
if user.auth_source
# user has an external authentication method
return nil unless user.auth_source.authenticate(login, password)
else
# authentication with local password
return nil unless User.hash_password(password) == user.hashed_password
end
else
# user is not yet registered, try to authenticate with available sources
attrs = AuthSource.authenticate(login, password)
if attrs
Jean-Philippe Lang
Improved on-the-fly account creation. If some attributes are missing (eg. not present in the LDAP) or are invalid, the registration form is displayed so that the user is able to fill or fix these attributes....
r1661 user = new(*attrs)
user.login = login
user.language = Setting.default_language
if user.save
user.reload
Jean-Philippe Lang
Better error message and AR errors in log for failed LDAP on-the-fly user creation (closes #932, #1042)....
r1330 logger.info("User '#{user.login}' created from the LDAP") if logger
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 end
end
end
Jean-Philippe Lang
Improved on-the-fly account creation. If some attributes are missing (eg. not present in the LDAP) or are invalid, the registration form is displayed so that the user is able to fill or fix these attributes....
r1661 user.update_attribute(:last_login_on, Time.now) if user && !user.new_record?
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 user
Jean-Philippe Lang
Better error message and AR errors in log for failed LDAP on-the-fly user creation (closes #932, #1042)....
r1330 rescue => text
raise text
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 end
# Return user's full name for display
Jean-Philippe Lang
User display format is now configurable in administration settings....
r1089 def name(formatter = nil)
Jean-Philippe Lang
Fixes #2170: user display format in application settings broken by r2010....
r2029 if formatter
eval('"' + (USER_FORMATS[formatter] || USER_FORMATS[:firstname_lastname]) + '"')
else
@name ||= eval('"' + (USER_FORMATS[Setting.user_format] || USER_FORMATS[:firstname_lastname]) + '"')
end
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 end
def active?
self.status == STATUS_ACTIVE
end
def registered?
self.status == STATUS_REGISTERED
end
def locked?
self.status == STATUS_LOCKED
end
def check_password?(clear_password)
User.hash_password(clear_password) == self.hashed_password
end
def pref
self.preference ||= UserPreference.new(:user => self)
end
Jean-Philippe Lang
added rss/atom feeds at project levels for:...
r336
Jean-Philippe Lang
* Added time zone support: users can select their time zone on their account view....
r904 def time_zone
Jean-Philippe Lang
Merged r2109, r2118, r2130, r2131, r2134, r2135, r2136 and r2139 to r2145 from trunk....
r2144 @time_zone ||= (self.pref.time_zone.blank? ? nil : ActiveSupport::TimeZone[self.pref.time_zone])
Jean-Philippe Lang
* Added time zone support: users can select their time zone on their account view....
r904 end
Jean-Philippe Lang
Add a user preference to choose how comments/replies are displayed: in chronological or reverse chronological order (#589, #776)....
r1183 def wants_comments_in_reverse_order?
self.pref[:comments_sorting] == 'desc'
end
Jean-Philippe Lang
Merged 0.6 branch into trunk....
r663 # Return user's RSS key (a 40 chars long string), used to access feeds
def rss_key
token = self.rss_token || Token.create(:user => self, :action => 'feeds')
token.value
Jean-Philippe Lang
added rss/atom feeds at project levels for:...
r336 end
Jean-Philippe Lang
More flexible mail notifications settings at user level. A user has now 3 options:...
r842 # Return an array of project ids for which the user has explicitly turned mail notifications on
def notified_projects_ids
@notified_projects_ids ||= memberships.select {|m| m.mail_notification?}.collect(&:project_id)
end
def notified_project_ids=(ids)
Member.update_all("mail_notification = #{connection.quoted_false}", ['user_id = ?', id])
Member.update_all("mail_notification = #{connection.quoted_true}", ['user_id = ? AND project_id IN (?)', id, ids]) if ids && !ids.empty?
@notified_projects_ids = nil
notified_projects_ids
end
Jean-Philippe Lang
added rss/atom feeds at project levels for:...
r336 def self.find_by_rss_key(key)
token = Token.find_by_value(key)
token && token.user.active? ? token.user : nil
end
Jean-Philippe Lang
Added autologin feature (disabled by default)....
r511
def self.find_by_autologin_key(key)
token = Token.find_by_action_and_value('autologin', key)
token && (token.created_on > Setting.autologin.to_i.day.ago) && token.user.active? ? token.user : nil
end
Jean-Philippe Lang
Merged r2119 to r2127 from trunk....
r2131
# Makes find_by_mail case-insensitive
def self.find_by_mail(mail)
find(:first, :conditions => ["LOWER(mail) = ?", mail.to_s.downcase])
end
Jean-Philippe Lang
Various changes on views. On project summary, members are now grouped by role and subprojects are listed inline....
r431
Jean-Philippe Lang
Sort users by their display names so that user dropdown lists are sorted alphabetically (#2015)....
r2008 # Sort users by their display names
Jean-Philippe Lang
Various changes on views. On project summary, members are now grouped by role and subprojects are listed inline....
r431 def <=>(user)
Jean-Philippe Lang
Sort users by their display names so that user dropdown lists are sorted alphabetically (#2015)....
r2008 self.to_s.downcase <=> user.to_s.downcase
Jean-Philippe Lang
Various changes on views. On project summary, members are now grouped by role and subprojects are listed inline....
r431 end
Jean-Philippe Lang
Merged 0.6 branch into trunk....
r663 def to_s
name
end
def logged?
true
end
Jean-Philippe Lang
Adds links to the user page on various views....
r1657 def anonymous?
!logged?
end
Jean-Philippe Lang
Merged 0.6 branch into trunk....
r663 # Return user's role for project
def role_for_project(project)
# No role on archived projects
return nil unless project && project.active?
Jean-Philippe Lang
Slight optimization in User#role_for_project....
r915 if logged?
# Find project membership
membership = memberships.detect {|m| m.project_id == project.id}
if membership
membership.role
else
@role_non_member ||= Role.non_member
end
Jean-Philippe Lang
Merged 0.6 branch into trunk....
r663 else
Jean-Philippe Lang
Slight optimization in User#role_for_project....
r915 @role_anonymous ||= Role.anonymous
Jean-Philippe Lang
Merged 0.6 branch into trunk....
r663 end
end
# Return true if the user is a member of project
def member_of?(project)
role_for_project(project).member?
end
# Return true if the user is allowed to do the specified action on project
# action can be:
# * a parameter-like Hash (eg. :controller => 'projects', :action => 'edit')
# * a permission Symbol (eg. :edit_project)
Jean-Philippe Lang
Global queries can be saved from the global issue list (follows r1311 and closes #897)....
r1297 def allowed_to?(action, project, options={})
if project
# No action allowed on archived projects
return false unless project.active?
# No action allowed on disabled modules
return false unless project.allows_to?(action)
# Admin users are authorized for anything else
return true if admin?
role = role_for_project(project)
return false unless role
role.allowed_to?(action) && (project.is_public? || role.member?)
elsif options[:global]
# authorize if user has at least one role that has this permission
roles = memberships.collect {|m| m.role}.uniq
Jean-Philippe Lang
Adds cross-project time reports support (#994)....
r1777 roles.detect {|r| r.allowed_to?(action)} || (self.logged? ? Role.non_member.allowed_to?(action) : Role.anonymous.allowed_to?(action))
Jean-Philippe Lang
Global queries can be saved from the global issue list (follows r1311 and closes #897)....
r1297 else
false
end
Jean-Philippe Lang
Merged 0.6 branch into trunk....
r663 end
def self.current=(user)
@current_user = user
end
def self.current
Jean-Philippe Lang
Anonymous users can now be allowed to create, edit, comment issues, comment news and post messages in the forums....
r906 @current_user ||= User.anonymous
Jean-Philippe Lang
Merged 0.6 branch into trunk....
r663 end
def self.anonymous
Jean-Philippe Lang
Anonymous users can now be allowed to create, edit, comment issues, comment news and post messages in the forums....
r906 anonymous_user = AnonymousUser.find(:first)
if anonymous_user.nil?
anonymous_user = AnonymousUser.create(:lastname => 'Anonymous', :firstname => '', :mail => '', :login => '', :status => 0)
raise 'Unable to create the anonymous user.' if anonymous_user.new_record?
end
Jean-Philippe Lang
Fixed: non member or anonymous permissions change is effective only after an application restart (#1280)....
r1429 anonymous_user
Jean-Philippe Lang
Merged 0.6 branch into trunk....
r663 end
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 private
# Return password digest
def self.hash_password(clear_password)
Digest::SHA1.hexdigest(clear_password || "")
Jean-Philippe Lang
v0.2.0...
r5 end
Jean-Philippe Lang
Initial commit...
r2 end
Jean-Philippe Lang
Merged 0.6 branch into trunk....
r663
class AnonymousUser < User
Jean-Philippe Lang
Anonymous users can now be allowed to create, edit, comment issues, comment news and post messages in the forums....
r906 def validate_on_create
# There should be only one AnonymousUser in the database
errors.add_to_base 'An anonymous user already exists.' if AnonymousUser.find(:first)
Jean-Philippe Lang
* Added time zone support: users can select their time zone on their account view....
r904 end
Jean-Philippe Lang
Custom fields refactoring: most of code moved from controllers to models (using new module ActsAsCustomizable)....
r1578 def available_custom_fields
[]
end
Jean-Philippe Lang
Anonymous users can now be allowed to create, edit, comment issues, comment news and post messages in the forums....
r906 # Overrides a few properties
def logged?; false end
def admin; false end
def name; 'Anonymous' end
def mail; nil end
def time_zone; nil end
def rss_key; nil end
Jean-Philippe Lang
Merged 0.6 branch into trunk....
r663 end