mirror of
https://gh.wpcy.net/https://github.com/discourse/discourse.git
synced 2026-06-19 00:25:57 +08:00
What is the problem? - The discourse-templates plugin lets users mark topics as templates and track usage counts via `TemplatesController#use` - The `use` action checks that the caller is logged in and passes the global `can_use_templates?` gate, then verifies the topic is a valid template via `Topic#template?` - However, `Topic#template?` for category templates only checks whether the topic's category is in the configured template categories list — it does not check whether the calling user can see that category - If an admin configures both a public and a restricted category as template sources, a regular user with access to the public category passes the global gate and can then call the `use` endpoint with a topic ID from the restricted category and succeed What is the solution? - Add `guardian.ensure_can_see!(topic)` to `TemplatesController#use`
49 lines
1.6 KiB
Ruby
Vendored
49 lines
1.6 KiB
Ruby
Vendored
# frozen_string_literal: true
|
|
|
|
module DiscourseTemplates
|
|
class TemplatesController < ::ApplicationController
|
|
requires_plugin PLUGIN_NAME
|
|
|
|
before_action :ensure_logged_in
|
|
before_action :ensure_discourse_templates_enabled
|
|
skip_before_action :check_xhr
|
|
|
|
def ensure_discourse_templates_enabled
|
|
raise Discourse::InvalidAccess.new unless guardian.can_use_templates?
|
|
end
|
|
|
|
def use
|
|
template_id = params.require(:id)
|
|
topic = Topic.find_by(id: template_id)
|
|
|
|
return render_json_error("Invalid template id", status: 422) if topic.blank?
|
|
|
|
guardian.ensure_can_see!(topic)
|
|
|
|
unless topic.template?(current_user)
|
|
return(render_json_error("Id does not belong to a template", status: 422))
|
|
end
|
|
|
|
record = topic.increment_template_item_usage_count!
|
|
|
|
render json: record
|
|
end
|
|
|
|
def index
|
|
list_options = {
|
|
# limit defined in a hidden setting with a sane default value (1000) that should be enough to fetch all
|
|
# templates at once in most cases, but it still small enough to prevent things to blow up if the user
|
|
# selected the wrong category in settings with thousands and thousands of posts
|
|
per_page: SiteSetting.discourse_templates_max_replies_fetched.to_i,
|
|
}
|
|
|
|
topic_query = TopicQuery.new(current_user, list_options)
|
|
category_templates = topic_query.list_category_templates&.topics || []
|
|
private_templates = topic_query.list_private_templates&.topics || []
|
|
|
|
templates = category_templates + private_templates
|
|
|
|
render json: templates, each_serializer: TemplatesSerializer
|
|
end
|
|
end
|
|
end
|