비활성 사용자를 정지하기 위해 짧은 Ruby 스크립트를 평가해 주세요

제가 처음 작성하는 커스텀 Ruby 스크립트입니다. :slight_smile: 20개 이상의 언어와 변형 언어로 50년 가까이 코딩을 해왔지만, Ruby로 작성할 필요(또는 욕구 :face_with_open_eyes_and_hand_over_mouth:)가 생긴 적은 한 번도 없었는데, 어쩔 수 없네요 … 너그러이 봐주세요. :pray:

제 목표는 이메일 링크로 인증되지 않은 사용자 계정을 식별하고, 삭제 전에 확인을 위해 해당 계정을 일시 정지하는 것입니다. 초기 설정 단계에서 여러 설정이 개발 중이던 상태였습니다. 일부 가입자에게 2FA 이메일이 발송되지 않았고, 이제 필터링하고 싶은 잘못된 가입 정보도 많았습니다.

Version 0.0.1

rails c

# First ensure user TLs conform to latest definitions
User.all.find_each do |user|
  Promotion.recalculate(user)
end
Group.ensure_consistency!

# Prep for loop
logger = StaffActionLogger.new(User.where("id = 'admin'"))
# temporary date, users will be removed before this date
suspend_till = DateTime.new(2028, 12, 31)
suspend_at = DateTime.now
reason = 'Inactive'

# Identify potentially dead accounts
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])
  # save the user, log the action, and ... do whatever is done for this trigger
  user.save!
  logger.log_user_suspend(user, reason)
  DiscourseEvent.trigger(:user_suspended, user: user)
  # avoid abusing the mail server
  sleep(10)
end

이벤트를 트리거하면 사용자에게 이메일이 발송되기를 바랍니다 - 바운스(수신 불가)가 꽤 있을 것이고, 인증을 위해 돌아오는 사람이 몇 명 있을 수도 있습니다. 일주일 후 여전히 일시 정지된 모든 계정을 선택하여 삭제할 것입니다.

질문:

  1. 일반적으로 이 코드가 의도한 대로 작동할까요?
  2. 더 나은 접근 방식이 있을까요?
  3. 로깅이 이벤트 트리거와 중복됩니까?
  4. JavaScript로 이것을 할 수 있을까요?
  5. 다른 카테고리에 이 내용을 게시해야 할까요?
  6. 다른 조언이 있을까요?

감사합니다!!

음, 그걸 보니 계정 정지(suspend)보다는 계정 무음 처리(silence)를 해야 할 것 같습니다. 계정이 정지되면 사용자가 로그인하여 계정을 주장(claim)할 수 없기 때문입니다.

다음은 수정된 내용입니다 …

Version 0.0.2
silence_reason = 'Inactive'
User.where("views = 0 OR approved = FALSE OR last_seen_at IS NULL")
    .where("id > 0") # avoid system users
    .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

네, 이 작업들을 수행하기 전에 백업을 실행하겠습니다.
네, 일부 기존 신뢰 수준(Trust Level, TL)이 변경될 것이며 이를 수정해야 한다는 것을 알고 있습니다.

추가로, 무음 처리(silencing)를 하거나 그 대신 Approved=false 또는 Active=false를 설정해야 할까요? 그렇게 하면 사용자가 수동으로 로그인하는 대신 이메일 링크를 클릭하도록 강제되어, 이메일 주소를 검증하는 목적에 부합한다고 생각합니다.

이것은 모두 저의 최근 스레드와 관련이 있습니다: notes-on-silencing-or-deleting-users

[편집]
또한 "미활성화 사용자 격리 기간(일)"을 7로 설정해 두었습니다.
무음 처리(silence)나 정지(suspend)가 이 기간을 초기화합니까? 만약 그렇다면, 사람들이 7일 이내에 계정 조치에 반응하지 않는다면 삭제(purge)하는 데 문제가 없습니다.

마지막으로 (네, 정말로요) "비활성 사용자 정리 기간(일)"을 365로 설정해 두었습니다. 포럼이 아직 개방 단계이므로 이를 60으로 낮추고 기존 계정들이 목록에서 자연스럽게 제외되도록 한 뒤, 나중에 다시 365로 높이는 것이 새로운 환경에서 자동 계정 정리(automated account pruning)에 합리적인 접근 방식일까요?

그 설정이 문제를 해결하는 데 충분하지 않은 이유는 무엇일까요?

여기서는 OR가 아니라 AND여야 하지 않나요?

Discourse는 주소를 검증하기 위해 이를 강제하므로, 정확히 어떤 문제를 해결하려는 건지 잘 이해가 되지 않습니다. 질문자님은 이렇게 말씀하셨습니다.

이전에 로그인하고 싶었지만 하지 못했던 사용자를 발견할 가능성은 매우 낮아 보입니다. 하지만 질문자님의 환경에 대해 제가 모르는 부분이 있을 수 있습니다.

그리고 Discourse는 검증되지 않은 주소에는 이메일을 보내지 않으므로, 이 방법으로 이메일이 발송될 것 같지 않습니다.

저는 항상 이런 작업을 몇몇 계정에서 먼저 수행해서 무슨 일이 일어나는지 직접 확인해 봅니다.

관심 가져주셔서 감사합니다, @pfaffman !

last_seen_at 값이 없고 몇 달 전에 생성되었지만 approved=False, active=False인 사용자 기록들이 삭제되지 않고 있습니다.
last_seen_at이 7일 전(몇 달 전)이고 views가 0인 사용자 기록들도 삭제되지 않고 있습니다.

해당 grace period 플래그에 사용되는 기준이 무엇이든, 이 기록들을 선택하지 못하고 있습니다.
거기에 어떤 다른 요소들이 관여하는지 이해할 수 있도록, 해당 부분에서 정확히 사용되고 있는 쿼리를 게시해 주실 수 있을까요?

아니요, 데이터베이스를 직접 살펴보면 각 기준에 해당하는 기록은 있지만 모두에 해당하는 기록은 없습니다. 데이터베이스의 users 테이블이 일관성이 없어 보입니다. views=0인데 topics_entered나 posts_read_count가 0이 아닌 기록들이 있고, topics_entered=0이고 posts_read_count=0인데 views가 0이 아닌 기록들도 있습니다.

기억해야 할 핵심은 이 사이트가 개발되던 당시 설정이 최적화되어 있지 않았으며, 인간과 봇이 모두 등록되고 있었다는 점입니다. OR 절은 이러한 모든 경우를 포착하는 것 같습니다. 이제 사이트가 (바라건대) 합리적인 설정으로 안정화되었으므로, 새로운 등록에서 같은 이상 현상이 발생하지 않을 것으로 예상합니다.

저는 다양한 기준으로 스크립트를 여러 번 실행할 예정입니다. 먼저 환경 밖에서 기록을 쿼리하고, 그런 다음 실제로 원하는 기록만 대상으로 하기 위해 silence 스크립트를 실행할 것입니다. 몇 주 후 최종 실행을 하여, 침묵(silenced)된 기록만 선택(실제로 돌아온 사용자는 플래그가 제거됨)하고 모두 삭제할 것입니다:

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

제 전체적인 질문은 v0.0.2 스크립트의 선택, 로깅, 침묵 처리 방식이 Discourse 시스템에 적합한지 여부입니다. 이러한 루프에서 해야 할 다른 작업이 있는지 모르겠습니다. 저는 아직 직접 스크립트를 작성하고 실행해 본 적이 없으므로, 초보자가 흔히 하는 실수를 점검해 주시길 부탁드립니다.

감사합니다!!