Support for a new site setting: newuser_spam_host_threshold. If a new user posts a link

to the same host enough tiles, they will not be able to post the same link again.

Additionally, the site will flag all their previous posts with links as spam and they will
be instantly hidden via the auto hide workflow.
This commit is contained in:
Robin Ward
2013-05-10 16:58:23 -04:00
parent 04b8cd5c95
commit d554a59102
19 changed files with 355 additions and 75 deletions

View File

@@ -155,6 +155,29 @@ describe PostAction do
describe 'flagging' do
context "flag_counts_for" do
it "returns the correct flag counts" do
post = Fabricate(:post)
SiteSetting.stubs(:flags_required_to_hide_post).returns(7)
# A post with no flags has 0 for flag counts
PostAction.flag_counts_for(post.id).should == [0, 0]
flag = PostAction.act(Fabricate(:evil_trout), post, PostActionType.types[:spam])
PostAction.flag_counts_for(post.id).should == [0, 1]
# If an admin flags the post, it is counted higher
admin = Fabricate(:admin)
PostAction.act(admin, post, PostActionType.types[:spam])
PostAction.flag_counts_for(post.id).should == [0, 8]
# If a flag is dismissed
PostAction.clear_flags!(post, admin)
PostAction.flag_counts_for(post.id).should == [8, 0]
end
end
it 'does not allow you to flag stuff with 2 reasons' do
post = Fabricate(:post)
u1 = Fabricate(:evil_trout)

View File

