Discourse 3.5.0.beta5-dev에서 Rails 콘솔로 사용자 일괄 정지/비활성화 불가

안녕하세요 여러분,

Discourse 인스턴스(버전 3.5.0.beta5-dev)에서 Rails 콘솔을 통해 사용자를 일괄 정지/비활성화하려는 시도에 지속적인 문제가 발생하고 있습니다. 관리자 계정(hoangthai, 사용자 ID 100)은 제외하고, 나머지 모든 활성 상태의 일반 사용자(관리자/모더레이터 제외)를 “Chưa gia hạn tài khoản”(계정 갱신 대기 중)라는 커스텀 사유로 영구 정지시키려고 합니다.

일반적인 Discourse 콘솔 명령어와 디버깅 제안에 기반한 여러 가지 방법을 시도해 보았지만, suspended_at와 suspended_till이 설정된 것처럼 보임에도 불구하고 계정들은 여전히 active: true 상태를 유지하고 있습니다.

시도한 내용과 발생한 오류/결과를 정리하면 다음과 같습니다:

목표: hoangthai(ID 100)를 제외하고 모든 사용자를 “Chưa gia hạn tài khoản”(계정 갱신 대기 중) 사유로 영구 정지시키기.

시도 및 문제점:

  1. 첫 번째 시도 (suspend_reason, suspended_at, suspended_till 직접 설정):

    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." # 첫 번째 사유 시도
        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
    
    • 결과: NoMethodError: undefined method 'suspend_reason=' for an instance of User (suspended_at= 권장). 이는 suspend_reason이 올바른 속성이 아니라는 것을 의미했습니다.
  2. 두 번째 시도 (신규 버전에 권장되는 UserSuspension.suspend_user 사용):

    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
    
    • 결과: NameError: uninitialized constant UserSuspension (UserSuspender 권장). 이는 클래스 이름이 올바르지 않다는 것을 의미했습니다.
  3. 세 번째 시도 (클래스 이름을 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( # 여전히 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
    
    • 결과: NoMethodError: undefined method 'suspend_user' for class UserSuspender (UserSuspended? 권장). 이는 메서드 이름도 올바르지 않다는 것을 보여주었습니다.
  4. 네 번째 시도 (서비스 객체 패턴으로 UserSuspender.new(...).suspend 사용):

    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 # 영구 정지를 위해
            ).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
    
    • 결과: 이 명령어는 콘솔에서 오류 없이 실행되었습니다. "Đã khóa tài khoản: [username]"이 출력되었습니다.
    • 그러나, 관리자 UI에서 사용자 상태를 확인하거나 콘솔에서 user.active를 직접 쿼리했을 때, 사용자들은 여전히 active: true로 표시되었습니다. suspended_at와 suspended_till만 업데이트되었습니다(예: suspended_at: "2025-05-26 00:37:01.406064419 +0000", suspended_till: nil). 계정들은 여전히 로그인할 수 있었습니다.
  5. 다섯 번째 시도 (정지 필드와 함께 active = false 직접 설정):

    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 # 영구
            user.custom_suspension_reason = "Chưa gia hạn tài khoản" # 커스텀 사유
            user.active = false # 핵심 부분
            user.save!
            puts "Đã **khóa VĨNH VIỄN** và 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
    
    • 결과: 이 명령어도 오류 없이 실행되어 성공 메시지가 출력되었습니다.
    • 그러나 결과는 동일했습니다: active: true가 유지되었고, suspended_at/suspended_till은 업데이트되었지만, 계정들은 실제로 비활성화되지 않았으며 로그인도 차단되지 않았습니다.

현재 상황:

관리자 UI(관리자 → 사용자 → 정지)를 통해 수동으로 사용자를 정지시키면 올바르게 정지됩니다(예: 이전 스크린샷에 표시된 "Tạm khóa bởi: hoangthai, Lý do: Chưa gia hạn tài khoản"와 같이, 로그인이 불가능해짐). 이는 핵심 기능이 정상 작동한다는 것을 확인시켜 줍니다.

Discourse 3.5.0.beta5-dev에서 사용자를 프로그래매틱하게 정지/비활성화하는 데 특정한 API 미묘한 차이가 있어서 제가 놓치고 있거나, 캐시 문제가 제대로 해제되지 않거나, 실행되어야 할 백그라운드 작업이 있는 것 같습니다.

Discourse 3.5.x 베타 버전이나 깊은 Rails 콘솔 지식이 있는 분 중, 사용자의 로그인을 실제로 방지하고 active 상태를 false로 설정하는 일괄 영구 정지를 올바르게 수행하는 방법에 대해 조언해 주실 수 있을까요?

시간 내어 도와주셔서 감사합니다!

비활성화(deactivation)가 사용자 정지(suspension) 과정의 일부라고 생각하지 않습니다. UI에서는 복귀한 정지된 사용자에게 이메일 재확인을 요구하려면 ‘비활성화’ 버튼을 별도로 눌러야 합니다.

이것이 원하는 동작인지 판단하고, 이를 별도의 작업으로 처리하면 더 나은 결과를 얻을 수 있을 것입니다. :crossed_fingers:

도움이 된다면, 이 주제에서 대량 정지에 대한 안내를 찾을 수 있습니다: Administrative Bulk Operations

다만, 해당 내용을 시도해 보았는데 내용이 오래되었음을 발견하면 알려주세요. 그러면 가이드를 적절히 업데이트할 수 있을 것입니다.