UX: Skip applying link-type watched words to user custom fields (#20465)

We currently apply type: :link watched words to custom user fields. This makes the user card pretty ugly because we don't allow html / links there. Additionally, the admin UI also does not say that we apply this to custom user fields, but only words in posts.

So this PR is to remove the replacement of link-type watch words for custom user fields.
This commit is contained in:
Natalie Tay 2023-03-01 10:43:34 +08:00 committed by GitHub
parent d3a1b09361
commit 44b7706a2b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 79 additions and 31 deletions

View File

@ -1523,7 +1523,9 @@ class User < ActiveRecord::Base
def apply_watched_words
validatable_user_fields.each do |id, value|
set_user_field(id, WordWatcher.apply_to_text(value))
field = WordWatcher.censor_text(value)
field = WordWatcher.replace_text(field)
set_user_field(id, field)
end
end

View File

@ -132,18 +132,18 @@ class WordWatcher
def self.replace_text(text)
return text if text.blank?
replace(text, :replace)
end
%i[replace link]
.flat_map { |type| word_matcher_regexps(type).to_a }
.reduce(text) do |t, (word_regexp, attrs)|
case_flag = attrs[:case_sensitive] ? nil : Regexp::IGNORECASE
replace_text_with_regexp(t, Regexp.new(word_regexp, case_flag), attrs[:replacement])
end
def self.replace_link(text)
return text if text.blank?
replace(text, :link)
end
def self.apply_to_text(text)
text = censor_text(text)
text = replace_text(text)
text = replace_link(text)
text
end
@ -246,4 +246,15 @@ class WordWatcher
end
private_class_method :censor_text_with_regexp
private
def self.replace(text, watch_word_type)
word_matcher_regexps(watch_word_type)
.to_a
.reduce(text) do |t, (word_regexp, attrs)|
case_flag = attrs[:case_sensitive] ? nil : Regexp::IGNORECASE
replace_text_with_regexp(t, Regexp.new(word_regexp, case_flag), attrs[:replacement])
end
end
end

View File

@ -362,6 +362,23 @@ RSpec.describe User do
end
end
end
context "when watched words are of type 'link'" do
let(:value) { "don't replace me" }
let!(:replace_word) do
Fabricate(
:watched_word,
word: "replace",
replacement: "touch",
action: WatchedWord.actions[:link],
)
end
it "does not replace anything" do
user.save!
expect(user_field_value).to eq value
end
end
end
context "when user fields do not contain watched words" do

View File

@ -361,7 +361,7 @@ RSpec.describe WordWatcher do
end
end
describe ".apply_to_text" do
describe "word replacement" do
fab!(:censored_word) do
Fabricate(:watched_word, word: "censored", action: WatchedWord.actions[:censor])
end
@ -382,36 +382,54 @@ RSpec.describe WordWatcher do
)
end
it "replaces all types of words" do
text = "hello censored world to replace https://notdiscourse.org"
expected =
"hello #{described_class::REPLACEMENT_LETTER * 8} world replaced https://discourse.org"
expect(described_class.apply_to_text(text)).to eq(expected)
it "censors text" do
expect(described_class.censor_text("a censored word")).to eq(
"a #{described_class::REPLACEMENT_LETTER * 8} word",
)
end
context "when watched_words_regular_expressions = true" do
it "replaces captured non-word prefix" do
SiteSetting.watched_words_regular_expressions = true
Fabricate(
:watched_word,
word: "\\Wplaceholder",
replacement: "replacement",
action: WatchedWord.actions[:replace],
)
it "replaces text" do
expect(described_class.replace_text("a word to replace meow")).to eq("a word replaced meow")
end
text = "is \tplaceholder in https://notdiscourse.org"
expected = "is replacement in https://discourse.org"
it "replaces links" do
expect(described_class.replace_link("please visit https://notdiscourse.org meow")).to eq(
"please visit https://discourse.org meow",
)
end
describe ".apply_to_text" do
it "replaces all types of words" do
text = "hello censored world to replace https://notdiscourse.org"
expected =
"hello #{described_class::REPLACEMENT_LETTER * 8} world replaced https://discourse.org"
expect(described_class.apply_to_text(text)).to eq(expected)
end
end
context "when watched_words_regular_expressions = false" do
it "maintains non-word character prefix" do
SiteSetting.watched_words_regular_expressions = false
context "when watched_words_regular_expressions = true" do
it "replaces captured non-word prefix" do
SiteSetting.watched_words_regular_expressions = true
Fabricate(
:watched_word,
word: "\\Wplaceholder",
replacement: "replacement",
action: WatchedWord.actions[:replace],
)
text = "to replace and\thttps://notdiscourse.org"
expected = "replaced and\thttps://discourse.org"
expect(described_class.apply_to_text(text)).to eq(expected)
text = "is \tplaceholder in https://notdiscourse.org"
expected = "is replacement in https://discourse.org"
expect(described_class.apply_to_text(text)).to eq(expected)
end
end
context "when watched_words_regular_expressions = false" do
it "maintains non-word character prefix" do
SiteSetting.watched_words_regular_expressions = false
text = "to replace and\thttps://notdiscourse.org"
expected = "replaced and\thttps://discourse.org"
expect(described_class.apply_to_text(text)).to eq(expected)
end
end
end
end