twitter-login 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -28,17 +28,17 @@ frameworks.
28
28
 
29
29
  ## Sinatra
30
30
  enable :sessions
31
- use Twitter::Login, :key => 'CONSUMER KEY', :secret => 'SECRET'
31
+ use Twitter::Login, :consumer_key => 'KEY', :secret => 'SECRET'
32
32
  helpers Twitter::Login::Helpers
33
33
 
34
34
  ## Rails
35
35
  # environment.rb:
36
- config.middleware.use Twitter::Login, :key => 'CONSUMER KEY', :secret => 'SECRET'
36
+ config.middleware.use Twitter::Login, :consumer_key => 'KEY', :secret => 'SECRET'
37
37
 
38
38
  # application_controller.rb
39
39
  include Twitter::Login::Helpers
40
40
 
41
- Fill in the `:key`, `:secret` placeholders with real values. You're done.
41
+ Fill in the `:consumer_key`, `:secret` placeholders with real values. You're done.
42
42
 
43
43
 
44
44
  What it does
@@ -58,7 +58,7 @@ Configuration
58
58
 
59
59
  Available options for `Twitter::Login` middleware are:
60
60
 
61
- * `:key` -- OAuth consumer key *(required)*
61
+ * `:consumer_key` -- OAuth consumer key *(required)*
62
62
  * `:secret` -- OAuth secret *(required)*
63
63
  * `:login_path` -- where user goes to login (default: "/login")
64
64
  * `:return_to` -- where user goes after login (default: "/")
@@ -72,8 +72,8 @@ The `Twitter::Login::Helpers` module (for Sinatra, Rails) adds these methods to
72
72
  * `twitter_user` (Hashie::Mash) -- Info about authenticated user. Check this object to
73
73
  know whether there is a currently logged-in user. Access user data like `twitter_user.screen_name`
74
74
  * `twitter_logout` -- Erases info about Twitter login from session, effectively logging-out the Twitter user
75
- * `twitter_consumer` (Twitter::Base) -- An OAuth consumer client from ["twitter" gem][gem].
76
- With it you can query anything on behalf of authenticated user, e.g. `twitter_consumer.friends_timeline`
75
+ * `twitter_client` (Twitter::Base) -- An OAuth consumer client from ["twitter" gem][gem].
76
+ With it you can query anything on behalf of authenticated user, e.g. `twitter_client.friends_timeline`
77
77
 
78
78
  [register]: http://twitter.com/apps/new
79
79
  [gem]: http://rdoc.info/projects/jnunemaker/twitter
@@ -5,20 +5,23 @@ require 'hashie/mash'
5
5
  class Twitter::Login
6
6
  attr_reader :options
7
7
 
8
- DEFAULTS = {
9
- :login_path => '/login', :return_to => '/',
10
- :site => 'http://twitter.com', :authorize_path => '/oauth/authenticate'
11
- }
8
+ class << self
9
+ attr_accessor :consumer_key, :secret
10
+ end
11
+
12
+ DEFAULTS = { :login_path => '/login', :return_to => '/' }
12
13
 
13
14
  def initialize(app, options)
14
15
  @app = app
15
16
  @options = DEFAULTS.merge options
17
+ self.class.consumer_key, self.class.secret = @options[:consumer_key], @options[:secret]
16
18
  end
17
19
 
18
20
  def call(env)
19
21
  request = Request.new(env)
20
22
 
21
23
  if request.get? and request.path == options[:login_path]
24
+ @oauth = nil
22
25
  # detect if Twitter redirected back here
23
26
  if request[:oauth_verifier]
24
27
  handle_twitter_authorization(request) do
@@ -26,7 +29,7 @@ class Twitter::Login
26
29
  end
27
30
  elsif request[:denied]
28
31
  # user refused to log in with Twitter, so give up
29
- redirect_to_return_path(request)
32
+ handle_denied_access(request)
30
33
  else
31
34
  # user clicked to login; send them to Twitter
32
35
  redirect_to_twitter(request)
@@ -37,13 +40,14 @@ class Twitter::Login
37
40
  end
38
41
 
39
42
  module Helpers
40
- def twitter_consumer
41
- token = OAuth::AccessToken.new(oauth_consumer, *session[:access_token])
42
- Twitter::Base.new token
43
+ def twitter_client
44
+ oauth = twitter_oauth
45
+ oauth.authorize_from_access(*session[:access_token])
46
+ Twitter::Base.new oauth
43
47
  end
44
48
 
45
- def oauth_consumer
46
- OAuth::Consumer.new(*session[:oauth_consumer])
49
+ def twitter_oauth
50
+ Twitter::OAuth.new Twitter::Login.consumer_key, Twitter::Login.secret
47
51
  end
