Hi everyone,
I’m facing a persistent issue trying to bulk suspend/deactivate users on my Discourse instance (version 3.5.0.beta5-dev) via the Rails console. I’m trying to exclude my admin account (hoangthai, user ID 100) and permanently suspend all other active non-admin/non-moderator users with a custom reason “Chưa gia hạn tài khoản” (Account renewal pending).
I’ve tried several approaches based on common Discourse console commands and debugging suggestions, but the accounts remain active: true even though suspended_at and suspended_till might get set.
Here’s a breakdown of what I’ve attempted and the errors/results:
My Goal: Suspend all users permanently (except hoangthai, ID 100) with the reason “Chưa gia hạn tài khoản” (Account renewal pending).
Attempts & Issues:
-
Initial Attempt (Setting
suspend_reason,suspended_at,suspended_tilldirectly):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." # First reason attempt 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- Result:
NoMethodError: undefined method 'suspend_reason=' for an instance of User(suggestedsuspended_at=). This indicatedsuspend_reasonwas not the correct attribute.
- Result:
-
Second Attempt (Using
UserSuspension.suspend_useras suggested for newer versions):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- Result:
NameError: uninitialized constant UserSuspension(suggestedUserSuspender). This indicated the class name was incorrect.
- Result:
-
Third Attempt (Corrected class name to
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( # Still trying 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- Result:
NoMethodError: undefined method 'suspend_user' for class UserSuspender(suggestedUserSuspended?). This showed the method name was also incorrect.
- Result:
-
Fourth Attempt (Using
UserSuspender.new(...).suspendas the service object pattern):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- Result: This command ran without errors in the console. It printed “Đã khóa tài khoản: [username]”.
- However, when checking user status in the admin UI or directly querying
user.activein console, users still showedactive: true. Onlysuspended_atandsuspended_tillwere updated (e.g.,suspended_at: "2025-05-26 00:37:01.406064419 +0000", suspended_till: nil). The accounts were still able to log in.
-
Fifth Attempt (Directly setting
active = falsealong with suspension fields):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** 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- Result: This command also ran without errors and printed success messages.
- However, the outcome was the same:
active: trueremained, andsuspended_at/suspended_tillwere updated, but accounts were not actually deactivated or prevented from logging in.
My Current Situation:
I can manually suspend users via the admin UI (Admin → Users → Suspend) and they get correctly suspended (e.g., as shown in your previous screenshot with “Tạm khóa bởi: hoangthai, Lý do: Chưa gia hạn tài khoản”, and they cannot log in). This confirms the core functionality works.
I suspect there’s a specific API nuance in Discourse 3.5.0.beta5-dev for programmatically suspending/deactivating users that I’m missing, or perhaps a caching issue that’s not being cleared, or a background job that needs to run.
Could anyone with experience in Discourse 3.5.x beta versions or deep Rails console knowledge offer some guidance on how to correctly achieve a bulk, permanent suspension that actually prevents user logins and sets the active status to false?
Thank you for your time and help!