@@ -7,6 +7,13 @@ describe Post do
ImageSorcery.any_instance.stubs(:convert).returns(false)
end
# Help us build a post with a raw body
def post_with_body(body, user=nil)
args = post_args.merge(raw: body)
args[:user] = user if user.present?
Fabricate.build(:post, args)
end
it { should belong_to :user }
it { should belong_to :topic }
it { should validate_presence_of :raw }
@@ -89,12 +96,12 @@ describe Post do
describe "maximum images" do
let(:newuser) { Fabricate(:user, trust_level: TrustLevel.levels[:newuser]) }
let(:post_no_images) { Fabricate.build(:post, post_args.merge(user: newuser)) }
let(:post_one_image) { Fabricate.build(:post, post_args.merge(raw: "![sherlock](http://bbc.co.uk/sherlock.jpg)", user: newuser)) }
let(:post_two_images) { Fabricate.build(:post, post_args.merge(raw: "<img src='http://discourse.org/logo.png'> <img src='http://bbc.co.uk/sherlock.jpg'>", user: newuser)) }
let(:post_with_avatars) { Fabricate.build(:post, post_args.merge(raw: '<img alt="smiley" title=":smiley:" src="/assets/emoji/smiley.png" class="avatar"> <img alt="wink" title=":wink:" src="/assets/emoji/wink.png" class="avatar">', user: newuser)) }
let(:post_with_favicon) { Fabricate.build(:post, post_args.merge(raw: '<img src="/assets/favicons/wikipedia.png" class="favicon">', user: newuser)) }
let(:post_with_thumbnail) { Fabricate.build(:post, post_args.merge(raw: '<img src="/assets/emoji/smiley.png" class="thumbnail">', user: newuser)) }
let(:post_with_two_classy_images) { Fabricate.build(:post, post_args.merge(raw: "<img src='http://discourse.org/logo.png' class='classy'> <img src='http://bbc.co.uk/sherlock.jpg' class='classy'>", user: newuser)) }
let(:post_one_image) { post_with_body("![sherlock](http://bbc.co.uk/sherlock.jpg)", newuser) }
let(:post_two_images) { post_with_body("<img src='http://discourse.org/logo.png'> <img src='http://bbc.co.uk/sherlock.jpg'>", newuser) }
let(:post_with_avatars) { post_with_body('<img alt="smiley" title=":smiley:" src="/assets/emoji/smiley.png" class="avatar"> <img alt="wink" title=":wink:" src="/assets/emoji/wink.png" class="avatar">', newuser) }
let(:post_with_favicon) { post_with_body('<img src="/assets/favicons/wikipedia.png" class="favicon">', newuser) }
let(:post_with_thumbnail) { post_with_body('<img src="/assets/emoji/smiley.png" class="thumbnail">', newuser) }
let(:post_with_two_classy_images) { post_with_body("<img src='http://discourse.org/logo.png' class='classy'> <img src='http://bbc.co.uk/sherlock.jpg' class='classy'>", newuser) }
it "returns 0 images for an empty post" do
Fabricate.build(:post).image_count.should == 0
@@ -159,11 +166,78 @@ describe Post do
end
context "links" do
let(:newuser) { Fabricate(:user, trust_level: TrustLevel.levels[:newuser]) }
let(:no_links) { post_with_body("hello world my name is evil trout", newuser) }
let(:one_link) { post_with_body("[jlawr](http://www.imdb.com/name/nm2225369)", newuser) }
let(:two_links) { post_with_body("<a href='http://disneyland.disney.go.com/'>disney</a> <a href='http://reddit.com'>reddit</a>", newuser)}
let(:three_links) { post_with_body("http://discourse.org and http://discourse.org/another_url and http://www.imdb.com/name/nm2225369", newuser)}
describe "raw_links" do
it "returns a blank collection for a post with no links" do
no_links.raw_links.should be_blank
end
it "finds a link within markdown" do
one_link.raw_links.should == ["http://www.imdb.com/name/nm2225369"]
end
it "can find two links from html" do
two_links.raw_links.should == ["http://disneyland.disney.go.com/", "http://reddit.com"]
end
it "can find three links without markup" do
three_links.raw_links.should == ["http://discourse.org", "http://discourse.org/another_url", "http://www.imdb.com/name/nm2225369"]
end
end
describe "linked_hosts" do
it "returns blank with no links" do
no_links.linked_hosts.should be_blank
end
it "returns the host and a count for links" do
two_links.linked_hosts.should == {"disneyland.disney.go.com" => 1, "reddit.com" => 1}
end
it "it counts properly with more than one link on the same host" do
three_links.linked_hosts.should == {"discourse.org" => 2, "www.imdb.com" => 1}
end
end
describe "total host usage" do
it "has none for a regular post" do
no_links.total_hosts_usage.should be_blank
end
context "with a previous host" do
let(:user) { old_post.newuser }
let(:another_disney_link) { post_with_body("[radiator springs](http://disneyland.disney.go.com/disney-california-adventure/radiator-springs-racers/)", newuser) }
before do
another_disney_link.save
TopicLink.extract_from(another_disney_link)
end
it "contains the new post's links, PLUS the previous one" do
two_links.total_hosts_usage.should == {'disneyland.disney.go.com' => 2, 'reddit.com' => 1}
end
end
end
end
describe "maximum links" do
let(:newuser) { Fabricate(:user, trust_level: TrustLevel.levels[:newuser]) }
let(:post_one_link) { Fabricate.build(:post, post_args.merge(raw: "[sherlock](http://www.bbc.co.uk/programmes/b018ttws)", user: newuser)) }
let(:post_two_links) { Fabricate.build(:post, post_args.merge(raw: "<a href='http://discourse.org'>discourse</a> <a href='http://twitter.com'>twitter</a>", user: newuser)) }
let(:post_with_mentions) { Fabricate.build(:post, post_args.merge(raw: "hello @#{newuser.username} how are you doing?") )}
let(:post_one_link) { post_with_body("[sherlock](http://www.bbc.co.uk/programmes/b018ttws)", newuser) }
let(:post_two_links) { post_with_body("<a href='http://discourse.org'>discourse</a> <a href='http://twitter.com'>twitter</a>", newuser) }
let(:post_with_mentions) { post_with_body("hello @#{newuser.username} how are you doing?", newuser) }
it "returns 0 links for an empty post" do
Fabricate.build(:post).link_count.should == 0
@@ -251,8 +325,8 @@ describe Post do
context "max mentions" do
let(:newuser) { Fabricate(:user, trust_level: TrustLevel.levels[:newuser]) }
let(:post_with_one_mention) { Fabricate.build(:post, post_args.merge(raw: "@Jake is the person I'm mentioning", user: newuser)) }
let(:post_with_two_mentions) { Fabricate.build(:post, post_args.merge(raw: "@Jake @Finn are the people I'm mentioning", user: newuser)) }
let(:post_with_one_mention) { post_with_body("@Jake is the person I'm mentioning", newuser) }
let(:post_with_two_mentions) { post_with_body("@Jake @Finn are the people I'm mentioning", newuser) }
context 'new user' do
before do
@@ -298,7 +372,7 @@ describe Post do
context "raw_hash" do
let(:raw) { "this is our test post body"}
let(:post) { Fabricate.build(:post, raw: raw) }
let(:post) { post_with_body(raw) }
it "returns a value" do
post.raw_hash.should be_present
@@ -310,19 +384,19 @@ describe Post do
end
it "returns the same value for the same raw" do
post.raw_hash.should == Fabricate.build(:post, raw: raw).raw_hash
post.raw_hash.should == post_with_body(raw).raw_hash
end
it "returns a different value for a different raw" do
post.raw_hash.should_not == Fabricate.build(:post, raw: "something else").raw_hash
post.raw_hash.should_not == post_with_body("something else").raw_hash
end
it "returns the same hash even with different white space" do
post.raw_hash.should == Fabricate.build(:post, raw: " thisis ourt est postbody").raw_hash
post.raw_hash.should == post_with_body(" thisis ourt est postbody").raw_hash
end
it "returns the same hash even with different text case" do
post.raw_hash.should == Fabricate.build(:post, raw: "THIS is OUR TEST post BODy").raw_hash
post.raw_hash.should == post_with_body("THIS is OUR TEST post BODy").raw_hash
end
end
@@ -600,12 +674,12 @@ describe Post do
end
describe 'urls' do
it 'no-ops for empty list' do
it 'no-ops for empty list' do
Post.urls([]).should == {}
end
# integration test -> should move to centralized integration test
it 'finds urls for posts presented' do
# integration test -> should move to centralized integration test
it 'finds urls for posts presented' do
p1 = Fabricate(:post)
p2 = Fabricate(:post)
Post.urls([p1.id, p2.id]).should == {p1.id => p1.url, p2.id => p2.url}

