File Coverage

blib/lib/Modern/OpenAPI/Generator/CodeGen/Auth.pm
Criterion Covered Total %
statement 24 27 88.8
branch 1 4 25.0
condition 3 8 37.5
subroutine 7 8 87.5
pod 1 1 100.0
total 36 48 75.0


line stmt bran cond sub pod time code
1             package Modern::OpenAPI::Generator::CodeGen::Auth;
2              
3 6     6   83 use v5.26;
  6         19  
4 6     6   23 use strict;
  6         41  
  6         136  
5 6     6   44 use warnings;
  6         9  
  6         279  
6 6     6   24 use Carp qw(croak);
  6         9  
  6         2152  
7              
8             sub emit_plugins {
9 4     4 1 22 my ( $class, %arg ) = @_;
10 4   33     18 my $writer = $arg{writer} // croak 'writer';
11 4   33     15 my $base = $arg{base} // croak 'base';
12 4   50     16 my $sigs = $arg{signatures} // [];
13              
14 4         15 my $lib = 'lib/' . _pathify_dir($base);
15              
16 4         17 for my $sig (@$sigs) {
17 1 50       4 if ( $sig eq 'hmac' ) {
    0          
18 1         4 $writer->write( "$lib/Auth/Plugin/Hmac.pm", _hmac_pm("$base\::Auth::Plugin::Hmac") );
19             }
20             elsif ( $sig eq 'bearer' ) {
21 0         0 $writer->write( "$lib/Auth/Plugin/Bearer.pm", _bearer_pm("$base\::Auth::Plugin::Bearer") );
22             }
23             }
24             }
25              
26             sub _pathify_dir {
27 4     4   8 my ($name) = @_;
28 4         22 $name =~ s{::}{/}g;
29 4         10 return $name;
30             }
31              
32             sub _hmac_pm {
33 1     1   2 my ($pkg) = @_;
34 1         5 return <<"HEAD" . <<'BODY';
35             package $pkg;
36              
37             use v5.26;
38             use Modern::Perl::Prelude -class;
39              
40             use Moo;
41             use Carp qw(croak);
42             use Digest::SHA qw(sha256_hex hmac_sha256_hex);
43              
44             has api_secret => (
45             is => 'ro',
46             required => 0,
47             );
48              
49             HEAD
50             sub apply {
51             my ( $self, $tx, $meta ) = @_;
52             return unless $self->api_secret;
53              
54             my $req = $tx->req;
55             my $ts = time;
56             my $method = $req->method;
57             my $path = $req->url->path->to_string;
58             my $body = $req->body // '';
59             my $idem = $req->headers->header('Idempotency-Key') // '';
60             my $bh = sha256_hex($body);
61             my $canonical = join "\n", $ts, $method, $path, ( length $idem ? "$idem\n" : '' ), $bh;
62             my $sig = hmac_sha256_hex( $canonical, $self->api_secret );
63             $req->headers->header( 'X-Signature' => "t=$ts,v1=$sig" );
64             }
65              
66             1;
67              
68             =encoding utf8
69              
70             =head1 NAME
71              
72             HMAC request signing plugin (adjust canonical string for your API)
73              
74             =cut
75             BODY
76             }
77              
78             sub _bearer_pm {
79 0     0     my ($pkg) = @_;
80 0           return <<"HEAD" . <<'BODY';
81             package $pkg;
82              
83             use v5.26;
84             use Modern::Perl::Prelude -class;
85              
86             use Moo;
87              
88             has token => (
89             is => 'ro',
90             required => 0,
91             );
92              
93             HEAD
94             sub apply {
95             my ( $self, $tx, $meta ) = @_;
96             return unless my $t = $self->token;
97             $tx->req->headers->header( Authorization => "Bearer $t" );
98             }
99              
100             1;
101             BODY
102             }
103              
104             1;
105              
106             __END__