Files
danbooru/app/models/user_feedback.rb
evazion d9dc84325f Fix #5365: Don't allow whitespace-only text submission.
Fix bug where it was possible to submit blank text in various text fields.

Caused by `String#blank?` not considering certain Unicode characters as blank. `blank?` is defined
as `match?(/\A[[:space:]]*\z/)`, where `[[:space:]]` matches ASCII spaces (space, tab, newline, etc)
and Unicode characters in the Space category ([1]). However, there are other space-like characters
not in the Space category. This includes U+200B (Zero-Width Space), and many more.

It turns out the "Default ignorable code points" [2][3] are what we're after. These are the set of 400
or so formatting and control characters that are invisible when displayed.

Note that there are other control characters that aren't invisible when rendered, instead they're
shown with a placeholder glyph. These include the ASCII C0 and C1 control codes [4], certain Unicode
control characters [5], and unassigned, reserved, and private use codepoints.

There is one outlier: the Braille pattern blank (U+2800) [6]. This character is visually blank, but is
not considered to be a space or an ignorable code point.

[1]: https://codepoints.net/search?gc[]=Z
[2]: https://codepoints.net/search?DI=1
[3]: https://www.unicode.org/review/pr-5.html
[4]: https://codepoints.net/search?gc[]=Cc
[5]: https://codepoints.net/search?gc[]=Cf
[6]: https://codepoints.net/U+2800
[7]: https://en.wikipedia.org/wiki/Whitespace_character
[8]: https://character.construction/blanks
[9]: https://invisible-characters.com
2022-12-05 01:58:34 -06:00

67 lines
2.3 KiB
Ruby

# frozen_string_literal: true
class UserFeedback < ApplicationRecord
self.table_name = "user_feedback"
attr_accessor :disable_dmail_notification, :updater
belongs_to :user
belongs_to :creator, class_name: "User"
validates :body, visible_string: true
validates :category, presence: true, inclusion: { in: %w[positive negative neutral] }
after_create :create_dmail, unless: :disable_dmail_notification
after_update :create_mod_action
deletable
scope :positive, -> { where(category: "positive") }
scope :neutral, -> { where(category: "neutral") }
scope :negative, -> { where(category: "negative") }
module SearchMethods
def visible(viewer)
viewer.is_moderator? ? all : undeleted
end
def default_order
order(created_at: :desc)
end
def search(params, current_user)
q = search_attributes(params, [:id, :created_at, :updated_at, :category, :body, :is_deleted, :creator, :user], current_user: current_user)
q.apply_default_order(params)
end
end
extend SearchMethods
def user_name=(name)
self.user = User.find_by_name(name)
end
def create_dmail
body = %{@#{creator.name} created a "#{category} record":#{Routes.user_feedbacks_path(search: { user_id: user_id })} for your account:\n\n#{self.body}}
if category == "negative"
body += "\n\n---\n\nA negative feedback is a record on your account that you've engaged in negative or rule-breaking behavior. You can appeal this feedback if you think it's unfair by petitioning the mods and admins in the forum. Negative feedback generally doesn't affect your usability of the site, but serious or repeated infractions may lead to a ban."
end
Dmail.create_automated(:to_id => user_id, :title => "Your user record has been updated", :body => body)
end
def create_mod_action
raise "Updater not set" if updater.nil?
if saved_change_to_is_deleted == [false, true] && creator != updater
ModAction.log(%{deleted user feedback for "#{user.name}":#{Routes.user_path(user)}}, :user_feedback_delete, subject: user, user: updater)
elsif creator != updater
ModAction.log(%{updated user feedback for "#{user.name}":#{Routes.user_path(user)}}, :user_feedback_update, subject: user, user: updater)
end
end
def self.available_includes
[:creator, :user]
end
end