이모지가 안전 항목으로 표시됨

운영 중인 공개 사이트에서 이모지가 깨지는 현상을 발견했습니다. 해당 사이트의 ACL은 private로 설정되어 있으며, access control post dictates security | source: post creator라는 이유로 secure로 표시되어 있습니다.

uploads:secure_upload_analyse_and_update 태스크를 실행하면 문제가 해결되지만, 며칠 후 다시 발생합니다. 사이트 로고에서도 한 번 같은 문제가 발생했으나, 그 이후로는 다시 일어나지 않았습니다.

3개의 좋아요

안녕하세요 @Wolftallemo, 커스텀 이모지(또는 게시글에서 사용될 수 있는 공개적으로 접근 가능한 업로드)과 보안 업로드가 함께 사용될 때 꽤 까다로운 문제입니다. 얼마 전부터 어떤 업로드가 무엇에 연결되어 있는지 확인하기 위해 UploadReference 테이블을 사용하기 시작했는데, 이 테이블로 마이그레이션할 때 모든 created_at 날짜시간 값을 동일한 값으로 설정했습니다. 그 결과, 보안 목적으로 업로드의 최초 사용이 공개적인 것인지 확인하는 과정에서 정렬이 어긋나고 잘못된 값을 사용하는 경우가 발생했습니다. 두 값의 created_at이 정확히 동일하다면 PostgreSQL은 자체적으로 처리하기 때문입니다:

질문자님의 언급 덕분에 이 문제를 다시 살펴봤고, created_at ASC 기준으로 정렬한 이후 id ASC 기준으로 정렬하면 이러한 충돌이 발생할 경우 실제 첫 번째 레코드가 사용되도록 더 잘 처리할 수 있다고 생각합니다.

이 PR이 병합된 후(오늘 병합될 수 있도록 노력하겠습니다) 문제가 지속되고, 질문자님이 사이트를 업로드하셨다면 추가적인 옵션에 대해 논의할 수 있습니다. 하지만 이것이 질문자님의 문제의 원인일 것이라 의심하고 있습니다. 질문자님의 사이트에서 다음을 실행하고 결과를 비교하여 확인할 수 있습니다:

CustomEmoji.find_by(name: "success").upload.upload_references.order("created_at ASC")

CustomEmoji.find_by(name: "success").upload.upload_references.order("created_at ASC, id ASC")

첫 번째 쿼리의 경우 target_type이 Post여야 하고, 두 번째 쿼리의 경우 target_type이 CustomEmoji여야 합니다.

4개의 좋아요

다시 그런 일이 발생하기 시작했는데, 매번 같은 이모지가 나오는 것 같습니다.

2개의 좋아요

위 게시물에서 @martin이 공유한 쿼리를 실행해 주시겠어요?

2개의 좋아요

결과를 살펴보니 실제로는 정반대입니다(첫 번째는 CustomEmoji를, 두 번째는 Post를 반환합니다).

2개의 좋아요

흥미롭네요, 그러면 올바른 값을 반환하고 있는 것이군요. 링크된 업로드에 대해 security_last_changed_reason과 security_last_changed_at 값을 게시해 주시고, access_control_post_id가 채워져 있는지 확인해 주시겠습니까? 첫 번째 참조가 커스텀 이모지인 경우 해당 업로드를 보안 상태로 표시해서는 안 됩니다. 이것도 시도해 보세요:

Upload.find(ID)
  .upload_references
  .joins(<<~SQL)
    LEFT JOIN posts ON upload_references.target_type = 'Post' AND upload_references.target_id = posts.id
  SQL
  .where("posts.deleted_at IS NULL")
  .order("upload_references.created_at ASC, upload_references.id ASC")
  .first

그리고 어떤 레코드가 반환되는지 확인해 보세요.

1개의 좋아요

access control post dictates security | source: post creator라는 메시지와 함께 날짜 Wed, 22 Mar 2023 09:13:10.341411000 UTC +00:00를 받았습니다.

3년 이상 전에 생성되어 이후 한 번도 수정된 적 없는 비공개 카테고리의 게시글에 대한 제어 게시글 ID를 반환했습니다.

2개의 좋아요

