Skip to content

Commit f9e33ec

Browse files
committed
store ip address and current user with incoming links
make links long an readable in share dialog
1 parent a56a926 commit f9e33ec

10 files changed

Lines changed: 80 additions & 43 deletions

File tree

app/assets/javascripts/discourse/models/post.js

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,24 @@ Discourse.Post = Discourse.Model.extend({
1010

1111
shareUrl: function(){
1212
var user = Discourse.get('currentUser');
13-
return '/p/' + this.get('id') + (user ? '/' + user.get('id') : '');
14-
}.property('id'),
13+
if (this.get('postnumber') === 1){
14+
return this.get('topic.url');
15+
} else {
16+
return this.get('url') + (user ? '?u=' + user.get('username_lower') : '');
17+
}
18+
}.property('url'),
1519

1620
new_user:(function(){
1721
return this.get('trust_level') === 0;
1822
}).property('trust_level'),
1923

20-
url: (function() {
24+
url: function() {
2125
return Discourse.Utilities.postUrl(this.get('topic.slug') || this.get('topic_slug'), this.get('topic_id'), this.get('post_number'));
22-
}).property('post_number', 'topic_id', 'topic.slug'),
26+
}.property('post_number', 'topic_id', 'topic.slug'),
2327

24-
originalPostUrl: (function() {
28+
originalPostUrl: function() {
2529
return Discourse.getURL("/t/") + (this.get('topic_id')) + "/" + (this.get('reply_to_post_number'));
26-
}).property('reply_to_post_number'),
30+
}.property('reply_to_post_number'),
2731

2832
usernameUrl: (function() {
2933
return Discourse.getURL("/users/" + this.get('username'));

app/assets/javascripts/discourse/models/topic.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,16 @@ Discourse.Topic = Discourse.Model.extend({
3030
}
3131
},
3232

33-
category: (function() {
33+
category: function() {
3434
if (this.get('categories')) {
3535
return this.get('categories').findProperty('name', this.get('categoryName'));
3636
}
37-
}).property('categoryName', 'categories'),
37+
}.property('categoryName', 'categories'),
3838

3939
shareUrl: function(){
4040
var user = Discourse.get('currentUser');
41-
return '/st/' + this.get('id') + (user ? '/' + user.get('id') : '');
42-
}.property('id'),
41+
return this.get('url') + (user ? '?u=' + user.get('username_lower') : '');
42+
}.property('url'),
4343

4444
url: function() {
4545
var slug = this.get('slug');

app/controllers/application_controller.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ def requires_parameters(*required)
240240
alias :requires_parameter :requires_parameters
241241

242242
def store_incoming_links
243-
IncomingLink.add(request)
243+
IncomingLink.add(request,current_user) unless request.xhr?
244244
end
245245

246246
def check_xhr

app/controllers/posts_controller.rb

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ class PostsController < ApplicationController
1111

1212
def short_link
1313
post = Post.find(params[:post_id].to_i)
14-
user = User.select(:id).where(id: params[:user_id].to_i).first
15-
IncomingLink.add(request, user ? user.id : nil)
14+
IncomingLink.add(request,current_user)
1615
redirect_to post.url
1716
end
1817

app/controllers/topics_controller.rb

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,9 @@ class TopicsController < ApplicationController
1919

2020
before_filter :consider_user_for_promotion, only: :show
2121

22-
skip_before_filter :check_xhr, only: [:avatar, :show, :feed, :short_link]
23-
skip_before_filter :store_incoming_links, only: [:short_link]
22+
skip_before_filter :check_xhr, only: [:avatar, :show, :feed]
2423
caches_action :avatar, cache_path: Proc.new {|c| "#{c.params[:post_number]}-#{c.params[:topic_id]}" }
2524

26-
def short_link
27-
topic = Topic.find(params[:topic_id].to_i)
28-
user = User.select(:id).where(id: params[:user_id].to_i).first
29-
IncomingLink.add(request, user ? user.id : nil)
30-
redirect_to topic.relative_url
31-
end
32-
3325
def show
3426
create_topic_view
3527

app/models/incoming_link.rb

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,41 @@
11
class IncomingLink < ActiveRecord::Base
22
belongs_to :topic
33

4-
validates :domain, length: { in: 1..100 }
5-
validates :referer, length: { in: 3..1000 }
64
validates :url, presence: true
75

6+
validate :referer_valid
7+
88
before_validation :extract_domain
99
before_validation :extract_topic_and_post
1010
after_create :update_link_counts
1111

12-
def self.add(request, user_id = nil)
13-
host, referer = nil
12+
def self.add(request,current_user=nil)
13+
user_id, host, referer = nil
14+
15+
if request['u']
16+
u = User.select(:id).where(username_lower: request['u'].downcase).first
17+
user_id = u.id if u
18+
end
1419

1520
if request.referer.present?
1621
host = URI.parse(request.referer).host
1722
referer = request.referer[0..999]
23+
end
1824

19-
if host != request.host
20-
IncomingLink.create(url: request.url, referer: referer, user_id: user_id)
25+
if host != request.host && (user_id || referer)
26+
cid = current_user.id if current_user
27+
unless cid && cid == user_id
28+
IncomingLink.create(url: request.url,
29+
referer: referer,
30+
user_id: user_id,
31+
current_user_id: cid,
32+
ip_address: request.remote_ip)
2133
end
2234
end
2335

2436
end
2537

38+
2639
# Internal: Extract the domain from link.
2740
def extract_domain
2841
if referer.present?
@@ -58,4 +71,17 @@ def update_link_counts
5871
end
5972
end
6073
end
74+
75+
protected
76+
77+
def referer_valid
78+
return true unless referer
79+
if (referer.length < 3 || referer.length > 100) || (domain.length < 1 || domain.length > 100)
80+
# internal, no need to localize
81+
errors.add(:referer, 'referer is invalid')
82+
false
83+
else
84+
true
85+
end
86+
end
6187
end

config/routes.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,6 @@
130130
end
131131

132132
get 'p/:post_id/:user_id' => 'posts#short_link'
133-
get 'st/:topic_id/:user_id' => 'topics#short_link'
134133

135134
resources :notifications
136135
resources :categories
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
class AllowNullsInIncomingLinks < ActiveRecord::Migration
2+
def change
3+
change_column :incoming_links, :referer, :string, limit:1000, null: true
4+
change_column :incoming_links, :domain, :string, limit:100, null: true
5+
end
6+
end
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
class AddIncomingIpCurrentUserIdToIncomingLinks < ActiveRecord::Migration
2+
def change
3+
add_column :incoming_links, :ip_address, :inet
4+
add_column :incoming_links, :current_user_id, :int
5+
end
6+
end

spec/models/incoming_link_spec.rb

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,6 @@
55
it { should belong_to :topic }
66
it { should validate_presence_of :url }
77

8-
it { should ensure_length_of(:referer).is_at_least(3).is_at_most(1000) }
9-
it { should ensure_length_of(:domain).is_at_least(1).is_at_most(100) }
10-
118
let :post do
129
Fabricate(:post)
1310
end
@@ -46,27 +43,35 @@
4643
end
4744

4845
describe 'add' do
46+
class TestRequest<Rack::Request
47+
attr_accessor :remote_ip
48+
end
49+
def req(url, referer=nil)
50+
env = Rack::MockRequest.env_for(url)
51+
env['HTTP_REFERER'] = referer if referer
52+
TestRequest.new(env)
53+
end
54+
4955
it "does nothing if referer is empty" do
50-
env = Rack::MockRequest.env_for("http://somesite.com")
51-
request = Rack::Request.new(env)
5256
IncomingLink.expects(:create).never
53-
IncomingLink.add(request)
57+
IncomingLink.add(req('http://somesite.com'))
5458
end
5559

5660
it "does nothing if referer is same as host" do
57-
env = Rack::MockRequest.env_for("http://somesite.com")
58-
env['HTTP_REFERER'] = 'http://somesite.com'
59-
request = Rack::Request.new(env)
6061
IncomingLink.expects(:create).never
61-
IncomingLink.add(request)
62+
IncomingLink.add(req('http://somesite.com', 'http://somesite.com'))
6263
end
6364

6465
it "expects to be called with referer and user id" do
65-
env = Rack::MockRequest.env_for("http://somesite.com")
66-
env['HTTP_REFERER'] = 'http://some.other.site.com'
67-
request = Rack::Request.new(env)
6866
IncomingLink.expects(:create).once.returns(true)
69-
IncomingLink.add(request, 100)
67+
IncomingLink.add(req('http://somesite.com', 'http://some.other.site.com'), build(:user))
68+
end
69+
70+
it "is able to look up user_id and log it from the GET params" do
71+
user = Fabricate(:user, username: "Bob")
72+
IncomingLink.add(req('http://somesite.com?u=bob'))
73+
first = IncomingLink.first
74+
first.user_id.should == user.id
7075
end
7176
end
7277

0 commit comments

Comments
 (0)