0
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2026-08-08 17:53:55 +08:00
discourse/app/serializers/category_detailed_serializer.rb
Gabriel Grubba a5996e7bf5
SECURITY: Filter private subcategory counts from category listings [backport 2026.1] (#41438)
Backport of #41384 to release/2026.1.

The category list aggregate topic counts included direct subcategories
without
checking whether the current guardian could see them.

Before, the only information that could be leaked was:

  - private subcategory topic counts
  - recency buckets for topic creation: day/week/month/year/all-time

The auto-backport bot could not cherry-pick cleanly onto 2026.1 due to a
cosmetic difference on the `count_with_subcategories` line
(parenthesised
addend); the conflict was resolved manually and the fix + spec are
otherwise
identical to the original.

Co-authored-by: discourse-patch-triage
<272280883+discourse-patch-triage[bot]@users.noreply.github.com>
2026-07-03 16:10:00 -03:00

68 lines
1.4 KiB
Ruby
Vendored

# frozen_string_literal: true
class CategoryDetailedSerializer < BasicCategorySerializer
attributes :topic_count,
:post_count,
:topics_day,
:topics_week,
:topics_month,
:topics_year,
:topics_all_time,
:is_uncategorized,
:subcategory_ids
has_many :displayable_topics, serializer: ListableTopicSerializer, embed: :objects, key: :topics
has_many :subcategory_list,
serializer: CategoryDetailedSerializer,
embed: :objects,
key: :subcategory_list
def include_displayable_topics?
displayable_topics.present?
end
def include_subcategory_list?
subcategory_list.present?
end
def is_uncategorized
object.id == SiteSetting.uncategorized_category_id
end
def include_is_uncategorized?
is_uncategorized
end
def topics_day
count_with_subcategories(:topics_day)
end
def topics_week
count_with_subcategories(:topics_week)
end
def topics_month
count_with_subcategories(:topics_month)
end
def topics_year
count_with_subcategories(:topics_year)
end
def topics_all_time
count_with_subcategories(:topic_count)
end
def count_with_subcategories(method)
count = object.public_send(method) || 0
object.subcategories.each do |category|
next if !scope.can_see_category?(category)
count += category.public_send(method) || 0
end
count
end
end