File Coverage

blib/lib/Gcis/Client.pm
Criterion Covered Total %
statement 27 186 14.5
branch 0 110 0.0
condition 0 21 0.0
subroutine 9 25 36.0
pod 9 16 56.2
total 45 358 12.5


line stmt bran cond sub pod time code
1             package Gcis::Client;
2 3     3   37068 use Mojo::UserAgent;
  3         4844052  
  3         40  
3 3     3   144 use Mojo::Base -base;
  3         3  
  3         18  
4 3     3   2542 use Mojo::Log;
  3         4290  
  3         42  
5 3     3   2355 use JSON::XS;
  3         15824  
  3         281  
6 3     3   1495 use YAML::XS qw/LoadFile/;
  3         7870  
  3         246  
7 3     3   1762 use Path::Class qw/file/;
  3         2474582  
  3         179  
8 3     3   21 use Data::Dumper;
  3         4  
  3         133  
9 3     3   12 use Time::HiRes qw/sleep/;
  3         4  
  3         24  
10 3     3   398 use v5.14;
  3         8  
  3         6782  
11              
12             our $VERSION = '0.12';
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 1   my $s = shift;
94 0           my $path = shift;
95 0           my $payload = shift;
96 0 0         my $tx = $s->ua->delete($s->url."$path", ( $payload ? (json => $payload) : () ) );
97 0           $s->tx($tx);
98 0           my $res = $tx->success;
99 0 0         unless ($res) {
100 0 0 0       if ($tx->res->code && $tx->res->code == 404) {
101 0           $s->error("not found : $path");
102 0           return;
103             }
104 0           $s->error($tx->error->{message});
105 0           $s->logger->error($tx->error->{message});
106 0           return;
107             };
108 0           return $res->body;
109             }
110              
111             sub put_file {
112 0     0 1   my $s = shift;
113 0           my $path = shift;
114 0           my $file = shift;
115 0           my $data = file($file)->slurp;
116 0           my $tx = $s->ua->put($s->url."$path" => $data );
117 0           $s->tx($tx);
118 0 0         my $res = $tx->success or do {
119 0           $s->error(join "\n",$tx->error->{message},$tx->res->body);
120 0           $s->logger->error($path." : ".$tx->error->{message});
121 0           $s->logger->error($tx->res->body);
122 0           return;
123             };
124 0 0         return unless $res;
125 0 0         my $json = $res->json or return $res->body;
126 0           return $res->json;
127             }
128              
129             sub add_file_url {
130 0     0 1   my $s = shift;
131 0           my $gcid = shift;
132 0           my $args = shift;
133 0           my $path = $gcid;
134 0           $path =~ s[/([^/]+)$][/files/$1];
135 0           $s->post($path => $args);
136             }
137              
138             sub post_quiet {
139 0     0 0   my $s = shift;
140 0           my $path = shift;
141 0           my $data = shift;
142 0           my $tx = $s->ua->post($s->url."$path" => json => $data );
143 0           $s->tx($tx);
144 0 0         my $res = $tx->success or do {
145 0 0         $s->logger->error("$path : ".$tx->error.$tx->res->body) unless $tx->res->code == 404;
146 0           return;
147             };
148 0 0         return unless $res;
149 0 0         my $json = $res->json or return $res->body;
150 0           return $res->json;
151             }
152              
153             sub find_credentials {
154 0     0 1   my $s = shift;
155 0           my $home = $ENV{HOME};
156 0 0         die "need url to find credentials" unless $s->url;
157 0           my $conf_file = "$home/etc/Gcis.conf";
158 0 0         -e $conf_file or die "Missing $conf_file";
159 0           my $conf = LoadFile($conf_file);
160 0           my @found = grep { $_->{url} eq $s->url } @$conf;
  0            
161 0 0         die "Multiple matches for ".$s->url." in $conf_file." if @found > 1;
162 0 0         die "No matches for ".$s->url." in $conf_file." if @found < 1;
163 0 0         my $key = $found[0]->{key} or die "no key for ".$s->url." in $conf_file";
164 0           $s->logger->info("Loaded configuration from $conf_file");
165 0           $s->key($key);
166 0           return $s;
167             }
168              
169             sub login {
170 0     0 1   my $c = shift;
171 0 0         my $got = $c->get('/login') or return;
172 0 0         $c->get('/login')->{login} eq 'ok' or return;
173 0           return $c;
174             }
175              
176             sub use_env {
177 0     0 1   my $c = shift;
178 0 0         my $url = $ENV{GCIS_API_URL} or die "please set GCIS_API_URL";
179 0           $c->url($url);
180 0           return $c;
181             }
182              
183             sub get_chapter_map {
184 0     0 1   my $c = shift;
185 0 0         my $report = shift or die "no report";
186 0 0         my $all = $c->get("/report/$report/chapter?all=1") or die $c->url.' : '.$c->error;
187 0   0       my %map = map { $_->{number} // $_->{identifier} => $_->{identifier} } @$all;
  0            
188 0 0         return wantarray ? %map : \%map;
189             }
190              
191             sub tables {
192 0     0 0   my $c = shift;
193 0           my %a = @_;
194 0 0         my $report = $a{report} or die "no report";
195 0 0         if (my $chapter_number = $a{chapter_number}) {
196 0   0       $c->{_chapter_map}->{$report} //= $c->get_chapter_map($report);
197 0           $a{chapter} = $c->{_chapter_map}->{$report}->{$chapter_number};
198             }
199 0           my $tables;
200 0 0         if (my $chapter = $a{chapter}) {
201 0 0         $tables = $c->get("/report/$report/chapter/$chapter/table?all=1") or die $c->error;
202             } else {
203 0 0         $tables = $c->get("/report/$report/table?all=1") or die $c->error;
204             }
205 0 0         return wantarray ? @$tables : $tables;
206             }
207              
208             sub figures {
209 0     0 0   my $c = shift;
210 0           my %a = @_;
211 0 0         my $report = $a{report} or die "no report";
212 0 0         if (my $chapter_number = $a{chapter_number}) {
213 0   0       $c->{_chapter_map}->{$report} //= $c->get_chapter_map($report);
214 0           $a{chapter} = $c->{_chapter_map}->{$report}->{$chapter_number};
215             }
216 0           my $figures;
217 0 0         if (my $chapter = $a{chapter}) {
218 0 0         $figures = $c->get("/report/$report/chapter/$chapter/figure?all=1") or die $c->error;
219             } else {
220 0 0         $figures = $c->get("/report/$report/figure?all=1") or die $c->error;
221             }
222 0 0         return wantarray ? @$figures : $figures;
223             }
224              
225             sub findings {
226 0     0 0   my $c = shift;
227 0           my %a = @_;
228 0 0         my $report = $a{report} or die "no report";
229 0 0         if (my $chapter_number = $a{chapter_number}) {
230 0   0       $c->{_chapter_map}->{$report} //= $c->get_chapter_map($report);
231 0           $a{chapter} = $c->{_chapter_map}->{$report}->{$chapter_number};
232             }
233 0           my $findings;
234 0 0         if (my $chapter = $a{chapter}) {
235 0 0         $findings = $c->get("/report/$report/chapter/$chapter/finding?all=1") or die $c->error;
236             } else {
237 0 0         $findings = $c->get("/report/$report/finding?all=1") or die $c->error;
238             }
239 0 0         return wantarray ? @$findings : $findings;
240             }
241              
242             sub get_form {
243 0     0 0   my $c = shift;
244 0           my $obj = shift;
245 0 0         my $uri = $obj->{uri} or die "no uri in ".Dumper($obj);
246 0 0         if ($uri =~ m[/article]) {
247 0           $uri =~ s[article][article/form/update];
248             } else {
249             # The last backslash becomes /form/update
250 0           $uri =~ s[/([^/]+)$][/form/update/$1];
251             }
252 0           return $c->get($uri);
253             }
254              
255             sub connect {
256 0     0 1   my $class = shift;
257 0           my %args = @_;
258              
259 0 0         my $url = $args{url} or die "missing url";
260 0           my $c = $class->new;
261 0           $c->url($url);
262 0 0         $c->find_credentials->login or die "Failed to log in to $url";
263 0           return $c;
264             }
265              
266             1;
267              
268             __END__