From ee43823179ee627ac16ea9da8168e5f1bf9619c0 Mon Sep 17 00:00:00 2001 From: "Jannis M. Hoffmann" Date: Thu, 29 Oct 2020 12:13:04 +0100 Subject: Initial commit; Stable version --- lib/JWebmail/Plugin/ServerSideSessionData.pm | 147 +++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 lib/JWebmail/Plugin/ServerSideSessionData.pm (limited to 'lib/JWebmail/Plugin/ServerSideSessionData.pm') diff --git a/lib/JWebmail/Plugin/ServerSideSessionData.pm b/lib/JWebmail/Plugin/ServerSideSessionData.pm new file mode 100644 index 0000000..9890358 --- /dev/null +++ b/lib/JWebmail/Plugin/ServerSideSessionData.pm @@ -0,0 +1,147 @@ +package JWebmail::Plugin::ServerSideSessionData; + +use Mojo::Base 'Mojolicious::Plugin'; + +use Mojo::JSON qw(decode_json encode_json); +use Mojo::File; + +use constant { + S_KEY => 's3d.key', +}; + + +has '_session_directory'; +sub session_directory { my $self = shift; @_ ? $self->_session_directory(Mojo::File->new(@_)) : $self->_session_directory } + +has 'expiration'; +has 'cleanup_interval'; + +has '_cleanup'; +sub cleanup { + my $self = shift; + if (@_) { + return $self->_cleanup(@_); + } + else { + if ($self->_cleanup < time) { + return 0; + } + else { + $self->_cleanup(time + $self->cleanup_interval); + return 1; + } + } +} + + +sub s3d { + my $self = shift; + my $c = shift; + + # cleanup old sessions + if ($self->cleanup) { + my $t = time; + for ($self->session_directory->list->each) { + if ( $_->stat->mtime + $self->expiration < $t ) { + $_->remove; + } + } + } + + my $file = $self->session_directory->child($c->session(S_KEY) || $c->req->request_id . $$); + + if (-e $file) { + if ($file->stat->mtime + $self->expiration < time) { + $file->remove; + } + else { + $file->touch; + } + } + my $data = decode_json($file->slurp) if (-s $file); + + my ($key, $val) = @_; + + if (defined $val) { # set + unless (-e $file) { + $c->session(S_KEY, $file->basename); + } + $data = ref $data ? $data : {}; + $data->{$key} = $val; + + #$file->spurt(encode_json $data); + open(my $f, '>', $file) or die "$!"; + chmod 0600, $f; + $f->say(encode_json $data); + close($f); + } + else { # get + return defined $key ? $data->{$key} : $data; + } +}; + + +sub register { + my ($self, $app, $conf) = @_; + + $self->session_directory($conf->{directory} || "/tmp/" . $app->moniker); + $self->expiration($conf->{expiration} || $app->sessions->default_expiration); + $self->cleanup_interval($conf->{cleanup_interval} || $self->expiration); + $self->cleanup(time + $self->cleanup_interval); + + unless (-d $self->session_directory) { + mkdir($self->session_directory) + or $! ? die "failed to create directory: $!" : 1; + } + + $app->helper( s3d => sub { $self->s3d(@_) } ); +} + + +1 + +__END__ + +=encoding utf-8 + +=head1 NAME + +ServeSideSessionData - Stores session data on the server (alias SSSD or S3D) + +=head1 SYNOPSIS + + $app->plugin('ServeSideSessionData'); + + $c->s3d(data => 'Hello, S3D'); + $c->s3d('data'); + +=head1 DESCRIPTION + +Store data temporarily on the server. +The only protetction on the server are struct user access rights. + +=head1 OPTIONS + +=head2 directory + +default C<< 'tmp/' . $app->moniker >> + +=head2 expiration + +default session expiration + +=head2 cleanup_interval + +default session expiration + +=head1 HELPERS + +=head2 s3d + +Stores and retrieves values. + + $c->s3d(data => 'Hello, S3D'); + $c->s3d('data'); + $c->s3d->{data}; + +=cut \ No newline at end of file -- cgit v1.2.3