48
52
 
49
53
  def twitter_user
@@ -53,7 +57,7 @@ class Twitter::Login
53
57
  end
54
58
 
55
59
  def twitter_logout
56
- [:oauth_consumer, :access_token, :twitter_user].each do |key|
60
+ [:access_token, :twitter_user].each do |key|
57
61
  session[key] = nil # work around a Rails 2.3.5 bug
58
62
  session.delete key
59
63
  end
@@ -83,17 +87,16 @@ class Twitter::Login
83
87
 
84
88
  def redirect_to_twitter(request)
85
89
  # create a request token and store its parameter in session
86
- token = oauth_consumer.get_request_token(:oauth_callback => request.url)
87
- request.session[:request_token] = [token.token, token.secret]
90
+ oauth.set_callback_url(request.url)
91
+ request.session[:request_token] = [oauth.request_token.token, oauth.request_token.secret]
88
92
  # redirect to Twitter authorization page
89
- redirect token.authorize_url
93
+ redirect oauth.request_token.authorize_url
90
94
  end
91
95
 
92
96
  def handle_twitter_authorization(request)
93
- access_token = get_access_token(request)
97
+ authorize_from_request(request)
94
98
 
95
99
  # get and store authenticated user's info from Twitter
96
- twitter = Twitter::Base.new access_token
97
100
  request.session[:twitter_user] = twitter.verify_credentials.to_hash
98
101
 
99
102
  # pass the request down to the main app
@@ -109,20 +112,21 @@ class Twitter::Login
109
112
  end
110
113
  end
111
114
 
115
+ def handle_denied_access(request)
116
+ request.session[:request_token] = nil # work around a Rails 2.3.5 bug
117
+ request.session.delete(:request_token)
118
+ redirect_to_return_path(request)
119
+ end
120
+
112
121
  private
113
122
 
114
- def get_access_token(request)
115
- # replace the request token in session with access token
116
- request_token = ::OAuth::RequestToken.new(oauth_consumer, *request.session[:request_token])
117
- access_token = request_token.get_access_token(:oauth_verifier => request[:oauth_verifier])
123
+ # replace the request token in session with access token
124
+ def authorize_from_request(request)
125
+ rtoken, rsecret = request.session[:request_token]
126
+ oauth.authorize_from_request(rtoken, rsecret, request[:oauth_verifier])
118
127
 
119
- # store access token and OAuth consumer parameters in session
120
128
  request.session.delete(:request_token)
121
- request.session[:access_token] = [access_token.token, access_token.secret]
122
- consumer = access_token.consumer
123
- request.session[:oauth_consumer] = [consumer.key, consumer.secret, consumer.options]
124
-
125
- return access_token
129
+ request.session[:access_token] = [oauth.access_token.token, oauth.access_token.secret]
126
130
  end
127
131
 
128
132
  def redirect_to_return_path(request)
@@ -133,8 +137,11 @@ class Twitter::Login
133
137
  ["302", {'Location' => url, 'Content-type' => 'text/plain'}, []]
134
138
  end
135
139
 
136
- def oauth_consumer
137
- ::OAuth::Consumer.new options[:key], options[:secret],
138
- :site => options[:site], :authorize_path => options[:authorize_path]
140
+ def oauth
141
+ @oauth ||= Twitter::OAuth.new options[:consumer_key], options[:secret], :sign_in => true
142
+ end
143
+
144
+ def twitter
145
+ Twitter::Base.new oauth
139
146
  end
140
147
  end
@@ -21,7 +21,7 @@ describe Twitter::Login do
21
21
 
22
22
  builder = Rack::Builder.new
23
23
  builder.use Rack::Session::Cookie
24
- builder.use described_class, :key => 'abc', :secret => '123'
24
+ builder.use described_class, :consumer_key => 'abc', :secret => '123'
25
25
  builder.run main_app
26
26
  builder.to_app
27
27
  end
@@ -31,12 +31,21 @@ describe Twitter::Login do
31
31
  @request = Rack::MockRequest.new(@app)
32
32
  end
33
33
 
34
+ it "should expose consumer key/secret globally" do
35
+ Twitter::Login.consumer_key.should == 'abc'
36
+ Twitter::Login.secret.should == '123'
37
+ end
38
+
39
+ it "should ignore normal requests" do
40
+ get('/', :lint => true)
41
+ response.status.should == 200
42
+ response.body.should == 'Hello world'
43
+ end
44
+
34
45
  it "should login with Twitter" do
