mirror of
https://github.com/discourse/discourse-data-explorer.git
synced 2025-03-06 09:29:12 +00:00
When checking `attach_csv` in the `Schedule a PM with Data Explorer results` automation script, `csv` has to be added to the list of authorized extensions in the site settings. This will now raise an error if it's not the case.
191 lines
6.7 KiB
Ruby
191 lines
6.7 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
# name: discourse-data-explorer
|
|
# about: Allows you to make SQL queries against your live database, allowing for up-to-the-minute stats reporting.
|
|
# meta_topic_id: 32566
|
|
# version: 0.3
|
|
# authors: Riking
|
|
# url: https://github.com/discourse/discourse-data-explorer
|
|
|
|
enabled_site_setting :data_explorer_enabled
|
|
|
|
register_asset "stylesheets/explorer.scss"
|
|
|
|
register_svg_icon "caret-down"
|
|
register_svg_icon "caret-right"
|
|
register_svg_icon "chevron-left"
|
|
register_svg_icon "circle-exclamation"
|
|
register_svg_icon "info"
|
|
register_svg_icon "pencil"
|
|
register_svg_icon "upload"
|
|
|
|
add_admin_route "explorer.title", "explorer"
|
|
|
|
module ::DiscourseDataExplorer
|
|
PLUGIN_NAME = "discourse-data-explorer"
|
|
|
|
# This should always match the max value for the
|
|
# data_explorer_query_result_limit site setting
|
|
QUERY_RESULT_MAX_LIMIT = 10_000
|
|
end
|
|
|
|
require_relative "lib/discourse_data_explorer/engine"
|
|
|
|
after_initialize do
|
|
GlobalSetting.add_default(:max_data_explorer_api_reqs_per_10_seconds, 2)
|
|
|
|
# Available options:
|
|
# - warn
|
|
# - warn+block
|
|
# - block
|
|
GlobalSetting.add_default(:max_data_explorer_api_req_mode, "warn")
|
|
|
|
add_to_class(:guardian, :user_is_a_member_of_group?) do |group|
|
|
return false if !current_user
|
|
return true if current_user.admin?
|
|
current_user.group_ids.include?(group.id)
|
|
end
|
|
|
|
add_to_class(:guardian, :user_can_access_query?) do |query|
|
|
return false if !current_user
|
|
return true if current_user.admin?
|
|
query.groups.blank? || query.groups.any? { |group| user_is_a_member_of_group?(group) }
|
|
end
|
|
|
|
add_to_class(:guardian, :group_and_user_can_access_query?) do |group, query|
|
|
return false if !current_user
|
|
return true if current_user.admin?
|
|
user_is_a_member_of_group?(group) && query.groups.exists?(id: group.id)
|
|
end
|
|
|
|
add_to_serializer(
|
|
:group_show,
|
|
:has_visible_data_explorer_queries,
|
|
include_condition: -> { scope.user_is_a_member_of_group?(object) },
|
|
) { DiscourseDataExplorer::Query.for_group(object).exists? }
|
|
|
|
register_bookmarkable(DiscourseDataExplorer::QueryGroupBookmarkable)
|
|
|
|
add_api_key_scope(
|
|
:discourse_data_explorer,
|
|
{ run_queries: { actions: %w[discourse_data_explorer/query#run], params: %i[id] } },
|
|
)
|
|
|
|
reloadable_patch do
|
|
if defined?(DiscourseAutomation)
|
|
add_automation_scriptable("recurring_data_explorer_result_pm") do
|
|
queries =
|
|
DiscourseDataExplorer::Query
|
|
.where(hidden: false)
|
|
.map { |q| { id: q.id, translated_name: q.name } }
|
|
field :recipients, component: :email_group_user, required: true
|
|
field :query_id, component: :choices, required: true, extra: { content: queries }
|
|
field :query_params, component: :"key-value", accepts_placeholders: true
|
|
field :skip_empty, component: :boolean
|
|
field :attach_csv,
|
|
component: :boolean,
|
|
validator: ->(attach_csv) do
|
|
return if !attach_csv
|
|
|
|
extensions = SiteSetting.authorized_extensions.split("|")
|
|
if (extensions & %w[csv *]).empty?
|
|
I18n.t(
|
|
"discourse_automation.scriptables.recurring_data_explorer_result_pm.no_csv_allowed",
|
|
)
|
|
end
|
|
end
|
|
|
|
version 1
|
|
triggerables [:recurring]
|
|
|
|
script do |_, fields, automation|
|
|
recipients = Array(fields.dig("recipients", "value")).uniq
|
|
query_id = fields.dig("query_id", "value")
|
|
query_params = fields.dig("query_params", "value") || {}
|
|
skip_empty = fields.dig("skip_empty", "value") || false
|
|
attach_csv = fields.dig("attach_csv", "value") || false
|
|
|
|
unless SiteSetting.data_explorer_enabled
|
|
Rails.logger.warn "#{DiscourseDataExplorer::PLUGIN_NAME} - plugin must be enabled to run automation #{automation.id}"
|
|
next
|
|
end
|
|
|
|
if recipients.blank?
|
|
Rails.logger.warn "#{DiscourseDataExplorer::PLUGIN_NAME} - couldn't find any recipients for automation #{automation.id}"
|
|
next
|
|
end
|
|
|
|
DiscourseDataExplorer::ReportGenerator
|
|
.generate(
|
|
query_id,
|
|
query_params,
|
|
recipients,
|
|
{ skip_empty:, attach_csv:, render_url_columns: true },
|
|
)
|
|
.each do |pm|
|
|
begin
|
|
utils.send_pm(pm, automation_id: automation.id, prefers_encrypt: false)
|
|
rescue ActiveRecord::RecordNotSaved => e
|
|
Rails.logger.warn "#{DiscourseDataExplorer::PLUGIN_NAME} - couldn't send PM for automation #{automation.id}: #{e.message}"
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
add_automation_scriptable("recurring_data_explorer_result_topic") do
|
|
queries =
|
|
DiscourseDataExplorer::Query
|
|
.where(hidden: false)
|
|
.map { |q| { id: q.id, translated_name: q.name } }
|
|
field :topic_id, component: :text, required: true
|
|
field :query_id, component: :choices, required: true, extra: { content: queries }
|
|
field :query_params, component: :"key-value", accepts_placeholders: true
|
|
field :skip_empty, component: :boolean
|
|
field :attach_csv, component: :boolean
|
|
|
|
version 1
|
|
triggerables [:recurring]
|
|
|
|
script do |_, fields, automation|
|
|
topic_id = fields.dig("topic_id", "value")
|
|
query_id = fields.dig("query_id", "value")
|
|
query_params = fields.dig("query_params", "value") || {}
|
|
skip_empty = fields.dig("skip_empty", "value") || false
|
|
attach_csv = fields.dig("attach_csv", "value") || false
|
|
|
|
unless SiteSetting.data_explorer_enabled
|
|
Rails.logger.warn "#{DiscourseDataExplorer::PLUGIN_NAME} - plugin must be enabled to run automation #{automation.id}"
|
|
next
|
|
end
|
|
|
|
topic = Topic.find_by(id: topic_id)
|
|
if topic.blank?
|
|
Rails.logger.warn "#{DiscourseDataExplorer::PLUGIN_NAME} - couldn't find topic ID (#{topic_id}) for automation #{automation.id}"
|
|
next
|
|
end
|
|
|
|
begin
|
|
post =
|
|
DiscourseDataExplorer::ReportGenerator.generate_post(
|
|
query_id,
|
|
query_params,
|
|
{ skip_empty:, attach_csv:, render_url_columns: true },
|
|
)
|
|
|
|
next if post.empty?
|
|
|
|
PostCreator.create!(
|
|
Discourse.system_user,
|
|
topic_id: topic.id,
|
|
raw: post["raw"],
|
|
skip_validations: true,
|
|
)
|
|
rescue ActiveRecord::RecordNotSaved => e
|
|
Rails.logger.warn "#{DiscourseDataExplorer::PLUGIN_NAME} - couldn't reply to topic ID #{topic_id} for automation #{automation.id}: #{e.message}"
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|