DEV: Update plugin to match latest guidelines (#76)

- Use different files instead of plugin.rb
- Make sure plugin is disabled according to the setting
This commit is contained in:
Bianca Nenciu 2023-02-23 15:20:10 +02:00 committed by GitHub
parent cf428c4bbc
commit 3af2747ed1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 190 additions and 189 deletions

View File

@ -0,0 +1,62 @@
# frozen_string_literal: true
module DiscourseUserNotes
class UserNotesController < ::ApplicationController
requires_plugin DiscourseUserNotes::PLUGIN_NAME
before_action :ensure_logged_in
before_action :ensure_staff
def index
user = User.where(id: params[:user_id]).first
raise Discourse::NotFound if user.blank?
notes = ::DiscourseUserNotes.notes_for(params[:user_id])
render json: { extras: { username: user.username }, user_notes: create_json(notes.reverse) }
end
def create
user = User.where(id: params[:user_note][:user_id]).first
raise Discourse::NotFound if user.blank?
extras = {}
if post_id = params[:user_note][:post_id]
extras[:post_id] = post_id
end
user_note =
::DiscourseUserNotes.add_note(user, params[:user_note][:raw], current_user.id, extras)
render json: create_json(user_note)
end
def destroy
user = User.where(id: params[:user_id]).first
raise Discourse::NotFound if user.blank?
raise Discourse::InvalidAccess.new unless guardian.can_delete_user_notes?
::DiscourseUserNotes.remove_note(user, params[:id])
render json: success_json
end
protected
def create_json(obj)
# Avoid n+1
if obj.is_a?(Array)
users_by_id = {}
posts_by_id = {}
User.where(id: obj.map { |o| o[:created_by] }).each { |u| users_by_id[u.id] = u }
Post.with_deleted.where(id: obj.map { |o| o[:post_id] }).each { |p| posts_by_id[p.id] = p }
obj.each do |o|
o[:created_by] = users_by_id[o[:created_by].to_i]
o[:post] = posts_by_id[o[:post_id].to_i]
end
else
obj[:created_by] = User.where(id: obj[:created_by]).first
obj[:post] = Post.with_deleted.where(id: obj[:post_id]).first
end
serialize_data(obj, ::UserNoteSerializer)
end
end
end

View File

@ -0,0 +1,60 @@
# frozen_string_literal: true
class ::UserNoteSerializer < ApplicationSerializer
attributes(
:id,
:user_id,
:raw,
:created_by,
:created_at,
:can_delete,
:post_id,
:post_url,
:post_title,
)
def id
object[:id]
end
def user_id
object[:user_id]
end
def raw
object[:raw]
end
def created_by
BasicUserSerializer.new(object[:created_by], scope: scope, root: false)
end
def created_at
object[:created_at]
end
def can_delete
scope.can_delete_user_notes?
end
def post_id
object[:post_id]
end
def post_url
url = object[:post].try(:url)
# In case the topic is deleted
url = "/t/#{object[:post].topic_id}/#{object[:post].post_number}" if url == "/404"
"#{Discourse.base_path}#{url}"
end
def post_title
object[:post].try(:title)
end
def topic_id
object[:topic_id]
end
end

257
plugin.rb
View File

@ -11,16 +11,17 @@ enabled_site_setting :user_notes_enabled
register_asset "stylesheets/user_notes.scss" register_asset "stylesheets/user_notes.scss"
register_svg_icon "sticky-note" if respond_to?(:register_svg_icon) register_svg_icon "sticky-note"
COUNT_FIELD = "user_notes_count"
after_initialize do after_initialize do
require_dependency "user" require_dependency "user"
module ::DiscourseUserNotes module ::DiscourseUserNotes
PLUGIN_NAME = "discourse_user_notes"
COUNT_FIELD = "user_notes_count"
class Engine < ::Rails::Engine class Engine < ::Rails::Engine
engine_name "discourse_user_notes" engine_name PLUGIN_NAME
isolate_namespace DiscourseUserNotes isolate_namespace DiscourseUserNotes
end end
@ -47,7 +48,7 @@ after_initialize do
notes << record notes << record
::PluginStore.set("user_notes", key_for(user.id), notes) ::PluginStore.set("user_notes", key_for(user.id), notes)
user.custom_fields[COUNT_FIELD] = notes.size user.custom_fields[DiscourseUserNotes::COUNT_FIELD] = notes.size
user.save_custom_fields user.save_custom_fields
record record
@ -62,136 +63,23 @@ after_initialize do
else else
::PluginStore.remove("user_notes", key_for(user.id)) ::PluginStore.remove("user_notes", key_for(user.id))
end end
user.custom_fields[COUNT_FIELD] = notes.size user.custom_fields[DiscourseUserNotes::COUNT_FIELD] = notes.size
user.save_custom_fields user.save_custom_fields
end end
end end
require_dependency "application_serializer" require_relative "app/serializers/user_note_serializer.rb"
class ::UserNoteSerializer < ApplicationSerializer require_relative "app/controllers/discourse_user_notes/user_notes_controller.rb"
attributes(
:id,
:user_id,
:raw,
:created_by,
:created_at,
:can_delete,
:post_id,
:post_url,
:post_title,
)
def id Discourse::Application.routes.append { mount ::DiscourseUserNotes::Engine, at: "/user_notes" }
object[:id]
end
def user_id DiscourseUserNotes::Engine.routes.draw do
object[:user_id] get "/" => "user_notes#index"
end post "/" => "user_notes#create"
delete "/:id" => "user_notes#destroy"
def raw
object[:raw]
end
def created_by
BasicUserSerializer.new(object[:created_by], scope: scope, root: false)
end
def created_at
object[:created_at]
end
def can_delete
scope.can_delete_user_notes?
end
def post_id
object[:post_id]
end
def post_url
url = object[:post].try(:url)
# In case the topic is deleted
url = "/t/#{object[:post].topic_id}/#{object[:post].post_number}" if url == "/404"
"#{Discourse.base_path}#{url}"
end
def post_title
object[:post].try(:title)
end
def topic_id
object[:topic_id]
end
end end
require_dependency "application_controller" allow_staff_user_custom_field(DiscourseUserNotes::COUNT_FIELD)
class DiscourseUserNotes::UserNotesController < ::ApplicationController
before_action :ensure_logged_in
before_action :ensure_staff
def index
user = User.where(id: params[:user_id]).first
raise Discourse::NotFound if user.blank?
notes = ::DiscourseUserNotes.notes_for(params[:user_id])
render json: { extras: { username: user.username }, user_notes: create_json(notes.reverse) }
end
def create
user = User.where(id: params[:user_note][:user_id]).first
raise Discourse::NotFound if user.blank?
extras = {}
if post_id = params[:user_note][:post_id]
extras[:post_id] = post_id
end
user_note =
::DiscourseUserNotes.add_note(user, params[:user_note][:raw], current_user.id, extras)
render json: create_json(user_note)
end
def destroy
user = User.where(id: params[:user_id]).first
raise Discourse::NotFound if user.blank?
raise Discourse::InvalidAccess.new unless guardian.can_delete_user_notes?
::DiscourseUserNotes.remove_note(user, params[:id])
render json: success_json
end
protected
def create_json(obj)
# Avoid n+1
if obj.is_a?(Array)
users_by_id = {}
posts_by_id = {}
User.where(id: obj.map { |o| o[:created_by] }).each { |u| users_by_id[u.id] = u }
Post.with_deleted.where(id: obj.map { |o| o[:post_id] }).each { |p| posts_by_id[p.id] = p }
obj.each do |o|
o[:created_by] = users_by_id[o[:created_by].to_i]
o[:post] = posts_by_id[o[:post_id].to_i]
end
else
obj[:created_by] = User.where(id: obj[:created_by]).first
obj[:post] = Post.with_deleted.where(id: obj[:post_id]).first
end
serialize_data(obj, ::UserNoteSerializer)
end
end
# TODO Drop after Discourse 2.6.0 release
if respond_to?(:allow_staff_user_custom_field)
allow_staff_user_custom_field(COUNT_FIELD)
else
whitelist_staff_user_custom_field(COUNT_FIELD)
end
add_to_class(Guardian, :can_delete_user_notes?) do add_to_class(Guardian, :can_delete_user_notes?) do
(SiteSetting.user_notes_moderators_delete? && user.staff?) || user.admin? (SiteSetting.user_notes_moderators_delete? && user.staff?) || user.admin?
@ -201,14 +89,6 @@ after_initialize do
object.custom_fields && object.custom_fields["user_notes_count"].to_i object.custom_fields && object.custom_fields["user_notes_count"].to_i
end end
DiscourseUserNotes::Engine.routes.draw do
get "/" => "user_notes#index"
post "/" => "user_notes#create"
delete "/:id" => "user_notes#destroy"
end
Discourse::Application.routes.append { mount ::DiscourseUserNotes::Engine, at: "/user_notes" }
add_model_callback(UserWarning, :after_commit, on: :create) do add_model_callback(UserWarning, :after_commit, on: :create) do
user = User.find_by_id(self.user_id) user = User.find_by_id(self.user_id)
created_by_user = User.find_by_id(self.created_by_id) created_by_user = User.find_by_id(self.created_by_id)
@ -261,6 +141,7 @@ after_initialize do
reason: details[:reason], reason: details[:reason],
) )
end end
note_args = {} note_args = {}
if post = Post.with_deleted.where(id: details[:post_id]).first if post = Post.with_deleted.where(id: details[:post_id]).first
note_args = { post_id: post.id, topic_id: post.topic_id } note_args = { post_id: post.id, topic_id: post.topic_id }
@ -269,68 +150,66 @@ after_initialize do
::DiscourseUserNotes.add_note(details[:user], raw_note, Discourse::SYSTEM_USER_ID, note_args) ::DiscourseUserNotes.add_note(details[:user], raw_note, Discourse::SYSTEM_USER_ID, note_args)
end end
if respond_to? :add_report add_report("user_notes") do |report|
add_report("user_notes") do |report| report.modes = [:table]
report.modes = [:table]
report.data = [] report.data = []
report.labels = [ report.labels = [
{ {
type: :user, type: :user,
properties: { properties: {
username: :username, username: :username,
id: :user_id, id: :user_id,
avatar: :user_avatar_template, avatar: :user_avatar_template,
},
title: I18n.t("reports.user_notes.labels.user"),
}, },
{ title: I18n.t("reports.user_notes.labels.user"),
type: :user, },
properties: { {
username: :moderator_username, type: :user,
id: :moderator_id, properties: {
avatar: :moderator_avatar_template, username: :moderator_username,
}, id: :moderator_id,
title: I18n.t("reports.user_notes.labels.moderator"), avatar: :moderator_avatar_template,
}, },
{ type: :text, property: :note, title: I18n.t("reports.user_notes.labels.note") }, title: I18n.t("reports.user_notes.labels.moderator"),
] },
{ type: :text, property: :note, title: I18n.t("reports.user_notes.labels.note") },
]
values = [] values = []
values = values =
PluginStoreRow PluginStoreRow
.where(plugin_name: "user_notes") .where(plugin_name: "user_notes")
.where("value::json->0->>'created_at'>=?", report.start_date) .where("value::json->0->>'created_at'>=?", report.start_date)
.where("value::json->0->>'created_at'<=?", report.end_date) .where("value::json->0->>'created_at'<=?", report.end_date)
.pluck(:value) .pluck(:value)
values.each do |value| values.each do |value|
notes = JSON.parse(value) notes = JSON.parse(value)
notes.each do |note| notes.each do |note|
data = {} data = {}
created_at = Time.parse(note["created_at"]) created_at = Time.parse(note["created_at"])
user = User.find_by(id: note["user_id"]) user = User.find_by(id: note["user_id"])
moderator = User.find_by(id: note["created_by"]) moderator = User.find_by(id: note["created_by"])
if user && moderator if user && moderator
data[:created_at] = created_at data[:created_at] = created_at
data[:user_id] = user.id data[:user_id] = user.id
data[:username] = user.username_lower data[:username] = user.username_lower
data[:user_avatar_template] = User.avatar_template( data[:user_avatar_template] = User.avatar_template(
user.username_lower, user.username_lower,
user.uploaded_avatar_id, user.uploaded_avatar_id,
) )
data[:moderator_id] = moderator.id data[:moderator_id] = moderator.id
data[:moderator_username] = moderator.username_lower data[:moderator_username] = moderator.username_lower
data[:moderator_avatar_template] = User.avatar_template( data[:moderator_avatar_template] = User.avatar_template(
moderator.username_lower, moderator.username_lower,
moderator.uploaded_avatar_id, moderator.uploaded_avatar_id,
) )
data[:note] = note["raw"] data[:note] = note["raw"]
report.data << data report.data << data
end
end end
end end
end end