35
- consumer = mock_oauth_consumer('OAuth Consumer')
36
- token = mock('Request Token', :authorize_url => 'http://disney.com/oauth', :token => 'abc', :secret => '123')
37
- consumer.should_receive(:get_request_token).with(:oauth_callback => 'http://example.org/login').and_return(token)
38
- # request.session[:request_token] = token
39
- # redirect token.authorize_url
46
+ request_token = mock('Request Token', :authorize_url => 'http://disney.com/oauth', :token => 'abc', :secret => '123')
47
+ oauth = mock_oauth('Twitter OAuth', :request_token => request_token)
48
+ oauth.should_receive(:set_callback_url).with('http://example.org/login')
40
49
 
41
50
  get('/login', :lint => true)
42
51
  response.status.should == 302
@@ -46,31 +55,40 @@ describe Twitter::Login do
46
55
  end
47
56
 
48
57
  it "should authorize with Twitter" do
49
- consumer = mock_oauth_consumer('OAuth Consumer', :key => 'con', :secret => 'sumer', :options => {:one=>'two'})
50
- request_token = mock('Request Token')
51
- OAuth::RequestToken.should_receive(:new).with(consumer, 'abc', '123').and_return(request_token)
52
- access_token = mock('Access Token', :token => 'access1', :secret => '42', :consumer => consumer)
53
- request_token.should_receive(:get_access_token).with(:oauth_verifier => 'abc').and_return(access_token)
58
+ consumer = mock('OAuth consumer')
59
+ access_token = mock('Access Token', :token => 'access1', :secret => '42')
60
+ oauth = mock_oauth('Twitter OAuth', :access_token => access_token, :consumer => consumer)
61
+ oauth.should_receive(:authorize_from_request).with('abc', '123', 'allrighty')
54
62
 
55
63
  twitter = mock('Twitter Base')
56
- Twitter::Base.should_receive(:new).with(access_token).and_return(twitter)
57
- user_credentials = Hashie::Mash.new :screen_name => 'faker',
58
- :name => 'Fake Jr.', :profile_image_url => 'http://disney.com/mickey.png',
59
- :followers_count => '13', :friends_count => '6', :statuses_count => '52'
60
- twitter.should_receive(:verify_credentials).and_return(user_credentials)
64
+ Twitter::Base.should_receive(:new).with(oauth).and_return(twitter)
65
+
66
+ twitter.should_receive(:verify_credentials).and_return {
67
+ Hashie::Mash.new :screen_name => 'faker',
68
+ :name => 'Fake Jr.', :profile_image_url => 'http://disney.com/mickey.png',
69
+ :followers_count => '13', :friends_count => '6', :statuses_count => '52'
70
+ }
61
71
 
62
72
  session_data = {:request_token => ['abc', '123']}
63
- get('/login?oauth_verifier=abc', build_session(session_data).update(:lint => true))
73
+ get('/login?oauth_verifier=allrighty', build_session(session_data).update(:lint => true))
64
74
  response.status.should == 302
65
75
  response['Location'].should == 'http://example.org/'
66
76
  session[:request_token].should be_nil
67
77
  session[:access_token].should == ['access1', '42']
68
- session[:oauth_consumer].should == ['con', 'sumer', {:one => 'two'}]
78
+ session[:oauth_consumer].should be_nil
69
79
 
70
80
  current_user = session[:twitter_user]
71
81
  current_user['screen_name'].should == 'faker'
72
82
  end
73
83
 
84
+ it "should handle denied access" do
85
+ session_data = {:request_token => ['abc', '123']}
86
+ get('/login?denied=OMG', build_session(session_data).update(:lint => true))
87
+ response.status.should == 302
88
+ response['Location'].should == 'http://example.org/'
89
+ session[:request_token].should be_nil
90
+ end
91
+
74
92
  protected
75
93
 
76
94
  [:get, :post, :put, :delete, :head].each do |method|
@@ -104,11 +122,9 @@ describe Twitter::Login do
104
122
  [Marshal.dump(obj)].pack('m*')
105
123
  end
106
124
 
107
- def mock_oauth_consumer(*args)
125
+ def mock_oauth(*args)
108
126
  consumer = mock(*args)
109
- OAuth::Consumer.should_receive(:new).and_return(consumer)
110
- # .with(instance_of(String), instance_of(String),
111
- # :site => 'http://twitter.com', :authorize_path => '/oauth/authenticate')
127
+ Twitter::OAuth.should_receive(:new).and_return(consumer)
112
128
  consumer
113
129
  end
114
130
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: twitter-login
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - "Mislav Marohni\xC4\x87"
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-01-03 00:00:00 +01:00
12
+ date: 2010-01-04 00:00:00 +01:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency