discourse/plugins/discourse-policy/plugin.rb
Ted Johansson 47286766da
DEV: Support deprecating site settings in plugins (#36371)
In /app/models/site_setting.rb we call the method to setup deprecated setting methods in the class body. This iterates through the SiteSettings::DeprecatedSettings::SETTINGS array and defines the deprecation methods.

Because this is setup on class load, it becomes dependent on the order that files are loaded in. For example, if we try to add a deprecated setting from a plugin, using something like:

```rb
SiteSettings::DeprecatedSettings::SETTINGS << [
  "policy_restrict_to_staff_posts",
  "create_policy_allowed_groups",
  false,
  "3.6"
]
```

it will get appended to the array, but it won’t have the appropriate method generated, because #setup_deprecated_methods is evaluated before this plugin.rb file.

This change extracts the meat of #setup_deprecated_methods into #setup_deprecated_method, which can be called with a single setting.

We then use that in a new #deprecate_setting method on Plugin::Instance.
2025-12-03 13:30:35 +08:00

204 lines
6.8 KiB
Ruby

# frozen_string_literal: true
# name: discourse-policy
# about: Gives the ability to confirm your users have seen or done something, with optional reminders.
# meta_topic_id: 88557
# version: 0.1.1
# authors: Sam Saffron
# url: https://github.com/discourse/discourse/tree/main/plugins/discourse-policy
register_asset "stylesheets/common/discourse-policy.scss"
register_asset "stylesheets/common/discourse-policy-builder.scss"
register_svg_icon "user-check"
register_svg_icon "file-signature"
enabled_site_setting :policy_enabled
module ::DiscoursePolicy
PLUGIN_NAME = "discourse-policy"
end
require_relative "lib/discourse_policy/engine"
after_initialize do
require_relative "app/controllers/discourse_policy/policy_controller"
require_relative "app/models/policy_user"
require_relative "app/models/post_policy_group"
require_relative "app/models/post_policy"
require_relative "jobs/scheduled/check_policy"
require_relative "lib/email_controller_helper/policy_email_unsubscriber"
require_relative "lib/extensions/post_extension"
require_relative "lib/extensions/post_serializer_extension"
require_relative "lib/extensions/user_notifications_extension"
require_relative "lib/extensions/user_option_extension"
require_relative "lib/policy_mailer"
Discourse::Application.routes.append { mount DiscoursePolicy::Engine, at: "/policy" }
Post.prepend DiscoursePolicy::PostExtension
PostSerializer.prepend DiscoursePolicy::PostSerializerExtension
UserNotifications.prepend DiscoursePolicy::UserNotificationsExtension
UserOption.prepend DiscoursePolicy::UserOptionExtension
UserUpdater::OPTION_ATTR.push(:policy_email_frequency)
UserNotifications.append_view_path(File.expand_path("../app/views", __FILE__))
deprecate_setting(
"policy_restrict_to_staff_posts",
"create_policy_allowed_groups",
false,
"3.7.0",
)
add_to_serializer(:user_option, :policy_email_frequency) { object.policy_email_frequency }
register_email_unsubscriber("policy_email", EmailControllerHelper::PolicyEmailUnsubscriber)
TopicView.default_post_custom_fields << DiscoursePolicy::HAS_POLICY
on(:post_process_cooked) do |doc, post|
has_group = false
if post&.user&.in_any_groups?(SiteSetting.create_policy_allowed_groups_map)
if policy = doc.search(".policy")&.first
post_policy = post.post_policy || post.build_post_policy
group_names = []
if group = policy["data-group"]
group_names << group
end
if groups = policy["data-groups"]
group_names.concat(groups.split(","))
end
new_group_ids = Group.where("name in (?)", group_names).pluck(:id)
has_group = true if new_group_ids.length > 0
existing_ids = post_policy.post_policy_groups.pluck(:group_id)
missing = (new_group_ids - existing_ids)
new_relations = []
post_policy.post_policy_groups.each do |relation|
new_relations << relation if new_group_ids.include?(relation.group_id)
end
missing.each do |id|
new_relations << PostPolicyGroup.new(post_policy_id: post_policy.id, group_id: id)
end
post_policy.post_policy_groups = new_relations
renew_days = policy["data-renew"]
if (renew_days.to_i) > 0 || PostPolicy.renew_intervals.keys.include?(renew_days)
post_policy.renew_days =
PostPolicy.renew_intervals.keys.include?(renew_days) ? nil : renew_days
post_policy.renew_interval = post_policy.renew_days.present? ? nil : renew_days
post_policy.renew_start = nil
if (renew_start = policy["data-renew-start"])
begin
renew_start = Date.parse(renew_start)
post_policy.renew_start = renew_start
if !post_policy.next_renew_at || post_policy.next_renew_at < renew_start
post_policy.next_renew_at = renew_start
end
rescue ArgumentError
# already nil
end
else
post_policy.next_renew_at = nil
end
else
post_policy.renew_days = nil
post_policy.renew_start = nil
post_policy.next_renew_at = nil
end
if version = policy["data-version"]
old_version = post_policy.version || "1"
if version != old_version
post_policy.version = version
if post_policy.add_users_to_group.present?
previously_accepted_users = post_policy.accepted_policy_users
Group.find_by(id: post_policy.add_users_to_group)&.remove(previously_accepted_users)
end
end
end
if reminder = policy["data-reminder"]
post_policy.reminder = reminder
post_policy.last_reminded_at ||= Time.zone.now
end
post_policy.private = policy["data-private"] == "true"
if policy["data-add-users-to-group"].present?
post_policy.add_users_to_group = Group.find_by_name(policy["data-add-users-to-group"])&.id
end
if has_group
if !post.custom_fields[DiscoursePolicy::HAS_POLICY]
post.custom_fields[DiscoursePolicy::HAS_POLICY] = true
post.save_custom_fields
end
post_policy.save!
end
end
end
if !has_group && (post.custom_fields[DiscoursePolicy::HAS_POLICY] || !post_policy&.new_record?)
post.custom_fields.delete(DiscoursePolicy::HAS_POLICY)
post.save_custom_fields
PostPolicy.where(post_id: post.id).destroy_all
end
end
add_to_serializer(:current_user, :can_create_policy) do
object.in_any_groups?(SiteSetting.create_policy_allowed_groups_map)
end
add_report("unaccepted-policies") do |report|
report.modes = [:table]
report.labels = [
{ property: :topic_id, title: I18n.t("reports.unaccepted-policies.labels.topic_id") },
{ property: :user_id, title: I18n.t("reports.unaccepted-policies.labels.user_id") },
]
results = DB.query(<<~SQL)
SELECT distinct t.id AS topic_id, gu.user_id AS user_id
FROM post_policies pp
JOIN post_policy_groups pg on pg.post_policy_id = pp.id
JOIN posts p ON p.id = pp.post_id AND p.deleted_at is null
JOIN topics t ON t.id = p.topic_id AND t.deleted_at is null
JOIN group_users gu ON gu.group_id = pg.group_id
LEFT JOIN policy_users pu ON
pu.user_id = gu.user_id AND
pu.post_policy_id = pp.id AND
pu.accepted_at IS NOT NULL AND
pu.revoked_at IS NULL AND
(pu.expired_at IS NULL OR pu.expired_at < pu.accepted_at) AND
((pu.version IS NULL AND pp.version IS NULL) OR
(pp.version IS NOT NULL AND pu.version IS NOT NULL AND pu.version = pp.version))
WHERE pu.id IS NULL
SQL
report.data = []
results.each do |row|
data = {}
data[:user_id] = row.user_id
data[:topic_id] = row.topic_id
report.data << data
end
end
end