twitter-auth-with-mongo-mapper 0.0.9
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.markdown +11 -0
- data/README.markdown +5 -0
- data/Rakefile +31 -0
- data/VERSION.yml +4 -0
- data/app/controllers/sessions_controller.rb +81 -0
- data/app/models/twitter_auth/basic_user.rb +64 -0
- data/app/models/twitter_auth/generic_user.rb +135 -0
- data/app/models/twitter_auth/oauth_user.rb +50 -0
- data/app/views/sessions/_login_form.html.erb +17 -0
- data/app/views/sessions/new.html.erb +5 -0
- data/config/routes.rb +6 -0
- data/generators/twitter_auth/USAGE +12 -0
- data/generators/twitter_auth/templates/migration.rb +49 -0
- data/generators/twitter_auth/templates/twitter_auth.yml +47 -0
- data/generators/twitter_auth/templates/user.rb +5 -0
- data/generators/twitter_auth/twitter_auth_generator.rb +34 -0
- data/lib/twitter_auth.rb +100 -0
- data/lib/twitter_auth/controller_extensions.rb +82 -0
- data/lib/twitter_auth/cryptify.rb +31 -0
- data/lib/twitter_auth/dispatcher/basic.rb +46 -0
- data/lib/twitter_auth/dispatcher/oauth.rb +27 -0
- data/lib/twitter_auth/dispatcher/shared.rb +40 -0
- data/rails/init.rb +8 -0
- data/spec/controllers/controller_extensions_spec.rb +162 -0
- data/spec/controllers/sessions_controller_spec.rb +221 -0
- data/spec/fixtures/config/twitter_auth.yml +17 -0
- data/spec/fixtures/factories.rb +20 -0
- data/spec/fixtures/fakeweb.rb +18 -0
- data/spec/fixtures/twitter.rb +5 -0
- data/spec/models/twitter_auth/basic_user_spec.rb +138 -0
- data/spec/models/twitter_auth/generic_user_spec.rb +146 -0
- data/spec/models/twitter_auth/oauth_user_spec.rb +100 -0
- data/spec/schema.rb +42 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +51 -0
- data/spec/twitter_auth/cryptify_spec.rb +51 -0
- data/spec/twitter_auth/dispatcher/basic_spec.rb +83 -0
- data/spec/twitter_auth/dispatcher/oauth_spec.rb +72 -0
- data/spec/twitter_auth/dispatcher/shared_spec.rb +26 -0
- data/spec/twitter_auth_spec.rb +160 -0
- metadata +151 -0
@@ -0,0 +1,221 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe SessionsController do
|
4
|
+
integrate_views
|
5
|
+
|
6
|
+
describe 'routes' do
|
7
|
+
it 'should route /session/new to SessionsController#new' do
|
8
|
+
params_from(:get, '/session/new').should == {:controller => 'sessions', :action => 'new'}
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'should route /login to SessionsController#new' do
|
12
|
+
params_from(:get, '/login').should == {:controller => 'sessions', :action => 'new'}
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should route /logout to SessionsController#destroy' do
|
16
|
+
params_from(:get, '/logout').should == {:controller => 'sessions', :action => 'destroy'}
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should route DELETE /session to SessionsController#destroy' do
|
20
|
+
params_from(:delete, '/session').should == {:controller => 'sessions', :action => 'destroy'}
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should route /oauth_callback to SessionsController#oauth_callback' do
|
24
|
+
params_from(:get, '/oauth_callback').should == {:controller => 'sessions', :action => 'oauth_callback'}
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should route POST /session to SessionsController#create' do
|
28
|
+
params_from(:post, '/session').should == {:controller => 'sessions', :action => 'create'}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe 'with OAuth strategy' do
|
33
|
+
before do
|
34
|
+
stub_oauth!
|
35
|
+
end
|
36
|
+
|
37
|
+
describe '#new' do
|
38
|
+
it 'should retrieve a request token' do
|
39
|
+
get :new
|
40
|
+
assigns[:request_token].token.should == 'faketoken'
|
41
|
+
assigns[:request_token].secret.should == 'faketokensecret'
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'should set session variables for the request token' do
|
45
|
+
get :new
|
46
|
+
session[:request_token].should == 'faketoken'
|
47
|
+
session[:request_token_secret].should == 'faketokensecret'
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'should redirect to the oauth authorization url' do
|
51
|
+
get :new
|
52
|
+
response.should redirect_to('https://twitter.com/oauth/authorize?oauth_token=faketoken')
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'should redirect to the oauth_callback if one is specified' do
|
56
|
+
TwitterAuth.stub!(:oauth_callback).and_return('http://localhost:3000/development')
|
57
|
+
TwitterAuth.stub!(:oauth_callback?).and_return(true)
|
58
|
+
|
59
|
+
get :new
|
60
|
+
response.should redirect_to('https://twitter.com/oauth/authorize?oauth_token=faketoken&oauth_callback=' + CGI.escape(TwitterAuth.oauth_callback))
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe '#oauth_callback' do
|
65
|
+
describe 'with no session info' do
|
66
|
+
it 'should set the flash[:error]' do
|
67
|
+
get :oauth_callback, :oauth_token => 'faketoken'
|
68
|
+
flash[:error].should == 'No authentication information was found in the session. Please try again.'
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'should redirect to "/" by default' do
|
72
|
+
get :oauth_callback, :oauth_token => 'faketoken'
|
73
|
+
response.should redirect_to('/')
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'should call authentication_failed' do
|
77
|
+
controller.should_receive(:authentication_failed).any_number_of_times
|
78
|
+
get :oauth_callback, :oauth_token => 'faketoken'
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe 'with proper info' do
|
83
|
+
before do
|
84
|
+
@user = Factory.create(:twitter_oauth_user, :twitter_id => '123')
|
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
|
+
|
91
|
+
request.session[:request_token] = 'faketoken'
|
92
|
+
request.session[:request_token_secret] = 'faketokensecret'
|
93
|
+
get :oauth_callback, :oauth_token => 'faketoken'
|
94
|
+
end
|
95
|
+
|
96
|
+
describe 'building the access token' do
|
97
|
+
it 'should rebuild the request token' do
|
98
|
+
correct_token = OAuth::RequestToken.new(TwitterAuth.consumer,'faketoken','faketokensecret')
|
99
|
+
|
100
|
+
%w(token secret).each do |att|
|
101
|
+
assigns[:request_token].send(att).should == correct_token.send(att)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'should exchange the request token for an access token' do
|
106
|
+
assigns[:access_token].should be_a(OAuth::AccessToken)
|
107
|
+
assigns[:access_token].token.should == 'fakeaccesstoken'
|
108
|
+
assigns[:access_token].secret.should == 'fakeaccesstokensecret'
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'should wipe the request token after exchange' do
|
112
|
+
session[:request_token].should be_nil
|
113
|
+
session[:request_token_secret].should be_nil
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe 'identifying the user' do
|
118
|
+
it "should find the user" do
|
119
|
+
assigns[:user].should == @user
|
120
|
+
end
|
121
|
+
|
122
|
+
it "should assign the user id to the session" do
|
123
|
+
session[:user_id].should == @user.id
|
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
|
134
|
+
end
|
135
|
+
|
136
|
+
describe "when OAuth doesn't work" do
|
137
|
+
before do
|
138
|
+
request.session[:request_token] = 'faketoken'
|
139
|
+
request.session[:request_token_secret] = 'faketokensecret'
|
140
|
+
@request_token = OAuth::RequestToken.new(TwitterAuth.consumer, session[:request_token], session[:request_token_secret])
|
141
|
+
OAuth::RequestToken.stub!(:new).and_return(@request_token)
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'should call authentication_failed when it gets a 401 from OAuth' do
|
145
|
+
@request_token.stub!(:get_access_token).and_raise(Net::HTTPServerException.new('401 "Unauthorized"', '401 "Unauthorized"'))
|
146
|
+
controller.should_receive(:authentication_failed).with('This authentication request is no longer valid. Please try again.')
|
147
|
+
# the should raise_error is hacky because of the expectation
|
148
|
+
# stubbing the proper behavior :-(
|
149
|
+
lambda{get :oauth_callback, :oauth_token => 'faketoken'}.should raise_error(ActionView::MissingTemplate)
|
150
|
+
end
|
151
|
+
|
152
|
+
it 'should call authentication_failed when it gets a different HTTPServerException' do
|
153
|
+
@request_token.stub!(:get_access_token).and_raise(Net::HTTPServerException.new('404 "Not Found"', '404 "Not Found"'))
|
154
|
+
controller.should_receive(:authentication_failed).with('There was a problem trying to authenticate you. Please try again.')
|
155
|
+
lambda{get :oauth_callback, :oauth_token => 'faketoken'}.should raise_error(ActionView::MissingTemplate)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
describe 'with Basic strategy' do
|
163
|
+
before do
|
164
|
+
stub_basic!
|
165
|
+
end
|
166
|
+
|
167
|
+
describe '#new' do
|
168
|
+
it 'should render the new action' do
|
169
|
+
get :new
|
170
|
+
response.should render_template('sessions/new')
|
171
|
+
end
|
172
|
+
|
173
|
+
it 'should render the login form' do
|
174
|
+
get :new
|
175
|
+
response.should have_tag('form[action=/session][id=login_form][method=post]')
|
176
|
+
end
|
177
|
+
|
178
|
+
describe '#create' do
|
179
|
+
before do
|
180
|
+
@user = Factory.create(:twitter_basic_user, :twitter_id => '123')
|
181
|
+
end
|
182
|
+
|
183
|
+
it 'should call logout_keeping_session! to remove session info' do
|
184
|
+
controller.should_receive(:logout_keeping_session!)
|
185
|
+
post :create
|
186
|
+
end
|
187
|
+
|
188
|
+
it 'should try to authenticate the user' do
|
189
|
+
User.should_receive(:authenticate)
|
190
|
+
post :create
|
191
|
+
end
|
192
|
+
|
193
|
+
it 'should call authentication_failed on authenticate failure' do
|
194
|
+
User.should_receive(:authenticate).and_return(nil)
|
195
|
+
post :create, :login => 'wrong', :password => 'false'
|
196
|
+
response.should redirect_to('/login')
|
197
|
+
end
|
198
|
+
|
199
|
+
it 'should call authentication_succeeded on authentication success' do
|
200
|
+
User.should_receive(:authenticate).and_return(@user)
|
201
|
+
post :create, :login => 'twitterman', :password => 'cool'
|
202
|
+
response.should redirect_to('/')
|
203
|
+
flash[:notice].should_not be_blank
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
end
|
209
|
+
|
210
|
+
describe '#destroy' do
|
211
|
+
it 'should call logout_keeping_session!' do
|
212
|
+
controller.should_receive(:logout_keeping_session!).once
|
213
|
+
get :destroy
|
214
|
+
end
|
215
|
+
|
216
|
+
it 'should redirect to the root' do
|
217
|
+
get :destroy
|
218
|
+
response.should redirect_to('/')
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
development:
|
2
|
+
strategy: oauth
|
3
|
+
base_url: "https://twitter.com"
|
4
|
+
oauth_consumer_key: devkey
|
5
|
+
oauth_consumer_secret: devsecret
|
6
|
+
oauth_callback: "http://localhost:3000"
|
7
|
+
test:
|
8
|
+
strategy: oauth
|
9
|
+
base_url: "https://twitter.com"
|
10
|
+
oauth_consumer_key: testkey
|
11
|
+
oauth_consumer_secret: testsecret
|
12
|
+
production:
|
13
|
+
strategy: oauth
|
14
|
+
base_url: "https://twitter.com"
|
15
|
+
oauth_consumer_key: prodkey
|
16
|
+
oauth_consumer_secret: prodsecret
|
17
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'factory_girl'
|
2
|
+
|
3
|
+
Factory.define(:twitter_oauth_user, :class => User) do |u|
|
4
|
+
u.twitter_id { User.count + 1 }
|
5
|
+
u.login 'twitterman'
|
6
|
+
u.access_token 'fakeaccesstoken'
|
7
|
+
u.access_secret 'fakeaccesstokensecret'
|
8
|
+
|
9
|
+
u.name 'Twitter Man'
|
10
|
+
u.description 'Saving the world for all Twitter kind.'
|
11
|
+
end
|
12
|
+
|
13
|
+
Factory.define(:twitter_basic_user, :class => User) do |u|
|
14
|
+
u.twitter_id { User.count + 1 }
|
15
|
+
u.login 'twitterman'
|
16
|
+
u.password 'test'
|
17
|
+
|
18
|
+
u.name 'Twitter Man'
|
19
|
+
u.description 'Saving the world for all Twitter kind.'
|
20
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# This is where we fake out all of the URLs that we
|
2
|
+
# will be calling as a part of this spec suite.
|
3
|
+
# You must have the 'fakeweb' gem in order to run
|
4
|
+
# the tests for TwitterAuth.
|
5
|
+
#
|
6
|
+
# gem install 'mbleigh-fakeweb'
|
7
|
+
|
8
|
+
require 'fake_web'
|
9
|
+
|
10
|
+
FakeWeb.allow_net_connect = false
|
11
|
+
|
12
|
+
FakeWeb.register_uri(:post, 'https://twitter.com:443/oauth/request_token', :string => 'oauth_token=faketoken&oauth_token_secret=faketokensecret')
|
13
|
+
|
14
|
+
FakeWeb.register_uri(:post, 'https://twitter.com:443/oauth/access_token', :string => 'oauth_token=fakeaccesstoken&oauth_token_secret=fakeaccesstokensecret')
|
15
|
+
|
16
|
+
FakeWeb.register_uri(:get, 'https://twitter.com:443/account/verify_credentials.json', :string => "{\"profile_image_url\":\"http:\\/\\/static.twitter.com\\/images\\/default_profile_normal.png\",\"description\":\"Saving the world for all Twitter kind.\",\"utc_offset\":null,\"favourites_count\":0,\"profile_sidebar_fill_color\":\"e0ff92\",\"screen_name\":\"twitterman\",\"statuses_count\":0,\"profile_background_tile\":false,\"profile_sidebar_border_color\":\"87bc44\",\"friends_count\":2,\"url\":null,\"name\":\"Twitter Man\",\"time_zone\":null,\"protected\":false,\"profile_background_image_url\":\"http:\\/\\/static.twitter.com\\/images\\/themes\\/theme1\\/bg.gif\",\"profile_background_color\":\"9ae4e8\",\"created_at\":\"Fri Feb 06 18:10:32 +0000 2009\",\"profile_text_color\":\"000000\",\"followers_count\":2,\"location\":null,\"id\":123,\"profile_link_color\":\"0000ff\"}")
|
17
|
+
|
18
|
+
#FakeWeb.register_uri(:get, 'https://twitter.com:443/)
|
@@ -0,0 +1,5 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
|
3
|
+
TWITTER_JSON = {
|
4
|
+
:verify_credentials => "{\"profile_image_url\":\"http:\\/\\/static.twitter.com\\/images\\/default_profile_normal.png\",\"description\":\"Saving the world for all Twitter kind.\",\"utc_offset\":null,\"favourites_count\":0,\"profile_sidebar_fill_color\":\"e0ff92\",\"screen_name\":\"twitterman\",\"statuses_count\":0,\"profile_background_tile\":false,\"profile_sidebar_border_color\":\"87bc44\",\"friends_count\":2,\"url\":null,\"name\":\"Twitter Man\",\"time_zone\":null,\"protected\":false,\"profile_background_image_url\":\"http:\\/\\/static.twitter.com\\/images\\/themes\\/theme1\\/bg.gif\",\"profile_background_color\":\"9ae4e8\",\"created_at\":\"Fri Feb 06 18:10:32 +0000 2009\",\"profile_text_color\":\"000000\",\"followers_count\":2,\"location\":null,\"id\":20256865,\"profile_link_color\":\"0000ff\"}"
|
5
|
+
}
|
@@ -0,0 +1,138 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
2
|
+
|
3
|
+
describe TwitterAuth::BasicUser do
|
4
|
+
before do
|
5
|
+
stub_basic!
|
6
|
+
end
|
7
|
+
|
8
|
+
describe '#password=' do
|
9
|
+
before do
|
10
|
+
@user = Factory.build(:twitter_basic_user, :twitter_id => '123')
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should change the value of crypted_password' do
|
14
|
+
lambda{@user.password = 'newpass'}.should change(@user, :crypted_password)
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should change the value of salt' do
|
18
|
+
lambda{@user.password = 'newpass'}.should change(@user, :salt)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should not store the plaintext password' do
|
22
|
+
@user.password = 'newpass'
|
23
|
+
@user.crypted_password.should_not == 'newpass'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '#password' do
|
28
|
+
before do
|
29
|
+
@user = Factory.build(:twitter_basic_user, :password => 'monkey')
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'should return the password' do
|
33
|
+
@user.password.should == 'monkey'
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should not be a database attribute' do
|
37
|
+
@user['password'].should_not == 'monkey'
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe '.verify_credentials' do
|
42
|
+
before do
|
43
|
+
@user = Factory.create(:twitter_basic_user)
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should return a JSON hash of the user when successful' do
|
47
|
+
hash = User.verify_credentials('twitterman','test')
|
48
|
+
hash.should be_a(Hash)
|
49
|
+
hash['screen_name'].should == 'twitterman'
|
50
|
+
hash['name'].should == 'Twitter Man'
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should return false when a 401 unauthorized happens' do
|
54
|
+
FakeWeb.register_uri(:get, 'https://twitter.com:443/account/verify_credentials.json', :string => '401 "Unauthorized"', :status => ['401',' Unauthorized'])
|
55
|
+
User.verify_credentials('twitterman','wrong').should be_false
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe '.authenticate' do
|
60
|
+
before do
|
61
|
+
@user = Factory.create(:twitter_basic_user, :twitter_id => '123')
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'should make a call to verify_credentials' do
|
65
|
+
User.should_receive(:verify_credentials).with('twitterman','test')
|
66
|
+
User.authenticate('twitterman','test')
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'should return nil if verify_credentials returns false' do
|
70
|
+
User.stub!(:verify_credentials).and_return(false)
|
71
|
+
User.authenticate('twitterman','test').should be_nil
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'should return the user if verify_credentials succeeds' do
|
75
|
+
User.stub!(:verify_credentials).and_return(JSON.parse("{\"profile_image_url\":\"http:\\/\\/static.twitter.com\\/images\\/default_profile_normal.png\",\"description\":\"Saving the world for all Twitter kind.\",\"utc_offset\":null,\"favourites_count\":0,\"profile_sidebar_fill_color\":\"e0ff92\",\"screen_name\":\"twitterman\",\"statuses_count\":0,\"profile_background_tile\":false,\"profile_sidebar_border_color\":\"87bc44\",\"friends_count\":2,\"url\":null,\"name\":\"Twitter Man\",\"time_zone\":null,\"protected\":false,\"profile_background_image_url\":\"http:\\/\\/static.twitter.com\\/images\\/themes\\/theme1\\/bg.gif\",\"profile_background_color\":\"9ae4e8\",\"created_at\":\"Fri Feb 06 18:10:32 +0000 2009\",\"profile_text_color\":\"000000\",\"followers_count\":2,\"location\":null,\"id\":123,\"profile_link_color\":\"0000ff\"}"))
|
76
|
+
User.authenticate('twitterman','test').should == @user
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe '.find_or_create_by_twitter_hash_and_password' do
|
81
|
+
before do
|
82
|
+
@user = Factory.create(:twitter_basic_user, :twitter_id => '123')
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'should return the existing user if there is one' do
|
86
|
+
User.identify_or_create_from_twitter_hash_and_password({'id' => '123', 'screen_name' => 'twitterman'},'test').should == @user
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'should update the attributes from the hash' do
|
90
|
+
User.identify_or_create_from_twitter_hash_and_password({'id' => 123, 'screen_name' => 'twitterman', 'name' => 'New Name'}, 'test').name.should == 'New Name'
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'should update the password from the argument' do
|
94
|
+
User.identify_or_create_from_twitter_hash_and_password({'id' => '123', 'screen_name' => 'twitterman', 'name' => 'New Name'}, 'test2').password.should == 'test2'
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'should create a user if one does not exist' do
|
98
|
+
lambda{User.identify_or_create_from_twitter_hash_and_password({'id' => 124, 'screen_name' => 'dude', 'name' => "Lebowski"}, 'test')}.should change(User, :count).by(1)
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'should assign the attributes from the hash to a created user' do
|
102
|
+
user = User.identify_or_create_from_twitter_hash_and_password({'id' => 124, 'screen_name' => 'dude', 'name' => "Lebowski"}, 'test')
|
103
|
+
user.twitter_id.should == '124'
|
104
|
+
user.login.should == 'dude'
|
105
|
+
user.name.should == 'Lebowski'
|
106
|
+
user.password.should == 'test'
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe '#twitter' do
|
111
|
+
before do
|
112
|
+
@user = Factory.create(:twitter_basic_user, :twitter_id => '123')
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'should be an instance of TwitterAuth::Dispatcher::Basic' do
|
116
|
+
@user.twitter.class.should == TwitterAuth::Dispatcher::Basic
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'should have the correct user set' do
|
120
|
+
@user.twitter.user.should == @user
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
describe 'changing usernames' do
|
125
|
+
before do
|
126
|
+
@user = Factory.create(:twitter_basic_user, :twitter_id => '123')
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'should not create a new record when a screen_name has changed' do
|
130
|
+
lambda{User.identify_or_create_from_twitter_hash_and_password({'id' => '123', 'screen_name' => 'dude'},'awesome')}.should_not change(User,:count)
|
131
|
+
end
|
132
|
+
|
133
|
+
it 'should update the record with the new screen name' do
|
134
|
+
User.identify_or_create_from_twitter_hash_and_password({'id' => '123', 'screen_name' => 'dude'},'awesome').should == @user.reload
|
135
|
+
@user.login.should == 'dude'
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
2
|
+
|
3
|
+
describe TwitterAuth::GenericUser do
|
4
|
+
should_validate_presence_of :login, :twitter_id
|
5
|
+
should_validate_format_of :login, 'some_guy', 'awesome', 'cool_man'
|
6
|
+
should_not_validate_format_of :login, 'with-dashes', 'with.periods', 'with spaces'
|
7
|
+
should_validate_length_of :login, :in => 1..15
|
8
|
+
|
9
|
+
it 'should validate uniqueness of login' do
|
10
|
+
Factory.create(:twitter_oauth_user)
|
11
|
+
Factory.build(:twitter_oauth_user).should have_at_least(1).errors_on(:login)
|
12
|
+
end
|
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
|
+
|
19
|
+
it 'should allow capital letters in the username' do
|
20
|
+
Factory.build(:twitter_oauth_user, :login => 'TwitterMan').should have(:no).errors_on(:login)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should not allow the same login with different capitalization' do
|
24
|
+
Factory.create(:twitter_oauth_user, :login => 'twitterman')
|
25
|
+
Factory.build(:twitter_oauth_user, :login => 'TwitterMan').should have_at_least(1).errors_on(:login)
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '.new_from_twitter_hash' do
|
29
|
+
it 'should raise an argument error if the hash does not have a screen_name attribute' do
|
30
|
+
lambda{User.new_from_twitter_hash({'id' => '123'})}.should raise_error(ArgumentError, 'Invalid hash: must include screen_name.')
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should raise an argument error if the hash does not have an id attribute' do
|
34
|
+
lambda{User.new_from_twitter_hash({'screen_name' => 'abc123'})}.should raise_error(ArgumentError, 'Invalid hash: must include id.')
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should return a user' do
|
38
|
+
User.new_from_twitter_hash({'id' => '123', 'screen_name' => 'twitterman'}).should be_a(User)
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should assign login to the screen_name' do
|
42
|
+
User.new_from_twitter_hash({'id' => '123', 'screen_name' => 'twitterman'}).login.should == 'twitterman'
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should assign twitter attributes that are provided' do
|
46
|
+
u = User.new_from_twitter_hash({'id' => '4566', 'screen_name' => 'twitterman', 'name' => 'Twitter Man', 'description' => 'Saving the world for all Tweet kind.'})
|
47
|
+
u.name.should == 'Twitter Man'
|
48
|
+
u.description.should == 'Saving the world for all Tweet kind.'
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe '#update_twitter_attributes' do
|
53
|
+
it 'should assign values to the user' do
|
54
|
+
user = Factory.create(:twitter_oauth_user, :name => "Dude", :description => "Awesome, man.")
|
55
|
+
user.update_twitter_attributes({'name' => 'Twitter Man', 'description' => 'Works.'})
|
56
|
+
user.reload
|
57
|
+
user.name.should == 'Twitter Man'
|
58
|
+
user.description.should == 'Works.'
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'should not throw an error with extraneous info' do
|
62
|
+
user = Factory.create(:twitter_oauth_user, :name => "Dude", :description => "Awesome, man.")
|
63
|
+
lambda{user.update_twitter_attributes({'name' => 'Twitter Man', 'description' => 'Works.', 'whoopsy' => 'noworks.'})}.should_not raise_error
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe '#remember_me' do
|
68
|
+
before do
|
69
|
+
@user = Factory(:twitter_oauth_user)
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'should check for the remember_token column' do
|
73
|
+
@user.should_receive(:respond_to?).with(:remember_token).and_return(false)
|
74
|
+
@user.remember_me
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'should return nil if there is no remember_token column' do
|
78
|
+
@user.should_receive(:respond_to?).with(:remember_token).and_return(false)
|
79
|
+
@user.remember_me.should be_false
|
80
|
+
end
|
81
|
+
|
82
|
+
describe ' with proper columns' do
|
83
|
+
it 'should generate a secure random token' do
|
84
|
+
ActiveSupport::SecureRandom.should_receive(:hex).with(10).and_return('abcdef')
|
85
|
+
@user.remember_me
|
86
|
+
@user.remember_token.should == 'abcdef'
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'should set the expiration to the current time plus the remember_for period' do
|
90
|
+
TwitterAuth.stub!(:remember_for).and_return(10)
|
91
|
+
time = Time.now
|
92
|
+
Time.stub!(:now).and_return(time)
|
93
|
+
|
94
|
+
@user.remember_me
|
95
|
+
|
96
|
+
@user.remember_token_expires_at.should == Time.now + 10.days
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'should return a hash with a :value and :expires key' do
|
100
|
+
result = @user.remember_me
|
101
|
+
result.should be_a(Hash)
|
102
|
+
result.key?(:value).should be_true
|
103
|
+
result.key?(:expires).should be_true
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'should return a hash with appropriate values' do
|
107
|
+
TwitterAuth.stub!(:remember_for).and_return(10)
|
108
|
+
time = Time.now
|
109
|
+
Time.stub!(:now).and_return(time)
|
110
|
+
ActiveSupport::SecureRandom.stub!(:hex).and_return('abcdef')
|
111
|
+
|
112
|
+
@user.remember_me.should == {:value => 'abcdef', :expires => (Time.now + 10.days)}
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe '#forget_me' do
|
118
|
+
it 'should reset remember_token and remember_token_expires_at' do
|
119
|
+
@user = Factory(:twitter_oauth_user, :remember_token => "abcdef", :remember_token_expires_at => Time.now + 10.days)
|
120
|
+
@user.forget_me
|
121
|
+
@user.reload
|
122
|
+
@user.remember_token.should be_nil
|
123
|
+
@user.remember_token_expires_at.should be_nil
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
describe '.from_remember_token' do
|
128
|
+
before do
|
129
|
+
@user = Factory(:twitter_oauth_user, :remember_token => 'abcdef', :remember_token_expires_at => (Time.now + 10.days))
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'should find the user with the specified remember_token' do
|
133
|
+
User.from_remember_token('abcdef').should == @user
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'should not find a user with an expired token' do
|
137
|
+
user2 = Factory(:twitter_oauth_user, :login => 'walker', :remember_token => 'ghijkl', :remember_token_expires_at => (Time.now - 10.days))
|
138
|
+
User.from_remember_token('ghijkl').should be_nil
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'should not find a user with a nil token and an expiration' do
|
142
|
+
user = Factory(:twitter_oauth_user, :login => 'stranger', :remember_token => nil, :remember_token_expires_at => (Time.now + 10.days))
|
143
|
+
User.from_remember_token(nil).should be_nil
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|