authpwn_rails 0.10.3 → 0.10.4
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/Gemfile.lock +2 -2
- data/VERSION +1 -1
- data/app/models/credentials/email.rb +31 -3
- data/app/models/credentials/password.rb +20 -9
- data/authpwn_rails.gemspec +2 -2
- data/legacy/migrate_09_to_010.rb +1 -0
- data/lib/authpwn_rails/engine.rb +1 -0
- data/lib/authpwn_rails/generators/templates/session_controller.rb +10 -0
- data/lib/authpwn_rails/session_controller.rb +14 -4
- data/lib/authpwn_rails/test_extensions.rb +38 -3
- data/lib/authpwn_rails/user_model.rb +8 -0
- data/test/email_credential_test.rb +34 -2
- data/test/password_credential_test.rb +25 -7
- data/test/session_controller_api_test.rb +26 -2
- metadata +17 -17
data/Gemfile.lock
CHANGED
|
@@ -60,13 +60,13 @@ GEM
|
|
|
60
60
|
bundler (~> 1.0)
|
|
61
61
|
git (>= 1.2.5)
|
|
62
62
|
rake
|
|
63
|
-
json (1.6.
|
|
63
|
+
json (1.6.2)
|
|
64
64
|
mail (2.3.0)
|
|
65
65
|
i18n (>= 0.4.0)
|
|
66
66
|
mime-types (~> 1.16)
|
|
67
67
|
treetop (~> 1.4.8)
|
|
68
68
|
mime-types (1.17.2)
|
|
69
|
-
multi_json (1.0.
|
|
69
|
+
multi_json (1.0.4)
|
|
70
70
|
multipart-post (1.1.4)
|
|
71
71
|
oauth2 (0.5.1)
|
|
72
72
|
faraday (~> 0.7.4)
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.10.
|
|
1
|
+
0.10.4
|
|
@@ -10,13 +10,41 @@ class Email < ::Credential
|
|
|
10
10
|
:message => 'This e-mail address is already claimed by an account' }
|
|
11
11
|
|
|
12
12
|
# '1' if the user proved ownership of the e-mail address.
|
|
13
|
-
|
|
14
|
-
validates :verified, :presence => true
|
|
13
|
+
validates :key, :presence => true, :inclusion => { :in => ['0', '1'] }
|
|
15
14
|
|
|
16
15
|
before_validation :set_verified_to_false, :on => :create
|
|
17
16
|
# :nodoc: by default, e-mail addresses are not verified
|
|
18
17
|
def set_verified_to_false
|
|
19
|
-
self.
|
|
18
|
+
self.key ||= '0' if self.key.nil?
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# True if the e-mail has been verified via a token URL.
|
|
22
|
+
def verified?
|
|
23
|
+
key == '1'
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# True if the e-mail has been verified via a token URL.
|
|
27
|
+
def verified=(new_verified_value)
|
|
28
|
+
self.key = new_verified_value ? '1' : '0'
|
|
29
|
+
new_verified_value ? true : false
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Locates the user that owns an e-mail address, for authentication purposes.
|
|
33
|
+
#
|
|
34
|
+
# Presenting the correct e-mail is almost never sufficient for authentication
|
|
35
|
+
# purposes. This method will most likely used to kick off an authentication
|
|
36
|
+
# process, such as in Password#authenticate_email.
|
|
37
|
+
#
|
|
38
|
+
# Returns the authenticated User instance, or a symbol indicating the reason
|
|
39
|
+
# why the (potentially valid) password was rejected.
|
|
40
|
+
def self.authenticate(email)
|
|
41
|
+
# This method is likely to be used to kick off a complex authentication
|
|
42
|
+
# process, so it makes sense to pre-fetch the user's other credentials.
|
|
43
|
+
credential = Credentials::Email.where(:name => email).
|
|
44
|
+
includes(:user => :credentials).first
|
|
45
|
+
return :invalid unless credential
|
|
46
|
+
user = credential.user
|
|
47
|
+
user.auth_bounce_reason(credential) || user
|
|
20
48
|
end
|
|
21
49
|
|
|
22
50
|
# Forms can only change the e-mail in the credential.
|
|
@@ -14,14 +14,23 @@ class Password < ::Credential
|
|
|
14
14
|
# A user can have a single password
|
|
15
15
|
validates :user_id, :uniqueness => true
|
|
16
16
|
|
|
17
|
-
# Compares
|
|
17
|
+
# Compares a plain-text password against the password hash in this credential.
|
|
18
18
|
#
|
|
19
19
|
# Returns +true+ for a match, +false+ otherwise.
|
|
20
|
-
def
|
|
20
|
+
def check_password(password)
|
|
21
21
|
return false unless key
|
|
22
22
|
key == self.class.hash_password(password, key.split('|', 2).first)
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
+
# Compares a plain-text password against the password hash in this credential.
|
|
26
|
+
#
|
|
27
|
+
# Returns the authenticated User instance, or a symbol indicating the reason
|
|
28
|
+
# why the (potentially valid) password was rejected.
|
|
29
|
+
def authenticate(password)
|
|
30
|
+
return :invalid unless check_password(password)
|
|
31
|
+
user.auth_bounce_reason(self) || user
|
|
32
|
+
end
|
|
33
|
+
|
|
25
34
|
# Password virtual attribute.
|
|
26
35
|
def password=(new_password)
|
|
27
36
|
@password = new_password
|
|
@@ -34,14 +43,16 @@ class Password < ::Credential
|
|
|
34
43
|
@password = @password_confirmation = nil
|
|
35
44
|
end
|
|
36
45
|
|
|
37
|
-
#
|
|
46
|
+
# Authenticates a user given an e-mail / password pair.
|
|
47
|
+
#
|
|
48
|
+
# Returns the authenticated User instance, or a symbol indicating the reason
|
|
49
|
+
# why the (potentially valid) credential was rejected.
|
|
38
50
|
def self.authenticate_email(email, password)
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
credential =
|
|
43
|
-
|
|
44
|
-
credential.authenticate(password) ? email_cred.user : nil
|
|
51
|
+
user = Credentials::Email.authenticate email
|
|
52
|
+
return user if user.is_a? Symbol
|
|
53
|
+
|
|
54
|
+
credential = user.credentials.find { |c| c.kind_of? Credentials::Password }
|
|
55
|
+
credential ? credential.authenticate(password) : :invalid
|
|
45
56
|
end
|
|
46
57
|
|
|
47
58
|
# Computes a password hash from a raw password and a salt.
|
data/authpwn_rails.gemspec
CHANGED
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
|
|
6
6
|
Gem::Specification.new do |s|
|
|
7
7
|
s.name = "authpwn_rails"
|
|
8
|
-
s.version = "0.10.
|
|
8
|
+
s.version = "0.10.4"
|
|
9
9
|
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
|
11
11
|
s.authors = ["Victor Costan"]
|
|
12
|
-
s.date = "2011-11-
|
|
12
|
+
s.date = "2011-11-30"
|
|
13
13
|
s.description = "Works with Facebook."
|
|
14
14
|
s.email = "victor@costan.us"
|
|
15
15
|
s.extra_rdoc_files = [
|
data/legacy/migrate_09_to_010.rb
CHANGED
data/lib/authpwn_rails/engine.rb
CHANGED
|
@@ -16,6 +16,16 @@ class SessionController < ApplicationController
|
|
|
16
16
|
end
|
|
17
17
|
private :home
|
|
18
18
|
|
|
19
|
+
# The notification text displayed when a session authentication fails.
|
|
20
|
+
def bounce_notice_text(reason)
|
|
21
|
+
case reason
|
|
22
|
+
when :invalid
|
|
23
|
+
'Invalid e-mail or password'
|
|
24
|
+
when :blocked
|
|
25
|
+
'Account blocked. Please verify your e-mail address'
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
19
29
|
# You shouldn't extend the session controller, so you can benefit from future
|
|
20
30
|
# features, like Facebook / Twitter / OpenID integration. But, if you must,
|
|
21
31
|
# you can do it here.
|
|
@@ -54,8 +54,8 @@ module SessionController
|
|
|
54
54
|
def create
|
|
55
55
|
@redirect_url = params[:redirect_url] || session_url
|
|
56
56
|
@email = params[:email]
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
auth = Credentials::Password.authenticate_email @email, params[:password]
|
|
58
|
+
self.current_user = auth unless auth.kind_of? Symbol
|
|
59
59
|
|
|
60
60
|
respond_to do |format|
|
|
61
61
|
if current_user
|
|
@@ -69,12 +69,12 @@ module SessionController
|
|
|
69
69
|
:csrf => form_authenticity_token }
|
|
70
70
|
end
|
|
71
71
|
else
|
|
72
|
-
notice =
|
|
72
|
+
notice = bounce_notice_text auth
|
|
73
73
|
format.html do
|
|
74
74
|
redirect_to new_session_url, :flash => { :notice => notice,
|
|
75
75
|
:auth_redirect_url => @redirect_url }
|
|
76
76
|
end
|
|
77
|
-
format.json { render :json => { :error => notice} }
|
|
77
|
+
format.json { render :json => { :error => auth, :text => notice } }
|
|
78
78
|
end
|
|
79
79
|
end
|
|
80
80
|
end
|
|
@@ -97,6 +97,16 @@ module SessionController
|
|
|
97
97
|
def welcome
|
|
98
98
|
end
|
|
99
99
|
private :welcome
|
|
100
|
+
|
|
101
|
+
# Hook for customizing the bounce notification text.
|
|
102
|
+
def bounce_notice_text(reason)
|
|
103
|
+
case reason
|
|
104
|
+
when :invalid
|
|
105
|
+
'Invalid e-mail or password'
|
|
106
|
+
when :blocked
|
|
107
|
+
'Account blocked. Please verify your e-mail address'
|
|
108
|
+
end
|
|
109
|
+
end
|
|
100
110
|
end # module Authpwn::SessionController::InstanceMethods
|
|
101
111
|
|
|
102
112
|
end # module Authpwn::SessionController
|
|
@@ -1,8 +1,39 @@
|
|
|
1
1
|
# :nodoc: namespace
|
|
2
2
|
module Authpwn
|
|
3
3
|
|
|
4
|
-
# Included in test cases.
|
|
4
|
+
# Included in all test cases.
|
|
5
5
|
module TestExtensions
|
|
6
|
+
# Stubs User#auth_bounce_reason to block a given credential.
|
|
7
|
+
#
|
|
8
|
+
# The default implementation of User#auth_bounce_reason always returns nil.
|
|
9
|
+
# Your application's implementation might differ. Either way, the method is
|
|
10
|
+
# replaced for the duration of the block, such that it returns :block if
|
|
11
|
+
# the credential matches the given argument, and nil otherwise.
|
|
12
|
+
def with_blocked_credential(blocked_credential, reason = :blocked, &block)
|
|
13
|
+
# Stub a method in all User instances for this test only.
|
|
14
|
+
# flexmock.new_instances doesn't work because ActiveRecord doesn't use new
|
|
15
|
+
# to instantiate records.
|
|
16
|
+
::User.class_eval do
|
|
17
|
+
alias_method :_auth_bounce_reason_wbc_stub, :auth_bounce_reason
|
|
18
|
+
define_method :auth_bounce_reason do |credential|
|
|
19
|
+
credential == blocked_credential ? reason : nil
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
begin
|
|
24
|
+
yield
|
|
25
|
+
ensure
|
|
26
|
+
::User.class_eval do
|
|
27
|
+
undef_method :auth_bounce_reason
|
|
28
|
+
alias_method :auth_bounce_reason, :_auth_bounce_reason_wbc_stub
|
|
29
|
+
undef_method :_auth_bounce_reason_wbc_stub
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end # module Authpwn::TestExtensions
|
|
34
|
+
|
|
35
|
+
# Included in controller test cases.
|
|
36
|
+
module ControllerTestExtensions
|
|
6
37
|
# Sets the authenticated user in the test session.
|
|
7
38
|
def set_session_current_user(user)
|
|
8
39
|
request.session[:user_exuid] = user ? user.to_param : nil
|
|
@@ -13,12 +44,16 @@ module TestExtensions
|
|
|
13
44
|
return nil unless user_param = request.session[:user_exuid]
|
|
14
45
|
User.find_by_param user_param
|
|
15
46
|
end
|
|
16
|
-
end # module Authpwn::
|
|
47
|
+
end # module Authpwn::ControllerTestExtensions
|
|
17
48
|
|
|
18
49
|
end # namespace Authpwn
|
|
19
50
|
|
|
51
|
+
# :nodoc: extend Test::Unit
|
|
52
|
+
class ActiveSupport::TestCase
|
|
53
|
+
include Authpwn::TestExtensions
|
|
54
|
+
end
|
|
20
55
|
|
|
21
56
|
# :nodoc: extend Test::Unit
|
|
22
57
|
class ActionController::TestCase
|
|
23
|
-
include Authpwn::
|
|
58
|
+
include Authpwn::ControllerTestExtensions
|
|
24
59
|
end
|
|
@@ -42,6 +42,14 @@ module UserModel
|
|
|
42
42
|
|
|
43
43
|
# Included in models that include Authpwn::UserModel.
|
|
44
44
|
module InstanceMethods
|
|
45
|
+
# Checks if a credential is acceptable for authenticating a user.
|
|
46
|
+
#
|
|
47
|
+
# Returns nil if the credential is acceptable, or a String containing a
|
|
48
|
+
# user-visible reason why the credential is not acceptable.
|
|
49
|
+
def auth_bounce_reason(crdential)
|
|
50
|
+
nil
|
|
51
|
+
end
|
|
52
|
+
|
|
45
53
|
# Use e-mails instead of exposing ActiveRecord IDs.
|
|
46
54
|
def to_param
|
|
47
55
|
exuid
|
|
@@ -10,11 +10,28 @@ class EmailCredentialTest < ActiveSupport::TestCase
|
|
|
10
10
|
assert @credential.valid?
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
-
test '
|
|
14
|
-
@credential.
|
|
13
|
+
test 'key required' do
|
|
14
|
+
@credential.key = ''
|
|
15
|
+
assert !@credential.valid?
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
test 'key cannot be some random string' do
|
|
19
|
+
@credential.key = 'xoxo'
|
|
15
20
|
assert !@credential.valid?
|
|
16
21
|
end
|
|
17
22
|
|
|
23
|
+
test 'verified set to true' do
|
|
24
|
+
@credential.verified = true
|
|
25
|
+
assert_equal '1', @credential.key, 'key'
|
|
26
|
+
assert_equal true, @credential.verified?, 'verified?'
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
test 'verified set to false' do
|
|
30
|
+
@credential.verified = false
|
|
31
|
+
assert_equal '0', @credential.key, 'key'
|
|
32
|
+
assert_equal false, @credential.verified?, 'verified?'
|
|
33
|
+
end
|
|
34
|
+
|
|
18
35
|
test 'user presence' do
|
|
19
36
|
@credential.user = nil
|
|
20
37
|
assert !@credential.valid?
|
|
@@ -41,4 +58,19 @@ class EmailCredentialTest < ActiveSupport::TestCase
|
|
|
41
58
|
@credential.email = credentials(:john_email).email
|
|
42
59
|
assert !@credential.valid?
|
|
43
60
|
end
|
|
61
|
+
|
|
62
|
+
test 'authenticate' do
|
|
63
|
+
assert_equal users(:john), Credentials::Email.authenticate('john@gmail.com')
|
|
64
|
+
assert_equal users(:jane), Credentials::Email.authenticate('jane@gmail.com')
|
|
65
|
+
assert_equal :invalid, Credentials::Email.authenticate('bill@gmail.com')
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
test 'authenticate calls User#auth_bounce_reason' do
|
|
69
|
+
with_blocked_credential credentials(:john_email), :reason do
|
|
70
|
+
assert_equal :reason, Credentials::Email.authenticate('john@gmail.com')
|
|
71
|
+
assert_equal users(:jane),
|
|
72
|
+
Credentials::Email.authenticate('jane@gmail.com')
|
|
73
|
+
assert_equal :invalid, Credentials::Email.authenticate('bill@gmail.com')
|
|
74
|
+
end
|
|
75
|
+
end
|
|
44
76
|
end
|
|
@@ -36,27 +36,45 @@ class PasswordCredentialTest < ActiveSupport::TestCase
|
|
|
36
36
|
assert !@credential.valid?
|
|
37
37
|
end
|
|
38
38
|
|
|
39
|
-
test '
|
|
40
|
-
assert_equal true, @credential.
|
|
41
|
-
assert_equal false, @credential.
|
|
39
|
+
test 'check_password' do
|
|
40
|
+
assert_equal true, @credential.check_password('awesome')
|
|
41
|
+
assert_equal false, @credential.check_password('not awesome'),
|
|
42
42
|
'Bogus password'
|
|
43
|
-
assert_equal false, @credential.
|
|
43
|
+
assert_equal false, @credential.check_password('password'),
|
|
44
44
|
"Another user's password"
|
|
45
45
|
end
|
|
46
|
+
|
|
47
|
+
test 'authenticate' do
|
|
48
|
+
assert_equal users(:bill), @credential.authenticate('awesome')
|
|
49
|
+
assert_equal :invalid, @credential.authenticate('not awesome')
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
test 'authenticate calls User#auth_bounce_reason' do
|
|
53
|
+
user = @credential.user
|
|
54
|
+
flexmock(user).should_receive(:auth_bounce_reason).and_return(:reason)
|
|
55
|
+
assert_equal :reason, @credential.authenticate('awesome')
|
|
56
|
+
assert_equal :invalid, @credential.authenticate('not awesome')
|
|
57
|
+
end
|
|
46
58
|
|
|
47
59
|
test 'authenticate_email' do
|
|
48
60
|
assert_equal users(:john),
|
|
49
61
|
Credentials::Password.authenticate_email('john@gmail.com', 'password')
|
|
50
|
-
assert_equal
|
|
62
|
+
assert_equal :invalid,
|
|
51
63
|
Credentials::Password.authenticate_email('john@gmail.com', 'pa55w0rd'),
|
|
52
64
|
"Jane's password on John's account"
|
|
53
65
|
assert_equal users(:jane),
|
|
54
66
|
Credentials::Password.authenticate_email('jane@gmail.com', 'pa55w0rd')
|
|
55
|
-
assert_equal
|
|
67
|
+
assert_equal :invalid,
|
|
56
68
|
Credentials::Password.authenticate_email('jane@gmail.com', 'password'),
|
|
57
69
|
"John's password on Jane's account"
|
|
58
|
-
assert_equal
|
|
70
|
+
assert_equal :invalid,
|
|
59
71
|
Credentials::Password.authenticate_email('john@gmail.com', 'awesome'),
|
|
60
72
|
'Bogus password'
|
|
73
|
+
assert_equal :invalid,
|
|
74
|
+
Credentials::Password.authenticate_email('bill@gmail.com', 'pa55w0rd'),
|
|
75
|
+
'Password authentication on account without password credential'
|
|
76
|
+
assert_equal :invalid,
|
|
77
|
+
Credentials::Password.authenticate_email('none@gmail.com', 'pa55w0rd'),
|
|
78
|
+
'Bogus e-mail'
|
|
61
79
|
end
|
|
62
80
|
end
|
|
@@ -106,7 +106,17 @@ class SessionControllerApiTest < ActionController::TestCase
|
|
|
106
106
|
assert_redirected_to new_session_url
|
|
107
107
|
assert_nil assigns(:current_user), 'instance variable'
|
|
108
108
|
assert_nil session_current_user, 'session'
|
|
109
|
-
|
|
109
|
+
assert_match(/Invalid/, flash[:notice])
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
test "create does not log in blocked accounts" do
|
|
113
|
+
with_blocked_credential @email_credential do
|
|
114
|
+
post :create, :email => @email_credential.email, :password => 'password'
|
|
115
|
+
end
|
|
116
|
+
assert_redirected_to new_session_url
|
|
117
|
+
assert_nil assigns(:current_user), 'instance variable'
|
|
118
|
+
assert_nil session_current_user, 'session'
|
|
119
|
+
assert_match(/ blocked/, flash[:notice])
|
|
110
120
|
end
|
|
111
121
|
|
|
112
122
|
test "create by json does not log in with bad password" do
|
|
@@ -114,11 +124,25 @@ class SessionControllerApiTest < ActionController::TestCase
|
|
|
114
124
|
:format => 'json'
|
|
115
125
|
assert_response :ok
|
|
116
126
|
data = ActiveSupport::JSON.decode response.body
|
|
117
|
-
|
|
127
|
+
assert_equal 'invalid', data['error']
|
|
128
|
+
assert_match(/invalid/i , data['text'])
|
|
118
129
|
assert_nil assigns(:current_user), 'instance variable'
|
|
119
130
|
assert_nil session_current_user, 'session'
|
|
120
131
|
end
|
|
121
132
|
|
|
133
|
+
test "create by json does not log in blocked accounts" do
|
|
134
|
+
with_blocked_credential @email_credential do
|
|
135
|
+
post :create, :email => @email_credential.email, :password => 'password',
|
|
136
|
+
:format => 'json'
|
|
137
|
+
end
|
|
138
|
+
assert_response :ok
|
|
139
|
+
data = ActiveSupport::JSON.decode response.body
|
|
140
|
+
assert_equal 'blocked', data['error']
|
|
141
|
+
assert_match(/blocked/i , data['text'])
|
|
142
|
+
assert_nil assigns(:current_user), 'instance variable'
|
|
143
|
+
assert_nil session_current_user, 'session'
|
|
144
|
+
end
|
|
145
|
+
|
|
122
146
|
test "create maintains redirect_url for bad logins" do
|
|
123
147
|
url = 'http://authpwn.redirect.url'
|
|
124
148
|
post :create, :email => @email_credential.email, :password => 'fail',
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: authpwn_rails
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.10.
|
|
4
|
+
version: 0.10.4
|
|
5
5
|
prerelease:
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
@@ -9,11 +9,11 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2011-11-
|
|
12
|
+
date: 2011-11-30 00:00:00.000000000Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: fbgraph_rails
|
|
16
|
-
requirement: &
|
|
16
|
+
requirement: &14255560 !ruby/object:Gem::Requirement
|
|
17
17
|
none: false
|
|
18
18
|
requirements:
|
|
19
19
|
- - ! '>='
|
|
@@ -21,10 +21,10 @@ dependencies:
|
|
|
21
21
|
version: 0.2.2
|
|
22
22
|
type: :runtime
|
|
23
23
|
prerelease: false
|
|
24
|
-
version_requirements: *
|
|
24
|
+
version_requirements: *14255560
|
|
25
25
|
- !ruby/object:Gem::Dependency
|
|
26
26
|
name: rails
|
|
27
|
-
requirement: &
|
|
27
|
+
requirement: &14254720 !ruby/object:Gem::Requirement
|
|
28
28
|
none: false
|
|
29
29
|
requirements:
|
|
30
30
|
- - ! '>='
|
|
@@ -32,10 +32,10 @@ dependencies:
|
|
|
32
32
|
version: 3.1.3
|
|
33
33
|
type: :runtime
|
|
34
34
|
prerelease: false
|
|
35
|
-
version_requirements: *
|
|
35
|
+
version_requirements: *14254720
|
|
36
36
|
- !ruby/object:Gem::Dependency
|
|
37
37
|
name: bundler
|
|
38
|
-
requirement: &
|
|
38
|
+
requirement: &14253940 !ruby/object:Gem::Requirement
|
|
39
39
|
none: false
|
|
40
40
|
requirements:
|
|
41
41
|
- - ~>
|
|
@@ -43,10 +43,10 @@ dependencies:
|
|
|
43
43
|
version: 1.0.0
|
|
44
44
|
type: :development
|
|
45
45
|
prerelease: false
|
|
46
|
-
version_requirements: *
|
|
46
|
+
version_requirements: *14253940
|
|
47
47
|
- !ruby/object:Gem::Dependency
|
|
48
48
|
name: flexmock
|
|
49
|
-
requirement: &
|
|
49
|
+
requirement: &14252840 !ruby/object:Gem::Requirement
|
|
50
50
|
none: false
|
|
51
51
|
requirements:
|
|
52
52
|
- - ~>
|
|
@@ -54,10 +54,10 @@ dependencies:
|
|
|
54
54
|
version: 0.9.0
|
|
55
55
|
type: :development
|
|
56
56
|
prerelease: false
|
|
57
|
-
version_requirements: *
|
|
57
|
+
version_requirements: *14252840
|
|
58
58
|
- !ruby/object:Gem::Dependency
|
|
59
59
|
name: jeweler
|
|
60
|
-
requirement: &
|
|
60
|
+
requirement: &14251980 !ruby/object:Gem::Requirement
|
|
61
61
|
none: false
|
|
62
62
|
requirements:
|
|
63
63
|
- - ~>
|
|
@@ -65,10 +65,10 @@ dependencies:
|
|
|
65
65
|
version: 1.6.0
|
|
66
66
|
type: :development
|
|
67
67
|
prerelease: false
|
|
68
|
-
version_requirements: *
|
|
68
|
+
version_requirements: *14251980
|
|
69
69
|
- !ruby/object:Gem::Dependency
|
|
70
70
|
name: rcov
|
|
71
|
-
requirement: &
|
|
71
|
+
requirement: &14248280 !ruby/object:Gem::Requirement
|
|
72
72
|
none: false
|
|
73
73
|
requirements:
|
|
74
74
|
- - ! '>='
|
|
@@ -76,10 +76,10 @@ dependencies:
|
|
|
76
76
|
version: '0'
|
|
77
77
|
type: :development
|
|
78
78
|
prerelease: false
|
|
79
|
-
version_requirements: *
|
|
79
|
+
version_requirements: *14248280
|
|
80
80
|
- !ruby/object:Gem::Dependency
|
|
81
81
|
name: sqlite3
|
|
82
|
-
requirement: &
|
|
82
|
+
requirement: &14247460 !ruby/object:Gem::Requirement
|
|
83
83
|
none: false
|
|
84
84
|
requirements:
|
|
85
85
|
- - ! '>='
|
|
@@ -87,7 +87,7 @@ dependencies:
|
|
|
87
87
|
version: 1.3.3
|
|
88
88
|
type: :development
|
|
89
89
|
prerelease: false
|
|
90
|
-
version_requirements: *
|
|
90
|
+
version_requirements: *14247460
|
|
91
91
|
description: Works with Facebook.
|
|
92
92
|
email: victor@costan.us
|
|
93
93
|
executables: []
|
|
@@ -167,7 +167,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
167
167
|
version: '0'
|
|
168
168
|
segments:
|
|
169
169
|
- 0
|
|
170
|
-
hash: -
|
|
170
|
+
hash: -3462448452980002093
|
|
171
171
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
172
172
|
none: false
|
|
173
173
|
requirements:
|