<commit_before># == Schema Information
# Schema version: 20100504203833
#
# Table name: users
#
#  id            :integer(4)      not null, primary key
#  name          :string(64)      not null
#  password_salt :string(16)      not null
#  password_hash :string(64)      not null
#  email         :string(64)      not null
#  active        :boolean(1)      not null
#  admin         :boolean(1)      not null
#  created_at    :datetime
#  updated_at    :datetime
#

class User < ActiveRecord::Base
  has_many :tokens, :dependent => :destroy
  has_many :registrations, :dependent => :destroy
  has_one :profile, :dependent => :destroy
  has_many :direct_grades, :class_name => 'Grade', :dependent => :destroy,
           :as => :subject
  has_many :submissions, :dependent => :destroy
  has_many :notice_statuses, :dependent => :destroy
  has_many :notices, :through => :notice_statuses
  has_many :team_memberships, :dependent => :destroy
  has_many :teams, :through => :team_memberships
  has_many :survey_answers

  attr_protected :admin, :active
  
  # The user name.
  validates_length_of :name, :in => 2..64, :allow_nil => false
  validates_format_of :name, :with => /^\w+$/, :message => 'can only contain letters, numbers, and _'  
  validates_uniqueness_of :name  
  
  # Random string preventing dictionary attacks on the password database.
  validates_length_of :password_salt, :in => 1..16, :allow_nil => false
    
  # SHA-256 of (salt + password).
  validates_length_of :password_hash, :in => 1..64, :allow_nil => false
  
  # @mit.edu e-mail address used to endorse the user account.
  validates_format_of :email, :with => /^[A-Za-z0-9.+_]+@<EMAIL>$/,
                      :message => 'needs to be an @mit.edu e-mail address',
                      :allow_nil => false
  validates_length_of :email, :in => 1..64
  validates_uniqueness_of :email
  
  # Administrators are staff members.  
  validates_inclusion_of :admin, :in => [true, false]
  
  # Prevents logins from un-confirmed accounts.
  validates_inclusion_of :active, :in => [true, false]
  
  # Virtual attribute: the user's password.
  validates_presence_of :password, :on => :create
  attr_reader :password
  attr_accessor :password_confirmation
  def password=(new_password)
    @password = <PASSWORD>
    self.password_salt = (0...16).map { |i| 1 + rand(255) }.pack('C*')
    self.password_hash = User.hash_password new_password, password_salt
  end
  
  # Virtual attribute: confirmation for the user's password.
  validates_confirmation_of :password
  
  # Compares the given password against the user's stored password.
  #
  # Returns +true+ for a match, +false+ otherwise.
  def check_password(passwd)
    password_hash == User.hash_password(passwd, password_salt)
  end
  
  # Computes a password hash from a raw password and a salt.
  def self.hash_password(password, salt)
    Digest::SHA2.hexdigest(password + salt)
  end
  
  # Resets the virtual password attributes.
  def reset_password
    @password = @password_confirmation = nil
  end
  
  # The authenticated user or nil.
  def self.authenticate(user_name, password)
    @user = User.find :first, :conditions => {:name => user_name }    
    (@user && @user.check_password(password)) ? @user : nil
  end  
  
  # Submissions connected to this user.
  #
  # Returns the submissions authored by the user, as well as the submissions<commit_msg>Fixed bug preventing user registration.<commit_after># == Schema Information
# Schema version: 20100504203833
#
# Table name: users
#
#  id            :integer(4)      not null, primary key
#  name          :string(64)      not null
#  password_salt :string(16)      not null
#  password_hash :string(64)      not null
#  email         :string(64)      not null
#  active        :boolean(1)      not null
#  admin         :boolean(1)      not null
#  created_at    :datetime
#  updated_at    :datetime
#

class User < ActiveRecord::Base
  has_many :tokens, :dependent => :destroy
  has_many :registrations, :dependent => :destroy
  has_one :profile, :dependent => :destroy
  has_many :direct_grades, :class_name => 'Grade', :dependent => :destroy,
           :as => :subject
  has_many :submissions, :dependent => :destroy
  has_many :notice_statuses, :dependent => :destroy
  has_many :notices, :through => :notice_statuses
  has_many :team_memberships, :dependent => :destroy
  has_many :teams, :through => :team_memberships
  has_many :survey_answers

  attr_protected :admin, :active
  
  # The user name.
  validates_length_of :name, :in => 2..64, :allow_nil => false
  validates_format_of :name, :with => /^\w+$/,
      :message => 'can only contain letters, numbers, and _'  
  validates_uniqueness_of :name  
  
  # Random string preventing dictionary attacks on the password database.
  validates_length_of :password_salt, :in => 1..16, :allow_nil => false
    
  # SHA-256 of (salt + password).
  validates_length_of :password_hash, :in => 1..64, :allow_nil => false
  
  # @mit.edu e-mail address used to endorse the user account.
  validates_format_of :email, :with => /^[A-Za-z0-9.+_]+@mit.edu$/,
                      :message => 'needs to be an @mit.edu e-mail address',
                      :allow_nil => false
  validates_length_of :email, :in => 1..64
  validates_uniqueness_of :email
  
  # Administrators are staff members.  
  validates_inclusion_of :admin, :in => [true, false]
  
  # Prevents logins from un-confirmed accounts.
  validates_inclusion_of :active, :in => [true, false]
  
  # Virtual attribute: the user's password.
  attr_reader :password
  def password=(<PASSWORD>)
    @password = <PASSWORD>
    if new_password
      self.password_salt = [(0...12).map { |i| 1 + rand(255) }.pack('C*')].
                                     pack('m').strip
      self.password_hash = User.hash_password new_password, password_salt
    else
      self.password_salt = self.password_hash = nil
    end
  end
  
  # Virtual attribute: confirmation for the user's password.
  attr_accessor :password_confirmation
  validates_confirmation_of :password, :allow_nil => true
  
  # Compares the given password against the user's stored password.
  #
  # Returns +true+ for a match, +false+ otherwise.
  def check_password(passwd)
    password_hash == User.hash_password(passwd, password_salt)
  end
  
  # Computes a password hash from a raw password and a salt.
  def self.hash_password(password, salt)
    Digest::SHA2.hexdigest(password + salt)
  end
  
  # Resets the virtual password attributes.
  def reset_password
    self.password = self.password_confirmation = nil
  end
  
  # The authenticated user or nil.
  def self.authenticate(user_name, password)
    @user = User.find :first, :conditions => {:name => user_name }    
    (@user && @user.check_password(password)) ? @user : nil
  end  
  
  # Submissions connected to this user.
  #
  # Returns the submissions authored by the user, as well as the submissions
{'fraction_non_alphanumeric': 0.10852936931736182, 'fraction_numerical': 0.01443209698369173, 'mean_word_length': 3.2411260709914322, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 63, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7512933', 'n_tokens_mistral': 2289, 'n_tokens_neox': 2166, 'n_words': 627}