File Coverage

blib/lib/App/Spoor/ParsedFileManager.pm
Criterion Covered Total %
statement 37 37 100.0
branch 5 6 83.3
condition n/a
subroutine 8 8 100.0
pod 1 1 100.0
total 51 52 98.0


line stmt bran cond sub pod time code
1             package App::Spoor::ParsedFileManager;
2              
3 1     1   201815 use v5.10;
  1         8  
4 1     1   5 use strict;
  1         2  
  1         20  
5 1     1   5 use warnings;
  1         2  
  1         24  
6              
7 1     1   5 use File::Spec;
  1         2  
  1         24  
8 1     1   501 use File::Copy qw(move);
  1         2252  
  1         62  
9 1     1   7 use Path::Tiny qw(path);
  1         2  
  1         39  
10 1     1   6 use JSON;
  1         2  
  1         6  
11              
12             =head1 NAME
13              
14             App::Spoor::ParsedFileManager
15              
16             =head1 VERSION
17              
18             Version 0.06
19              
20             =cut
21              
22             our $VERSION = '0.06';
23              
24              
25             =head1 SYNOPSIS
26              
27             This module is responsible for looping through the contents of the parsed files directory and passing them to the
28             transmitter.
29              
30             =head1 SUBROUTINES
31              
32             =head2 process_parsed_files
33              
34             Loops through all files in the /var/lib/spoor/parsed directory. If a file passes a rudimentary security check the
35             contents of the file are passed to the transmitter. If the file fails the security check or does not match the expected
36             naming convention, it is left where it is.
37              
38              
39             If the file is successfully transmitted, it is moved into /var/lib/spoor/transmitted. If not, it is moved into
40             /var/lib/spoor/transmission_failed - for transmission to be reattempted, it must be manually moved into
41             /var/lib/spoor/parsed once more.
42              
43              
44             my $application_config = App::Spoor::Config::get_application_config();
45             my $transmission_config = App::Spoor::Config::get_transmission_config();
46             $transmission_config->{'reporter'} = hostname;
47              
48             sub transmitter {
49             App::Spoor::EntryTransmitter::transmit(
50             App::Spoor::TransmissionFormatter::format(shift, $transmission_config),
51             LWP::UserAgent->new,
52             $transmission_config
53             );
54             }
55              
56             sub parsed_file_security_check {
57             App::Spoor::Security::check_file(shift, $>, 0600);
58             }
59              
60             while(1) {
61             App::Spoor::ParsedFileManager::process_parsed_files(
62             $application_config, \&parsed_file_security_check, \&transmitter
63             );
64             sleep 5;
65             }
66              
67             =cut
68              
69             sub process_parsed_files {
70 7     7 1 56985 my $config = shift;
71 7         14 my $file_security_check = shift;
72 7         8 my $transmitter = shift;
73              
74 7         14 my ($source_file_path, $file_contents);
75 7         200 opendir my $parsed_entries_dir, $config->{parsed_entries_path};
76              
77 7         221 my @file_names = grep { /\A((error|access|login)\.\d+\.\d+\.json)\z/ } readdir $parsed_entries_dir;
  84         237  
78              
79 7         22 foreach my $file_name (@file_names) {
80             # Untaint
81 21 50       1731 if ($file_name =~ /\A((error|access|login)\.\d+\.\d+\.json)\z/) {
82 21         62 my $sanitised_file_name = $1;
83 21         221 $source_file_path = File::Spec->catfile($config->{parsed_entries_path}, $sanitised_file_name);
84 21 100       70 if ($file_security_check->($source_file_path)) {
85 15         97 $file_contents = from_json(path($source_file_path)->slurp_utf8());
86              
87 15 100       3094 if ($transmitter->($file_contents)) {
88 12         126 move($source_file_path, $config->{transmitted_entries_path});
89             } else {
90 3         18 move($source_file_path, $config->{transmission_failed_entries_path});
91             }
92             }
93             }
94             }
95              
96 7         840 closedir $parsed_entries_dir;
97             }
98              
99             =head1 AUTHOR
100              
101             Rory McKinley, C<< <rorymckinley at capefox.co> >>
102              
103             =head1 BUGS
104              
105             Please report any bugs or feature requests to C<bug-. at rt.cpan.org>, or through
106             the web interface at L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=.>. I will be notified, and then you'll
107             automatically be notified of progress on your bug as I make changes.
108              
109              
110             =head1 SUPPORT
111              
112             You can find documentation for this module with the perldoc command.
113              
114             perldoc App::Spoor::ParsedFileManager
115              
116              
117             You can also look for information at:
118              
119             =over 4
120              
121             =item * RT: CPAN's request tracker (report bugs here)
122              
123             L<https://rt.cpan.org/NoAuth/Bugs.html?Dist=.>
124              
125             =item * AnnoCPAN: Annotated CPAN documentation
126              
127             L<http://annocpan.org/dist/.>
128              
129             =item * CPAN Ratings
130              
131             L<https://cpanratings.perl.org/d/.>
132              
133             =item * Search CPAN
134              
135             L<https://metacpan.org/release/.>
136              
137             =back
138              
139             =head1 LICENSE AND COPYRIGHT
140              
141             Copyright 2019 Rory McKinley.
142              
143             This program is free software; you can redistribute it and/or modify it
144             under the terms of the the Artistic License (2.0). You may obtain a
145             copy of the full license at:
146              
147             L<http://www.perlfoundation.org/artistic_license_2_0>
148              
149             Any use, modification, and distribution of the Standard or Modified
150             Versions is governed by this Artistic License. By using, modifying or
151             distributing the Package, you accept this license. Do not use, modify,
152             or distribute the Package, if you do not accept this license.
153              
154             If your Modified Version has been derived from a Modified Version made
155             by someone other than you, you are nevertheless required to ensure that
156             your Modified Version complies with the requirements of this license.
157              
158             This license does not grant you the right to use any trademark, service
159             mark, tradename, or logo of the Copyright Holder.
160              
161             This license includes the non-exclusive, worldwide, free-of-charge
162             patent license to make, have made, use, offer to sell, sell, import and
163             otherwise transfer the Package with respect to any patent claims
164             licensable by the Copyright Holder that are necessarily infringed by the
165             Package. If you institute patent litigation (including a cross-claim or
166             counterclaim) against any party alleging that the Package constitutes
167             direct or contributory patent infringement, then this Artistic License
168             to you shall terminate on the date that such litigation is filed.
169              
170             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
171             AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
172             THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
173             PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
174             YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
175             CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
176             CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
177             EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
178              
179              
180             =cut
181              
182             1; # End of App::Spoor::ParsedFileManager