3 # A User is used to validate people trying to log in.
4 # Users can have downloads, create files and folders
5 # and belong to a group.
6 # A user's plain text password is not accessible.
7 # Therefore passwords are hashed before they are stored.
8 class User < ActiveRecord::Base
9 has_and_belongs_to_many :groups
10 has_many :clipboards, :dependent => :destroy
11 has_many :usages, :dependent => :destroy
12 has_many :myfiles, :dependent => :nullify
13 has_many :folders, :dependent => :nullify
15 # The password_required field, which determines if
16 # the presence of a password has to be checked
17 attr_accessor :password_required
18 cattr_accessor :logged_in_user
19 # We never allow the hashed password to be set from a form
20 attr_accessible :name, :email, :password, :password_confirmation, :password_required
22 validates_confirmation_of :password
23 validates_uniqueness_of :name, :email
24 validates_presence_of :name, :email
25 validates_format_of :email, :with => VALID_EMAIL
27 # Validates if the data for this user is valid.
29 # Only validate the presence of a password when it's required
30 if self.password_required and self.password.blank?
31 errors.add(:password, " can't be blank")
36 (is_admin? || groups.include?(Group.folderadmins)) ? true : false
39 def can_update_folderinfo?(folder)
40 ((folder.user == self) || can_update_perms?) ? true : false
50 temp == 0 ? nil : temp
53 def no_files_clipboard; no_or_nil(self.clipboards.collect(&:myfile).compact.size); end
54 def no_folders_clipboard; no_or_nil(self.clipboards.collect(&:folder).compact.size); end
55 def empty_clipboard; self.clipboards.collect(&:destroy); end
58 def password=(new_password)
59 @password = new_password
60 unless @password.blank?
61 salt = User.random_password(6) # whenever the password is set, a new random salt is set too
62 self.password_salt = salt
63 self.hashed_password = User.hash_password(@password + salt)
67 # Return the User with the given name and plain-text password.
68 def self.login(name, password)
69 user = User.find_by_name(name)
70 if (not user.blank?) and (user.hashed_password == User.hash_password(password + user.password_salt))
77 before_create :generate_rss_access_key
78 # Generates an access key for the RSS feeds.
79 def generate_rss_access_key
80 self.rss_access_key = User.random_password(36)
83 before_destroy :dont_destroy_admin
84 # Don't delete 'admin' from the database.
85 def dont_destroy_admin
86 raise "Can't delete admin" if self.is_the_administrator?
89 after_save :clear_plain_text_password
90 # Clear out the plain-text password. This stops it being made
91 # available in the session
92 def clear_plain_text_password
96 # Hash the given password (and return it)
97 def self.hash_password(password)
98 return Digest::SHA1.hexdigest(password)
101 # Generate a random password of <i>len</i> charachters
102 def self.random_password(len)
103 chars = ('a'..'z').to_a + ('A'..'Z').to_a + ('0'..'9').to_a
105 1.upto(len) { |i| random_password << chars[rand(chars.size-1)] }
106 return random_password
109 # Returns whether or not the admin user exists
110 def self.admin_exists?
111 user = User.find_by_is_the_administrator(true)
112 return (not user.blank?)
115 # Creates the admin user (but doesn't save it!)
116 def self.create_admin(email, name, password, password_confirmation)
117 unless User.admin_exists?
121 user.password = password
122 user.password_confirmation = password_confirmation
123 user.is_the_administrator = true
124 user.password_required = true
129 # Generates a new password for the user with the given username
130 # and/or password and mails the password to the user.
131 # Returns an appriopriate error message if the given user does not exists.
132 def self.generate_and_mail_new_password(name, email)
133 # This is the hash that will be returned
136 # Check if the name and/or email are valid
137 if not name.blank? and not email.blank? # The user entered both name and email
138 user = self.find_by_name_and_email(name, email)
140 result['flash'] = 'forgotten_notice'
141 result['message'] = 'Could not find a user with this combination of username and e-mail address'
144 elsif not name.blank? # The user only entered the name
145 user = self.find_by_name(name)
147 result['flash'] = 'forgotten_notice'
148 result['message'] = 'Could not find a user with this username'
151 elsif not email.blank? # The user only entered an e-mail address
152 user = User.find_by_email(email)
154 result['flash'] = 'forgotten_notice'
155 result['message'] = 'Could not find a user with this e-mail address'
158 else # The user didn't enter anything
159 result['flash'] = 'forgotten_notice'
160 result['message'] = 'Please enter a username and/or an e-mail address'
165 # Generate a new password
166 new_password = User.random_password(8)
167 user.password = new_password
169 # Store the new password and try to mail it to the user
171 if PasswordMailer.deliver_forgotten(user.name, user.email, new_password) and user.save
172 result['flash'] = 'login_confirmation'
173 result['message'] = 'A new password has been e-mailed to ' + user.email
175 result['flash'] = 'forgotten_notice'
176 result['message'] = 'Could not create a new password'
178 rescue Exception => e
179 if e.message.match('getaddrinfo: No address associated with nodename')
180 result['flash'] = 'forgotten_notice'
181 result['message'] = "The mail server settings in the environment file are incorrect. Check the installation instructions to solve this problem. Your password hasn't changed yet."
183 result['flash'] = 'forgotten_notice'
184 result['message'] = e.message + ".<br /><br />This means either your e-mail address or Boxroom's configuration for e-mailing is invalid. Please contact the administrator or check the installation instructions. Your password hasn't changed yet."
188 # finally return the result
192 # Returns if the user is member of the admins group or not
194 unless self.groups.find_by_is_the_administrators_group(true).blank?
201 # Use this method to determine if a user is permitted to create in the given folder
202 def can_create(folder_id)
203 self.groups.each do |group|
204 group_permission = group.group_permissions.find_by_folder_id(folder_id)
205 return true unless group_permission.blank? or not group_permission.can_create
210 # Use this method to determine if a user is permitted to read in the given folder
211 def can_read(folder_id)
212 self.groups.each do |group|
213 group_permission = group.group_permissions.find_by_folder_id(folder_id)
214 return true unless group_permission.blank? or not group_permission.can_read
219 # Use this method to determine if a user is permitted to update in the given folder
220 def can_update(folder_id)
221 self.groups.each do |group|
222 group_permission = group.group_permissions.find_by_folder_id(folder_id)
223 return true unless group_permission.blank? or not group_permission.can_update
228 # Use this method to determine if a user is permitted to delete in the given folder
229 def can_delete(folder_id)
230 self.groups.each do |group|
231 group_permission = group.group_permissions.find_by_folder_id(folder_id)
232 return true unless group_permission.blank? or not group_permission.can_delete