mbleigh-twitter-auth 0.1.8 → 0.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.markdown +4 -0
- data/VERSION.yml +1 -1
- data/app/controllers/sessions_controller.rb +2 -0
- data/app/models/twitter_auth/generic_user.rb +23 -2
- data/generators/twitter_auth/templates/migration.rb +3 -0
- data/generators/twitter_auth/templates/twitter_auth.yml +12 -6
- data/lib/twitter_auth/controller_extensions.rb +2 -1
- data/lib/twitter_auth.rb +4 -0
- data/spec/controllers/controller_extensions_spec.rb +25 -9
- data/spec/controllers/sessions_controller_spec.rb +15 -0
- data/spec/models/twitter_auth/generic_user_spec.rb +86 -1
- data/spec/schema.rb +4 -0
- data/spec/twitter_auth_spec.rb +13 -1
- metadata +1 -1
data/README.markdown
CHANGED
@@ -76,6 +76,10 @@ TwitterAuth provides some default controller methods that may be overridden in y
|
|
76
76
|
* `authentication_succeeded(message=default)`: called when Twitter authorization has completed successfully. By default, simply redirects to the site root and sets the `flash[:notice]`.
|
77
77
|
* `access_denied`: what happens when the `login_required` before filter fails. By default it stores the current location to return to and redirects to the login process.
|
78
78
|
|
79
|
+
Resources
|
80
|
+
---------
|
81
|
+
|
82
|
+
* **Bug Reports:** See the [Lighthouse Project](http://mbleigh.lighthouseapp.com/projects/27783-twitterauth) to report any problems you have using TwitterAuth.
|
79
83
|
|
80
84
|
Copyright
|
81
85
|
---------
|
data/VERSION.yml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module TwitterAuth
|
2
2
|
class GenericUser < ActiveRecord::Base
|
3
|
-
attr_protected :login
|
4
|
-
|
3
|
+
attr_protected :login, :remember_token, :remember_token_expires_at
|
4
|
+
|
5
5
|
TWITTER_ATTRIBUTES = [
|
6
6
|
:name,
|
7
7
|
:location,
|
@@ -26,6 +26,7 @@ module TwitterAuth
|
|
26
26
|
validates_format_of :login, :with => /\A[a-z0-9_]+\z/i
|
27
27
|
validates_length_of :login, :in => 1..15
|
28
28
|
validates_uniqueness_of :login, :case_sensitive => false
|
29
|
+
validates_uniqueness_of :remember_token, :allow_blank => true
|
29
30
|
|
30
31
|
def self.table_name; 'users' end
|
31
32
|
|
@@ -41,6 +42,10 @@ module TwitterAuth
|
|
41
42
|
|
42
43
|
user
|
43
44
|
end
|
45
|
+
|
46
|
+
def self.from_remember_token(token)
|
47
|
+
first(:conditions => ["remember_token = ? AND remember_token_expires_at > ?", token, Time.now])
|
48
|
+
end
|
44
49
|
|
45
50
|
def assign_twitter_attributes(hash)
|
46
51
|
TWITTER_ATTRIBUTES.each do |att|
|
@@ -66,5 +71,21 @@ module TwitterAuth
|
|
66
71
|
TwitterAuth::Dispatcher::Basic.new(self)
|
67
72
|
end
|
68
73
|
end
|
74
|
+
|
75
|
+
def remember_me
|
76
|
+
return false unless respond_to?(:remember_token)
|
77
|
+
|
78
|
+
self.remember_token = ActiveSupport::SecureRandom.hex(10)
|
79
|
+
self.remember_token_expires_at = Time.now + TwitterAuth.remember_for.days
|
80
|
+
|
81
|
+
save
|
82
|
+
|
83
|
+
{:value => self.remember_token, :expires => self.remember_token_expires_at}
|
84
|
+
end
|
85
|
+
|
86
|
+
def forget_me
|
87
|
+
self.remember_token = self.remember_token_expires_at = nil
|
88
|
+
self.save
|
89
|
+
end
|
69
90
|
end
|
70
91
|
end
|
@@ -10,6 +10,9 @@ class TwitterAuthMigration < ActiveRecord::Migration
|
|
10
10
|
t.string :salt
|
11
11
|
<% end -%>
|
12
12
|
|
13
|
+
t.string :remember_token
|
14
|
+
t.datetime :remember_token_expires_at
|
15
|
+
|
13
16
|
# This information is automatically kept
|
14
17
|
# in-sync at each login of the user. You
|
15
18
|
# may remove any/all of these columns.
|
@@ -1,24 +1,27 @@
|
|
1
1
|
<% if options[:oauth] -%>
|
2
2
|
development:
|
3
3
|
strategy: oauth
|
4
|
-
base_url: "https://twitter.com"
|
5
|
-
api_timeout: 10
|
6
4
|
oauth_consumer_key: devkey
|
7
5
|
oauth_consumer_secret: devsecret
|
6
|
+
base_url: "https://twitter.com"
|
7
|
+
api_timeout: 10
|
8
|
+
remember_for: 14 # days
|
8
9
|
oauth_callback: "http://localhost:3000/oauth_callback"
|
9
10
|
test:
|
10
11
|
strategy: oauth
|
11
|
-
base_url: "https://twitter.com"
|
12
|
-
api_timeout: 10
|
13
12
|
oauth_consumer_key: testkey
|
14
13
|
oauth_consumer_secret: testsecret
|
14
|
+
base_url: "https://twitter.com"
|
15
|
+
api_timeout: 10
|
16
|
+
remember_for: 14 # days
|
15
17
|
oauth_callback: "http://localhost:3000/oauth_callback"
|
16
18
|
production:
|
17
19
|
strategy: oauth
|
18
|
-
api_timeout: 10
|
19
|
-
base_url: "https://twitter.com"
|
20
20
|
oauth_consumer_key: prodkey
|
21
21
|
oauth_consumer_secret: prodsecret
|
22
|
+
base_url: "https://twitter.com"
|
23
|
+
api_timeout: 10
|
24
|
+
remember_for: 14 # days
|
22
25
|
<% else -%>
|
23
26
|
development:
|
24
27
|
strategy: basic
|
@@ -26,13 +29,16 @@ development:
|
|
26
29
|
base_url: "https://twitter.com"
|
27
30
|
# randomly generated key for encrypting Twitter passwords
|
28
31
|
encryption_key: "<%= key = ActiveSupport::SecureRandom.hex(12) %>"
|
32
|
+
remember_for: 14 # days
|
29
33
|
test:
|
30
34
|
strategy: basic
|
31
35
|
api_timeout: 10
|
32
36
|
base_url: "https://twitter.com"
|
33
37
|
encryption_key: "<%= key %>"
|
38
|
+
remember_for: 14 # days
|
34
39
|
production:
|
35
40
|
strategy: basic
|
36
41
|
api_timeout: 10
|
37
42
|
encryption_key: "<%= key %>"
|
43
|
+
remember_for: 14 # days
|
38
44
|
<% end %>
|
@@ -20,7 +20,7 @@ module TwitterAuth
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def current_user
|
23
|
-
@current_user ||= User.find_by_id(session[:user_id])
|
23
|
+
@current_user ||= User.find_by_id(session[:user_id]) || User.from_remember_token(cookies[:remember_token])
|
24
24
|
end
|
25
25
|
|
26
26
|
def current_user=(new_user)
|
@@ -57,6 +57,7 @@ module TwitterAuth
|
|
57
57
|
def logout_keeping_session!
|
58
58
|
@current_user = nil
|
59
59
|
session[:user_id] = nil
|
60
|
+
cookies.delete(:remember_token)
|
60
61
|
end
|
61
62
|
end
|
62
63
|
end
|
data/lib/twitter_auth.rb
CHANGED
@@ -27,6 +27,10 @@ module TwitterAuth
|
|
27
27
|
config['oauth_callback']
|
28
28
|
end
|
29
29
|
|
30
|
+
def self.remember_for
|
31
|
+
(config['remember_for'] || 14).to_i
|
32
|
+
end
|
33
|
+
|
30
34
|
# The authentication strategy employed by this
|
31
35
|
# application. Set in +config/twitter.yml+ as
|
32
36
|
# strategy; valid options are oauth or basic.
|
@@ -35,9 +35,18 @@ class TwitterAuthTestController < ApplicationController
|
|
35
35
|
logout_keeping_session!
|
36
36
|
redirect_back_or_default('/')
|
37
37
|
end
|
38
|
+
|
39
|
+
def current_user_action
|
40
|
+
@user = current_user
|
41
|
+
render :nothing => true
|
42
|
+
end
|
38
43
|
end
|
39
44
|
|
40
45
|
describe TwitterAuthTestController do
|
46
|
+
before do
|
47
|
+
controller.stub!(:cookies).and_return({})
|
48
|
+
end
|
49
|
+
|
41
50
|
%w(authentication_failed authentication_succeeded current_user authorized? login_required access_denied store_location redirect_back_or_default logout_keeping_session!).each do |m|
|
42
51
|
it "should respond to the extension method '#{m}'" do
|
43
52
|
controller.should respond_to(m)
|
@@ -72,19 +81,21 @@ describe TwitterAuthTestController do
|
|
72
81
|
it 'should find the user based on the session user_id' do
|
73
82
|
user = Factory.create(:twitter_oauth_user)
|
74
83
|
request.session[:user_id] = user.id
|
75
|
-
|
84
|
+
get(:current_user_action)
|
85
|
+
assigns[:user].should == user
|
76
86
|
end
|
77
87
|
|
78
|
-
it 'should
|
79
|
-
|
80
|
-
controller.
|
88
|
+
it 'should log the user in through a cookie' do
|
89
|
+
user = Factory(:twitter_oauth_user, :remember_token => 'abc', :remember_token_expires_at => (Time.now + 10.days))
|
90
|
+
controller.stub!(:cookies).and_return({:remember_token => 'abc'})
|
91
|
+
get :current_user_action
|
92
|
+
assigns[:user].should == user
|
81
93
|
end
|
82
94
|
|
83
|
-
it 'should
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
controller.send(:current_user).should == user
|
95
|
+
it 'should return nil if there is no user matching that id' do
|
96
|
+
request.session[:user_id] = 2345
|
97
|
+
get :current_user_action
|
98
|
+
assigns[:user].should be_nil
|
88
99
|
end
|
89
100
|
end
|
90
101
|
|
@@ -142,5 +153,10 @@ describe TwitterAuthTestController do
|
|
142
153
|
get :logout_keeping_session_action
|
143
154
|
controller.send(:current_user).should be_nil
|
144
155
|
end
|
156
|
+
|
157
|
+
it 'should unset the cookie' do
|
158
|
+
controller.send(:cookies).should_receive(:delete).with(:remember_token)
|
159
|
+
get :logout_keeping_session_action
|
160
|
+
end
|
145
161
|
end
|
146
162
|
end
|
@@ -82,6 +82,12 @@ describe SessionsController do
|
|
82
82
|
describe 'with proper info' do
|
83
83
|
before do
|
84
84
|
@user = Factory.create(:twitter_oauth_user)
|
85
|
+
@time = Time.now
|
86
|
+
@remember_token = ActiveSupport::SecureRandom.hex(10)
|
87
|
+
|
88
|
+
Time.stub!(:now).and_return(@time)
|
89
|
+
ActiveSupport::SecureRandom.stub!(:hex).and_return(@remember_token)
|
90
|
+
|
85
91
|
request.session[:request_token] = 'faketoken'
|
86
92
|
request.session[:request_token_secret] = 'faketokensecret'
|
87
93
|
get :oauth_callback, :oauth_token => 'faketoken'
|
@@ -116,6 +122,15 @@ describe SessionsController do
|
|
116
122
|
it "should assign the user id to the session" do
|
117
123
|
session[:user_id].should == @user.id
|
118
124
|
end
|
125
|
+
|
126
|
+
it "should call remember me" do
|
127
|
+
@user.reload
|
128
|
+
@user.remember_token.should == @remember_token
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should set a cookie" do
|
132
|
+
cookies[:remember_token].should == @remember_token
|
133
|
+
end
|
119
134
|
end
|
120
135
|
|
121
136
|
describe "when OAuth doesn't work" do
|
@@ -5,12 +5,17 @@ describe TwitterAuth::GenericUser do
|
|
5
5
|
should_validate_format_of :login, 'some_guy', 'awesome', 'cool_man'
|
6
6
|
should_not_validate_format_of :login, 'with-dashes', 'with.periods', 'with spaces'
|
7
7
|
should_validate_length_of :login, :in => 1..15
|
8
|
-
|
8
|
+
|
9
9
|
it 'should validate uniqueness of login' do
|
10
10
|
Factory.create(:twitter_oauth_user)
|
11
11
|
Factory.build(:twitter_oauth_user).should have_at_least(1).errors_on(:login)
|
12
12
|
end
|
13
13
|
|
14
|
+
it 'should validate uniqueness of remember_token' do
|
15
|
+
Factory.create(:twitter_oauth_user, :remember_token => 'abc')
|
16
|
+
Factory.build(:twitter_oauth_user, :remember_token => 'abc').should have_at_least(1).errors_on(:remember_token)
|
17
|
+
end
|
18
|
+
|
14
19
|
it 'should allow capital letters in the username' do
|
15
20
|
Factory.build(:twitter_oauth_user, :login => 'TwitterMan').should have(:no).errors_on(:login)
|
16
21
|
end
|
@@ -54,4 +59,84 @@ describe TwitterAuth::GenericUser do
|
|
54
59
|
lambda{user.update_twitter_attributes({'name' => 'Twitter Man', 'description' => 'Works.', 'whoopsy' => 'noworks.'})}.should_not raise_error
|
55
60
|
end
|
56
61
|
end
|
62
|
+
|
63
|
+
describe '#remember_me' do
|
64
|
+
before do
|
65
|
+
@user = Factory(:twitter_oauth_user)
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'should check for the remember_token column' do
|
69
|
+
@user.should_receive(:respond_to?).with(:remember_token).and_return(false)
|
70
|
+
@user.remember_me
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'should return nil if there is no remember_token column' do
|
74
|
+
@user.should_receive(:respond_to?).with(:remember_token).and_return(false)
|
75
|
+
@user.remember_me.should be_false
|
76
|
+
end
|
77
|
+
|
78
|
+
describe ' with proper columns' do
|
79
|
+
it 'should generate a secure random token' do
|
80
|
+
ActiveSupport::SecureRandom.should_receive(:hex).with(10).and_return('abcdef')
|
81
|
+
@user.remember_me
|
82
|
+
@user.remember_token.should == 'abcdef'
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'should set the expiration to the current time plus the remember_for period' do
|
86
|
+
TwitterAuth.stub!(:remember_for).and_return(10)
|
87
|
+
time = Time.now
|
88
|
+
Time.stub!(:now).and_return(time)
|
89
|
+
|
90
|
+
@user.remember_me
|
91
|
+
|
92
|
+
@user.remember_token_expires_at.should == Time.now + 10.days
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'should return a hash with a :value and :expires key' do
|
96
|
+
result = @user.remember_me
|
97
|
+
result.should be_a(Hash)
|
98
|
+
result.key?(:value).should be_true
|
99
|
+
result.key?(:expires).should be_true
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'should return a hash with appropriate values' do
|
103
|
+
TwitterAuth.stub!(:remember_for).and_return(10)
|
104
|
+
time = Time.now
|
105
|
+
Time.stub!(:now).and_return(time)
|
106
|
+
ActiveSupport::SecureRandom.stub!(:hex).and_return('abcdef')
|
107
|
+
|
108
|
+
@user.remember_me.should == {:value => 'abcdef', :expires => (Time.now + 10.days)}
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
describe '#forget_me' do
|
114
|
+
it 'should reset remember_token and remember_token_expires_at' do
|
115
|
+
@user = Factory(:twitter_oauth_user, :remember_token => "abcdef", :remember_token_expires_at => Time.now + 10.days)
|
116
|
+
@user.forget_me
|
117
|
+
@user.reload
|
118
|
+
@user.remember_token.should be_nil
|
119
|
+
@user.remember_token_expires_at.should be_nil
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
describe '.from_remember_token' do
|
124
|
+
before do
|
125
|
+
@user = Factory(:twitter_oauth_user, :remember_token => 'abcdef', :remember_token_expires_at => (Time.now + 10.days))
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'should find the user with the specified remember_token' do
|
129
|
+
User.from_remember_token('abcdef').should == @user
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'should not find a user with an expired token' do
|
133
|
+
user2 = Factory(:twitter_oauth_user, :login => 'walker', :remember_token => 'ghijkl', :remember_token_expires_at => (Time.now - 10.days))
|
134
|
+
User.from_remember_token('ghijkl').should be_nil
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'should not find a user with a nil token and an expiration' do
|
138
|
+
user = Factory(:twitter_oauth_user, :login => 'stranger', :remember_token => nil, :remember_token_expires_at => (Time.now + 10.days))
|
139
|
+
User.from_remember_token(nil).should be_nil
|
140
|
+
end
|
141
|
+
end
|
57
142
|
end
|
data/spec/schema.rb
CHANGED
@@ -10,6 +10,10 @@ ActiveRecord::Schema.define :version => 0 do
|
|
10
10
|
t.binary :crypted_password
|
11
11
|
t.string :salt
|
12
12
|
|
13
|
+
# Remember token fields
|
14
|
+
t.string :remember_token
|
15
|
+
t.datetime :remember_token_expires_at
|
16
|
+
|
13
17
|
# This information is automatically kept
|
14
18
|
# in-sync at each login of the user. You
|
15
19
|
# may remove any/all of these columns.
|
data/spec/twitter_auth_spec.rb
CHANGED
@@ -13,7 +13,7 @@ describe TwitterAuth do
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
-
describe '
|
16
|
+
describe '.api_timeout' do
|
17
17
|
it 'should default to 10' do
|
18
18
|
TwitterAuth.stub!(:config).and_return({})
|
19
19
|
TwitterAuth.api_timeout.should == 10
|
@@ -25,6 +25,18 @@ describe TwitterAuth do
|
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
|
+
describe '.remember_for' do
|
29
|
+
it 'should default to 14' do
|
30
|
+
TwitterAuth.stub!(:config).and_return({})
|
31
|
+
TwitterAuth.remember_for.should == 14
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should be settable via config' do
|
35
|
+
TwitterAuth.stub!(:config).and_return({'remember_for' => '7'})
|
36
|
+
TwitterAuth.remember_for.should == 7
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
28
40
|
describe '.net' do
|
29
41
|
before do
|
30
42
|
stub_basic!
|