File Coverage

lib/Net/API/RPX.pm
Criterion Covered Total %
statement 64 64 100.0
branch 16 16 100.0
condition n/a
subroutine 17 17 100.0
pod 4 4 100.0
total 101 101 100.0


line stmt bran cond sub pod time code
1 3     3   23786 use 5.006;
  3         6  
  3         79  
2 3     3   10 use strict;
  3         4  
  3         62  
3 3     3   7 use warnings;
  3         2  
  3         128  
4              
5             package Net::API::RPX;
6              
7             # ABSTRACT: Perl interface to Janrain's RPX service
8              
9             our $VERSION = '1.000000';
10              
11             our $AUTHORITY = 'cpan:KONOBI'; # AUTHORITY
12              
13 3     3   1211 use Moose qw( has );
  3         899616  
  3         27  
14 3     3   13095 use LWP::UserAgent;
  3         38459  
  3         62  
15 3     3   1124 use URI;
  3         5816  
  3         70  
16 3     3   1129 use JSON::MaybeXS qw( decode_json );
  3         4386  
  3         134  
17 3     3   1024 use Net::API::RPX::Exception::Usage;
  3         9  
  3         116  
18 3     3   1310 use Net::API::RPX::Exception::Network;
  3         8  
  3         102  
19 3     3   1309 use Net::API::RPX::Exception::Service;
  3         9  
  3         369  
20              
21              
22              
23              
24              
25              
26              
27              
28             has api_key => (
29             is => 'rw',
30             isa => 'Str',
31             required => 1,
32             );
33              
34              
35              
36              
37              
38              
39              
40             has base_url => (
41             is => 'rw',
42             isa => 'Str',
43             required => 1,
44             lazy => 1,
45             default => 'https://rpxnow.com/api/v2/',
46             );
47              
48              
49              
50              
51              
52              
53              
54              
55             has ua => (
56             is => 'rw',
57             isa => 'Object',
58             required => 1,
59             lazy => 1,
60             builder => '_build_ua',
61             );
62              
63             sub _build_ua {
64 13     13   21 my ($self) = @_;
65 13         280 return LWP::UserAgent->new( agent => $self->_agent_string );
66             }
67              
68             has _agent_string => (
69             is => 'rw',
70             isa => 'Str',
71             required => 1,
72             lazy => 1,
73             default => sub { 'net-api-rpx-perl/' . $Net::API::RPX::VERSION },
74             );
75              
76             __PACKAGE__->meta->make_immutable;
77 3     3   21 no Moose;
  3         3  
  3         24  
