FIX: Allow to add the same watched word with a different case (#17799)
Currently we can’t add a case-sensitive watched word if another one exists with a different case. For example, the existing watched word `Meta` has been created and is case-sensitive. Now an admin tries to add `metA` while marking it as case-sensitive too, this won’t work and the word won’t be added. This patch changes this behavior by allowing to add same words that have different cases, so the example above will now work as expected. We still check for uniqueness but case-sensitivy is now taken into account. It means that if the watched word `meta` already exists and is not case-sensitive then it will not be possible to add `Meta` (case-sensitive or not) as `meta` already matches every possible variations of this word.
This commit is contained in:
parent
39f12ddeca
commit
5c37a5d0f2
|
@ -47,9 +47,12 @@ export default Component.extend({
|
||||||
const filtered = words.filter(
|
const filtered = words.filter(
|
||||||
(content) => content.action === this.actionKey
|
(content) => content.action === this.actionKey
|
||||||
);
|
);
|
||||||
return filtered.every(
|
return filtered.every((content) => {
|
||||||
(content) => content.word.toLowerCase() !== word.toLowerCase()
|
if (content.case_sensitive === true) {
|
||||||
);
|
return content.word !== word;
|
||||||
|
}
|
||||||
|
return content.word.toLowerCase() !== word.toLowerCase();
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
|
|
|
@ -86,6 +86,14 @@ acceptance("Admin - Watched Words", function (needs) {
|
||||||
assert
|
assert
|
||||||
.dom(".watched-words-list .watched-word")
|
.dom(".watched-words-list .watched-word")
|
||||||
.hasText(`Discourse ${I18n.t("admin.watched_words.case_sensitive")}`);
|
.hasText(`Discourse ${I18n.t("admin.watched_words.case_sensitive")}`);
|
||||||
|
|
||||||
|
fillIn(".watched-word-form input", "discourse");
|
||||||
|
click(".case-sensitivity-checkbox");
|
||||||
|
await click(".watched-word-form button");
|
||||||
|
|
||||||
|
assert
|
||||||
|
.dom(".watched-words-list .watched-word")
|
||||||
|
.hasText(`discourse ${I18n.t("admin.watched_words.case_sensitive")}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("remove words", async function (assert) {
|
test("remove words", async function (assert) {
|
||||||
|
|
|
@ -40,6 +40,9 @@ class WatchedWord < ActiveRecord::Base
|
||||||
after_destroy :clear_cache
|
after_destroy :clear_cache
|
||||||
|
|
||||||
scope :by_action, -> { order("action ASC, word ASC") }
|
scope :by_action, -> { order("action ASC, word ASC") }
|
||||||
|
scope :for, ->(word:) do
|
||||||
|
where("(word ILIKE :word AND case_sensitive = 'f') OR (word LIKE :word AND case_sensitive = 't')", word: word)
|
||||||
|
end
|
||||||
|
|
||||||
def self.normalize_word(w)
|
def self.normalize_word(w)
|
||||||
w.strip.squeeze('*')
|
w.strip.squeeze('*')
|
||||||
|
@ -61,7 +64,7 @@ class WatchedWord < ActiveRecord::Base
|
||||||
|
|
||||||
def self.create_or_update_word(params)
|
def self.create_or_update_word(params)
|
||||||
new_word = normalize_word(params[:word])
|
new_word = normalize_word(params[:word])
|
||||||
w = WatchedWord.where("word ILIKE ?", new_word).first || WatchedWord.new(word: new_word)
|
w = self.for(word: new_word).first_or_initialize(word: new_word)
|
||||||
w.replacement = params[:replacement] if params[:replacement]
|
w.replacement = params[:replacement] if params[:replacement]
|
||||||
w.action_key = params[:action_key] if params[:action_key]
|
w.action_key = params[:action_key] if params[:action_key]
|
||||||
w.action = params[:action] if params[:action]
|
w.action = params[:action] if params[:action]
|
||||||
|
|
|
@ -125,5 +125,36 @@ RSpec.describe WatchedWord do
|
||||||
expect(updated.case_sensitive?).to eq(false)
|
expect(updated.case_sensitive?).to eq(false)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "when a case-sensitive word already exists" do
|
||||||
|
subject(:create_or_update) do
|
||||||
|
described_class.create_or_update_word(word: word, action_key: :block, case_sensitive: true)
|
||||||
|
end
|
||||||
|
|
||||||
|
fab!(:existing_word) { Fabricate(:watched_word, case_sensitive: true, word: "Meta") }
|
||||||
|
|
||||||
|
context "when providing the exact same word" do
|
||||||
|
let(:word) { existing_word.word }
|
||||||
|
|
||||||
|
it "doesn't create a new watched word" do
|
||||||
|
expect { create_or_update }.not_to change { described_class.count }
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns the existing watched word" do
|
||||||
|
expect(create_or_update).to eq(existing_word)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when providing the same word with a different case" do
|
||||||
|
let(:word) { "metA" }
|
||||||
|
|
||||||
|
it "creates a new watched word" do
|
||||||
|
expect(create_or_update).not_to eq(existing_word)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns the new watched word" do
|
||||||
|
expect(create_or_update).to have_attributes word: "metA", case_sensitive: true, action: 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue