X-Git-Url: https://projects.mako.cc/source/selectricity/blobdiff_plain/fd484b33a3920e0031007c5c2f1dec61913cbab5..2fed9b6ceaf0953daf0f085f78520263ab0fa804:/app/models/user.rb diff --git a/app/models/user.rb b/app/models/user.rb index 4f25e06..0b4b3b3 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,10 +1,96 @@ -class User < ActiveRecord::Base - include LoginEngine::AuthenticatedUser +# Selectricity: Voting Machinery for the Masses +# Copyright (C) 2007, 2008 Benjamin Mako Hill +# Copyright (C) 2007 Massachusetts Institute of Technology +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 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 +# Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public +# License along with this program. If not, see +# . +require 'digest/sha1' +class User < ActiveRecord::Base has_many :elections + # Virtual attribute for the unencrypted password + attr_accessor :password + attr_accessor :current_user + + validates_presence_of :email + validates_presence_of :password, :if => :password_required? + validates_presence_of :password_confirmation, :if => :password_required? + validates_length_of :password, :within => 4..40, :if => :password_required? + validates_confirmation_of :password, :if => :password_required? + validates_length_of :login, :within => 3..40 + validates_uniqueness_of :login, :email, :case_sensitive => false + before_save :encrypt_password + def name - [ firstname, lastname].join(" ") + [ firstname, lastname].join(" ") + end + + # Authenticates a user by their login name and unencrypted password. Returns the user or nil. + def self.authenticate(login, password) + u = find_by_login(login) # need to get the salt + u && u.authenticated?(password) ? u : nil + end + + # Encrypts some data with the salt. + def self.encrypt(password, salt) + Digest::SHA1.hexdigest("--#{salt}--#{password}--") + end + + # Encrypts the password with the user salt + def encrypt(password) + self.class.encrypt(password, salt) end -end + def authenticated?(password) + crypted_password == encrypt(password) + end + + def remember_token? + remember_token_expires_at && Time.now.utc < remember_token_expires_at + end + + # These create and unset the fields required for remembering users between browser closes + def remember_me + self.remember_token_expires_at = 2.weeks.from_now.utc + self.remember_token = encrypt("#{email}--#{remember_token_expires_at}") + save(false) + end + + def forget_me + self.remember_token_expires_at = nil + self.remember_token = nil + save(false) + end + + protected + # before filter + def encrypt_password + return if password.blank? + self.salt = Digest::SHA1.hexdigest("--#{Time.now.to_s}--#{login}--") if new_record? + self.crypted_password = encrypt(password) + end + + def password_required? + crypted_password.blank? || !password.blank? + end + def validate + # E-mail regex, moderate complexity + # Stolen from http://www.regular-expressions.info/email.html + errors.add(:email, "is not valid") unless email =~ + /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i + errors.add(:login, "should not begin or end with spaces") if login and login.strip! + errors.add(:login, "should contain only letters, numbers, and spaces") unless login =~ /^[A-Za-z0-9 ]*$/ + end +end