マルチサイト + 短縮URL + 安全なアップロード + S3

さて、今週はバグハンティングに夢中になっているようです。

当サイトでは secure_uploads が有効なフォーラムを運用しており、すべてのアップロードは(公式の)AWS S3 上に保存されています。

問題: 短縮 URL リンクが正しく機能していないようです。URL から uploads/{database_id} が欠落しています。

問題のコードは UploadsController::show_short にあるようです。

if upload = Upload.find_by(sha1: sha1)
  return handle_secure_upload_request(upload, Discourse.store.get_path_for_upload(upload)) 
     if upload.secure? && SiteSetting.secure_media?

  if Discourse.store.internal?
    send_file_local_upload(upload)
  else
    redirect_to Discourse.store.url_for(upload, force_download: params[:dl] == "1")
  end
else
  render_404
end

つまり、upload.secure? && SiteSetting.secure_media? が true の場合、リクエストは
handle_secure_upload_request(upload, Discourse.store.get_path_for_upload(upload)) によって処理されます。

ここで Discourse.store.get_path_for_upload(upload) は、uploads/{database_id} の部分が含まれていない URL を返します。

original/3X/f/d/fd0b5775899541b9d42e67f8e0dd6bf587a179d3.png

その結果、handle_secure_upload_request は署名付き URL を返しますが、URL の一部が欠落しています。なぜなら、これは /original から始まるからです。

https://redacted.s3.us-east-2.amazonaws.com/original/3X/f/d/fd0b5775899541b9d42e67f8e0dd6bf587a179d3.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKI....

もし upload.secure? && SiteSetting.secure_media? が false だった場合(実際はそうではありませんが)、リクエストは Discourse.store.url_for(upload, force_download: params[:dl] == "1") によって処理されます。

そして、こちらこそが正しい URL を返します。

https://redacted.s3.us-east-2.amazonaws.com/uploads/db3999/original/3X/f/d/fd0b5775899541b9d42e67f8e0dd6bf587a179d3.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKI...

つまり、どうやら url_forget_path_for_upload は異なる挙動を示し、誤った方が使われているようです。

「いいね!」 7

ご報告ありがとうございます。これは比較的簡単に修正できるはずです。handle_secure_upload_request はマルチサイト接続を考慮していません。本日内に修正に取り組み、完了次第ご連絡いたします。

「いいね!」 8

こちらで修正済み:

「いいね!」 9