Пожалуйста, оцените короткий скрипт на Ruby для приостановки неактивных пользователей

Это мой первый кастомный скрипт на Ruby. :slight_smile: За почти 50 лет программирования на более чем 20 языках и диалектах мне никогда не приходилось (и не хотелось :face_with_open_eyes_and_hand_over_mouth:) писать на Ruby, но ладно, вы меня поймали… пожалуйста, будьте мягче. :pray:

Моя цель — идентифицировать учетные записи пользователей, которые не были подтверждены по ссылкам в письмах, и приостановить их, чтобы я мог проверить их перед удалением. При первоначальной настройке у меня были настройки на разных стадиях разработки. Письма с 2FA не отправлялись для некоторых регистраций, и было много поддельных регистраций, которые я теперь хотел бы отфильтровать.

Версия 0.0.1

rails c

# Сначала убедитесь, что уровни доверия пользователей (TL) соответствуют последним определениям
User.all.find_each do |user|
  Promotion.recalculate(user)
end
Group.ensure_consistency!

# Подготовка к циклу
logger = StaffActionLogger.new(User.where("id = 'admin'"))
# временная дата, пользователи будут удалены до этой даты
suspend_till = DateTime.new(2028, 12, 31)
suspend_at = DateTime.now
reason = 'Неактивен'

# Идентификация потенциально неактивных учетных записей
User.where("views = 0 OR approved = FALSE OR last_seen_at IS NULL")
    .where("id > 0")
    .find_each do |user|
  user.suspended_till = suspend_till
  user.suspended_at = suspend_at
  user.change_trust_level!(TrustLevel[0])
  # сохраните пользователя, запишите действие и ... выполните всё, что требуется для этого триггера
  user.save!
  logger.log_user_suspend(user, reason)
  DiscourseEvent.trigger(:user_suspended, user: user)
  # избегайте перегрузки почтового сервера
  sleep(10)
end

Запуская событие, я хочу, чтобы пользователям отправлялись письма — будет много отскоков, и возможно, несколько человек вернутся для подтверждения. Через неделю я выберу все ещё приостановленные учетные записи и удалю их.

Вопросы:

  1. В целом, сделает ли это то, что задумано?
  2. Есть ли лучший подход?
  3. Является ли логирование избыточным по сравнению с триггером события?
  4. Можно ли сделать это с помощью JavaScript?
  5. Стоит ли мне опубликовать это в другой категории?
  6. Есть ли какие-либо другие советы?

Спасибо!!

Хм, глядя на это, я думаю, что мне следует именно замолчать аккаунт, а не приостанавливать его. Если аккаунт приостановлен, пользователь не сможет войти в систему, чтобы подтвердить его.

Вот исправленный вариант …

Версия 0.0.2
silence_reason = 'Inactive'
User.where("views = 0 OR approved = FALSE OR last_seen_at IS NULL")
    .where("id > 0") # избегаем системных пользователей
    .find_each do |user|
  user.silence(reason: silence_reason)
  user.change_trust_level!(TrustLevel[0])
  user.save!
  logger.log_user_silence(user, silence_reason)
  DiscourseEvent.trigger(:user_silenced, user: user)
  sleep(5)
end

Да, я сделаю резервную копию перед выполнением любых действий.
Да, я знаю, что некоторые существующие уровни доверия (TL) будут изменены, и мне придется их исправить.

Кроме того, вместо молчания или вместе с ним, стоит ли установить Approved=false или Active=false? Я полагаю, что это заставит пользователя нажать на ссылку в письме, а не просто войти в систему вручную, что служит целью подтверждения адреса электронной почты.

Всё это связано с моей недавней темой: notes-on-silencing-or-deleting-users

[EDIT]
У меня также установлено значение “grace period days для удаления неактивированных пользователей” равным 7.
Сбрасывает ли молчание или приостановка этот период? Если да, то если пользователи не отреагируют на действие с аккаунтом в течение 7 дней, я не возражаю против их удаления.

Наконец (да, действительно), у меня также установлено значение “clean up inactive users after days” равным 365. Я могу уменьшить его до 60, пока форум ещё открывается, и просто позволить существующим аккаунтам исчезнуть из списка. Затем увеличить обратно до 365. Является ли это разумным подходом к автоматической очистке аккаунтов в новой среде?

Почему этого недостаточно, чтобы решить вашу проблему?

Разве там не должно быть AND вместо OR?

Discourse принуждает пользователей подтверждать адреса, поэтому я не совсем понимаю, какую проблему вы пытаетесь решить. Вы говорите следующее:

Кажется крайне маловероятным, что вы найдёте пользователей, которые хотели войти, но не могли сделать это раньше, хотя, возможно, вы знаете о вашей конфигурации что-то, что мне неизвестно.

Кроме того, Discourse не отправляет письма на неподтверждённые адреса, поэтому я не думаю, что это приведёт к отправке каких-либо писем.

Я всегда тестирую такие вещи на нескольких аккаунтах, но интересно посмотреть, что произойдёт.

Спасибо за ваш интерес, @pfaffman!

Есть записи пользователей без поля last_seen_at, созданные месяцы назад, с approved=False и active=False, но они не удаляются.
Есть записи пользователей с last_seen_at > 7 дней (созданные месяцы назад) и 0 просмотров, но они также не удаляются.

Какие бы критерии ни использовались с этим флагом grace period, они не отбирают эти записи.
Может ли кто-нибудь опубликовать точный запрос, который используется здесь, чтобы я мог понять, какие ещё факторы задействованы?

Нет, при прямом просмотре базы данных обнаруживаются записи пользователей, которые соответствуют каждому критерию по отдельности, но не всем сразу. Похоже, что таблица пользователей в базе данных несбалансирована. Есть записи с ненулевыми topics_entered или posts_read_count, но с views=0. Есть записи с topics_entered=0 и posts_read_count=0, но views не равен нулю.

Главное, что нужно помнить: в процессе разработки этого сайта настройки не были оптимальными, и регистрировались как люди, так и боты. Условие OR, похоже, охватывает все эти случаи. Теперь, когда сайт стабилизирован и (надеюсь) настройки разумны, я не ожидаю, что новые регистрации приведут к таким же аномалиям.

Я планирую запускать скрипт многократно с различными критериями. Сначала я буду выполнять запрос к записям вне среды, а затем запущу скрипт silence, чтобы воздействовать только на те записи, которые мне действительно нужны. Через пару недель я проведу финальный запуск: выберу только заглушённые записи (у тех, кто действительно вернулся, флаг будет снят), и удалю их все:

UserDestroyer.new(admin_user).destroy(user, reassign_to: archive_user)

Мой общий вопрос: корректен ли скрипт версии v0.0.2 с его подходом к выбору, логированию и заглушению для системы Discourse? Не знаю, нужно ли что-то ещё делать в цикле подобного рода. Я никогда не создавал и не запускал собственные скрипты, поэтому прошу проверить меня на наличие ошибок новичка.

Спасибо!!