applied my changes - initial import
[boxroom-stian.git] / app / models / user.rb
blob3781c32d38203f86bf6c4da11bb08255a5695dca
1 require 'digest/sha1'
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.
28   def validate
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")
32     end
33   end   
35   def can_update_perms?
36     (is_admin? || groups.include?(Group.folderadmins)) ? true : false 
37   end
38      
39   def can_update_folderinfo?(folder)
40     ((folder.user == self) || can_update_perms?) ? true : false
41   end
42     
44   # Password getter
45   def password
46     return @password
47   end
49   def no_or_nil(temp) 
50     temp == 0 ? nil : temp 
51   end
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
57   # Password setter
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)
64     end
65   end
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))
71       return user
72     else
73       return nil
74     end
75   end
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)
81   end
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?
87   end
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
93     @password = nil
94   end
96   # Hash the given password (and return it)
97   def self.hash_password(password)
98     return Digest::SHA1.hexdigest(password)
99   end
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
104     random_password = ''
105     1.upto(len) { |i| random_password << chars[rand(chars.size-1)] }
106     return random_password
107   end
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?)
113   end
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?
118       user = User.new
119       user.email = email
120       user.name = name
121       user.password = password
122       user.password_confirmation = password_confirmation
123       user.is_the_administrator = true
124       user.password_required = true
125     end
126     return user
127   end
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
134     result = Hash.new
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)
139       if user.blank?
140         result['flash'] = 'forgotten_notice'
141         result['message'] = 'Could not find a user with this combination of username and e-mail address'
142         return result
143       end
144     elsif not name.blank? # The user only entered the name
145       user = self.find_by_name(name)
146       if user.blank?
147         result['flash'] = 'forgotten_notice'
148         result['message'] = 'Could not find a user with this username'
149         return result
150       end
151     elsif not email.blank? # The user only entered an e-mail address
152       user = User.find_by_email(email)
153       if user.blank?
154         result['flash'] = 'forgotten_notice'
155         result['message'] = 'Could not find a user with this e-mail address'
156         return result
157       end
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'
161       return result
162     end
164     # So far, so good...
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
170     begin
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
174       else
175         result['flash'] = 'forgotten_notice'
176         result['message'] = 'Could not create a new password'
177       end
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."
182       else
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."
185       end
186     end
188     # finally return the result
189     return result
190   end
192   # Returns if the user is member of the admins group or not
193   def is_admin?
194     unless self.groups.find_by_is_the_administrators_group(true).blank?
195       return true
196     else
197       return false
198     end
199   end
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
206     end
207     return false
208   end
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
215     end
216     return false
217   end
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
224     end
225     return false
226   end
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
233     end
234     return false
235   end