##// END OF EJS Templates
scm: recovery showing "root @ branch" in repository tree viewing....
scm: recovery showing "root @ branch" in repository tree viewing. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5139 e93f8b46-1217-0410-a6f0-8f06a7374b81

File last commit:

r4816:ce84bb1a0194
r5019:b6dfa0b081d0
Show More
user.rb
572 lines | 18.7 KiB | text/x-ruby | RubyLexer
Jean-Philippe Lang
User groups branch merged....
r2755 # Redmine - project management software
# Copyright (C) 2006-2009 Jean-Philippe Lang
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 #
# 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"
Jean-Philippe Lang
User groups branch merged....
r2755 class User < Principal
Jean-Philippe Lang
Declare safe attributes for User and Projects models....
r4378 include Redmine::SafeAttributes
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
Eric Davis
Converted User#mail_notification from a boolean to a string....
r4102 MAIL_NOTIFICATION_OPTIONS = [
Jean-Philippe Lang
Validates user's mail_notification and turn options into strings (the attribute type)....
r4380 ['all', :label_user_mail_option_all],
['selected', :label_user_mail_option_selected],
['only_my_events', :label_user_mail_option_only_my_events],
['only_assigned', :label_user_mail_option_only_assigned],
['only_owner', :label_user_mail_option_only_owner],
['none', :label_user_mail_option_none]
]
Eric Davis
Converted User#mail_notification from a boolean to a string....
r4102
Jean-Philippe Lang
User groups branch merged....
r2755 has_and_belongs_to_many :groups, :after_add => Proc.new {|user, group| group.user_added(user)},
:after_remove => Proc.new {|user, group| group.user_removed(user)}
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
When destroying a user, remove all references to that user (#7296)....
r4606 has_one :rss_token, :class_name => 'Token', :conditions => "action='feeds'"
has_one :api_token, :class_name => 'Token', :conditions => "action='api'"
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
Jean-Philippe Lang
Extracts user groups assignment from controller....
r4385 attr_protected :login, :admin, :password, :password_confirmation, :hashed_password
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330
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) }
Eric Davis
Change User#login to be case-insensitive. #2473...
r3693 validates_uniqueness_of :login, :if => Proc.new { |user| !user.login.blank? }, :case_sensitive => false
Jean-Philippe Lang
Makes email adress uniqueness case-insensitive (#2473)....
r2251 validates_uniqueness_of :mail, :if => Proc.new { |user| !user.mail.blank? }, :case_sensitive => false
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
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
added svn:eol-style native property on /app files...
r330 validates_confirmation_of :password, :allow_nil => true
Jean-Philippe Lang
Validates user's mail_notification and turn options into strings (the attribute type)....
r4380 validates_inclusion_of :mail_notification, :in => MAIL_NOTIFICATION_OPTIONS.collect(&:first), :allow_blank => true
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330
Jean-Philippe Lang
When destroying a user, remove all references to that user (#7296)....
r4606 before_destroy :remove_references_before_destroy
Jean-Philippe Lang
More flexible mail notifications settings at user level. A user has now 3 options:...
r842 def before_create
Eric Davis
Allow admins to edit user's email notifications and preferences. #3503...
r4109 self.mail_notification = Setting.default_notification_option if self.mail_notification.blank?
Jean-Philippe Lang
More flexible mail notifications settings at user level. A user has now 3 options:...
r842 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
Jean-Philippe Lang
Adds random salt to user passwords (#7410)....
r4816 if self.password && self.auth_source_id.blank?
salt_password(password)
end
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 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
Jean-Philippe Lang
Strips user email (#5834)....
r3759 def mail=(arg)
write_attribute(:mail, arg.to_s.strip)
end
Eric Davis
Normalize the identity_url when it's set....
r2392 def identity_url=(url)
Jean-Philippe Lang
Fixed: User#identity_url raises an error when invalid url is supplied (#2742)....
r2415 if url.blank?
write_attribute(:identity_url, '')
else
begin
write_attribute(:identity_url, OpenIdAuthentication.normalize_identifier(url))
rescue OpenIdAuthentication::InvalidOpenId
# Invlaid url, don't save
end
Eric Davis
Normalize the identity_url when it's set....
r2392 end
self.read_attribute(:identity_url)
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?
Eric Davis
Change User#login to be case-insensitive. #2473...
r3693 user = find_by_login(login)
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 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
Jean-Philippe Lang
Adds random salt to user passwords (#7410)....
r4816 return nil unless user.check_password?(password)
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 end
else
# user is not yet registered, try to authenticate with available sources
attrs = AuthSource.authenticate(login, password)
if attrs
Jean-Philippe Lang
Makes AuthSource.authenticate return a hash instead of an array....
r3378 user = new(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.login = login
user.language = Setting.default_language
if user.save
user.reload
Eric Davis
Allow AuthSources to control if they allow password changes....
r3631 logger.info("User '#{user.login}' created from external auth source: #{user.auth_source.type} - #{user.auth_source.name}") if logger && user.auth_source
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
Jean-Philippe Lang
Fixed: When logging in via an autologin cookie the user's last_login_on should be updated (#2820)....
r2460
# Returns the user who matches the given autologin +key+ or nil
def self.try_to_autologin(key)
Jean-Philippe Lang
Do not autologin if more that one token is found (#3351)....
r2643 tokens = Token.find_all_by_action_and_value('autologin', key)
# Make sure there's only 1 token that matches the key
if tokens.size == 1
token = tokens.first
if (token.created_on > Setting.autologin.to_i.day.ago) && token.user && token.user.active?
token.user.update_attribute(:last_login_on, Time.now)
token.user
end
Jean-Philippe Lang
Fixed: When logging in via an autologin cookie the user's last_login_on should be updated (#2820)....
r2460 end
end
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330
# 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
Eric Davis
Refactor: Add methods to User to edit the encapsulate the status field....
r3792 def activate
self.status = STATUS_ACTIVE
end
def register
self.status = STATUS_REGISTERED
end
def lock
self.status = STATUS_LOCKED
end
def activate!
update_attribute(:status, STATUS_ACTIVE)
end
def register!
update_attribute(:status, STATUS_REGISTERED)
end
def lock!
update_attribute(:status, STATUS_LOCKED)
end
Jean-Philippe Lang
Adds random salt to user passwords (#7410)....
r4816 # Returns true if +clear_password+ is the correct user's password, otherwise false
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 def check_password?(clear_password)
Eric Davis
Allow AuthSources to control if they allow password changes....
r3631 if auth_source_id.present?
auth_source.authenticate(self.login, clear_password)
else
Jean-Philippe Lang
Adds random salt to user passwords (#7410)....
r4816 User.hash_password("#{salt}#{User.hash_password clear_password}") == hashed_password
Eric Davis
Allow AuthSources to control if they allow password changes....
r3631 end
end
Jean-Philippe Lang
Adds random salt to user passwords (#7410)....
r4816
# Generates a random salt and computes hashed_password for +clear_password+
# The hashed password is stored in the following form: SHA1(salt + SHA1(password))
def salt_password(clear_password)
self.salt = User.generate_salt
self.hashed_password = User.hash_password("#{salt}#{User.hash_password clear_password}")
end
Eric Davis
Allow AuthSources to control if they allow password changes....
r3631
# Does the backend storage allow this user to change their password?
def change_password_allowed?
return true if auth_source_id.blank?
return auth_source.allow_password_changes?
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 end
Eric Davis
Hooked up on the fly OpenID user creation....
r2382
# Generate and set a random password. Useful for automated user creation
# Based on Token#generate_token_value
#
def random_password
chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
password = ''
40.times { |i| password << chars[rand(chars.size-1)] }
self.password = password
self.password_confirmation = password
self
end
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330
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
Rails 2.1.2 deprecations (#2332)....
r2132 @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
Eric Davis
Added an API token for each User to use when making API requests. (#3920)...
r3103
# Return user's API key (a 40 chars long string), used to access the API
def api_key
Eric Davis
Create and assign the api token so the current instance can access it. (#4497)...
r3151 token = self.api_token || self.create_api_token(:action => 'api')
Eric Davis
Added an API token for each User to use when making API requests. (#3920)...
r3103 token.value
end
Jean-Philippe Lang
added rss/atom feeds at project levels for:...
r336
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
Eric Davis
Refactor and documentation for User#find_by_login....
r3694
Eric Davis
Refactor: move method to model...
r4110 def valid_notification_options
Jean-Philippe Lang
Do not show "for only project I select" notification option on application settings form (#7294)....
r4610 self.class.valid_notification_options(self)
end
# Only users that belong to more than 1 project can select projects for which they are notified
def self.valid_notification_options(user=nil)
Eric Davis
Refactor: move method to model...
r4110 # Note that @user.membership.size would fail since AR ignores
# :include association option when doing a count
Jean-Philippe Lang
Do not show "for only project I select" notification option on application settings form (#7294)....
r4610 if user.nil? || user.memberships.length < 1
Jean-Philippe Lang
Fixed: "Notifiy for only project I select" is randomly displayed (#7294)....
r4607 MAIL_NOTIFICATION_OPTIONS.reject {|option| option.first == 'selected'}
Eric Davis
Refactor: move method to model...
r4110 else
MAIL_NOTIFICATION_OPTIONS
end
end
Eric Davis
Refactor and documentation for User#find_by_login....
r3694 # Find a user account by matching the exact login and then a case-insensitive
# version. Exact matches will be given priority.
Eric Davis
Change User#login to be case-insensitive. #2473...
r3693 def self.find_by_login(login)
Eric Davis
Force string comparison for login search to be case sensitive on MySQL. #2473...
r3699 # force string comparison to be case sensitive on MySQL
type_cast = (ActiveRecord::Base.connection.adapter_name == 'MySQL') ? 'BINARY' : ''
Eric Davis
Change User#login to be case-insensitive. #2473...
r3693 # First look for an exact match
Eric Davis
Force string comparison for login search to be case sensitive on MySQL. #2473...
r3699 user = first(:conditions => ["#{type_cast} login = ?", login])
Eric Davis
Change User#login to be case-insensitive. #2473...
r3693 # Fail over to case-insensitive if none was found
Eric Davis
Force string comparison for login search to be case sensitive on MySQL. #2473...
r3699 user ||= first(:conditions => ["#{type_cast} LOWER(login) = ?", login.to_s.downcase])
Eric Davis
Change User#login to be case-insensitive. #2473...
r3693 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
Eric Davis
Added an API token for each User to use when making API requests. (#3920)...
r3103 def self.find_by_api_key(key)
token = Token.find_by_action_and_value('api', key)
token && token.user.active? ? token.user : nil
end
Jean-Philippe Lang
Makes User.find_by_mail case-insensitive (password reminder #2322, repo users mapping)....
r2120 # 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
Merged 0.6 branch into trunk....
r663 def to_s
name
end
Jean-Philippe Lang
Fixed: Pre-filled time tracking date ignores timezone (#4160)....
r2898 # Returns the current day according to user's time zone
def today
if time_zone.nil?
Date.today
else
Time.now.in_time_zone(time_zone).to_date
end
end
Jean-Philippe Lang
Merged 0.6 branch into trunk....
r663 def logged?
true
end
Jean-Philippe Lang
Adds links to the user page on various views....
r1657 def anonymous?
!logged?
end
Jean-Philippe Lang
Allows multiple roles on the same project (#706). Prerequisite for user groups feature....
r2627 # Return user's roles for project
def roles_for_project(project)
roles = []
Jean-Philippe Lang
Merged 0.6 branch into trunk....
r663 # No role on archived projects
Jean-Philippe Lang
Allows multiple roles on the same project (#706). Prerequisite for user groups feature....
r2627 return roles 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
Jean-Philippe Lang
Allows multiple roles on the same project (#706). Prerequisite for user groups feature....
r2627 roles = membership.roles
Jean-Philippe Lang
Slight optimization in User#role_for_project....
r915 else
@role_non_member ||= Role.non_member
Jean-Philippe Lang
Allows multiple roles on the same project (#706). Prerequisite for user groups feature....
r2627 roles << @role_non_member
Jean-Philippe Lang
Slight optimization in User#role_for_project....
r915 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
Allows multiple roles on the same project (#706). Prerequisite for user groups feature....
r2627 roles << @role_anonymous
Jean-Philippe Lang
Merged 0.6 branch into trunk....
r663 end
Jean-Philippe Lang
Allows multiple roles on the same project (#706). Prerequisite for user groups feature....
r2627 roles
Jean-Philippe Lang
Merged 0.6 branch into trunk....
r663 end
# Return true if the user is a member of project
def member_of?(project)
Jean-Philippe Lang
Allows multiple roles on the same project (#706). Prerequisite for user groups feature....
r2627 !roles_for_project(project).detect {|role| role.member?}.nil?
Jean-Philippe Lang
Merged 0.6 branch into trunk....
r663 end
Jean-Baptiste Barth
Added ability to specify multiple projects in User#allowed_to? (#5332)...
r4113 # Return true if the user is allowed to do the specified action on a specific context
# Action can be:
Jean-Philippe Lang
Merged 0.6 branch into trunk....
r663 # * a parameter-like Hash (eg. :controller => 'projects', :action => 'edit')
# * a permission Symbol (eg. :edit_project)
Jean-Baptiste Barth
Added ability to specify multiple projects in User#allowed_to? (#5332)...
r4113 # Context can be:
# * a project : returns true if user is allowed to do the specified action on this project
# * a group of projects : returns true if user is allowed on every project
# * nil with options[:global] set : check if user has at least one role allowed for this action,
# or falls back to Non Member / Anonymous permissions depending if the user is logged
Jean-Baptiste Barth
Code cleanup: renamed variables in User#allowed_to? with explicit names...
r4120 def allowed_to?(action, context, options={})
if context && context.is_a?(Project)
Jean-Philippe Lang
Global queries can be saved from the global issue list (follows r1311 and closes #897)....
r1297 # No action allowed on archived projects
Jean-Baptiste Barth
Code cleanup: renamed variables in User#allowed_to? with explicit names...
r4120 return false unless context.active?
Jean-Philippe Lang
Global queries can be saved from the global issue list (follows r1311 and closes #897)....
r1297 # No action allowed on disabled modules
Jean-Baptiste Barth
Code cleanup: renamed variables in User#allowed_to? with explicit names...
r4120 return false unless context.allows_to?(action)
Jean-Philippe Lang
Global queries can be saved from the global issue list (follows r1311 and closes #897)....
r1297 # Admin users are authorized for anything else
return true if admin?
Jean-Baptiste Barth
Code cleanup: renamed variables in User#allowed_to? with explicit names...
r4120 roles = roles_for_project(context)
Jean-Philippe Lang
Allows multiple roles on the same project (#706). Prerequisite for user groups feature....
r2627 return false unless roles
Jean-Baptiste Barth
Code cleanup: renamed variables in User#allowed_to? with explicit names...
r4120 roles.detect {|role| (context.is_public? || role.member?) && role.allowed_to?(action)}
Jean-Philippe Lang
Global queries can be saved from the global issue list (follows r1311 and closes #897)....
r1297
Jean-Baptiste Barth
Code cleanup: renamed variables in User#allowed_to? with explicit names...
r4120 elsif context && context.is_a?(Array)
Jean-Baptiste Barth
Added ability to specify multiple projects in User#allowed_to? (#5332)...
r4113 # Authorize if user is authorized on every element of the array
Jean-Baptiste Barth
Code cleanup: renamed variables in User#allowed_to? with explicit names...
r4120 context.map do |project|
allowed_to?(action,project,options)
end.inject do |memo,allowed|
memo && allowed
Jean-Baptiste Barth
Added ability to specify multiple projects in User#allowed_to? (#5332)...
r4113 end
Jean-Philippe Lang
Global queries can be saved from the global issue list (follows r1311 and closes #897)....
r1297 elsif options[:global]
Jean-Philippe Lang
Ability to allow non-admin users to create projects (#1007)....
r2651 # Admin users are always authorized
return true if admin?
Jean-Philippe Lang
Global queries can be saved from the global issue list (follows r1311 and closes #897)....
r1297 # authorize if user has at least one role that has this permission
Jean-Philippe Lang
Allows multiple roles on the same project (#706). Prerequisite for user groups feature....
r2627 roles = memberships.collect {|m| m.roles}.flatten.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
Eric Davis
Add User#allowed_to_globally? which wraps User#allowed_to?...
r4050
# Is the user allowed to do the specified action on any project?
# See allowed_to? for the actions and valid options.
def allowed_to_globally?(action, options)
allowed_to?(action, nil, options.reverse_merge(:global => true))
end
Jean-Philippe Lang
Declare safe attributes for User and Projects models....
r4378
safe_attributes 'login',
'firstname',
'lastname',
'mail',
'mail_notification',
'language',
'custom_field_values',
'custom_fields',
'identity_url'
safe_attributes 'status',
'auth_source_id',
:if => lambda {|user, current_user| current_user.admin?}
Jean-Philippe Lang
Merged 0.6 branch into trunk....
r663
Jean-Philippe Lang
Extracts user groups assignment from controller....
r4385 safe_attributes 'group_ids',
:if => lambda {|user, current_user| current_user.admin? && !user.new_record?}
Eric Davis
Added User#notify_about? to check when a user should be notified about an event...
r4104 # Utility method to help check if a user should be notified about an
# event.
#
# TODO: only supports Issue events currently
def notify_about?(object)
Jean-Philippe Lang
Validates user's mail_notification and turn options into strings (the attribute type)....
r4380 case mail_notification
when 'all'
Eric Davis
Added User#notify_about? to check when a user should be notified about an event...
r4104 true
Jean-Philippe Lang
Validates user's mail_notification and turn options into strings (the attribute type)....
r4380 when 'selected'
Jean-Philippe Lang
Fixed: no email sent with 'Notifiy for any event on the selected projects only' (#7421)....
r4641 # user receives notifications for created/assigned issues on unselected projects
if object.is_a?(Issue) && (object.author == self || object.assigned_to == self)
true
else
false
end
Jean-Philippe Lang
Validates user's mail_notification and turn options into strings (the attribute type)....
r4380 when 'none'
Eric Davis
Added User#notify_about? to check when a user should be notified about an event...
r4104 false
Jean-Philippe Lang
Validates user's mail_notification and turn options into strings (the attribute type)....
r4380 when 'only_my_events'
Eric Davis
Added User#notify_about? to check when a user should be notified about an event...
r4104 if object.is_a?(Issue) && (object.author == self || object.assigned_to == self)
true
else
false
end
Jean-Philippe Lang
Validates user's mail_notification and turn options into strings (the attribute type)....
r4380 when 'only_assigned'
Eric Davis
Added User#notify_about? to check when a user should be notified about an event...
r4104 if object.is_a?(Issue) && object.assigned_to == self
true
else
false
end
Jean-Philippe Lang
Validates user's mail_notification and turn options into strings (the attribute type)....
r4380 when 'only_owner'
Eric Davis
Added User#notify_about? to check when a user should be notified about an event...
r4104 if object.is_a?(Issue) && object.author == self
true
else
false
end
else
false
end
end
Jean-Philippe Lang
Merged 0.6 branch into trunk....
r663 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
Eric Davis
Added some RDoc documentation for some models....
r2536 # Returns the anonymous user. If the anonymous user does not exist, it is created. There can be only
# one anonymous user per database.
Jean-Philippe Lang
Merged 0.6 branch into trunk....
r663 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
Adds random salt to user passwords (#7410)....
r4816
# Salts all existing unsalted passwords
# It changes password storage scheme from SHA1(password) to SHA1(salt + SHA1(password))
# This method is used in the SaltPasswords migration and is to be kept as is
def self.salt_unsalted_passwords!
transaction do
User.find_each(:conditions => "salt IS NULL OR salt = ''") do |user|
next if user.hashed_password.blank?
salt = User.generate_salt
hashed_password = User.hash_password("#{salt}#{user.hashed_password}")
User.update_all("salt = '#{salt}', hashed_password = '#{hashed_password}'", ["id = ?", user.id] )
end
end
end
Jean-Philippe Lang
Merged 0.6 branch into trunk....
r663
Jean-Philippe Lang
Makes minimum password length configurable....
r2586 protected
def validate
# Password length validation based on setting
if !password.nil? && password.size < Setting.password_min_length.to_i
errors.add(:password, :too_short, :count => Setting.password_min_length.to_i)
end
end
private
Jean-Philippe Lang
When destroying a user, remove all references to that user (#7296)....
r4606
# Removes references that are not handled by associations
# Things that are not deleted are reassociated with the anonymous user
def remove_references_before_destroy
return if self.id.nil?
substitute = User.anonymous
Attachment.update_all ['author_id = ?', substitute.id], ['author_id = ?', id]
Comment.update_all ['author_id = ?', substitute.id], ['author_id = ?', id]
Issue.update_all ['author_id = ?', substitute.id], ['author_id = ?', id]
Issue.update_all 'assigned_to_id = NULL', ['assigned_to_id = ?', id]
Journal.update_all ['user_id = ?', substitute.id], ['user_id = ?', id]
JournalDetail.update_all ['old_value = ?', substitute.id.to_s], ["property = 'attr' AND prop_key = 'assigned_to_id' AND old_value = ?", id.to_s]
JournalDetail.update_all ['value = ?', substitute.id.to_s], ["property = 'attr' AND prop_key = 'assigned_to_id' AND value = ?", id.to_s]
Message.update_all ['author_id = ?', substitute.id], ['author_id = ?', id]
News.update_all ['author_id = ?', substitute.id], ['author_id = ?', id]
# Remove private queries and keep public ones
Query.delete_all ['user_id = ? AND is_public = ?', id, false]
Query.update_all ['user_id = ?', substitute.id], ['user_id = ?', id]
TimeEntry.update_all ['user_id = ?', substitute.id], ['user_id = ?', id]
Token.delete_all ['user_id = ?', id]
Watcher.delete_all ['user_id = ?', id]
WikiContent.update_all ['author_id = ?', substitute.id], ['author_id = ?', id]
WikiContent::Version.update_all ['author_id = ?', substitute.id], ['author_id = ?', id]
end
Jean-Philippe Lang
User groups branch merged....
r2755
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 # 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
Adds random salt to user passwords (#7410)....
r4816
# Returns a 128bits random salt as a hex string (32 chars long)
def self.generate_salt
ActiveSupport::SecureRandom.hex(16)
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
Jean-Philippe Lang
Fixes ApplicationHelper#link_to_user...
r2910 def name(*args); I18n.t(:label_user_anonymous) end
Jean-Philippe Lang
Anonymous users can now be allowed to create, edit, comment issues, comment news and post messages in the forums....
r906 def mail; nil end
def time_zone; nil end
def rss_key; nil end
Jean-Philippe Lang
When destroying a user, remove all references to that user (#7296)....
r4606
# Anonymous user can not be destroyed
def destroy
false
end
Jean-Philippe Lang
Merged 0.6 branch into trunk....
r663 end