mirror of
https://github.com/discourse/discourse.git
synced 2024-11-23 09:26:54 -06:00
2e478d8537
When accessed over IPv6, the ip address of the user is a 128-bit number, too big for PostgreSQL's bigint data type. Since PostgresSQL has the built-in inet type, which handles both IPv4 and IPv6 addresses, we should use that instead. Where this is done elsewhere in the codebase, the column is called ip_address, so we should follow that convention as well. This migration uses a SQL command to populate the new field from the old one, so as not to rely on the TopicLinkClick model class, which should keep the migration from failing if that class is modified in the future.
278 lines
8.2 KiB
Ruby
278 lines
8.2 KiB
Ruby
require 'spec_helper'
|
|
|
|
describe TopicLink do
|
|
|
|
it { should belong_to :topic }
|
|
it { should belong_to :post }
|
|
it { should belong_to :user }
|
|
it { should have_many :topic_link_clicks }
|
|
it { should validate_presence_of :url }
|
|
|
|
def test_uri
|
|
URI.parse(Discourse.base_url)
|
|
end
|
|
|
|
before do
|
|
@topic = Fabricate(:topic, title: 'unique topic name')
|
|
@user = @topic.user
|
|
end
|
|
|
|
it "can't link to the same topic" do
|
|
ftl = TopicLink.new(url: "/t/#{@topic.id}",
|
|
topic_id: @topic.id,
|
|
link_topic_id: @topic.id)
|
|
ftl.valid?.should be_false
|
|
end
|
|
|
|
describe 'external links' do
|
|
before do
|
|
@post = Fabricate(:post_with_external_links, user: @user, topic: @topic)
|
|
TopicLink.extract_from(@post)
|
|
end
|
|
|
|
it 'works' do
|
|
# has the forum topic links
|
|
@topic.topic_links.count.should == 4
|
|
|
|
# works with markdown links
|
|
@topic.topic_links.exists?(url: "http://forumwarz.com").should be_true
|
|
|
|
#works with markdown links followed by a period
|
|
@topic.topic_links.exists?(url: "http://www.codinghorror.com/blog").should be_true
|
|
end
|
|
|
|
end
|
|
|
|
describe 'internal links' do
|
|
|
|
context "rendered onebox" do
|
|
|
|
before do
|
|
@other_topic = Fabricate(:topic, user: @user)
|
|
@other_topic.posts.create(user: @user, raw: "some content for the first post")
|
|
@other_post = @other_topic.posts.create(user: @user, raw: "some content for the second post")
|
|
|
|
@url = "http://#{test_uri.host}/t/#{@other_topic.slug}/#{@other_topic.id}/#{@other_post.post_number}"
|
|
|
|
@topic.posts.create(user: @user, raw: 'initial post')
|
|
@post = @topic.posts.create(user: @user, raw: "Link to another topic:\n\n#{@url}\n\n")
|
|
@post.reload
|
|
TopicLink.extract_from(@post)
|
|
|
|
@link = @topic.topic_links.first
|
|
end
|
|
|
|
it 'works' do
|
|
# should have a link
|
|
@link.should be_present
|
|
# should be the canonical URL
|
|
@link.url.should == @url
|
|
end
|
|
|
|
end
|
|
|
|
context 'topic link' do
|
|
before do
|
|
@other_topic = Fabricate(:topic, user: @user)
|
|
@other_post = @other_topic.posts.create(user: @user, raw: "some content")
|
|
|
|
@url = "http://#{test_uri.host}/t/#{@other_topic.slug}/#{@other_topic.id}"
|
|
|
|
@topic.posts.create(user: @user, raw: 'initial post')
|
|
@post = @topic.posts.create(user: @user, raw: "Link to another topic: #{@url}")
|
|
|
|
TopicLink.extract_from(@post)
|
|
|
|
@link = @topic.topic_links.first
|
|
end
|
|
|
|
it 'works' do
|
|
# extracted the link
|
|
@link.should be_present
|
|
|
|
# is set to internal
|
|
@link.should be_internal
|
|
|
|
# has the correct url
|
|
@link.url.should == @url
|
|
|
|
# has the extracted domain
|
|
@link.domain.should == test_uri.host
|
|
|
|
# should have the id of the linked forum
|
|
@link.link_topic_id == @other_topic.id
|
|
|
|
# should not be the reflection
|
|
@link.should_not be_reflection
|
|
end
|
|
|
|
describe 'reflection in the other topic' do
|
|
|
|
before do
|
|
@reflection = @other_topic.topic_links.first
|
|
end
|
|
|
|
it 'works' do
|
|
# exists
|
|
@reflection.should be_present
|
|
@reflection.should be_reflection
|
|
@reflection.post_id.should be_present
|
|
@reflection.domain.should == test_uri.host
|
|
@reflection.url.should == "http://#{test_uri.host}/t/unique-topic-name/#{@topic.id}/#{@post.post_number}"
|
|
@reflection.link_topic_id.should == @topic.id
|
|
@reflection.link_post_id.should == @post.id
|
|
|
|
#has the user id of the original link
|
|
@reflection.user_id.should == @link.user_id
|
|
end
|
|
end
|
|
|
|
context 'removing a link' do
|
|
|
|
before do
|
|
@post.revise(@post.user, "no more linkies")
|
|
TopicLink.extract_from(@post)
|
|
end
|
|
|
|
it 'should remove the link' do
|
|
@topic.topic_links.where(post_id: @post.id).should be_blank
|
|
# should remove the reflected link
|
|
@reflection = @other_topic.topic_links.should be_blank
|
|
end
|
|
end
|
|
end
|
|
|
|
context "link to a user on discourse" do
|
|
let(:post) { @topic.posts.create(user: @user, raw: "<a href='/users/#{@user.username_lower}'>user</a>") }
|
|
before do
|
|
TopicLink.extract_from(post)
|
|
end
|
|
|
|
it 'does not extract a link' do
|
|
@topic.topic_links.should be_blank
|
|
end
|
|
end
|
|
|
|
context "link to a discourse resource like a FAQ" do
|
|
let(:post) { @topic.posts.create(user: @user, raw: "<a href='/faq'>faq link here</a>") }
|
|
before do
|
|
TopicLink.extract_from(post)
|
|
end
|
|
|
|
it 'does not extract a link' do
|
|
@topic.topic_links.should be_present
|
|
end
|
|
end
|
|
|
|
context "@mention links" do
|
|
let(:post) { @topic.posts.create(user: @user, raw: "Hey @#{@user.username_lower}") }
|
|
|
|
before do
|
|
TopicLink.extract_from(post)
|
|
end
|
|
|
|
it 'does not extract a link' do
|
|
@topic.topic_links.should be_blank
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
describe 'internal link from pm' do
|
|
before do
|
|
@pm = Fabricate(:topic, user: @user, archetype: 'private_message')
|
|
@other_post = @pm.posts.create(user: @user, raw: "some content")
|
|
|
|
@url = "http://#{test_uri.host}/t/topic-slug/#{@topic.id}"
|
|
|
|
@pm.posts.create(user: @user, raw: 'initial post')
|
|
@linked_post = @pm.posts.create(user: @user, raw: "Link to another topic: #{@url}")
|
|
|
|
TopicLink.extract_from(@linked_post)
|
|
|
|
@link = @topic.topic_links.first
|
|
end
|
|
|
|
it 'should not create a reflection' do
|
|
@topic.topic_links.first.should be_nil
|
|
end
|
|
|
|
it 'should not create a normal link' do
|
|
@pm.topic_links.first.should_not be_nil
|
|
end
|
|
end
|
|
|
|
describe 'internal link with non-standard port' do
|
|
it 'includes the non standard port if present' do
|
|
@other_topic = Fabricate(:topic, user: @user)
|
|
SiteSetting.stubs(:port).returns(5678)
|
|
alternate_uri = URI.parse(Discourse.base_url)
|
|
@url = "http://#{alternate_uri.host}:5678/t/topic-slug/#{@other_topic.id}"
|
|
@post = @topic.posts.create(user: @user,
|
|
raw: "Link to another topic: #{@url}")
|
|
TopicLink.extract_from(@post)
|
|
@reflection = @other_topic.topic_links.first
|
|
@reflection.url.should == "http://#{alternate_uri.host}:5678/t/unique-topic-name/#{@topic.id}"
|
|
end
|
|
end
|
|
|
|
describe 'counts_for and topic_summary' do
|
|
it 'returns blank without posts' do
|
|
TopicLink.counts_for(Guardian.new, nil, nil).should be_blank
|
|
end
|
|
|
|
context 'with data' do
|
|
|
|
let(:post) do
|
|
topic = Fabricate(:topic)
|
|
Fabricate(:post_with_external_links, user: topic.user, topic: topic)
|
|
end
|
|
|
|
let(:counts_for) do
|
|
TopicLink.counts_for(Guardian.new, post.topic, [post])
|
|
end
|
|
|
|
|
|
it 'has the correct results' do
|
|
TopicLink.extract_from(post)
|
|
topic_link = post.topic.topic_links.first
|
|
TopicLinkClick.create(topic_link: topic_link, ip_address: '192.168.1.1')
|
|
|
|
counts_for[post.id].should be_present
|
|
counts_for[post.id].find {|l| l[:url] == 'http://google.com'}[:clicks].should == 0
|
|
counts_for[post.id].first[:clicks].should == 1
|
|
|
|
array = TopicLink.topic_summary(Guardian.new, post.topic_id)
|
|
array.length.should == 4
|
|
array[0]["clicks"].should == "1"
|
|
end
|
|
|
|
it 'secures internal links correctly' do
|
|
category = Fabricate(:category)
|
|
secret_topic = Fabricate(:topic, category: category)
|
|
|
|
url = "http://#{test_uri.host}/t/topic-slug/#{secret_topic.id}"
|
|
post = Fabricate(:post, raw: "hello test topic #{url}")
|
|
TopicLink.extract_from(post)
|
|
|
|
TopicLink.topic_summary(Guardian.new, post.topic_id).count.should == 1
|
|
TopicLink.counts_for(Guardian.new, post.topic, [post]).length.should == 1
|
|
|
|
category.deny(:all)
|
|
category.allow(Group[:staff])
|
|
category.save
|
|
|
|
admin = Fabricate(:admin)
|
|
|
|
TopicLink.topic_summary(Guardian.new, post.topic_id).count.should == 0
|
|
TopicLink.topic_summary(Guardian.new(admin), post.topic_id).count.should == 1
|
|
|
|
TopicLink.counts_for(Guardian.new, post.topic, [post]).length.should == 0
|
|
TopicLink.counts_for(Guardian.new(admin), post.topic, [post]).length.should == 1
|
|
end
|
|
|
|
end
|
|
end
|
|
|
|
end
|