File Coverage

blib/lib/Gcis/Client.pm
Criterion Covered Total %
statement 27 185 14.5
branch 0 108 0.0
condition 0 21 0.0
subroutine 9 25 36.0
pod 8 16 50.0
total 44 355 12.3


line stmt bran cond sub pod time code
1             package Gcis::Client;
2 3     3   31637 use Mojo::UserAgent;
  3         697022  
  3         34  
3 3     3   120 use Mojo::Base -base;
  3         4  
  3         16  
4 3     3   2208 use Mojo::Log;
  3         5487  
  3         28  
5 3     3   1977 use JSON::XS;
  3         12903  
  3         172  
6 3     3   1216 use YAML::XS qw/LoadFile/;
  3         6278  
  3         157  
7 3     3   1307 use Path::Class qw/file/;
  3         71528  
  3         166  
8 3     3   20 use Data::Dumper;
  3         4  
  3         139  
9 3     3   13 use Time::HiRes qw/sleep/;
  3         5  
  3         25  
10 3     3   341 use v5.14;
  3         8  
  3         6622  
11              
12             our $VERSION = '0.10';
13              
14             has url => 'http://localhost:3000';
15             has 'key';
16             has 'error';
17             has 'delay' => $ENV{GCIS_API_DELAY};
18             has ua => sub {
19             my $c = shift;
20             state $ua;
21             return $ua if $ua;
22             $ua = Mojo::UserAgent->new();
23             $ua->on(
24             start => sub {
25             my ($ua, $tx) = @_;
26             $tx->req->headers->header($c->auth_hdr) if $c->auth_hdr;
27             $tx->req->headers->header(Accept => $c->accept);
28             }
29             );
30             $ua->max_redirects(5);
31             $ua;
32             };
33             has logger => sub { state $log ||= Mojo::Log->new(); };
34             has json => sub { state $json ||= JSON::XS->new(); };
35             has accept => "application/json";
36             has 'tx';
37              
38 0 0   0 0   sub auth_hdr { ($a = shift->key) ? ("Authorization" => "Basic $a") : () }
39              
40             sub get {
41 0     0 1   my $s = shift;
42 0 0         my $path = shift or die "missing path";
43 0           my $params = shift;
44 0 0         if (defined($s->delay)) {
45 0           $s->logger->debug("sleeping for ".$s->delay.'s');
46 0           sleep $s->delay;
47             }
48 0           my $url;
49 0 0         if ($params) {
50 0           $url = Mojo::URL->new($s->url);
51 0           $url->path($path);
52 0           $url->query(%$params);
53             } else {
54 0           $url = Mojo::URL->new($s->url.$path);
55             }
56 0           my $tx = $s->ua->get($url);
57 0           $s->tx($tx);
58 0           my $res = $tx->success;
59 0 0         unless ($res) {
60 0 0 0       if ($tx->res->code && $tx->res->code == 404) {
61             # $s->logger->debug("not found : $path");
62 0           $s->error("not found : $path");
63 0           return;
64             }
65 0           $s->error($tx->error->{message});
66 0           $s->logger->error($tx->error->{message});
67 0           return;
68             };
69 0 0         my $json = $res->json or do {
70 0           $s->logger->debug("no json from $path : ".$res->to_string);
71 0           $s->error("No JSON returned from $path : ".$res->to_string);
72 0           return;
73             };
74 0 0 0       return wantarray && ref($json) eq 'ARRAY' ? @$json : $json;
75             }
76              
77             sub post {
78 0     0 0   my $s = shift;
79 0 0         my $path = shift or Carp::confess "missing path";
80 0           my $data = shift;
81 0           my $tx = $s->ua->post($s->url."$path" => json => $data );
82 0           $s->tx($tx);
83 0 0         my $res = $tx->success or do {
84 0           $s->logger->error("got an error $path : ".Dumper($tx->error->{message}).$tx->res->body);
85 0           return;
86             };
87 0 0         return unless $res;
88 0 0         my $json = $res->json or return $res->body;
89 0           return $res->json;
90             }
91              
92             sub delete {
93 0     0 0   my $s = shift;
94 0           my $path = shift;
95 0           my $tx = $s->ua->delete($s->url."$path");
96 0           $s->tx($tx);
97 0           my $res = $tx->success;
98 0 0         unless ($res) {
99 0 0 0       if ($tx->res->code && $tx->res->code == 404) {
100 0           $s->error("not found : $path");
101 0           return;
102             }
103 0           $s->error($tx->error->{message});
104 0           $s->logger->error($tx->error->{message});
105 0           return;
106             };
107 0           return $res->body;
108             }
109              
110             sub put_file {
111 0     0 1   my $s = shift;
112 0           my $path = shift;
113 0           my $file = shift;
114 0           my $data = file($file)->slurp;
115 0           my $tx = $s->ua->put($s->url."$path" => $data );
116 0           $s->tx($tx);
117 0 0         my $res = $tx->success or do {
118 0           $s->error(join "\n",$tx->error->{message},$tx->res->body);
119 0           $s->logger->error($path." : ".$tx->error->{message});
120 0           $s->logger->error($tx->res->body);
121 0           return;
122             };
123 0 0         return unless $res;
124 0 0         my $json = $res->json or return $res->body;
125 0           return $res->json;
126             }
127              
128             sub add_file_url {
129 0     0 1   my $s = shift;
130 0           my $gcid = shift;
131 0           my $args = shift;
132 0           my $path = $gcid;
133 0           $path =~ s[/([^/]+)$][/files/$1];
134 0           $s->post($path => $args);
135             }
136              
137             sub post_quiet {
138 0     0 0   my $s = shift;
139 0           my $path = shift;
140 0           my $data = shift;
141 0           my $tx = $s->ua->post($s->url."$path" => json => $data );
142 0           $s->tx($tx);
143 0 0         my $res = $tx->success or do {
144 0 0         $s->logger->error("$path : ".$tx->error.$tx->res->body) unless $tx->res->code == 404;
145 0           return;
146             };
147 0 0         return unless $res;
148 0 0         my $json = $res->json or return $res->body;
149 0           return $res->json;
150             }
151              
152             sub find_credentials {
153 0     0 1   my $s = shift;
154 0           my $home = $ENV{HOME};
155 0 0         die "need url to find credentials" unless $s->url;
156 0           my $conf_file = "$home/etc/Gcis.conf";
157 0 0         -e $conf_file or die "Missing $conf_file";
158 0           my $conf = LoadFile($conf_file);
159 0           my @found = grep { $_->{url} eq $s->url } @$conf;
  0            
160 0 0         die "Multiple matches for ".$s->url." in $conf_file." if @found > 1;
161 0 0         die "No matches for ".$s->url." in $conf_file." if @found < 1;
162 0 0         my $key = $found[0]->{key} or die "no key for ".$s->url." in $conf_file";
163 0           $s->logger->info("Loaded configuration from $conf_file");
164 0           $s->key($key);
165 0           return $s;
166             }
167              
168             sub login {
169 0     0 1   my $c = shift;
170 0 0         my $got = $c->get('/login') or return;
171 0 0         $c->get('/login')->{login} eq 'ok' or return;
172 0           return $c;
173             }
174              
175             sub use_env {
176 0     0 1   my $c = shift;
177 0 0         my $url = $ENV{GCIS_API_URL} or die "please set GCIS_API_URL";
178 0           $c->url($url);
179 0           return $c;
180             }
181              
182             sub get_chapter_map {
183 0     0 1   my $c = shift;
184 0 0         my $report = shift or die "no report";
185 0 0         my $all = $c->get("/report/$report/chapter?all=1") or die $c->url.' : '.$c->error;
186 0   0       my %map = map { $_->{number} // $_->{identifier} => $_->{identifier} } @$all;
  0            
187 0 0         return wantarray ? %map : \%map;
188             }
189              
190             sub tables {
191 0     0 0   my $c = shift;
192 0           my %a = @_;
193 0 0         my $report = $a{report} or die "no report";
194 0 0         if (my $chapter_number = $a{chapter_number}) {
195 0   0       $c->{_chapter_map}->{$report} //= $c->get_chapter_map($report);
196 0           $a{chapter} = $c->{_chapter_map}->{$report}->{$chapter_number};
197             }
198 0           my $tables;
199 0 0         if (my $chapter = $a{chapter}) {
200 0 0         $tables = $c->get("/report/$report/chapter/$chapter/table?all=1") or die $c->error;
201             } else {
202 0 0         $tables = $c->get("/report/$report/table?all=1") or die $c->error;
203             }
204 0 0         return wantarray ? @$tables : $tables;
205             }
206              
207             sub figures {
208 0     0 0   my $c = shift;
209 0           my %a = @_;
210 0 0         my $report = $a{report} or die "no report";
211 0 0         if (my $chapter_number = $a{chapter_number}) {
212 0   0       $c->{_chapter_map}->{$report} //= $c->get_chapter_map($report);
213 0           $a{chapter} = $c->{_chapter_map}->{$report}->{$chapter_number};
214             }
215 0           my $figures;
216 0 0         if (my $chapter = $a{chapter}) {
217 0 0         $figures = $c->get("/report/$report/chapter/$chapter/figure?all=1") or die $c->error;
218             } else {
219 0 0         $figures = $c->get("/report/$report/figure?all=1") or die $c->error;
220             }
221 0 0         return wantarray ? @$figures : $figures;
222             }
223              
224             sub findings {
225 0     0 0   my $c = shift;
226 0           my %a = @_;
227 0 0         my $report = $a{report} or die "no report";
228 0 0         if (my $chapter_number = $a{chapter_number}) {
229 0   0       $c->{_chapter_map}->{$report} //= $c->get_chapter_map($report);
230 0           $a{chapter} = $c->{_chapter_map}->{$report}->{$chapter_number};
231             }
232 0           my $findings;
233 0 0         if (my $chapter = $a{chapter}) {
234 0 0         $findings = $c->get("/report/$report/chapter/$chapter/finding?all=1") or die $c->error;
235             } else {
236 0 0         $findings = $c->get("/report/$report/finding?all=1") or die $c->error;
237             }
238 0 0         return wantarray ? @$findings : $findings;
239             }
240              
241             sub get_form {
242 0     0 0   my $c = shift;
243 0           my $obj = shift;
244 0 0         my $uri = $obj->{uri} or die "no uri in ".Dumper($obj);
245 0 0         if ($uri =~ m[/article]) {
246 0           $uri =~ s[article][article/form/update];
247             } else {
248             # The last backslash becomes /form/update
249 0           $uri =~ s[/([^/]+)$][/form/update/$1];
250             }
251 0           return $c->get($uri);
252             }
253              
254             sub connect {
255 0     0 1   my $class = shift;
256 0           my %args = @_;
257              
258 0 0         my $url = $args{url} or die "missing url";
259 0           my $c = $class->new;
260 0           $c->url($url);
261 0 0         $c->find_credentials->login or die "Failed to log in to $url";
262 0           return $c;
263             }
264              
265             1;
266              
267             __END__