<commit_before>require 'active_record'
require 'authlogic'
require 'phpass'

class CASino::ActiveRecordAuthLogicAuthenticator

  class AuthDatabase < ::ActiveRecord::Base
    self.abstract_class = true
  end

    def initialize(options)
    if !options.respond_to?(:deep_symbolize_keys)
      raise ArgumentError, "When assigning attributes, you must pass a hash as an argument."
    end
    @options = options.deep_symbolize_keys
    raise ArgumentError, "Table name is missing" unless @options[:table]
    if @options[:model_name]
      model_name = @options[:model_name]
    else
      model_name = @options[:table]
      if @options[:connection].kind_of?(Hash) && @options[:connection][:database]
        model_name = "#{@options[:connection][:database].gsub(/[^a-zA-Z]+/, '')}_#{model_name}"
      end
      model_name = model_name.classify
    end
    model_class_name = "#{self.class.to_s}::#{model_name}"
    eval <<-END
      class #{model_class_name} < AuthDatabase
        self.table_name = "#{@options[:table]}"
        self.inheritance_column = :_type_disabled
      end
    END

    @model = model_class_name.constantize
    @model.establish_connection @options[:connection]
  end

  def validate(username, password)
    user = @model.send("find_by_#{@options[:username_column]}!", username)
    crypted_password = user.send(@options[:password_column])
    password_salt = user.send(@options[:password_salt_column])

    if valid_password?(password, crypted_password, password_salt)
      user_data(user)
    else
      false
    end
  rescue ActiveRecord::RecordNotFound
    false
  end

  def load_user_data(username)
    user = @model.send("find_by_#{@options[:username_column]}!", username)
    user_data(user)
  rescue ActiveRecord::RecordNotFound
    nil
  end

  private

  def user_data(user)
    { username: user.send(@options[:username_column]), extra_attributes: extra_attributes(user) }
  end

  def valid_password?(password, crypted_password, password_salt)
    return false if crypted_password.blank?
    tokens = [password, password_salt]
    encryptor.matches?(crypted_password, tokens)
  end

  def encryptor
    encryptor = @options[:encryptor] || "Sha512"
    eval("Authlogic::CryptoProviders::#{encryptor}")
  end


  def extra_attributes(user)
    attributes = {}<commit_msg>Refactor authenticator, validate options<commit_after>require 'active_record'
require 'authlogic'

class CASino::ActiveRecordAuthLogicAuthenticator

  class AuthDatabase < ::ActiveRecord::Base
    self.abstract_class = true
  end

  def initialize(options)
    set_options options
    validate_options
    model_name = get_model_name
    model_name = classify_table_model_name model_name if model_name == options[:table]
    model_class_name = "#{self.class.to_s}::#{model_name}"
    load_class model_class_name
    @model = model_class_name.constantize
    @model.establish_connection @options[:connection]
  end

  def validate(username, password)
    user = @model.send("find_by_#{@options[:username_column]}!", username)
    crypted_password = user.send(@options[:password_column])
    password_salt = user.send(@options[:password_salt_column])

    if valid_password?(password, crypted_password, password_salt)
      user_data(user)
    else
      false
    end
  rescue ActiveRecord::RecordNotFound
    false
  end

  def load_user_data(username)
    user = @model.send("find_by_#{@options[:username_column]}!", username)
    user_data(user)
  rescue ActiveRecord::RecordNotFound
    nil
  end

  private

  def set_options options
    if !options.respond_to?(:deep_symbolize_keys)
      raise ArgumentError, "When assigning attributes, you must pass a hash as an argument."
    end
    @options = options.deep_symbolize_keys
  end

  def validate_options
    raise ArgumentError, "Table name is missing" if @options[:table].blank?
    if @options[:encryptor] && !(@options[:encryptor].in? allowed_encryptors)
      raise ArgumentError, "Bad encryptor. Available encryptors: #{allowed_encryptors.join(',')}"
    end
  end

  def allowed_encryptors
    ["Sha512", "AES256", "BCrypt", "MD5", "Sha1"]
  end

  def get_model_name
    if @options[:model_name]
      @options[:model_name]
    else
      @options[:table]
    end
  end

  def classify_table_model_name model_name
    if @options[:connection].kind_of?(Hash) && @options[:connection][:database]
      model_name = "#{@options[:connection][:database].gsub(/[^a-zA-Z]+/, '')}_#{model_name}"
    end
    model_name.classify
  end

  def load_class model_class_name
    eval <<-END
        class #{model_class_name} < AuthDatabase
          self.table_name = "#{@options[:table]}"
          self.inheritance_column = :_type_disabled
        end
      END
  end

  def user_data user
    { username: user.send(@options[:username_column]), extra_attributes: extra_attributes(user) }
  end

  def valid_password? password, crypted_password, password_salt
    return false if crypted_password.blank?
    tokens = [password, password_<PASSWORD>]
    encryptor.matches?(crypted_password, tokens)
  end

  def encryptor
    encryptor = @options[:encryptor] || "Sha512"
    eval("Authlogic::CryptoProviders::#{encryptor}")
  end


  def extra_attributes(user)
    attributes = {}
{'fraction_non_alphanumeric': 0.11219232970807098, 'fraction_numerical': 0.0026712459454302615, 'mean_word_length': 4.179841897233201, 'pattern_counts': {'":': 0, '<': 12, '<?xml version=': 0, '>': 4, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1455090', 'n_tokens_mistral': 1659, 'n_tokens_neox': 1613, 'n_words': 333}