diff --git a/app/models/topic.rb b/app/models/topic.rb index 86674dfbb77..1e8078051fd 100644 --- a/app/models/topic.rb +++ b/app/models/topic.rb @@ -54,6 +54,7 @@ class Topic < ActiveRecord::Base validates :title, :if => Proc.new { |t| t.new_record? || t.title_changed? }, :presence => true, :topic_title_length => true, + :censored_words => true, :quality_title => { :unless => :private_message? }, :unique_among => { :unless => Proc.new { |t| (SiteSetting.allow_duplicate_topic_titles? || t.private_message?) }, :message => :has_already_been_used, diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index dd2f459440e..d4bb1d73f01 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -95,6 +95,8 @@ en: inclusion: is not included in the list invalid: is invalid is_invalid: "seems unclear, is it a complete sentence?" + contains_censored_words: "includes one or more of the censored words: %{censored_words}" + matches_censored_pattern: "matches the following censored Regex: %{censored_pattern}" less_than: must be less than %{count} less_than_or_equal_to: must be less than or equal to %{count} not_a_number: is not a number @@ -1342,7 +1344,7 @@ en: hide_user_profiles_from_public: "Disable user cards, user profiles and user directory for anonymous users." - user_website_domains_whitelist: "User website will be verified against these domains. Pipe-delimited list." + user_website_domains_whitelist: "User website will be verified against these domains. Pipe-delimited list." allow_profile_backgrounds: "Allow users to upload profile backgrounds." diff --git a/lib/validators/censored_words_validator.rb b/lib/validators/censored_words_validator.rb new file mode 100644 index 00000000000..b5727c53390 --- /dev/null +++ b/lib/validators/censored_words_validator.rb @@ -0,0 +1,15 @@ +class CensoredWordsValidator < ActiveModel::EachValidator + def validate_each(record, attribute, value) + if value =~ /#{SiteSetting.censored_words}/i + record.errors.add( + attribute, :contains_censored_words, + censored_words: SiteSetting.censored_words + ) + elsif value =~ /#{SiteSetting.censored_pattern}/i + record.errors.add( + attribute, :matches_censored_pattern, + censored_pattern: SiteSetting.censored_pattern + ) + end + end +end diff --git a/spec/models/topic_spec.rb b/spec/models/topic_spec.rb index e4574b75c98..809f7954299 100644 --- a/spec/models/topic_spec.rb +++ b/spec/models/topic_spec.rb @@ -4,11 +4,53 @@ require 'rails_helper' require_dependency 'post_destroyer' describe Topic do - let(:now) { Time.zone.local(2013,11,20,8,0) } let(:user) { Fabricate(:user) } - it { is_expected.to validate_presence_of :title } + context 'validations' do + let(:topic) { Fabricate.build(:topic) } + + context "#title" do + it { is_expected.to validate_presence_of :title } + + describe 'censored words' do + site_setting(:censored_words, 'pineapple|pen') + site_setting(:censored_pattern, 'orange.*') + + describe 'when title contains censored words' do + it 'should not be valid' do + topic.title = 'I have a Pineapple' + + expect(topic).to_not be_valid + + expect(topic.errors.full_messages.first).to include(I18n.t( + 'errors.messages.contains_censored_words', censored_words: SiteSetting.censored_words + )) + end + end + + describe 'when title matches censored pattern' do + it 'should not be valid' do + topic.title = 'I have orangEjuice' + + expect(topic).to_not be_valid + + expect(topic.errors.full_messages.first).to include(I18n.t( + 'errors.messages.matches_censored_pattern', censored_pattern: SiteSetting.censored_pattern + )) + end + end + + describe 'when title does not contain censored words' do + it 'should be valid' do + topic.title = 'The cake is a lie' + + expect(topic).to be_valid + end + end + end + end + end it { is_expected.to rate_limit }