| # == Schema Information |
| # Schema version: 1 |
| # |
| # Table name: users |
| # |
| # id :integer(11) not null, primary key |
| # email :string(250) default(), not null |
| # name :string(50) default(), not null |
| # ip_address :string(20) default(), not null |
| # hashed_password :string(40) |
| # hashed_password_new :string(40) |
| # admin :string(1) default(N), not null |
| # notify_daily :integer(1) default(0), not null |
| # notify_weekly :integer(1) default(0), not null |
| # notify_monthly :integer(1) default(0), not null |
| # site_id :integer(10) |
| # created_on :datetime |
| # updated_on :datetime |
| # http_user_agent :string(250) |
| # logon_count :integer(5) default(0) |
| # logon_using_cookie_count :integer(5) default(0) |
| # last_logon :datetime |
| # confirmed_on :datetime |
| # |
| |
| require 'digest/sha1' |
| |
| # More information: |
| # * {EPF Wiki Data model}[link:files/doc/DATAMODEL.html] |
| #--###################################################################### |
| # Copyright (c) 2006 LogicaCMG |
| # |
| # All rights reserved. This program and the accompanying materials |
| # are made available under the terms of the Eclipse Public License v1.0 |
| # which accompanies this distribution, and is available at |
| # http://www.eclipse.org/legal/epl-v10.html |
| # |
| # Contributors: |
| # |
| # Onno van der Straaten:: initial implementation |
| #++###################################################################### |
| # {Copyright (c) 2006 LogicaCMG}[link:files/COPYRIGHT.html] |
| |
| class User < ActiveRecord::Base |
| |
| DOMAIN_PATTERN = /@.*/ |
| |
| has_many :sites |
| has_many :checkouts |
| has_many :versions |
| has_many :comments |
| has_many :notifications |
| has_many :versions2review, :class_name => "Version", :foreign_key => "reviewer_id" |
| has_many :comments2review, :class_name => "Comment", :foreign_key => "reviewer_id" |
| belongs_to :user_thatmarkeddone, :class_name => "User", :foreign_key => "user_id_markdone" |
| belongs_to :user_thatmarkedtodo, :class_name => "User", :foreign_key => "user_id_marktodo" |
| belongs_to :site # default site of user TODO: not used |
| |
| validates_confirmation_of :password |
| validates_presence_of :name, :email |
| validates_uniqueness_of :name, :email |
| validates_format_of :email, :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i |
| validates_format_of :admin, :with => /Y|N|C/ |
| |
| attr_accessor :password, :remember_me, :email_extension |
| |
| # Changing account to admin or cadmin requires that |
| # you specify the user that is requesting the change |
| attr_accessor :user |
| validates_associated :user |
| |
| # #new_cadmin creates the central adminstrator user |
| def self.new_cadmin(params) |
| raise 'Already create central admin' if User.count > 0 |
| user = User.new(params) |
| user.hashed_password = hash_pw(user.password) if user.password |
| user.admin = "C" |
| user.confirmed_on = Time.now |
| return user |
| end |
| |
| # #new_signup creates an ordinary user account |
| def self.new_signup(params) |
| user = User.new(params) |
| user.email = user.email + user.email_extension if ENV['EPFWIKI_DOMAINS'] && user.email_extension |
| if ENV['EPFWIKI_GENERATE_PASSWORDS'] == '1' |
| logger.info("Creating account with generated password for #{user.email}") |
| user.password = user.generate_new_pw |
| user.password_confirmation = user.password |
| user.confirmed_on = Time.now # account does not need to be confirmed |
| else |
| logger.info("Creating account with supplied password for #{user.email}") |
| end |
| user.hashed_password = hash_pw(user.password) if user.password |
| return user |
| end |
| |
| # #login searches the user on email and hashed_password and returns it, see also #try_to_login |
| def self.login(email, password) |
| logger.info("Doing login for #{email} with password #{password}, hash_pw is #{hash_pw(password)}") |
| hashed_password = hash_pw(password) |
| user = find(:first, :conditions => ["email = ? and hashed_password = ?", email.downcase, hashed_password]) |
| return nil if user && (password.nil? || user.confirmed_on.nil?) |
| return user |
| end |
| |
| # #confirm_account is used to confirm new accounts or confirm new passwords in case user requested on |
| def confirm_account(token) |
| logger.debug("Confirming account with token: " + token) |
| logger.debug("Hashed password is: " + self.hashed_password) |
| logger.debug("Hashed password new is: " + (self.hashed_password_new || '')) |
| if self.hashed_password && (hash_pw(self.hashed_password) == token) |
| self.confirmed_on = Time.now |
| elsif self.hashed_password_new && (hash_pw(self.hashed_password_new) == token) |
| self.confirmed_on = Time.now |
| self.hashed_password = self.hashed_password_new |
| self.hashed_password_new = nil |
| else |
| raise "Failed to activate account for #{self.email}" |
| end |
| end |
| |
| # Use #set_new_pw to set and return a new password for a user. |
| # Needs to be confirmed using #confirm_account |
| def set_new_pw |
| new_pw = generate_new_pw |
| self.password = new_pw |
| self.hashed_password_new = hash_pw(new_pw) |
| end |
| |
| # Log in if the name and password (after hashing) |
| # match the database, or if the name matches |
| # an entry in the database with no password |
| def try_to_login |
| User.login(self.email.downcase, self.password) |
| end |
| |
| # #change_password changes the password of a User |
| def change_password(user) |
| raise "Password can't be blank" if user.password.blank? |
| self.password = user.password |
| self.password_confirmation = user.password_confirmation |
| self.hashed_password = hash_pw(user.password) |
| self.confirmed_on = Time.now |
| end |
| |
| def self.cadmin(from, to) |
| raise 'From needs to be central admin' if !from.cadmin? |
| User.transaction(from, to) do |
| to.admin = 'C' |
| to.user = from |
| from.admin = 'Y' |
| to.save |
| from.save |
| end |
| end |
| |
| # Count of versions of user without counting base versions |
| def versions_count_excluding_baseversions |
| return Version.count_by_sql('select count(*) from versions where user_id = ' + self.id.to_s + ' and version <> 0 ' ) |
| end |
| |
| # Token that can be used to confirm a account |
| def token |
| return Digest::SHA1.hexdigest(self.hashed_password) |
| end |
| |
| def user? |
| return admin == 'N' |
| end |
| |
| def admin? |
| return admin == 'Y' || admin == 'C' |
| end |
| |
| def cadmin? |
| return admin == 'C' |
| end |
| |
| def self.find_central_admin |
| return User.find(:first, :conditions => ["admin=?", "C"] ) |
| end |
| |
| def documents_path |
| return "users/" + id.to_s + "/docs" |
| end |
| |
| def images_path |
| return "users/" + id.to_s + "/images" |
| end |
| |
| # #sites returns Site records where user created versions or comments |
| def sites |
| return Site.find(:all, :conditions => ['exists (select * from versions where user_id = ? and site_id = sites.id) or exists (select * from comments where user_id = ? and site_id = sites.id)', id, id]) |
| end |
| |
| # Returns list of uploaded images |
| def images |
| path = "#{ENV['EPFWIKI_ROOT_DIR']}public/#{self.images_path}" |
| logger.debug("Getting entries in directory #{path}") |
| File.makedirs(path) |
| return Dir.entries(path) - [".", "..", "Thumbs.db"] # NOTE: dir entires returns array like [".", "..", "config.h", "main.rb"] |
| end |
| |
| # Returns list of uploaded documents |
| def documents |
| path = "#{ENV['EPFWIKI_ROOT_DIR']}public/#{self.documents_path}" |
| logger.debug("Getting documents in #{path}") |
| File.makedirs(path) |
| return Dir.entries(path) - [".", "..", "Thumbs.db"] |
| end |
| |
| def before_validation_on_update |
| end |
| |
| def validate |
| if ENV['EPFWIKI_DOMAINS'] |
| valid_domain = !ENV['EPFWIKI_DOMAINS'].split(" ").index(DOMAIN_PATTERN.match(email.downcase).to_s).nil? |
| errors.add(:email, "domain not valid") if !valid_domain && !self.cadmin? |
| end |
| end |
| |
| def validate_on_create |
| if ENV['EPFWIKI_GENERATE_PASSWORDS'] == '1' |
| else |
| errors.add(:password, "can't be blank") if password.blank? || hashed_password.blank? |
| errors.add(:password_confirmation, "can't be blank") if password_confirmation.blank? |
| end |
| errors.add("Central admin already exists") if User.count > 0 && admin == 'C' |
| end |
| |
| def validate_on_update |
| errors.add(:hashed_password, "can't be blank") if hashed_password.blank? |
| old_admin = User.find(id).admin |
| if admin == 'C' and old_admin != 'C' |
| if user.nil? || User.find(user.id).admin != 'C' |
| errors.add(:admin, 'can only be set to C by the central admin') |
| end |
| end |
| if admin == 'Y' and old_admin == 'N' |
| errors.add(:admin, 'can only be set by an admin') if user.nil? || user.admin == 'N' |
| end |
| if admin == 'N' and !old_admin.index(/Y|C/).nil? |
| errors.add(:admin, 'can only be revoked by the central admin') if user.nil? || user.admin != 'C' |
| end |
| end |
| |
| def before_save |
| self.email = self.email.downcase |
| end |
| |
| def generate_new_pw |
| random = rand(10-6+1)+6 # TODO: random is not used anymore? |
| chars = ["A".."Z","a".."z","0".."9"].collect { |r| r.to_a }.join + %q(!@$%^&*) |
| (1..8).collect { chars[rand(chars.size)] }.pack("C*") |
| end |
| |
| end |