View File

@@ -266,7 +266,7 @@ describe User do
describe "trust levels" do
# NOTE be sure to use build to avoid db calls
# NOTE be sure to use build to avoid db calls
let(:user) { Fabricate.build(:user, trust_level: TrustLevel.levels[:newuser]) }
it "sets to the default trust level setting" do
@@ -770,6 +770,31 @@ describe User do
end
end
describe "flag_linked_posts_as_spam" do
let(:user) { Fabricate(:user) }
let!(:admin) { Fabricate(:admin) }
let!(:post) { PostCreator.new(user, title: "this topic contains spam", raw: "this post has a link: http://discourse.org").create }
let!(:another_post) { PostCreator.new(user, title: "this topic also contains spam", raw: "this post has a link: http://discourse.org/asdfa").create }
let!(:post_without_link) { PostCreator.new(user, title: "this topic shouldn't be spam", raw: "this post has no links in it.").create }
it "has flagged all the user's posts as spam" do
user.flag_linked_posts_as_spam
post.reload
post.spam_count.should == 1
another_post.reload
another_post.spam_count.should == 1
post_without_link.reload
post_without_link.spam_count.should == 0
# It doesn't raise an exception if called again
user.flag_linked_posts_as_spam
end
end
describe 'update_time_read!' do
let(:user) { Fabricate(:user) }