| 1 | #!/usr/bin/perl -w |
| 2 | use v5.14; |
| 3 | no if $] >= 5.017011, warnings => 'experimental::smartmatch'; |
| 4 | |
| 5 | use Gruntmaster::Data; |
| 6 | use Plack::App::Gruntmaster; |
| 7 | use Plack::Builder; |
| 8 | use Plack::Request; |
| 9 | use Plack::Util; |
| 10 | use Digest::SHA qw/sha256/; |
| 11 | use Log::Log4perl; |
| 12 | use Tie::Hash::Expire; |
| 13 | |
| 14 | use constant AUTH_TIMEOUT => 5 * 60; |
| 15 | use constant ACCESSLOG_FORMAT => '%{X-Forwarded-For}i|%h %u "%r" %>s %b "%{Referer}i" "%{User-agent}i"'; |
| 16 | use constant CONTENT_SECURITY_POLICY => q,default-src 'none'; script-src 'self' www.google-analytics.com; style-src 'self'; img-src 'self'; connect-src 'self'; frame-src free.timeanddate.com,; |
| 17 | |
| 18 | my $db = Gruntmaster::Data->connect('dbi:Pg:'); |
| 19 | |
| 20 | tie my %auth, 'Tie::Hash::Expire', {expire_seconds => 300}; |
| 21 | |
| 22 | sub authenticate { |
| 23 | my ($user, $pass, $env) = @_; |
| 24 | my $key = sha256 "$user:$pass"; |
| 25 | $env->{'gruntmaster.user'} = $user; |
| 26 | return 1 if exists $auth{$key}; |
| 27 | return unless $db->user($user) && $db->user($user)->check_passphrase($pass); |
| 28 | $auth{key} = 1; |
| 29 | } |
| 30 | |
| 31 | sub add_headers { |
| 32 | my $app = $_[0]; |
| 33 | sub { |
| 34 | my $resp = $app->($_[0]); |
| 35 | my $hdrs = Plack::Util::headers($resp->[1]); |
| 36 | $hdrs->set('Content-Security-Policy', CONTENT_SECURITY_POLICY); |
| 37 | $hdrs->set('Cache-Control', 'public, max-age=604800') if $_[0]->{PATH_INFO} =~ qr,^/static/,; |
| 38 | $resp->[1] = $hdrs->headers; |
| 39 | $resp; |
| 40 | } |
| 41 | } |
| 42 | |
| 43 | Log::Log4perl->init('log.conf'); |
| 44 | my $access_logger = Log::Log4perl->get_logger('access'); |
| 45 | $ENV{DBIC_NULLABLE_KEY_NOWARN} = 1; |
| 46 | |
| 47 | builder { |
| 48 | enable 'AccessLog', format => ACCESSLOG_FORMAT, logger => sub { $access_logger->info(@_) }; |
| 49 | enable 'ContentLength'; |
| 50 | enable \&add_headers; |
| 51 | enable 'Static', path => qr,^/static/,; |
| 52 | enable 'Log4perl', category => 'plack'; |
| 53 | enable_if { shift->{HTTP_AUTHORIZATION} } 'Auth::Basic', authenticator => \&authenticate, realm => 'Gruntmaster 6000'; |
| 54 | enable_if { $_[0]->{PATH_INFO} eq '/ok' } sub { sub{ [200, [], []] }}; |
| 55 | enable sub { my $app = $_[0]; sub { $_[0]->{'gruntmaster.dbic'} = $db; $app->($_[0]) } }; |
| 56 | Plack::App::Gruntmaster->run_if_script |
| 57 | } |