Discurso-ip-alerta: Necesito ayuda con el plugin creado

Este plugin tiene la intención de enviar una alerta por correo electrónico a todos los administradores cada vez que un usuario inicia sesión desde una dirección IP sospechosa. Lo hace extrayendo la IP del último token de autenticación (usando el campo client_ip), verificando esta IP contra una lista negra definida en la configuración del sitio (ip_alert_suspicious_ips), y si la IP coincide con algún patrón bloqueado, envía un correo electrónico de advertencia a todos los usuarios administradores.

Error Observado:

A pesar de que el código del plugin parece correcto y sigue los patrones estándar de los plugins de Discourse, todavía encuentro el error genérico “Oops – The software powering this discussion forum encountered an unexpected problem” al iniciar sesión. Los registros de errores no muestran indicaciones claras de nuestros mensajes de registro [DiscourseIpAlert], y el rastreo de la pila no señala un problema directamente dentro del código de nuestro plugin.

Estado Actual:

He revisado y modificado el plugin varias veces, incluyendo la verificación de la configuración del sitio y asegurándome de que el hook (on(:user_logged_in)) esté correctamente registrado. La lógica de extracción de IP y envío de correo electrónico también parece estar implementada correctamente, sin embargo, el error 500 Internal Server Error persiste sin un rastreo de pila claro que lo vincule a nuestro plugin.

¿Alguna ayuda?

plugin.rb:

# frozen_string_literal: true

# name: discourse-ip-alert
# about: Sends an email alert when a user logs in from a suspicious IP address.
# version: 0.7
# authors: OrkoGrayskull (revised)
# required_version: 3.5.0

enabled_site_setting :ip_alert_enabled
enabled_site_setting :ip_alert_suspicious_ips

module ::DiscourseIpAlert
  PLUGIN_NAME = "discourse-ip-alert".freeze

  require "ipaddr"
  require "mail"

  # Extracts the IP address from the latest authentication token
  def self.extract_ip(user)
    token = UserAuthToken.where(user_id: user.id).order(created_at: :desc).first
    ip = token&.attributes["client_ip"]
    Rails.logger.info("[DiscourseIpAlert] extract_ip: Extracted IP from UserAuthToken: #{ip.inspect}")
    ip
  rescue => e
    Rails.logger.error("[DiscourseIpAlert] extract_ip error: #{e.message}")
    nil
  end

  # Checks if the given IP address is present in the blocklist
  def self.ip_blocked?(ip_address)
    return false if ip_address.blank?
    blocked_ips = SiteSetting.ip_alert_suspicious_ips.split(",").map(&:strip)
    Rails.logger.info("[DiscourseIpAlert] ip_blocked?: Blocked IPs: #{blocked_ips.inspect}")
    blocked_ips.any? do |blocked|
      if blocked.include?("*")
        regex = Regexp.new("^" + Regexp.escape(blocked).gsub("\\*", "\\d{1,3}") + "$")
        Rails.logger.info("[DiscourseIpAlert] ip_blocked?: Comparing #{ip_address} with wildcard regex #{regex.inspect}")
        ip_address.match?(regex)
      else
        begin
          result = IPAddr.new(blocked).include?(ip_address)
          Rails.logger.info("[DiscourseIpAlert] ip_blocked?: Comparing #{ip_address} with #{blocked}: #{result}")
          result
        rescue IPAddr::InvalidAddressError => e
          Rails.logger.error("[DiscourseIpAlert] ip_blocked?: Invalid IP in blocklist: #{blocked} (#{e.message})")
          false
        end
      end
    end
  rescue => e
    Rails.logger.error("[DiscourseIpAlert] ip_blocked? error: #{e.message}")
    false
  end

  # Sends a warning email to all admins
  def self.send_warning_email(user, ip_address)
    admin_emails = User.where(admin: true).pluck(:email)
    return if admin_emails.empty?
    subject = "⚠️ Warning: Login from a Suspicious IP!"
    body = <<~BODY
      Attention!

      The user #{user.username} (#{user.email}) has logged in from the IP address #{ip_address},
      which has been flagged as suspicious.

      Please review this account.
    BODY
    admin_emails.each do |email|
      begin
        mail = Mail.new do
          from    ENV["DISCOURSE_NOTIFICATION_EMAIL"] || "no-reply@example.org"
          to      email
          subject subject
          body    body
        end
        Rails.logger.info("[DiscourseIpAlert] Sending warning email to #{email}")
        mail.deliver!
      rescue => e
        Rails.logger.error("[DiscourseIpAlert] Error sending email to #{email}: #{e.message}")
      end
    end
  rescue => e
    Rails.logger.error("[DiscourseIpAlert] send_warning_email error: #{e.message}")
  end

  # Processes the user login: extracts the IP, checks the blocklist, and sends a warning email if necessary
  def self.process_user_login(user)
    Rails.logger.info("[DiscourseIpAlert] process_user_login for user: #{user.username}")
    ip_address = extract_ip(user)
    unless ip_address
      Rails.logger.warn("[DiscourseIpAlert] No IP address extracted – skipping further processing.")
      return
    end
    if ip_blocked?(ip_address)
      Rails.logger.warn("[DiscourseIpAlert] Suspicious IP detected: #{ip_address}")
      send_warning_email(user, ip_address)
    else
      Rails.logger.info("[DiscourseIpAlert] IP #{ip_address} is considered safe.")
    end
  rescue => e
    Rails.logger.error("[DiscourseIpAlert] process_user_login error: #{e.message}")
  end
end

after_initialize do
  Rails.logger.info("[DiscourseIpAlert] after_initialize: Plugin is being integrated into the login process.")

  # Register the hook that is called on every user login
  on(:user_logged_in) do |user|
    begin
      Rails.logger.info("[DiscourseIpAlert] on(:user_logged_in) hook called for user: #{user.username}")
      ::DiscourseIpAlert.process_user_login(user)
    rescue => e
      Rails.logger.error("[DiscourseIpAlert] Error in on(:user_logged_in) hook: #{e.message}")
    end
  end
end

config/settings.yml:

ip_alert_enabled:
  default: false
  client: true
  type: bool
  description: "Enable the IP alert"

ip_alert_suspicious_ips:
  default: "192.168.1.1,203.0.113.0/24"
  client: true
  type: string
  description: "List of suspicious IP addresses (comma-separated)"