mirror of
https://gh.wpcy.net/https://github.com/discourse/discourse.git
synced 2026-05-22 01:01:49 +08:00
The `create_policy_allowed_groups` setting controls who can create policies, but it only gates the composer UI and the `post_process_cooked` event handler. It does not prevent unauthorized users from injecting `[policy]` markup directly into post raw — for example, by editing a wiki post. Add `DiscoursePolicy::PostValidator` as an ActiveRecord validation on `Post`. When policies are added, removed, or modified, both the post owner and the acting user must belong to `create_policy_allowed_groups` or the save is rejected. Policies inside blockquotes are ignored.
44 lines
1 KiB
Ruby
Vendored
44 lines
1 KiB
Ruby
Vendored
# frozen_string_literal: true
|
|
|
|
module DiscoursePolicy
|
|
class PostValidator
|
|
def initialize(post)
|
|
@post = post
|
|
end
|
|
|
|
def validate_post
|
|
old_raw = @post.changes[:raw]&.first
|
|
new_raw = @post.raw
|
|
|
|
return true if !old_raw&.include?("[/policy]") && !new_raw.include?("[/policy]")
|
|
|
|
old_policies = extract_policies(@post.cooked)
|
|
new_policies = extract_policies(PrettyText.cook(new_raw, {}))
|
|
|
|
return true if old_policies == new_policies
|
|
|
|
if !user_allowed?(@post.acting_user) || !user_allowed?(@post.user)
|
|
@post.errors.add(:base, I18n.t("discourse_policy.errors.no_policy_permission"))
|
|
return false
|
|
end
|
|
|
|
true
|
|
end
|
|
|
|
private
|
|
|
|
def extract_policies(cooked)
|
|
return [] if cooked.blank?
|
|
|
|
Nokogiri::HTML5
|
|
.fragment(cooked)
|
|
.css("div.policy")
|
|
.reject { |p| p.ancestors("blockquote").any? }
|
|
.map(&:to_html)
|
|
end
|
|
|
|
def user_allowed?(user)
|
|
user&.in_any_groups?(SiteSetting.create_policy_allowed_groups_map)
|
|
end
|
|
end
|
|
end
|