No se pueden suspender/desactivar usuarios en bloque en la consola de Rails en Discourse 3.5.0.beta5-dev

Hola a todos,

Me enfrento a un problema persistente al intentar suspender/desactivar usuarios en masa en mi instancia de Discourse (versión 3.5.0.beta5-dev) a través de la consola de Rails. Estoy intentando excluir mi cuenta de administrador (hoangthai, ID de usuario 100) y suspender permanentemente a todos los demás usuarios activos que no son administradores/moderadores con una razón personalizada “Chưa gia hạn tài khoản” (Renovación de cuenta pendiente).

He intentado varios enfoques basados en comandos comunes de la consola de Discourse y sugerencias de depuración, pero las cuentas permanecen active: true aunque suspended_at y suspended_till puedan establecerse.

Aquí hay un desglose de lo que he intentado y los errores/resultados:

Mi objetivo: Suspender a todos los usuarios permanentemente (excepto hoangthai, ID 100) con la razón “Chưa gia hạn tài khoản” (Renovación de cuenta pendiente).

Intentos y problemas:

  1. Intento inicial (Estableciendo suspend_reason, suspended_at, suspended_till directamente):

    admin_id_to_exclude = 100
    User.where.not(id: admin_id_to_exclude).each do |user|
      if user.active? && !user.admin? && !user.moderator?
        user.suspend_reason = "Tài khoản tạm khóa do nghỉ phép dài hạn." # Primer intento de razón
        user.suspended_at = Time.current
        user.suspended_till = Time.current + 100.years
        user.save!
        puts "Khóa tài khoản: #{user.username}"
      end
    end
    
    • Resultado: NoMethodError: undefined method 'suspend_reason=' for an instance of User (sugirió suspended_at=). Esto indicó que suspend_reason no era el atributo correcto.
  2. Segundo intento (Usando UserSuspension.suspend_user como se sugirió para las versiones más recientes):

    admin_id_to_exclude = 100
    User.where.not(id: admin_id_to_exclude).each do |user|
      if user.active? && !user.admin? && !user.moderator?
        UserSuspension.suspend_user(
            user,
            Time.current + 100.years,
            nil, # suspend_reason_id
            "Tài khoản tạm khóa: Nghỉ phép dài hạn.", # custom_suspend_reason
            Discourse.system_user
        )
        puts "Đã khóa tài khoản: #{user.username}"
      end
    end
    
    • Resultado: NameError: uninitialized constant UserSuspension (sugirió UserSuspender). Esto indicó que el nombre de la clase era incorrecto.
  3. Tercer intento (Nombre de clase corregido a UserSuspender):

    admin_id_to_exclude = 100
    User.where.not(id: admin_id_to_exclude).each do |user|
      if user.active? && !user.admin? && !user.moderator?
        UserSuspender.suspend_user( # Todavía intentando suspend_user
            user,
            Time.current + 100.years,
            nil,
            "Tài khoản tạm khóa: Nghỉ phép dài hạn.",
            Discourse.system_user
        )
        puts "Đã khóa tài khoản: #{user.username}"
      end
    end
    
    • Resultado: NoMethodError: undefined method 'suspend_user' for class UserSuspender (sugirió UserSuspended?). Esto mostró que el nombre del método también era incorrecto.
  4. Cuarto intento (usando UserSuspender.new(...).suspend como patrón de objeto de servicio):

    admin_id_to_exclude = 100
    User.where.not(id: admin_id_to_exclude).each do |user|
      if user.active? 		 !user.admin? 		 !user.moderator?
        begin
            UserSuspender.new(
                user,
                Discourse.system_user,
                reason: "Tài khoản tạm khóa: Nghỉ phép dài hạn.",
                suspended_till: nil # For permanent suspension
            ).suspend
            puts "Đã khóa tài khoản: #{user.username}"
        rescue => e
            puts "Lỗi khi khóa tài khoản #{user.username}: #{e.message}"
        end
      end
    end
    
    • Resultado: Este comando se ejecutó sin errores en la consola. Imprimió “Đã khóa tài khoản: [username]”.
    • Sin embargo, al verificar el estado del usuario en la interfaz de usuario del administrador o consultar directamente user.active en la consola, los usuarios aún mostraban active: true. Solo se actualizaron suspended_at y suspended_till (por ejemplo, suspended_at: "2025-05-26 00:37:01.406064419 +0000", suspended_till: nil). Las cuentas aún podían iniciar sesión.
  5. Quinto intento (Estableciendo directamente active = false junto con los campos de suspensión):

    admin_id_to_exclude = 100
    User.where.not(id: admin_id_to_exclude).each do |user|
      if user.active? 		 !user.admin? 		 !user.moderator?
        begin
            user.suspended_at = Time.current
            user.suspended_till = nil # Permanent
            user.custom_suspension_reason = "Chưa gia hạn tài khoản" # Custom reason
            user.active = false # Crucial part
            user.save!
            puts "Đã **khóa VĨNH VIỄN** y vô hiệu hóa tài khoản: #{user.username}"
        rescue => e
            puts "LỖI khi xử lý tài khoản #{user.username}: #{e.message}"
        end
      end
    end
    
    • Resultado: Este comando también se ejecutó sin errores e imprimió mensajes de éxito.
    • Sin embargo, el resultado fue el mismo: active: true permaneció, y suspended_at/suspended_till se actualizaron, pero las cuentas no se desactivaron realmente…
1 me gusta

No creo que la desactivación sea parte del proceso de suspensión de usuarios. En la interfaz de usuario, tendrías que presionar el botón ‘desactivar’ por separado si quisieras que un usuario suspendido que regresa también volviera a verificar su correo electrónico.

Decidir si eso es lo que quieres y abordarlo como una operación separada puede dar mejores resultados. :crossed_fingers:

Hay algunas guías para suspensiones masivas en este tema si eso ayuda Administrative Bulk Operations

Aunque si lo intentas y descubres que está desactualizado, házselo saber y deberían poder actualizar la guía en consecuencia.

1 me gusta