The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
package <% $package // ($module ~ "::Web::Plugin::Session") %>;
use strict;
use warnings;
use utf8;

use Amon2::Util;
use HTTP::Session2::ClientStore2;
use Crypt::CBC;

sub init {
    my ($class, $c) = @_;

    # Validate XSRF Token.
    $c->add_trigger(
        BEFORE_DISPATCH => sub {
            my ( $c ) = @_;
            if ($c->req->method ne 'GET' && $c->req->method ne 'HEAD') {
                my $token = $c->req->header('X-XSRF-TOKEN') || $c->req->param('XSRF-TOKEN');
                unless ($c->session->validate_xsrf_token($token)) {
                    return $c->create_simple_status_page(
                        403, 'XSRF detected.'
                    );
                }
            }
            return;
        },
    );

    Amon2::Util::add_method($c, 'session', \&_session);

    # Inject cookie header after dispatching.
    $c->add_trigger(
        AFTER_DISPATCH => sub {
            my ( $c, $res ) = @_;
            if ($c->{session} && $res->can('cookies')) {
                $c->{session}->finalize_plack_response($res);
            }
            return;
        },
    );
}

# $c->session() accessor.
my $cipher = Crypt::CBC->new({
    key => '<% random_string(32) %>',
    cipher => 'Rijndael',
});
sub _session {
    my $self = shift;

    if (!exists $self->{session}) {
        $self->{session} = HTTP::Session2::ClientStore2->new(
            env => $self->req->env,
            secret => '<% random_string(32) %>',
            cipher => $cipher,
        );
    }
    return $self->{session};
}

1;
__END__

=head1 DESCRIPTION

This module manages session for <% $module %>.