mbleigh-twitter-auth 0.0.2 → 0.1.1

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.
@@ -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,18 @@
1
+ require 'factory_girl'
2
+
3
+ Factory.define(:twitter_oauth_user, :class => User) do |u|
4
+ u.login 'twitterman'
5
+ u.access_token 'fakeaccesstoken'
6
+ u.access_secret 'fakeaccesstokensecret'
7
+
8
+ u.name 'Twitter Man'
9
+ u.description 'Saving the world for all Twitter kind.'
10
+ end
11
+
12
+ Factory.define(:twitter_basic_user, :class => User) do |u|
13
+ u.login 'twitterman'
14
+ u.password 'test'
15
+
16
+ u.name 'Twitter Man'
17
+ u.description 'Saving the world for all Twitter kind.'
18
+ 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\":20256865,\"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,122 @@
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)
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)
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\":20256865,\"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)
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({'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({'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({'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({'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({'screen_name' => 'dude', 'name' => "Lebowski"}, 'test')
103
+ user.login.should == 'dude'
104
+ user.name.should == 'Lebowski'
105
+ user.password.should == 'test'
106
+ end
107
+ end
108
+
109
+ describe '#twitter' do
110
+ before do
111
+ @user = Factory.create(:twitter_basic_user)
112
+ end
113
+
114
+ it 'should be an instance of TwitterAuth::Dispatcher::Basic' do
115
+ @user.twitter.class.should == TwitterAuth::Dispatcher::Basic
116
+ end
117
+
118
+ it 'should have the correct user set' do
119
+ @user.twitter.user.should == @user
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,48 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe TwitterAuth::GenericUser do
4
+ should_validate_presence_of :login
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
+ describe '.new_from_twitter_hash' do
15
+ it 'should raise an argument error if the hash does not have a screen_name attribute' do
16
+ lambda{User.new_from_twitter_hash({})}.should raise_error(ArgumentError, 'Invalid hash: must include screen_name.')
17
+ end
18
+
19
+ it 'should return a user' do
20
+ User.new_from_twitter_hash({'screen_name' => 'twitterman'}).should be_a(User)
21
+ end
22
+
23
+ it 'should assign login to the screen_name' do
24
+ User.new_from_twitter_hash({'screen_name' => 'twitterman'}).login.should == 'twitterman'
25
+ end
26
+
27
+ it 'should assign twitter attributes that are provided' do
28
+ u = User.new_from_twitter_hash({'screen_name' => 'twitterman', 'name' => 'Twitter Man', 'description' => 'Saving the world for all Tweet kind.'})
29
+ u.name.should == 'Twitter Man'
30
+ u.description.should == 'Saving the world for all Tweet kind.'
31
+ end
32
+ end
33
+
34
+ describe '#update_twitter_attributes' do
35
+ it 'should assign values to the user' do
36
+ user = Factory.create(:twitter_oauth_user, :name => "Dude", :description => "Awesome, man.")
37
+ user.update_twitter_attributes({'name' => 'Twitter Man', 'description' => 'Works.'})
38
+ user.reload
39
+ user.name.should == 'Twitter Man'
40
+ user.description.should == 'Works.'
41
+ end
42
+
43
+ it 'should not throw an error with extraneous info' do
44
+ user = Factory.create(:twitter_oauth_user, :name => "Dude", :description => "Awesome, man.")
45
+ lambda{user.update_twitter_attributes({'name' => 'Twitter Man', 'description' => 'Works.', 'whoopsy' => 'noworks.'})}.should_not raise_error
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,85 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe TwitterAuth::OauthUser do
4
+ before do
5
+ stub_oauth!
6
+ end
7
+
8
+ describe '.identify_or_create_from_access_token' do
9
+ before do
10
+ @token = OAuth::AccessToken.new(TwitterAuth.consumer, 'faketoken', 'fakesecret')
11
+ end
12
+
13
+ it 'should accept an OAuth::AccessToken' do
14
+ lambda{ User.identify_or_create_from_access_token(@token) }.should_not raise_error(ArgumentError)
15
+ end
16
+
17
+ it 'should accept two strings' do
18
+ lambda{ User.identify_or_create_from_access_token('faketoken', 'fakesecret') }.should_not raise_error(ArgumentError)
19
+ end
20
+
21
+ it 'should not accept one string' do
22
+ lambda{ User.identify_or_create_from_access_token('faketoken') }.should raise_error(ArgumentError, 'Must authenticate with an OAuth::AccessToken or the string access token and secret.')
23
+ end
24
+
25
+ it 'should make a call to verify_credentials' do
26
+ # this is in the before, just making it explicit
27
+ User.identify_or_create_from_access_token(@token)
28
+ end
29
+
30
+ it 'should try to find the user with that login' do
31
+ User.should_receive(:find_by_login).once.with('twitterman')
32
+ User.identify_or_create_from_access_token(@token)
33
+ end
34
+
35
+ it 'should return the user if he/she exists' do
36
+ user = Factory.create(:twitter_oauth_user, :login => 'twitterman')
37
+ User.identify_or_create_from_access_token(@token).should == user
38
+ end
39
+
40
+ it 'should update the user\'s attributes based on the twitter info' do
41
+ user = Factory.create(:twitter_oauth_user, :login => 'twitterman', :name => 'Not Twitter Man')
42
+ User.identify_or_create_from_access_token(@token).name.should == 'Twitter Man'
43
+ end
44
+
45
+ it 'should create a user if one does not exist' do
46
+ lambda{User.identify_or_create_from_access_token(@token)}.should change(User, :count).by(1)
47
+ end
48
+
49
+ it 'should assign the oauth access token and secret' do
50
+ user = User.identify_or_create_from_access_token(@token)
51
+ user.access_token.should == @token.token
52
+ user.access_secret.should == @token.secret
53
+ end
54
+ end
55
+
56
+ describe '#token' do
57
+ before do
58
+ @user = Factory.create(:twitter_oauth_user, :access_token => 'token', :access_secret => 'secret')
59
+ end
60
+
61
+ it 'should return an AccessToken' do
62
+ @user.token.should be_a(OAuth::AccessToken)
63
+ end
64
+
65
+ it "should use the user's access_token and secret" do
66
+ @user.token.token.should == @user.access_token
67
+ @user.token.secret.should == @user.access_secret
68
+ end
69
+ end
70
+
71
+ describe '#twitter' do
72
+ before do
73
+ @user = Factory.create(:twitter_oauth_user, :access_token => 'token', :access_secret => 'secret')
74
+ end
75
+
76
+ it 'should return a TwitterAuth::Dispatcher::Oauth' do
77
+ @user.twitter.should be_a(TwitterAuth::Dispatcher::Oauth)
78
+ end
79
+
80
+ it 'should use my token and secret' do
81
+ @user.twitter.token.should == @user.access_token
82
+ @user.twitter.secret.should == @user.access_secret
83
+ end
84
+ end
85
+ end
data/spec/schema.rb ADDED
@@ -0,0 +1,37 @@
1
+ ActiveRecord::Schema.define :version => 0 do
2
+ create_table :twitter_auth_users, :force => true do |t|
3
+ t.string :login
4
+
5
+ # OAuth fields
6
+ t.string :access_token
7
+ t.string :access_secret
8
+
9
+ # Basic fields
10
+ t.binary :crypted_password
11
+ t.string :salt
12
+
13
+ # This information is automatically kept
14
+ # in-sync at each login of the user. You
15
+ # may remove any/all of these columns.
16
+ t.string :name
17
+ t.string :location
18
+ t.string :description
19
+ t.string :profile_image_url
20
+ t.string :url
21
+ t.boolean :protected
22
+ t.string :profile_background_color
23
+ t.string :profile_sidebar_fill_color
24
+ t.string :profile_link_color
25
+ t.string :profile_sidebar_border_color
26
+ t.string :profile_text_color
27
+ t.integer :friends_count
28
+ t.integer :statuses_count
29
+ t.integer :followers_count
30
+ t.integer :favourites_count
31
+ t.integer :utc_offset
32
+ t.string :time_zone
33
+
34
+ t.timestamps
35
+ end
36
+ end
37
+
data/spec/spec.opts ADDED
@@ -0,0 +1 @@
1
+ --colour
data/spec/spec_helper.rb CHANGED
@@ -5,6 +5,47 @@ rescue LoadError
5
5
  exit
6
6
  end
7
7
 
8
+ require File.dirname(__FILE__) + '/../app/models/twitter_auth/generic_user'
9
+
10
+ class TwitterAuth::GenericUser
11
+ def self.table_name; 'twitter_auth_users' end
12
+ end
13
+
14
+ class User < TwitterAuth::GenericUser; end
15
+
16
+ require 'remarkable'
17
+ require File.dirname(__FILE__) + '/fixtures/factories'
18
+ require File.dirname(__FILE__) + '/fixtures/fakeweb'
19
+ require File.dirname(__FILE__) + '/fixtures/twitter'
20
+
8
21
  plugin_spec_dir = File.dirname(__FILE__)
9
22
  ActiveRecord::Base.logger = Logger.new(plugin_spec_dir + "/debug.log")
10
23
 
24
+ load(File.dirname(__FILE__) + '/schema.rb')
25
+
26
+ def define_basic_user_class!
27
+ TwitterAuth::GenericUser.send :include, TwitterAuth::BasicUser
28
+ end
29
+
30
+ def define_oauth_user_class!
31
+ TwitterAuth::GenericUser.send :include, TwitterAuth::OauthUser
32
+ end
33
+
34
+ def stub_oauth!
35
+ TwitterAuth.stub!(:config).and_return({
36
+ 'strategy' => 'oauth',
37
+ 'oauth_consumer_key' => 'testkey',
38
+ 'oauth_consumer_secret' => 'testsecret'
39
+ })
40
+ define_oauth_user_class!
41
+ end
42
+
43
+ def stub_basic!
44
+ TwitterAuth.stub!(:config).and_return({
45
+ 'strategy' => 'basic',
46
+ 'encryption_key' => 'secretcode'
47
+ })
48
+ define_basic_user_class!
49
+ end
50
+
51
+ define_oauth_user_class!
@@ -0,0 +1,51 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe TwitterAuth::Cryptify do
4
+ before do
5
+ stub_basic!
6
+ end
7
+
8
+ it 'should have encrypt and decrypt methods' do
9
+ TwitterAuth::Cryptify.should respond_to(:encrypt)
10
+ TwitterAuth::Cryptify.should respond_to(:decrypt)
11
+ end
12
+
13
+ describe '.encrypt' do
14
+ it 'should return a hash with :encrypted_data and :salt keys' do
15
+ result = TwitterAuth::Cryptify.encrypt('some string')
16
+ result.should be_a(Hash)
17
+ result.key?(:encrypted_data).should be_true
18
+ result.key?(:salt).should be_true
19
+ end
20
+
21
+ it 'should make a call to EzCrypto::Key.encrypt_with_password' do
22
+ EzCrypto::Key.should_receive(:encrypt_with_password).once.and_return('gobbledygook')
23
+ TwitterAuth::Cryptify.encrypt('some string')
24
+ end
25
+
26
+ it 'should not have the same encrypted as plaintext data' do
27
+ TwitterAuth::Cryptify.encrypt('some string')[:encrypted_data].should_not == 'some string'
28
+ end
29
+ end
30
+
31
+ describe '.decrypt' do
32
+ before do
33
+ @salt = TwitterAuth::Cryptify.generate_salt
34
+ TwitterAuth::Cryptify.stub!(:generate_salt).and_return(@salt)
35
+ @string = 'decrypted string'
36
+ @encrypted = TwitterAuth::Cryptify.encrypt(@string)
37
+ end
38
+
39
+ it 'should return the original string' do
40
+ TwitterAuth::Cryptify.decrypt(@encrypted).should == @string
41
+ end
42
+
43
+ it 'should raise an argument error if encrypted data is provided without a salt' do
44
+ lambda{TwitterAuth::Cryptify.decrypt('asodiaoie2')}.should raise_error(ArgumentError)
45
+ end
46
+
47
+ it 'should raise an argument error if a string or hash are not provided' do
48
+ lambda{TwitterAuth::Cryptify.decrypt(23)}.should raise_error(ArgumentError)
49
+ end
50
+ end
51
+ end