# CommonPasswords will check a given password against a list of the most commonly used passwords.
# The list comes from https://xato.net/passwords/more-top-worst-passwords/#.UrR1AHmpxs4
# The list is stored in Redis at a key that is shared by all sites in a multisite config.
#
# If the password file is changed, you need to add a migration that deletes the list from redis
# so it gets re-populated:
#
#   $redis.without_namespace.del CommonPasswords::LIST_KEY

class CommonPasswords

  PASSWORD_FILE = File.join(Rails.root, 'lib', 'common_passwords', '10k-common-passwords.txt')
  LIST_KEY = 'discourse-common-passwords'

  @mutex = Mutex.new

  def self.common_password?(password)
    return false unless password.present?
    password_list.include?(password)
  end


  private

    class RedisPasswordList
      def include?(password)
        CommonPasswords.redis.sismember CommonPasswords::LIST_KEY, password
      end
    end

    def self.password_list
      @mutex.synchronize do
        load_passwords unless redis.scard(LIST_KEY) > 0
      end
      RedisPasswordList.new
    end

    def self.redis
      $redis.without_namespace
    end

    def self.load_passwords
      passwords = File.readlines(PASSWORD_FILE)
      passwords.map!(&:chomp).each do |pwd|
        # slower, but a tad more compatible
        redis.sadd LIST_KEY, pwd
      end
    rescue Errno::ENOENT
      # tolerate this so we don't block signups
      Rails.logger.error "Common passwords file #{PASSWORD_FILE} is not found! Common password checking is skipped."
    end

end
