0
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2026-08-08 14:34:02 +08:00
discourse/app/serializers/post_item_excerpt.rb
Chris Alberti 7584509977
SECURITY: Enforce first-post visibility for topic bookmarks [backport 2026.1] (#42356)
Backport of #42321 to release/2026.1.

Manual backport to also include the fix from PR #39873 (commit
05e03eab29) which was never backported to 2026.1

---

## Summary

Topic bookmark creation, listing, search, and reminder eligibility now
require the first post to be visible to the user. The fix adds an inner
join on the first post with hidden-post filtering to the list query and
delegates creation and visibility checks to `guardian.can_see_post?` on
the first post, preventing an authenticated user from bookmarking a
topic or searching its metadata after the first post is hidden.

## Source

- Patch Triage: https://patch.discourse.org/patch-triage/1530

Co-authored-by: discourse-patch-triage
<272280883+discourse-patch-triage[bot]@users.noreply.github.com>

---------

Co-authored-by: Sam <sam.saffron@gmail.com>
Co-authored-by: discourse-patch-triage[bot] <272280883+discourse-patch-triage[bot]@users.noreply.github.com>
Co-authored-by: Gabriel Grubba <70247653+Grubba27@users.noreply.github.com>
2026-08-05 12:53:28 -05:00

46 lines
956 B
Ruby
Vendored

# frozen_string_literal: true
module PostItemExcerpt
def self.included(base)
base.attributes(:excerpt, :truncated)
end
def cooked
@cooked ||= object.cooked || PrettyText.cook(object.raw)
end
def excerpt
return nil unless can_see_post_item_excerpt?
return nil unless cooked
@excerpt ||=
begin
PrettyText.excerpt(cooked, 300, keep_emoji_images: true)
rescue ArgumentError => e
e.message.include?("Document tree depth limit exceeded") ? "" : raise
end
end
def include_excerpt?
can_see_post_item_excerpt?
end
def include_cooked?
can_see_post_item_excerpt?
end
def truncated
true
end
def include_truncated?
can_see_post_item_excerpt? && cooked.length > 300
end
private
def can_see_post_item_excerpt?
return true if !respond_to?(:post_item_excerpt_post) || post_item_excerpt_post.blank?
scope&.can_see_post?(post_item_excerpt_post)
end
end