diff --git a/app/assets/javascripts/admin/addon/controllers/admin-watched-words-action.js b/app/assets/javascripts/admin/addon/controllers/admin-watched-words-action.js
index 323eaadb191..d84d80615dc 100644
--- a/app/assets/javascripts/admin/addon/controllers/admin-watched-words-action.js
+++ b/app/assets/javascripts/admin/addon/controllers/admin-watched-words-action.js
@@ -27,6 +27,17 @@ export default Controller.extend({
return this.findAction(actionName);
},
+ @discourseComputed("currentAction.words.[]")
+ regexpError(words) {
+ for (const { regexp, word } of words) {
+ try {
+ RegExp(regexp);
+ } catch {
+ return I18n.t("admin.watched_words.invalid_regex", { word });
+ }
+ }
+ },
+
@discourseComputed("actionNameKey")
actionDescription(actionNameKey) {
return I18n.t("admin.watched_words.action_descriptions." + actionNameKey);
diff --git a/app/assets/javascripts/admin/addon/templates/watched-words-action.hbs b/app/assets/javascripts/admin/addon/templates/watched-words-action.hbs
index 92a328a592e..3f6ce7db26a 100644
--- a/app/assets/javascripts/admin/addon/templates/watched-words-action.hbs
+++ b/app/assets/javascripts/admin/addon/templates/watched-words-action.hbs
@@ -1,3 +1,7 @@
+{{#if regexpError}}
+
{{regexpError}}
+{{/if}}
+
{{d-button
class="btn-default download-link"
diff --git a/app/assets/javascripts/discourse/tests/acceptance/admin-watched-words-test.js b/app/assets/javascripts/discourse/tests/acceptance/admin-watched-words-test.js
index 4094f6ba079..8d5595381cd 100644
--- a/app/assets/javascripts/discourse/tests/acceptance/admin-watched-words-test.js
+++ b/app/assets/javascripts/discourse/tests/acceptance/admin-watched-words-test.js
@@ -12,6 +12,8 @@ acceptance("Admin - Watched Words", function (needs) {
test("list words in groups", async function (assert) {
await visit("/admin/customize/watched_words/action/block");
+ assert.equal(find(".admin-watched-words .alert-error").length, 0);
+
assert.ok(
!exists(".watched-words-list"),
"Don't show bad words by default."
@@ -100,3 +102,35 @@ acceptance("Admin - Watched Words", function (needs) {
assert.equal(find(".modal-body li .tag").text(), "greeting");
});
});
+
+acceptance("Admin - Watched Words - Bad regular expressions", function (needs) {
+ needs.user();
+ needs.pretender((server, helper) => {
+ server.get("/admin/customize/watched_words.json", () => {
+ return helper.response({
+ actions: ["block", "censor", "require_approval", "flag", "replace"],
+ words: [
+ {
+ id: 1,
+ word: "[.*",
+ regexp: "[.*",
+ action: "block",
+ },
+ ],
+ regular_expressions: true,
+ compiled_regular_expressions: {
+ block: null,
+ censor: null,
+ require_approval: null,
+ flag: null,
+ replace: null,
+ },
+ });
+ });
+ });
+
+ test("shows an error message if regex is invalid", async function (assert) {
+ await visit("/admin/customize/watched_words/action/block");
+ assert.equal(find(".admin-watched-words .alert-error").length, 1);
+ });
+});
diff --git a/app/serializers/watched_word_serializer.rb b/app/serializers/watched_word_serializer.rb
index 6cc7972f0c9..4b3b138be0a 100644
--- a/app/serializers/watched_word_serializer.rb
+++ b/app/serializers/watched_word_serializer.rb
@@ -7,10 +7,6 @@ class WatchedWordSerializer < ApplicationSerializer
WordWatcher.word_to_regexp(word)
end
- def include_regexp?
- WatchedWord.has_replacement?(action)
- end
-
def action
WatchedWord.actions[object.action]
end
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index aa285607380..d0975397ed7 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -4701,6 +4701,7 @@ en:
download: Download
clear_all: Clear All
clear_all_confirm: "Are you sure you want to clear all watched words for the %{action} action?"
+ invalid_regex: 'The watched word "%{word}" is an invalid regular expression.'
actions:
block: "Block"
censor: "Censor"