잘못된 이메일 주소를 가진 사용자의 권한 강하 요청

역사적인 이유로, Google+ 가져오기(importer)는 Google+ 난민들에게 유리한 출발을 제공하기 위해 사용자를 TL1로 가져왔습니다. 이들은 .invalid 이메일 주소로 가져와지며, 로그인하여 Google 인증을 통해 기존 사용자 기록과 Google ID로 연결될 때 이를 수정합니다.

하지만 현재 제 trust_level_1 그룹에는 아직 콘텐츠를 팔로우하지 않은 수천 명의 사용자가 쌓여 있습니다. 몇 년 후에 그들이 등장하는 경우(때때로 실제로 그렇게 됩니다) Basic 사용자로 들어올 특별한 이유가 없습니다. 그들은 New 사용자가 되어야 합니다. 부트스트랩(초기 설정) 단계는 이미 지났습니다. 그들이 등장하여 둘러볼 때까지, 로그인하지 않은 사용자를 TL0으로 강등시키고 정상적인 승격 프로세스에 의존하고 싶습니다.

Rails 콘솔에서 다음을 시도해 보았습니다:

User.where(trust_level: 1) do |u|
    u.change_trust_level!(TrustLevel[0]) if !Email.is_valid?(u.primary_email&.email)
    u.save!
end

수 분 동안 CPU를 100% 사용했지만 아무것도 수행되지 않았습니다. (그 과정에서 if !u.primary_email.is_valid?나 if !Email.is_valid?(u.primary_email) 같은 다른 변형들도 시도해 보았고, 제가 실제로는 1년에 한 번 정도만 Ruby를 건드리는 것이 근본적인 문제라는 것을 알고 있습니다…) 다른 사람들에게는 분명히 자명한 것을 제가 놓치고 있는 것 같습니다. 힌트를 주실 수 있다면 감사하겠습니다!

분명히 .each를 빼먹고 있었습니다.

User.where(trust_level: 1).each do |u|
    u.change_trust_level!(TrustLevel[0]) if !Email.is_valid?(u.primary_email&.email)
    u.save!
end

이 코드를 실행한 결과, 대량의 IO가 발생하면서 사이트가 다운되었고, 여전히 아무런 변경 사항도 없었습니다. 그래서 여전히 뭔가 잘못되고 있다는 것을 알았고, 라이브 시스템에서 계속 시도하는 것에 대해 조금 걱정됩니다. :smiling_face:

is_valid?가 의미하는 바가 이것이 아님을 알아냈습니다. 그래서 이제 리터럴 문자열을 찾고 있으며, 이메일 주소를 출력하여 이를 테스트했습니다. 또한 change_trust_level이 이미 사용자를 저장한다는 것도 확인했으므로, 두 번 저장할 필요가 없습니다.

User.where(trust_level: 1).each do |u|
   if u.primary_email&.email.end_with?(".invalid")  
     u.change_trust_level!(TrustLevel[0])    
   end  
end  

하지만 trust_level_1의 사용자 수는 여전히 변하지 않아서, 여전히 중요한 무언가를 놓치고 있는 것 같습니다.

이 경우 일괄 관리자 작업을 사용할 수 있나요?


방금 두 번째 코드를 테스트해 보았는데, 제 테스트 사용자(이메일: test_thirteen@here.invalid, TL1이었고 지금은 TL0입니다)에게는 정상적으로 작동했습니다.

User.where(trust_level: 1).each do |u|
   if u.primary_email&.email.end_with?(".invalid")  
     u.change_trust_level!(TrustLevel[0])    
   end  
end

UserEmail 모델에서 이메일 주소에 "invalid"가 포함된 항목을 찾아서 순회하는 방식으로 시작할 것 같습니다. 하지만 스마트폰에서는 이를 정확히 파악하기 어렵습니다.

만약 'invalid’가 포함된 주소가 실제로 잘못된 것이라면, 저장 자체가 불가능했을 것입니다.

감사합니다!

기존 커뮤니티 멤버들에게 이미 잘 알려진 일부 사용자는 수동으로 승격했기 때문에, 일괄 재계산은 제가 원하는 결과를 가져오지 못할 것입니다. (저는 검색하면서 그 페이지를 _발견_했습니다.)

마지막 부분은 실제로 작동했습니다. 당신에게도 그랬던 것처럼요. 제 문제는 /g 그룹 개요 페이지를 보고 새로고침을 하면서 trust_level_1 그룹의 회원 수가 줄어드는지를 확인하려던 것이었습니다. 실행 중에는 회원 수 변화가 표시되지 않아서 저는 Ctrl-C로 실행을 중단했습니다. 오늘 아침에 보니 trust_level_1 그룹은 해당 페이지에서 수천 명 적은 회원 수가 표시되고 있었습니다. 이제야 그곳의 회원 수가 캐시되어 있다는 것을 깨달았으며, 저는 원래 그 카드를 클릭해서 /g/trust_level_1 페이지의 회원 수를 확인했어야 했습니다.

이제 그 페이지의 수치를 복구하기 위해 Group.ensure_consistency!를 후속 조치로 실행했어야 한다는 것을 이해했습니다.

더 간결하고 관용적으로 표현한 전체 코드는 다음과 같습니다:

User.where(trust_level: 1).each do |u|
     u.change_trust_level!(TrustLevel[0]) if u.primary_email&.email.end_with?(".invalid")  
end
Group.ensure_consistency!

우연히도, 실제로 사이트를 사용했고 TL1 요건을 충족한 기록이 있지만 이메일 주소가 무효인 몇몇 사용자의 기록을 가지고 있습니다. 어떻게 그렇게 되었는지 모르지만, 지금은 그걸 신경 쓰지 않습니다. 제가 정말로 신경 쓰는 것은 수천 명에 달하는 대다수를 처리하는 것이며, 소수의 예외는 걱정하지 않아도 됩니다. 다른 누군가에게도 이런 일이 발생한다면, 제게는 이렇게 작동했습니다:

User.where(trust_level: 1).each do |u|
  begin
     u.change_trust_level!(TrustLevel[0]) if u.primary_email&.email.end_with?(".invalid")  
  rescue
  end
end
Group.ensure_consistency!

배경은 다음과 같습니다:

script/import_scripts/friendsmegplus.rb

  def import_google_user(id, name)
    if !@emails[id].present?
      google_user_info = UserAssociatedAccount.find_by(provider_name: 'google_oauth2', provider_u
id: id.to_i)
      if google_user_info.nil?
        # create new google user on system; expect this user to merge
        # when they later log in with google authentication
        # Note that because email address is not included in G+ data, we
        # don't know if they already have another account not yet associated
        # with google ooauth2. If they didn't log in, they'll have an
        # @gplus.invalid address associated with their account
        email = "#{id}@gplus.invalid"

즉, 저는 primary_email만 신경 쓰면 되고 UserEmail부터 시작할 필요가 없다는 뜻입니다. 저는 그 경로를 따라가다가, primary_email이 아닌 것으로 변경된 것은 어쨌든 제가 변경하고 싶지 않을 것이라는 사실을 깨달았습니다. 따라서 여기서는 문자 그대로 .invalid로 끝나는 유일한(따라서 기본) 이메일을 가진 사용자들, 즉 제가 그렇게 처리한 사용자들에 대해 매우 구체적으로 이야기하는 것입니다.