File Coverage

blib/lib/WebService/JugemKey/Auth.pm
Criterion Covered Total %
statement 9 9 100.0
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 12 12 100.0


line stmt bran cond sub pod time code
1             package WebService::JugemKey::Auth;
2              
3 2     2   42304 use strict;
  2         6  
  2         75  
4 2     2   11 use warnings;
  2         4  
  2         112  
5             our $VERSION = '0.04';
6              
7 2     2   12 use base qw (Class::Accessor::Fast Class::ErrorHandler);
  2         14  
  2         2464  
8              
9             use URI;
10             use LWP::UserAgent;
11             use Digest::HMAC;
12             use Digest::SHA1;
13             use DateTime;
14             use DateTime::Format::W3CDTF;
15             use Carp;
16             use XML::Atom::Entry;
17              
18             __PACKAGE__->mk_accessors(qw(api_key secret perms));
19              
20             my $jugemkey_url = 'https://secure.jugemkey.jp';
21             my $auth_api_url = 'http://api.jugemkey.jp/api/auth';
22              
23             sub uri_to_login {
24             my $self = shift;
25             my %params = ref $_[0] eq 'HASH' ? %{$_[0]} : @_;
26             my $uri = URI->new($jugemkey_url);
27              
28             my $callback_url = URI->new($params{callback_url});
29             delete($params{callback_url});
30             $callback_url->query_form( %params );
31              
32             my $request = {
33             api_key => $self->api_key,
34             perms => $self->perms,
35             callback_url => $callback_url->as_string,
36             };
37              
38             $uri->query_form(
39             api_sig => $self->api_sig($request),
40             mode => 'auth_issue_frob',
41             %$request,
42             );
43             return $uri;
44             }
45              
46             sub api_sig {
47             my ($self, $args) = @_;
48              
49             my $hmac = Digest::HMAC->new($self->secret, 'Digest::SHA1');
50             for my $key (sort {$a cmp $b} keys %{$args}) {
51             my $value = $args->{$key} ? $args->{$key} : '';
52             $hmac->add($value);
53             }
54             return $hmac->hexdigest;
55             }
56              
57             sub get_token {
58             my $self = shift;
59             my $frob = shift or croak "Invalid argumet (no frob)";
60              
61             my $created = DateTime::Format::W3CDTF->new->format_datetime(DateTime->now);
62             my $sig = $self->api_sig({
63             api_key => $self->api_key,
64             created => $created,
65             frob => $frob,
66             });
67              
68             my $req = HTTP::Request->new(GET => "$auth_api_url/token");
69             $req->header('X-JUGEMKEY-API-KEY', $self->api_key);
70             $req->header('X-JUGEMKEY-API-FROB', $frob);
71             $req->header('X-JUGEMKEY-API-CREATED', $created);
72             $req->header('X-JUGEMKEY-API-SIG', $sig);
73              
74             my $res = $self->ua->request($req);
75             return $self->error("Error on GET token: " . $self->_extract_error($res->content))
76             unless $res->code == 200;
77              
78             my $entry = XML::Atom::Entry->new(Stream => \$res->content);
79              
80             my $pp = XML::Atom::Namespace->new( auth => 'http://paperboy.co.jp/atom/auth#' );
81             return WebService::JugemKey::Auth::User->new({
82             name => $entry->title,
83             token => $entry->get($pp, 'token'),
84             });
85             }
86              
87             sub get_user {
88             my $self = shift;
89             my $token = shift or croak "Invalid argument (no token)";
90              
91             my $created = DateTime::Format::W3CDTF->new->format_datetime(DateTime->now);
92             my $sig = $self->api_sig({
93             api_key => $self->api_key,
94             created => $created,
95             token => $token,
96             });
97              
98             my $req = HTTP::Request->new(GET => "$auth_api_url/user");
99             $req->header('X-JUGEMKEY-API-KEY', $self->api_key);
100             $req->header('X-JUGEMKEY-API-TOKEN', $token);
101             $req->header('X-JUGEMKEY-API-CREATED', $created);
102             $req->header('X-JUGEMKEY-API-SIG', $sig);
103              
104             my $res = $self->ua->request($req);
105             return $self->error("Error on GET user: " . $self->_extract_error($res->content))
106             unless $res->code == 200;
107             my $entry = XML::Atom::Entry->new(Stream => \$res->content);
108              
109             return WebService::JugemKey::Auth::User->new({
110             name => $entry->title,
111             });
112             }
113              
114             sub ua {
115             my $self = shift;
116             if (@_) {
117             $self->{_ua} = shift;
118             } else {
119             $self->{_ua} and return $self->{_ua};
120             $self->{_ua} = LWP::UserAgent->new;
121             $self->{_ua}->agent(join '/', __PACKAGE__, __PACKAGE__->VERSION);
122             }
123             $self->{_ua};
124             }
125              
126             sub _extract_error {
127             my ($self, $error) = @_;
128              
129             while ($error =~ /([^<]*)<\/error>/g) {
130             return $1;
131             }
132             }
133              
134             package WebService::JugemKey::Auth::User;
135             use base qw(Class::Accessor::Fast);
136              
137             __PACKAGE__->mk_accessors(qw(name token));
138              
139              
140             1;
141             __END__