File Coverage

blib/lib/Mojolicious/Plugin/AutoSecrets.pm
Criterion Covered Total %
statement 47 49 95.9
branch 4 10 40.0
condition 10 25 40.0
subroutine 9 9 100.0
pod 2 2 100.0
total 72 95 75.7


line stmt bran cond sub pod time code
1             package Mojolicious::Plugin::AutoSecrets;
2             # ABSTRACT: Automatic, Rotating Mojolicious Secrets
3             $Mojolicious::Plugin::AutoSecrets::VERSION = '0.005';
4              
5 1     1   1137 use Mojo::Base 'Mojolicious::Plugin';
  1         2  
  1         7  
6 1     1   185 use Mojo::JSON qw(encode_json decode_json);
  1         27  
  1         53  
7 1     1   520 use Session::Token;
  1         868  
  1         28  
8 1     1   6 use Carp qw(croak);
  1         1  
  1         40  
9 1     1   4 use Fcntl qw(:DEFAULT :flock);
  1         2  
  1         436  
10 1     1   6 use IO::File;
  1         2  
  1         164  
11 1     1   445 use autodie;
  1         10821  
  1         3  
12              
13              
14             sub register {
15 1     1 1 46 my ($self, $app, $config) = @_;
16 1   50     4 $config //= {};
17              
18 1   33     4 my $path = $config->{path} // $app->home->rel_file('.mojo-secrets');
19 1   50     6 my $mode = $config->{mode} // 0600;
20 1   50     4 my $expire_days = $config->{expire_days} // 60;
21 1   50     3 my $prune = $config->{prune} // 3;
22 1   50     5 my $generator = $config->{generator} // \&generator;
23              
24 1         2 my @secrets;
25              
26 1         4 sysopen my $fh, $path, O_RDWR | O_CREAT, $mode;
27 1         1609 flock $fh, LOCK_EX;
28              
29 1         286 my $rv;
30 1         3 my $disk = '';
31 1         9 while ($rv = $fh->sysread(my $buf, 4096, 0)) { $disk .= $buf }
  0         0  
32 1 50       32 croak "Can't read from $path: $!"
33             if !defined $rv;
34              
35 1   33     5 my $disk_secrets = $disk && decode_json($disk);
36              
37 1 50       3 unshift @secrets, @$disk_secrets
38             if $disk_secrets;
39              
40 1 0 33     3 if (!@secrets || -z $path || -M _ > $expire_days) {
      33        
41 1         5 unshift @secrets, $generator->();
42              
43 1 50 33     168 @secrets = @secrets[0 .. $prune - 1]
44             if $prune && @secrets > $prune;
45              
46 1         12 $fh->seek(0, 0);
47 1         16 $fh->syswrite(my $j = encode_json(\@secrets));
48             }
49 1         111 flock $fh, LOCK_UN;
50 1         69 $fh->close;
51              
52 0         0 push @secrets, @{$app->{secrets}}
53 1 50       18 if $app->{secrets};
54              
55 1         10 $app->secrets(\@secrets);
56             }
57              
58              
59             sub generator {
60 1     1 1 6 Session::Token->new->get;
61             }
62              
63              
64              
65             1;
66              
67             __END__