78              
79              
80              
81              
82              
83              
84              
85              
86              
87              
88              
89              
90             sub auth_info {
91 8     8 1 946 my ( $self, $opts ) = @_;
92 8 100       50 Net::API::RPX::Exception::Usage->throw(
93             ident => 'auth_info_usage_needs_token',
94             message => 'Token is required',
95             required_parameter => 'token',
96             method_name => '->auth_info',
97             package => __PACKAGE__,
98             signature => '{ token => \'authtoken\' }',
99             ) if !exists $opts->{token};
100 6         18 return $self->_fetch( 'auth_info', $opts );
101             }
102              
103              
104              
105              
106              
107              
108              
109              
110              
111              
112              
113             sub map { ## no critic (Subroutines::ProhibitBuiltinHomonyms)
114 6     6 1 838 my ( $self, $opts ) = @_;
115 6 100       43 Net::API::RPX::Exception::Usage->throw(
116             ident => 'map_usage_needs_identifier',
117             message => 'Identifier is required',
118             required_parameter => 'identifier',
119             method_name => '->map',
120             package => __PACKAGE__,
121             signature => '{ identifier => \'some.open.id\', primary_key => 12 }',
122             ) if !exists $opts->{identifier};
123              
124 4 100       29 Net::API::RPX::Exception::Usage->throw(
125             ident => 'map_usage_needs_primary_key',
126             message => 'Primary Key is required',
127             required_parameter => 'primary_key',
128             method_name => '->map',
129             package => __PACKAGE__,
130             signature => '{ identifier => \'some.open.id\', primary_key => 12 }',
131             ) if !exists $opts->{primary_key};
132 2         7 $opts->{primaryKey} = delete $opts->{primary_key};
133              
134 2         10 return $self->_fetch( 'map', $opts );
135             }
136              
137              
138              
139              
140              
141              
142              
143              
144              
145              
146              
147             sub unmap {
148 6     6 1 700 my ( $self, $opts ) = @_;
149 6 100       36 Net::API::RPX::Exception::Usage->throw(
150             ident => 'unmap_usage_needs_identifier',
151             message => 'Identifier is required',
152             required_parameter => 'identifier',
153             method_name => '->unmap',
154             package => __PACKAGE__,
155             signature => '{ identifier => \'some.open.id\', primary_key => 12 }',
156             ) if !exists $opts->{identifier};
157              
158 4 100       22 Net::API::RPX::Exception::Usage->throw(
159             ident => 'unmap_usage_needs_primay_key',
160             message => 'Primary Key is required',
161             required_parameter => 'primary_key',
162             method_name => '->unmap',
163             package => __PACKAGE__,
164             signature => '{ identifier => \'some.open.id\', primary_key => 12 }',
165             ) if !exists $opts->{primary_key};
166              
167 2         5 $opts->{primaryKey} = delete $opts->{primary_key};
168              
169 2         10 return $self->_fetch( 'unmap', $opts );
170             }
171              
172              
173              
174              
175              
176              
177              
178              
179              
180              
181              
182             sub mappings {
183 4     4 1 702 my ( $self, $opts ) = @_;
184 4 100       28 Net::API::RPX::Exception::Usage->throw(
185             ident => 'mappings_usage_needs_primary_key',
186             message => 'Primary Key is required',
187             required_parameter => 'primary_key',
188             method_name => '->mappings',
189             package => __PACKAGE__,
190             signature => '{ primary_key => 12 }',
191             ) if !exists $opts->{primary_key};
192              
193 2         6 $opts->{primaryKey} = delete $opts->{primary_key};
194              
195 2         8 return $self->_fetch( 'mappings', $opts );
196             }
197              
198             my $rpx_errors = {
199             -1 => 'Service Temporarily Unavailable',
200             0 => 'Missing parameter',
201             1 => 'Invalid parameter',
202             2 => 'Data not found',
203             3 => 'Authentication error',
204             4 => 'Facebook Error',
205             5 => 'Mapping exists',
206             };
207              
208             sub _fetch {
209 12     12   22 my ( $self, $uri_part, $opts ) = @_;
210              
211 12         300 my $uri = URI->new( $self->base_url . $uri_part );
212 12         276 my $res = $self->ua->post(
213             $uri => {
214 12         11276 %{$opts},
215             apiKey => $self->api_key,
216             format => 'json',
217             },
218             );
219              
220 12 100       301 if ( !$res->is_success ) {
221 2         13 Net::API::RPX::Exception::Network->throw(
222             ident => '_fetch_network_failure',
223             message => 'Could not contact RPX: ' . $res->status_line(),
224             ua_result => $res,
225             status_line => $res->status_line,
226             );
227             }
228              
229 10         59 my $result = decode_json( $res->content );
230 10 100       130 if ( $result->{'stat'} ne 'ok' ) {
231 2         4 my $err = $result->{'err'};
232 2         41 Net::API::RPX::Exception::Service->throw(
233             ident => '_fetch_service_error',
234             data => $result,
235             status => $result->{'stat'},
236             rpx_error => $result->{'err'},
237             rpx_error_code => $result->{err}->{code},
238             rpx_error_message => $result->{err}->{msg},
239             message => 'RPX returned error of type \'' . $rpx_errors->{ $err->{code} } . '\' with message: ' . $err->{msg},
240             );
241             }
242 8         17 delete $result->{'stat'};
243 8         47 return $result;
244             }
245              
246             1; # End of Net::API::RPX
247              
248             __END__
249              
250             =pod
251              
252             =encoding UTF-8
253              
254             =head1 NAME
255              
256             Net::API::RPX - Perl interface to Janrain's RPX service
257              
258             =head1 VERSION
259              
260             version 1.000000
261              
262             =head1 SYNOPSIS
263              
264             use Net::API::RPX;
265              
266             my $rpx = Net::API::RPX->new({ api_key => '<your_api_key_here>' });
267              
268             $rpx->auth_info({ token => $token });
269              
270             =head1 DESCRIPTION
271              
272             This module is a simple wrapper around Janrain's RPX service. RPX provides a single method for
273             dealing with third-party authentication.
274              
275             See L<http://www.rpxnow.com> for more details.
276              
277             For specific information regarding the RPX API and method arguments, please refer to
278             L<https://rpxnow.com/docs>.
279              
280             =head1 METHODS
281              
282             =head2 C<auth_info>
283              
284             my $user_data = $rpx->auth_info({ token => $params{token} });
285              
286             Upon redirection back from RPX, you will be supplied a token to use for verification. Call
287             auth_info to verify the authenticity of the token and gain user details.
288              
289             'token' argument is required, 'extended' argument is optional.
290              
291             =head2 C<map>
292              
293             $rpx->map({ identifier => 'yet.another.open.id', primary_key => 12 });
294              
295             This method allows you to map more than one 'identifier' to a user.
296              
297             'identifier' argument is required, 'primary_key' argument is required, 'overwrite' is optional.
298              
299             =head2 C<unmap>
300              
301             $rpx->unmap({ identifier => 'yet.another.open.id', primary_key => 12 });
302              
303             This is the inverse of 'map'.
304              
305             'identifier' argument is required, 'primary_key' argument is required.
306              
307             =head2 C<mappings>
308              
309             my $data = $rpx->mappings({ primary_key => 12 });
310              
311             This method returns information about the identifiers associated with a user.
312              
313             'primary_key' argument is required.
314              
315             =head1 ATTRIBUTES
316              
317             =head2 C<api_key>
318              
319             This is the api_key provided by Janrain to interface with RPX. You will need to sign up to RPX
320             to get one of these.
321              
322             =head2 C<base_url>
323              
324             This is the base URL that is used to make API calls against. It defaults to the RPX v2 API.
325              
326             =head2 C<ua>
327              
328             This is a LWP::UserAgent object. You may override it if you require more fine grain control
329             over remote queries.
330              
331             =head1 TEST COVERAGE
332              
333             This distribution is heavily unit and system tested for compatibility with
334             L<< <Test::Builder>|Test::Builder >>. If you come across any bugs, please send me or
335             submit failing tests to Net-API-RPX RT queue. Please see the 'SUPPORT' section below on
336             how to supply these.
337              
338             ---------------------------- ------ ------ ------ ------ ------ ------ ------
339             File stmt bran cond sub pod time total
340             ---------------------------- ------ ------ ------ ------ ------ ------ ------
341             blib/lib/Net/API/RPX.pm 100.0 100.0 n/a 100.0 100.0 100.0 100.0
342             Total 100.0 100.0 n/a 100.0 100.0 100.0 100.0
343             ---------------------------- ------ ------ ------ ------ ------ ------ ------
344              
345             =head1 SEE ALSO
346              
347             L<http://www.janrain.com/>, L<http://www.rpxnow.com/>
348              
349             =head1 AUTHORS
350              
351             =over 4
352              
353             =item *
354              
355             Scott McWhirter <konobi@cpan.org>
356              
357             =item *
358              
359             Kent Fredric <kentnl@cpan.org>
360              
361             =back
362              
363             =head1 COPYRIGHT AND LICENSE
364              
365             This software is Copyright (c) 2015 by Cloudtone Studios.
366              
367             This is free software, licensed under:
368              
369             The (three-clause) BSD License
370              
371             =cut