Show More
Commit Description:
added submission_status to store grading results, first page shows only unpassed problems.
Commit Description:
added submission_status to store grading results, first page shows only unpassed problems.
References:
File last commit:
Show/Diff file:
Action:
app/models/user.rb
| 227 lines
| 6.1 KiB
| text/x-ruby
| RubyLexer
|
|
r0 | require 'digest/sha1' | ||
class User < ActiveRecord::Base | ||||
has_and_belongs_to_many :roles | ||||
|
r64 | has_many :test_requests, :order => "submitted_at DESC" | ||
|
r36 | |||
|
r102 | has_many :messages, | ||
:class_name => "Message", | ||||
:foreign_key => "sender_id", | ||||
:order => 'created_at DESC' | ||||
has_many :replied_messages, | ||||
:class_name => "Message", | ||||
:foreign_key => "receiver_id", | ||||
:order => 'created_at DESC' | ||||
|
r213 | has_many :test_pair_assignments, :dependent => :delete_all | ||
|
r216 | has_many :submission_statuses | ||
|
r213 | |||
|
r85 | belongs_to :site | ||
|
r106 | belongs_to :country | ||
|
r85 | |||
|
r158 | named_scope :activated_users, :conditions => {:activated => true} | ||
|
r157 | |||
|
r0 | validates_presence_of :login | ||
|
r157 | validates_uniqueness_of :login | ||
|
r162 | validates_format_of :login, :with => /^[\_A-Za-z0-9]+$/ | ||
validates_length_of :login, :within => 3..30 | ||||
|
r157 | |||
|
r0 | validates_presence_of :full_name | ||
|
r23 | validates_length_of :full_name, :minimum => 1 | ||
|
r0 | |||
validates_presence_of :password, :if => :password_required? | ||||
validates_length_of :password, :within => 4..20, :if => :password_required? | ||||
validates_confirmation_of :password, :if => :password_required? | ||||
|
r162 | validates_format_of :email, | ||
:with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i, | ||||
:if => :email_validation? | ||||
validate :uniqueness_of_email_from_activated_users, | ||||
:if => :email_validation? | ||||
validate :enough_time_interval_between_same_email_registrations, | ||||
:if => :email_validation? | ||||
|
r157 | |||
|
r162 | # these are for ytopc | ||
# disable for now | ||||
#validates_presence_of :province | ||||
|
r157 | |||
|
r0 | attr_accessor :password | ||
before_save :encrypt_new_password | ||||
|
r162 | before_save :assign_default_site | ||
|
r0 | |||
def self.authenticate(login, password) | ||||
user = find_by_login(login) | ||||
return user if user && user.authenticated?(password) | ||||
end | ||||
def authenticated?(password) | ||||
|
r155 | if self.activated | ||
hashed_password == User.encrypt(password,self.salt) | ||||
else | ||||
false | ||||
end | ||||
|
r0 | end | ||
def admin? | ||||
self.roles.detect {|r| r.name == 'admin' } | ||||
end | ||||
|
r213 | # These are methods related to test pairs | ||
def get_test_pair_assignments_for(problem) | ||||
test_pair_assignments.find_all { |a| a.problem_id == problem.id } | ||||
end | ||||
def get_recent_test_pair_assignment_for(problem) | ||||
assignments = get_test_pair_assignments_for problem | ||||
if assignments.length == 0 | ||||
return nil | ||||
else | ||||
recent = assignments[0] | ||||
assignments.each do |a| | ||||
recent = a if a.request_number > recent.request_number | ||||
end | ||||
return recent | ||||
end | ||||
end | ||||
def can_request_new_test_pair_for?(problem) | ||||
recent = get_recent_test_pair_assignment_for problem | ||||
return (recent == nil or recent.submitted) | ||||
end | ||||
def get_new_test_pair_assignment_for(problem) | ||||
previous_assignment_numbers = | ||||
get_test_pair_assignments_for(problem).collect {|a| a.test_pair_number } | ||||
test_pair = problem.random_test_pair(previous_assignment_numbers) | ||||
if test_pair | ||||
assignment = TestPairAssignment.new(:user => self, | ||||
:problem => problem, | ||||
:test_pair => test_pair, | ||||
:test_pair_number => test_pair.number, | ||||
:request_number => | ||||
previous_assignment_numbers.length + 1, | ||||
:submitted => false) | ||||
return assignment | ||||
else | ||||
return nil | ||||
end | ||||
end | ||||
|
r216 | def get_submission_status_for(problem) | ||
SubmissionStatus.find(:first, | ||||
:conditions => { | ||||
:user_id => id, | ||||
:problem_id => problem.id | ||||
}) | ||||
end | ||||
|
r18 | def email_for_editing | ||
|
r23 | if self.email==nil | ||
"(unknown)" | ||||
elsif self.email=='' | ||||
"(blank)" | ||||
else | ||||
|
r18 | self.email | ||
end | ||||
end | ||||
def email_for_editing=(e) | ||||
self.email=e | ||||
end | ||||
def alias_for_editing | ||||
|
r23 | if self.alias==nil | ||
"(unknown)" | ||||
elsif self.alias=='' | ||||
"(blank)" | ||||
else | ||||
|
r18 | self.alias | ||
end | ||||
end | ||||
def alias_for_editing=(e) | ||||
self.alias=e | ||||
end | ||||
|
r155 | def activation_key | ||
|
r158 | if self.hashed_password==nil | ||
encrypt_new_password | ||||
end | ||||
|
r155 | Digest::SHA1.hexdigest(self.hashed_password)[0..7] | ||
end | ||||
def verify_activation_key(key) | ||||
key == activation_key | ||||
end | ||||
|
r157 | def self.random_password(length=5) | ||
chars = 'abcdefghjkmnopqrstuvwxyz' | ||||
password = '' | ||||
length.times { password << chars[rand(chars.length - 1)] } | ||||
password | ||||
end | ||||
|
r200 | def self.find_non_admin_with_prefix(prefix='') | ||
users = User.find(:all) | ||||
return users.find_all { |u| !(u.admin?) and u.login.index(prefix)==0 } | ||||
end | ||||
|
r18 | protected | ||
|
r0 | def encrypt_new_password | ||
return if password.blank? | ||||
self.salt = (10+rand(90)).to_s | ||||
|
r58 | self.hashed_password = User.encrypt(self.password,self.salt) | ||
|
r0 | end | ||
|
r162 | def assign_default_site | ||
# have to catch error when migrating (because self.site is not available). | ||||
begin | ||||
if self.site==nil | ||||
self.site = Site.find_by_name('default') | ||||
|
r190 | if self.site==nil | ||
self.site = Site.find(1) # when 'default has be renamed' | ||||
end | ||||
|
r162 | end | ||
rescue | ||||
end | ||||
end | ||||
|
r0 | def password_required? | ||
|
r58 | self.hashed_password.blank? || !self.password.blank? | ||
|
r0 | end | ||
|
r58 | def self.encrypt(string,salt) | ||
|
r0 | Digest::SHA1.hexdigest(salt + string) | ||
end | ||||
|
r157 | |||
def uniqueness_of_email_from_activated_users | ||||
|
r158 | user = User.activated_users.find_by_email(self.email) | ||
if user and (user.login != self.login) | ||||
|
r157 | self.errors.add_to_base("Email has already been taken") | ||
end | ||||
end | ||||
|
r158 | |||
def enough_time_interval_between_same_email_registrations | ||||
|
r160 | return if !self.new_record? | ||
|
r162 | return if self.activated | ||
|
r158 | open_user = User.find_by_email(self.email, | ||
:order => 'created_at DESC') | ||||
if open_user and open_user.created_at and | ||||
(open_user.created_at > Time.now.gmtime - 5.minutes) | ||||
self.errors.add_to_base("There are already unactivated registrations with this e-mail address (please wait for 5 minutes)") | ||||
end | ||||
end | ||||
|
r162 | |||
def email_validation? | ||||
begin | ||||
return VALIDATE_USER_EMAILS | ||||
rescue | ||||
return false | ||||
end | ||||
end | ||||
|
r0 | end | ||