dbalatero-evri_rpx 0.1.0

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,16 @@
1
+ module Evri
2
+ module RPX
3
+ class Mappings
4
+ attr_reader :json
5
+ alias :raw :json
6
+
7
+ def initialize(json)
8
+ @json = json
9
+ end
10
+
11
+ def identifiers
12
+ @json['identifiers'] || []
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,125 @@
1
+ module Evri
2
+ module RPX
3
+ class Session
4
+ API_VERSION = 'v2'
5
+ API_HOST = 'rpxnow.com'
6
+ ROOT_CA_PATH = File.expand_path(File.join(File.dirname(__FILE__),
7
+ '..', '..', '..', 'certs',
8
+ 'curl-ca-bundle.crt'))
9
+
10
+
11
+ class ServiceUnavailableError < StandardError; end
12
+ class APICallError < StandardError; end
13
+
14
+ attr_reader :api_key
15
+
16
+ def initialize(api_key)
17
+ @api_key = api_key
18
+ end
19
+
20
+ # Returns an auth_info User response from RPXNow.
21
+ # Options:
22
+ # :tokenUrl => 'http://...'
23
+ # RPX will validate that the tokenUrl that you received
24
+ # a login redirect from matches the tokenUrl they have on
25
+ # file. This is extra security to guard against spoofing.
26
+ #
27
+ # Default: nil
28
+ # :extended => (true|false)
29
+ # If you are a Plus/Pro customer, RPX will return extended
30
+ # data.
31
+ #
32
+ # Default: false
33
+ def auth_info(token, options = {})
34
+ params = { 'apiKey' => @api_key,
35
+ 'token' => token }
36
+ params.merge!(options)
37
+
38
+ json = parse_response(get("/api/#{API_VERSION}/auth_info",
39
+ params))
40
+ User.new(json)
41
+ end
42
+
43
+ # Returns the mappings for a given user's primary key, as a
44
+ # Evri::RPX::Mappings object.
45
+ #
46
+ # Takes either a string of the user's primary key:
47
+ # session.mappings('dbalatero')
48
+ # or a User object with an attached primary key:
49
+ # session.mappings(
50
+ def mappings(user_or_primary_key)
51
+ params = { 'apiKey' => @api_key }
52
+ params['primaryKey'] = user_or_primary_key.respond_to?(:primary_key) ?
53
+ user_or_primary_key.primary_key : user_or_primary_key
54
+
55
+ json = parse_response(get("/api/#{API_VERSION}/mappings",
56
+ params))
57
+ Mappings.new(json)
58
+ end
59
+
60
+
61
+ # Map an OpenID to a primary key. Future logins by this owner of
62
+ # this OpenID will return the mapped primaryKey in the auth_info
63
+ # API response, which you may use to sign the user in.
64
+ #
65
+ #
66
+ def map(user_or_identifier, primary_key, options = {})
67
+ params = { 'apiKey' => @api_key,
68
+ 'primaryKey' => primary_key,
69
+ 'overwrite' => true }
70
+ params.merge!(options)
71
+ params['identifier'] = identifier_param(user_or_identifier)
72
+ json = parse_response(get("/api/#{API_VERSION}/map",
73
+ params))
74
+
75
+ json['stat'] == 'ok'
76
+ end
77
+
78
+ def unmap(user_or_identifier, primary_key)
79
+ params = { 'apiKey' => @api_key,
80
+ 'primaryKey' => primary_key }
81
+ params['identifier'] = identifier_param(user_or_identifier)
82
+
83
+ json = parse_response(get("/api/#{API_VERSION}/unmap",
84
+ params))
85
+
86
+ json['stat'] == 'ok'
87
+ end
88
+
89
+ private
90
+ def identifier_param(user_or_identifier)
91
+ user_or_identifier.respond_to?(:identifier) ?
92
+ user_or_identifier.identifier : user_or_identifier
93
+ end
94
+
95
+ def get(resource, params)
96
+ request = Net::HTTP::Get.new(resource)
97
+ request.form_data = params
98
+ make_request(request)
99
+ end
100
+
101
+ def make_request(request)
102
+ http = Net::HTTP.new(API_HOST, 443)
103
+ http.ca_path = ROOT_CA_PATH
104
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
105
+ http.verify_depth = 5
106
+ http.request(request)
107
+ end
108
+
109
+ def parse_response(response)
110
+ if response.code.to_i >= 400
111
+ result = JSON.parse(response.body)
112
+
113
+ code = result['err']['code']
114
+ if code == -1
115
+ raise ServiceUnavailableError, "The RPX service is temporarily unavailable."
116
+ else
117
+ raise APICallError, "Got error: #{result['err']['msg']} (code: #{code}), HTTP status: #{response.code}"
118
+ end
119
+ else
120
+ JSON.parse(response.body)
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,86 @@
1
+ module Evri
2
+ module RPX
3
+ class User
4
+ class InvalidUserJsonError < StandardError; end
5
+
6
+ attr_reader :json
7
+ alias :raw :json
8
+
9
+ def initialize(json)
10
+ if json.nil? or !json['profile']
11
+ raise InvalidUserJsonError,
12
+ 'The JSON passed in is invalid!'
13
+ end
14
+ @json = json
15
+ end
16
+
17
+ # Returns the person's full name (aka David Balatero)
18
+ def name
19
+ @json['profile']['name']['formatted'] rescue nil
20
+ end
21
+
22
+ # Returns a name that should be displayed for this user.
23
+ def display_name
24
+ @json['profile']['displayName'] rescue nil
25
+ end
26
+
27
+ # Returns a username for this user.
28
+ def username
29
+ @json['profile']['preferredUsername'] rescue nil
30
+ end
31
+
32
+ # Returns a unique identifier for this user.
33
+ def identifier
34
+ @json['profile']['identifier'] rescue nil
35
+ end
36
+
37
+ # Returns the primary key for this user, if they have
38
+ # been mapped already.
39
+ def primary_key
40
+ @json['profile']['primaryKey'] rescue nil
41
+ end
42
+
43
+ # Returns a photo URL for a user if they have one.
44
+ def photo
45
+ @json['profile']['photo'] rescue nil
46
+ end
47
+
48
+ # Returns a URL to a person's profile on the 3rd-party site.
49
+ def profile_url
50
+ @json['profile']['url'] rescue nil
51
+ end
52
+
53
+ def credentials
54
+ nil
55
+ end
56
+
57
+ # Returns a user's email.
58
+ def email
59
+ @json['profile']['email'] rescue nil
60
+ end
61
+
62
+ # Returns the provider name for this user, aka "Twitter", "Google".
63
+ # Also, see convenience methods such as #google?, #twitter?
64
+ def provider_name
65
+ @json['profile']['providerName'] rescue nil
66
+ end
67
+
68
+ # Returns true if this is a Twitter login.
69
+ def twitter?
70
+ provider_name == 'Twitter'
71
+ end
72
+
73
+ def google?
74
+ provider_name == 'Google'
75
+ end
76
+
77
+ def facebook?
78
+ provider_name == 'Facebook'
79
+ end
80
+
81
+ def yahoo?
82
+ provider_name == 'Yahoo!'
83
+ end
84
+ end
85
+ end
86
+ end
data/lib/evri/rpx.rb ADDED
@@ -0,0 +1,4 @@
1
+ module Evri
2
+ module RPX
3
+ end
4
+ end
data/lib/evri_rpx.rb ADDED
@@ -0,0 +1,10 @@
1
+ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__)))
2
+
3
+ require 'json'
4
+ require 'net/http'
5
+ require 'net/https'
6
+
7
+ require 'evri/rpx'
8
+ require 'evri/rpx/mappings'
9
+ require 'evri/rpx/session'
10
+ require 'evri/rpx/user'
@@ -0,0 +1,21 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_helper'))
2
+
3
+ describe Evri::RPX::Mappings do
4
+ describe "identifiers" do
5
+ it "should return the identifiers present in the response" do
6
+ json = json_fixture('mappings/identifiers.json')
7
+ mappings = Evri::RPX::Mappings.new(json)
8
+ mappings.identifiers.should include("http://brian.myopenid.com/")
9
+ mappings.identifiers.should include("http://brianellin.com/")
10
+ end
11
+ end
12
+
13
+ describe "raw/json" do
14
+ it "should return the raw JSON that was passed to the constructor" do
15
+ json = {}
16
+ mappings = Evri::RPX::Mappings.new(json)
17
+ mappings.raw.should == json
18
+ mappings.json.should == json
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,114 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_helper'))
2
+
3
+ describe Evri::RPX::Session do
4
+ before(:all) do
5
+ @session = Evri::RPX::Session.new('fake_api_key')
6
+ end
7
+
8
+ describe "api_key" do
9
+ it "should return the current API key" do
10
+ @session.api_key.should == 'fake_api_key'
11
+ end
12
+ end
13
+
14
+ describe "auth_info" do
15
+ after(:each) do
16
+ FakeWeb.clean_registry
17
+ end
18
+
19
+ it "should raise an APICallError if RPX returns an error message" do
20
+ FakeWeb.register_uri(:get,
21
+ 'http://rpxnow.com:443/api/v2/auth_info',
22
+ :file => fixture_path('session/normal_error.json'),
23
+ :status => ['400', 'Bad Request'])
24
+ lambda {
25
+ @session.auth_info('errortoken')
26
+ }.should raise_error(Evri::RPX::Session::APICallError)
27
+ end
28
+
29
+ it "should raise ServiceUnavailableError if the service is not available" do
30
+ FakeWeb.register_uri(:get,
31
+ 'http://rpxnow.com:443/api/v2/auth_info',
32
+ :file => fixture_path('session/service_down_error.json'),
33
+ :status => ['404', 'Not Found'])
34
+ lambda {
35
+ @session.auth_info('errortoken')
36
+ }.should raise_error(Evri::RPX::Session::ServiceUnavailableError)
37
+ end
38
+
39
+ it "should return a User object for a mapping" do
40
+ FakeWeb.register_uri(:get,
41
+ 'http://rpxnow.com:443/api/v2/auth_info',
42
+ :file => fixture_path('user/dbalatero_gmail.json'))
43
+
44
+ result = @session.auth_info('mytoken')
45
+ result.should be_a_kind_of(Evri::RPX::User)
46
+ end
47
+ end
48
+
49
+ describe "map" do
50
+ before(:each) do
51
+ FakeWeb.register_uri(:get,
52
+ 'http://rpxnow.com:443/api/v2/map',
53
+ :file => fixture_path('session/map.json'))
54
+ end
55
+
56
+ it "should take in a User object as the second parameter" do
57
+ user = mock('user')
58
+ user.should_receive(:identifier).and_return('http://www.facebook.com/dbalatero')
59
+
60
+ result = @session.map(user, 50)
61
+ result.should be_true
62
+ end
63
+
64
+ it "should take in a identifier string as the second parameter" do
65
+ result = @session.map('http://www.facebook.com/dbalatero', 50)
66
+ result.should be_true
67
+ end
68
+ end
69
+
70
+ describe "mappings" do
71
+ it "should return a Mappings object" do
72
+ FakeWeb.register_uri(:get,
73
+ 'http://rpxnow.com:443/api/v2/mappings',
74
+ :file => fixture_path('mappings/identifiers.json'))
75
+
76
+ result = @session.mappings('dbalatero')
77
+ result.should be_a_kind_of(Evri::RPX::Mappings)
78
+ result.identifiers.should_not be_empty
79
+ end
80
+
81
+ it "should take a User object in" do
82
+ FakeWeb.register_uri(:get,
83
+ 'http://rpxnow.com:443/api/v2/mappings',
84
+ :file => fixture_path('mappings/identifiers.json'))
85
+ user = mock('user')
86
+ user.should_receive(:primary_key).and_return('dbalatero')
87
+
88
+ result = @session.mappings(user)
89
+ result.should be_a_kind_of(Evri::RPX::Mappings)
90
+ result.identifiers.should_not be_empty
91
+ end
92
+ end
93
+
94
+ describe "unmap" do
95
+ before(:each) do
96
+ FakeWeb.register_uri(:get,
97
+ 'http://rpxnow.com:443/api/v2/unmap',
98
+ :file => fixture_path('session/unmap.json'))
99
+ end
100
+
101
+ it "should take a string as the identifier" do
102
+ result = @session.unmap('http://www.facebook.com/dbalatero', 50)
103
+ result.should be_true
104
+ end
105
+
106
+ it "should take a User as the identifier" do
107
+ user = mock('user')
108
+ user.should_receive(:identifier).and_return('http://www.facebook.com/dbalatero')
109
+
110
+ result = @session.unmap(user, 50)
111
+ result.should be_true
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,303 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_helper'))
2
+
3
+ describe Evri::RPX::User do
4
+ describe "initialize" do
5
+ it "should not accept any JSON hash that doesn't have profile data in it" do
6
+ lambda {
7
+ Evri::RPX::User.new({})
8
+ }.should raise_error(Evri::RPX::User::InvalidUserJsonError)
9
+
10
+ lambda {
11
+ Evri::RPX::User.new(nil)
12
+ }.should raise_error(Evri::RPX::User::InvalidUserJsonError)
13
+ end
14
+ end
15
+
16
+ describe "raw / json methods" do
17
+ it "should return the raw JSON that was passed to the constructor" do
18
+ json = { 'profile' => { 'email' => 'foo@bar.com' } }
19
+ user = Evri::RPX::User.new(json)
20
+ user.raw.should == json
21
+ user.json.should == json
22
+ end
23
+ end
24
+
25
+ describe "parsing Twitter logins" do
26
+ before(:all) do
27
+ json = json_fixture('user/dbalatero_twitter.json')
28
+ @user = Evri::RPX::User.new(json)
29
+ end
30
+
31
+ describe "name" do
32
+ it "should be equal to the formatted name" do
33
+ @user.name.should == 'David Balatero'
34
+ end
35
+ end
36
+
37
+ describe "photo" do
38
+ it "should be a valid photo" do
39
+ @user.photo.should =~ /http:\/\/s3\.amazonaws\.com/
40
+ end
41
+ end
42
+
43
+ describe "display_name" do
44
+ it "should be the displayName in the JSON" do
45
+ @user.display_name.should == 'David Balatero'
46
+ end
47
+ end
48
+
49
+ describe 'profile_url' do
50
+ it "should point to the user's Twitter page" do
51
+ @user.profile_url.should == 'http://twitter.com/dbalatero'
52
+ end
53
+ end
54
+
55
+ describe 'username' do
56
+ it "should be the user's Twitter username" do
57
+ @user.username.should == 'dbalatero'
58
+ end
59
+ end
60
+
61
+ describe 'primary_key' do
62
+ it "should be nil" do
63
+ @user.primary_key.should be_nil
64
+ end
65
+ end
66
+
67
+ describe 'identifier' do
68
+ it "should be the identifier that Twitter gives" do
69
+ @user.identifier.should =~ /user_id=35834683/
70
+ end
71
+ end
72
+
73
+ describe "twitter?" do
74
+ it "should be true for Twitter responses" do
75
+ @user.twitter?.should be_true
76
+ end
77
+ end
78
+
79
+ describe "credentials" do
80
+ it "should not be nil" do
81
+ pending
82
+ end
83
+ end
84
+
85
+ describe 'provider_name' do
86
+ it 'should be Twitter' do
87
+ @user.provider_name.should == 'Twitter'
88
+ end
89
+ end
90
+ end
91
+
92
+ # Google logins
93
+ describe "parsing Google logins" do
94
+ before(:all) do
95
+ json = json_fixture('user/dbalatero_gmail.json')
96
+ @user = Evri::RPX::User.new(json)
97
+ end
98
+
99
+ describe "name" do
100
+ it "should be equal to the formatted name" do
101
+ @user.name.should == 'David Balatero'
102
+ end
103
+ end
104
+
105
+ describe "photo" do
106
+ it "should be nil" do
107
+ @user.photo.should be_nil
108
+ end
109
+ end
110
+
111
+ describe "display_name" do
112
+ it "should be the displayName in the JSON" do
113
+ @user.display_name.should == 'dbalatero'
114
+ end
115
+ end
116
+
117
+ describe 'profile_url' do
118
+ it "should be nil" do
119
+ @user.profile_url.should be_nil
120
+ end
121
+ end
122
+
123
+ describe 'username' do
124
+ it "should be the user's Google username" do
125
+ @user.username.should == 'dbalatero'
126
+ end
127
+ end
128
+
129
+ describe 'primary_key' do
130
+ it "should be set to the correct mapping" do
131
+ @user.primary_key.should == 'DavidBalateroTestRPXX'
132
+ end
133
+ end
134
+
135
+ describe 'identifier' do
136
+ it "should be the identifier that Twitter gives" do
137
+ @user.identifier.should =~ /https:\/\/www.google.com\/accounts/
138
+ end
139
+ end
140
+
141
+ describe "google?" do
142
+ it "should be true for Google responses" do
143
+ @user.google?.should be_true
144
+ end
145
+ end
146
+
147
+ describe "credentials" do
148
+ it "should be nil" do
149
+ @user.credentials.should be_nil
150
+ end
151
+ end
152
+
153
+ describe 'provider_name' do
154
+ it 'should be Google' do
155
+ @user.provider_name.should == 'Google'
156
+ end
157
+ end
158
+
159
+ describe "email" do
160
+ it "should be set to dbalatero@gmail.com" do
161
+ @user.email.should == 'dbalatero@gmail.com'
162
+ end
163
+ end
164
+ end
165
+
166
+ # Facebook logins
167
+ describe "parsing Facebook logins" do
168
+ before(:all) do
169
+ json = json_fixture('user/dbalatero_facebook.json')
170
+ @user = Evri::RPX::User.new(json)
171
+ end
172
+
173
+ describe "name" do
174
+ it "should be equal to the formatted name" do
175
+ @user.name.should == 'David Balatero'
176
+ end
177
+ end
178
+
179
+ describe "photo" do
180
+ it "should be a Facebook profile picture." do
181
+ @user.photo.should_not be_nil
182
+ @user.photo.should =~ /http:\/\/profile\.ak\.facebook\.com/
183
+ end
184
+ end
185
+
186
+ describe "display_name" do
187
+ it "should be the displayName in the JSON" do
188
+ @user.display_name.should == 'David Balatero'
189
+ end
190
+ end
191
+
192
+ describe 'profile_url' do
193
+ it "should be the correct Facebook profile URL" do
194
+ @user.profile_url.should == 'http://www.facebook.com/profile.php?id=10701789'
195
+ end
196
+ end
197
+
198
+ describe 'username' do
199
+ it "should be the user's Google username" do
200
+ @user.username.should == 'DavidBalatero'
201
+ end
202
+ end
203
+
204
+ describe 'identifier' do
205
+ it "should be the identifier that Twitter gives" do
206
+ @user.identifier.should == 'http://www.facebook.com/profile.php?id=10701789'
207
+ end
208
+ end
209
+
210
+ describe "facebook?" do
211
+ it "should be true for Google responses" do
212
+ @user.facebook?.should be_true
213
+ end
214
+ end
215
+
216
+ describe "credentials" do
217
+ it "should be set" do
218
+ pending
219
+ @user.credentials.should_not be_nil
220
+ end
221
+ end
222
+
223
+ describe 'provider_name' do
224
+ it 'should be Facebook' do
225
+ @user.provider_name.should == 'Facebook'
226
+ end
227
+ end
228
+ end
229
+
230
+ # Yahoo logins
231
+ describe "parsing Yahoo logins" do
232
+ before(:all) do
233
+ json = json_fixture('user/dbalatero_yahoo.json')
234
+ @user = Evri::RPX::User.new(json)
235
+ end
236
+
237
+ describe "name" do
238
+ it "should be equal to the formatted name" do
239
+ @user.name.should == 'David Balatero'
240
+ end
241
+ end
242
+
243
+ describe "photo" do
244
+ it "should be nil" do
245
+ @user.photo.should be_nil
246
+ end
247
+ end
248
+
249
+ describe "display_name" do
250
+ it "should be the displayName in the JSON" do
251
+ @user.display_name.should == 'David Balatero'
252
+ end
253
+ end
254
+
255
+ describe 'profile_url' do
256
+ it "should be nil" do
257
+ @user.profile_url.should be_nil
258
+ end
259
+ end
260
+
261
+ describe 'username' do
262
+ it "should be the user's Yahoo username" do
263
+ @user.username.should == 'David'
264
+ end
265
+ end
266
+
267
+ describe 'primary_key' do
268
+ it "should be nil" do
269
+ @user.primary_key.should == 'David'
270
+ end
271
+ end
272
+
273
+ describe 'identifier' do
274
+ it "should be the identifier that Yahoo gives" do
275
+ @user.identifier.should =~ /https:\/\/me\.yahoo\.com/
276
+ end
277
+ end
278
+
279
+ describe 'email' do
280
+ it "should be dbalatero@yahoo.com" do
281
+ @user.email.should == 'dbalatero@yahoo.com'
282
+ end
283
+ end
284
+
285
+ describe "yahoo?" do
286
+ it "should be true for Yahoo responses" do
287
+ @user.yahoo?.should be_true
288
+ end
289
+ end
290
+
291
+ describe "credentials" do
292
+ it "should be nil" do
293
+ @user.credentials.should be_nil
294
+ end
295
+ end
296
+
297
+ describe 'provider_name' do
298
+ it 'should be Yahoo' do
299
+ @user.provider_name.should == 'Yahoo!'
300
+ end
301
+ end
302
+ end
303
+ end
@@ -0,0 +1,7 @@
1
+ {
2
+ "stat": "ok",
3
+ "identifiers": [
4
+ "http:\/\/brian.myopenid.com\/",
5
+ "http:\/\/brianellin.com\/"
6
+ ]
7
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "stat": "ok"
3
+ }