File Coverage

blib/lib/WebService/IdoitAPI.pm
Criterion Covered Total %
statement 70 113 61.9
branch 23 50 46.0
condition n/a
subroutine 11 14 78.5
pod 6 6 100.0
total 110 183 60.1


line stmt bran cond sub pod time code
1             # vim: set sw=4 ts=4 et si ai:
2             #
3             package WebService::IdoitAPI;
4              
5 4     4   239887 use 5.006;
  4         37  
6 4     4   27 use strict;
  4         12  
  4         94  
7 4     4   23 use warnings;
  4         5  
  4         118  
8              
9 4     4   22 use Carp;
  4         7  
  4         279  
10 4     4   2051 use JSON::RPC::Legacy::Client;
  4         267779  
  4         5354  
11              
12             our $VERSION = 'v0.2.2';
13              
14             my @CONFIG_VARS = qw(apikey password url username);
15              
16             sub new {
17 5     5 1 2003753 my ($class,$config) = @_;
18 5         129 my $self = {
19             config => {},
20             version => '2.0',
21             };
22              
23 5         52 bless($self, $class);
24 5 50       63 if (defined $config) {
25 5         72 for my $cv (@CONFIG_VARS) {
26 20 100       123 if (exists $config->{$cv}) {
27 6         72 $self->{config}->{$cv} = $config->{$cv};
28             }
29             }
30 5         44 $self->_test_minimum_config();
31             }
32 2         26 return $self;
33             } # new()
34              
35             sub DESTROY {
36 5     5   4230 my $self = shift;
37              
38 5 50       16 if ($self->is_logged_in()) {
39 0         0 $self->logout();
40             }
41 5         33 return;
42             } # DESTROY()
43              
44             sub request {
45 1     1 1 445 my ($self,$request) = @_;
46 1 50       31 if (defined $request) {
47 1         22 my $client;
48 1 50       23 if (exists $self->{client}) {
49 0         0 $client = $self->{client};
50             }
51             else {
52 1         209 $client = new JSON::RPC::Legacy::Client;
53 1         10881 $self->{client} = $client;
54 1 50       9 if ($self->{session_id}) {
55 0         0 $client->{ua}->default_header('X-RPC-Auth-Session' => $self->{session_id});
56             }
57             else {
58 1 50       35 if (defined $self->{config}->{password}) {
59 0         0 $client->{ua}->default_header( 'X-RPC-Auth-Password' => $self->{config}->{password} );
60             }
61 1 50       41 if (defined $self->{config}->{username}) {
62 0         0 $client->{ua}->default_header( 'X-RPC-Auth-Username' => $self->{config}->{username} );
63             }
64             }
65             }
66             $request->{version} = "2.0"
67 1 50       8 unless (defined $request->{version});
68             $request->{id} = 1
69 1 50       15 unless (defined $request->{id});
70             $request->{params}->{language} = 'en'
71 1 50       32 unless (defined $request->{params}->{language});
72 1         4 $request->{params}->{apikey} = $self->{config}->{apikey};
73              
74 1         2 my $res = do {
75 1         3 local $@;
76 1         17 my $ret;
77 1         5 eval { $ret = $client->call($self->{config}->{url},$request); 1};
  1         18  
  0         0  
78 1 50       18173 if ( $@ ) {
79 1         4 my $status_line = $self->{client}->{status_line};
80 1 50       38 if ( $status_line !~ /^2[0-9]{2} / ) {
81 1         13 die "Connection problem: $status_line";
82             }
83 0         0 die "JSON RPC client failed: $@";
84             }
85 0         0 $ret;
86             };
87 0         0 return $res;
88             }
89 0         0 return;
90             } # request()
91              
92             sub login {
93 0     0 1 0 my ($self,$user,$pass) = @_;
94              
95 0 0       0 $user = $self->{config}->{username} unless ($user);
96 0 0       0 $pass = $self->{config}->{password} unless ($pass);
97              
98 0         0 my $client = new JSON::RPC::Legacy::Client;
99 0         0 $client->{ua}->default_header( 'X-RPC-Auth-Password' => $pass );
100 0         0 $client->{ua}->default_header( 'X-RPC-Auth-Username' => $user );
101 0         0 $self->{client} = $client;
102              
103 0         0 my $res = $self->request( { method => 'idoit.login' } );
104 0 0       0 if ($res->{is_success}) {
105 0         0 my $h = $self->{client}->{ua}->default_headers();
106 0         0 $h->header('X-RPC-Auth-Session' => $res->{content}->{result}->{'session-id'});
107 0         0 $h->remove_header('X-RPC-Auth-Username');
108 0         0 $h->remove_header('X-RPC-Auth-Password');
109 0         0 $self->{session_id} = $res->{content}->{result}->{'session-id'};
110 0         0 return $res;
111             }
112 0         0 return;
113             } # login()
114              
115             sub logout {
116 0     0 1 0 my $self = shift;
117              
118 0         0 my $res = $self->request( { method => 'idoit.login' } );
119 0         0 delete $self->{session_id};
120 0         0 delete $self->{client}; # grab a fresh client next time
121 0         0 return $res;
122             } # logout()
123              
124             sub is_logged_in {
125 5     5 1 18 return exists $_[0]->{session_id};
126             } # is_logged_in()
127              
128             sub read_config {
129 0     0 1 0 my $fname = shift;
130              
131 0         0 my $known_paths = [ # some known paths of other configuration files
132             "$ENV{HOME}/.idoitcli/config.json",
133             ];
134              
135 0 0       0 unless ( $fname ) {
136 0         0 for ( @$known_paths ) {
137 0 0       0 if ( -r $_ ) {
138 0         0 $fname = $_;
139 0         0 last;
140             }
141             }
142             }
143 0 0       0 open(my $fh, '<', $fname)
144             or die "Can't open config file '$fname': $!";
145              
146 0         0 my $config = _read_config_fh($fh);
147              
148 0         0 close($fh);
149              
150 0         0 $config->{config_file} = $fname;
151              
152 0         0 return $config;
153             } # read_config()
154              
155             sub _read_config_fh {
156 3     3   3604 my $fh = shift;
157              
158 3         11 my $config = {};
159 3         7 my %valid = map { $_ => 1 } qw(
  15         32  
160             apikey key password url username
161             );
162              
163 3         15 while (<$fh>) {
164 15 50       698 if ( /^\s*(\S[^:=]+)[:=]\s*(\S.+)$/ ) {
165 15         40 my ($key, $val) = ($1, $2);
166 15         30 for ($key, $val) {
167 30         82 s/\s+$//;
168 30         60 s/[,;]$//;
169 30         66 s/^"(.*)"$/$1/;
170 30         66 s/^'(.*)'$/$1/;
171             }
172 15 50       37 next unless ( $valid{$key} );
173 15         48 $config->{$key} = $val;
174             }
175             }
176              
177 3 50       118 $config->{apikey} = $config->{key} unless ( exists $config->{apikey} );
178 3 100       9 unless ( $config->{url} =~ m|/src/jsonrpc[.]php$| ) {
179 2         20 $config->{url} =~ s#/?$#/src/jsonrpc.php#;
180             }
181              
182 3         32 return $config;
183             } # _read_config_fh()
184              
185             sub _test_minimum_config {
186 5     5   41 my $self = shift;
187             croak "configuration is missing the API key"
188 5 100       102 unless ( $self->{config}->{apikey} );
189             croak "configuration is missing the URL for the API"
190 3 100       35 unless ( $self->{config}->{url} );
191             } # _test_minimum_config()
192              
193             1; # End of WebService::IdoitAPI
194              
195             __DATA__