흥미롭네요. 그 게시물에서 사용자 정의 이모지가 사용되었나요? 위에서 언급한 업로드 참조 코드를 해당 업로드 ID와 함께 실행하면 무엇이 반환되나요? 업로드 레코드와 함께 이 코드를 실행하고 결과를 게시해 주시면 도움이 될 것입니다:

UploadSecurity.new(upload).should_be_secure_with_reason
1개의 좋아요

그 게시글에서 사용되었습니다

쿼리는 다음을 반환했습니다:

 id: 752,
 upload_id: 236,
 target_type: "Post",
 target_id: 37246,
 created_at: Mon, 25 Nov 2019 22:24:50.002473000 UTC +00:00,
 updated_at: Sun, 29 May 2022 08:13:24.844072000 UTC +00:00>

target id는 이모지가 전혀 포함되어 있지 않은 게시글을 가리킵니다.

Upload security는 [true, "access control post dictates security"]를 반환합니다

2개의 좋아요

정말 예상치 못한 상황이네요. 이 코드를 실행하면 UploadReference를 통해 해당 포스트에 연결된 모든 업로드가 표시되어야 합니다:

UploadReference.where(
    target_type: "Post",
    target_id: 37246,
)

포스트에 참조는 있지만 UI에 업로드가 표시되지 않는다면, 마이그레이션 문제가 있었던 것일까요?

결국 ID를 잘못 입력했네요 :facepalm:

네, 이모지가 포함되어 있지만, 상위 토픽은 삭제되었습니다.

1개의 좋아요

허허, 괜찮아. 그러면 올바른 업로드 파일로 다시 실행하면 어떤 결과가 나와?

UploadSecurity.new(upload).should_be_secure_with_reason

그리고

upload
  .upload_references
  .joins(<<~SQL)
    LEFT JOIN posts ON upload_references.target_type = 'Post' AND upload_references.target_id = posts.id
  SQL
  .where("posts.deleted_at IS NULL")
  .order("upload_references.created_at ASC, upload_references.id ASC")
  .first

정말 필요하다면, 해당 업로드의 다른 UploadReference 레코드보다 이전인 날짜와 시간으로 CustomEmoji UploadReference 레코드의 created_at을 설정할 수도 있지만, 그렇게 해야 할 필요는 없을 거야.

더 명확히 설명했어야 했는데. 업로드 ID는 정확했고, 게시물 ID가 잘못되었습니다(이 때문에 이모지가 포함된 게시물을 찾지 못했습니다. 여기에 붙여넣은 것은 정확했지만, 게시물을 찾으려고 할 때 잘못 입력했거든요).

나머지 모든 명령어는 여전히 동일한 결과를 반환합니다.

1개의 좋아요

이러한 경우라면, 날짜 주위에 실제로 이상한 점이 있는 것 같습니다. 아마도 자동 마이그레이션으로 인해 발생한 문제일 수 있습니다. 다음을 실행해 보세요:

CustomEmoji.find_by(name: "success").upload.upload_references.order("created_at ASC, id ASC")

target_type: "CustomEmoji"라고 적혀 있는 UploadReference 레코드를 찾은 후, 다음을 수행하세요:

UploadReference.find(ID).update!(created_at: UploadReference.find(752).created_at - 1.day))

그런 다음 문제가 있는 업로드에서 다음을 실행하세요:

upload.update_secure_status

그러면 해결될 것입니다… 이 마이그레이션 이후의 오래된 업로드에서 주로 문제가 발생할 것이라고 생각합니다. 다른 방법으로, 커스텀 이모지를 삭제하고 다시 업로드한 후 다음을 실행할 수도 있습니다:

Jobs.enqueue(:rebake_custom_emoji_posts, name: EMOJI_NAME)

다만, 날짜 업데이트 방식이 더 쉬울 것입니다. 이 문제에 대해 번거롭게 해서 죄송합니다!

1개의 좋아요

지금은 이 이모지가 더 이상 안전하지 않습니다 :meow_heart:

몇일 후에 실제로 작동했는지 안 했는지 알게 되겠죠.

1개의 좋아요

안녕하세요 @Wolftallemo :slight_smile:

혹시 잘 되셨나요?

아직 아무것도 깨지지 않았습니다

1개의 좋아요