initial import boxroom 0.6.2
[boxroom-stian.git] / app / models / user.rb
blob53f8a3db61a79bd462cb924ac4f91b45cbbbfa47
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 :usages, :dependent => :destroy
11   has_many :myfiles, :dependent => :nullify
12   has_many :folders, :dependent => :nullify
14   # The password_required field, which determines if
15   # the presence of a password has to be checked
16   attr_accessor :password_required
18   # We never allow the hashed password to be set from a form
19   attr_accessible :name, :email, :password, :password_confirmation, :password_required
21   validates_confirmation_of :password
22   validates_uniqueness_of :name, :email
23   validates_presence_of :name, :email
24   validates_format_of :email, :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/
26   # Validates if the data for this user is valid.
27   def validate
28     # Only validate the presence of a password when it's required
29     if self.password_required and self.password.blank?
30       errors.add(:password, " can't be blank")
31     end
32   end
34   # Password getter
35   def password
36     return @password
37   end
39   # Password setter
40   def password=(new_password)
41     @password = new_password
42     unless @password.blank?
43       salt = User.random_password(6) # whenever the password is set, a new random salt is set too
44       self.password_salt = salt
45       self.hashed_password = User.hash_password(@password + salt)
46     end
47   end
49   # Return the User with the given name and plain-text password.
50   def self.login(name, password)
51     user = User.find_by_name(name)
52     if (not user.blank?) and (user.hashed_password == User.hash_password(password + user.password_salt))
53       return user
54     else
55       return nil
56     end
57   end
59   before_create :generate_rss_access_key
60   # Generates an access key for the RSS feeds.
61   def generate_rss_access_key
62     self.rss_access_key = User.random_password(36)
63   end
65   before_destroy :dont_destroy_admin
66   # Don't delete 'admin' from the database.
67   def dont_destroy_admin
68     raise "Can't delete admin" if self.is_the_administrator?
69   end
71   after_save :clear_plain_text_password
72   # Clear out the plain-text password. This stops it being made
73   # available in the session
74   def clear_plain_text_password
75     @password = nil
76   end
78   # Hash the given password (and return it)
79   def self.hash_password(password)
80     return Digest::SHA1.hexdigest(password)
81   end
83   # Generate a random password of <i>len</i> charachters
84   def self.random_password(len)
85     chars = ('a'..'z').to_a + ('A'..'Z').to_a + ('0'..'9').to_a
86     random_password = ''
87     1.upto(len) { |i| random_password << chars[rand(chars.size-1)] }
88     return random_password
89   end
91   # Returns whether or not the admin user exists
92   def self.admin_exists?
93     user = User.find_by_is_the_administrator(true)
94     return (not user.blank?)
95   end
97   # Creates the admin user (but doesn't save it!)
98   def self.create_admin(email, name, password, password_confirmation)
99     unless User.admin_exists?
100       user = User.new
101       user.email = email
102       user.name = name
103       user.password = password
104       user.password_confirmation = password_confirmation
105       user.is_the_administrator = true
106       user.password_required = true
107     end
108     return user
109   end
111   # Generates a new password for the user with the given username
112   # and/or password and mails the password to the user.
113   # Returns an appriopriate error message if the given user does not exists.
114   def self.generate_and_mail_new_password(name, email)
115     # This is the hash that will be returned
116     result = Hash.new
118     # Check if the name and/or email are valid
119     if not name.blank? and not email.blank? # The user entered both name and email
120       user = self.find_by_name_and_email(name, email)
121       if user.blank?
122         result['flash'] = 'forgotten_notice'
123         result['message'] = 'Could not find a user with this combination of username and e-mail address'
124         return result
125       end
126     elsif not name.blank? # The user only entered the name
127       user = self.find_by_name(name)
128       if user.blank?
129         result['flash'] = 'forgotten_notice'
130         result['message'] = 'Could not find a user with this username'
131         return result
132       end
133     elsif not email.blank? # The user only entered an e-mail address
134       user = User.find_by_email(email)
135       if user.blank?
136         result['flash'] = 'forgotten_notice'
137         result['message'] = 'Could not find a user with this e-mail address'
138         return result
139       end
140     else # The user didn't enter anything
141       result['flash'] = 'forgotten_notice'
142       result['message'] = 'Please enter a username and/or an e-mail address'
143       return result
144     end
146     # So far, so good...
147     # Generate a new password
148     new_password = User.random_password(8)
149     user.password = new_password
151     # Store the new password and try to mail it to the user
152     begin
153       if PasswordMailer.deliver_forgotten(user.name, user.email, new_password) and user.save
154         result['flash'] = 'login_confirmation'
155         result['message'] = 'A new password has been e-mailed to ' + user.email
156       else
157         result['flash'] = 'forgotten_notice'
158         result['message'] = 'Could not create a new password'
159       end
160     rescue Exception => e
161       if e.message.match('getaddrinfo: No address associated with nodename')
162         result['flash'] = 'forgotten_notice'
163         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."
164       else
165         result['flash'] = 'forgotten_notice'
166         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."
167       end
168     end
170     # finally return the result
171     return result
172   end
174   # Returns if the user is member of the admins group or not
175   def is_admin?
176     unless self.groups.find_by_is_the_administrators_group(true).blank?
177       return true
178     else
179       return false
180     end
181   end
183   # Use this method to determine if a user is permitted to create in the given folder
184   def can_create(folder_id)
185     self.groups.each do |group|
186       group_permission = group.group_permissions.find_by_folder_id(folder_id)
187       return true unless group_permission.blank? or not group_permission.can_create
188     end
189     return false
190   end
192   # Use this method to determine if a user is permitted to read in the given folder
193   def can_read(folder_id)
194     self.groups.each do |group|
195       group_permission = group.group_permissions.find_by_folder_id(folder_id)
196       return true unless group_permission.blank? or not group_permission.can_read
197     end
198     return false
199   end
201   # Use this method to determine if a user is permitted to update in the given folder
202   def can_update(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_update
206     end
207     return false
208   end
210   # Use this method to determine if a user is permitted to delete in the given folder
211   def can_delete(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_delete
215     end
216     return false
217   end