From bfdf68ea40cd50bc80128bffe48c622f1a17b7a3 Mon Sep 17 00:00:00 2001 From: Andreas Granig Date: Mon, 9 Apr 2018 16:26:38 +0200 Subject: [PATCH] TT#35523 Persist sessions in redis This will allow to apply changes or fail-over without re-login on the panel. Change-Id: Ie3dca1ea4ecfac75b1ffa939c3bba92afcc90db7 --- lib/Catalyst/Plugin/Session/Store/Redis.pm | 208 +++++++++++++++++++++ lib/NGCP/Panel.pm | 2 +- 2 files changed, 209 insertions(+), 1 deletion(-) create mode 100644 lib/Catalyst/Plugin/Session/Store/Redis.pm diff --git a/lib/Catalyst/Plugin/Session/Store/Redis.pm b/lib/Catalyst/Plugin/Session/Store/Redis.pm new file mode 100644 index 0000000000..ed8b4b740f --- /dev/null +++ b/lib/Catalyst/Plugin/Session/Store/Redis.pm @@ -0,0 +1,208 @@ +package Catalyst::Plugin::Session::Store::Redis; +use warnings; +use strict; + +# ABSTRACT: Redis Session store for Catalyst + +use base qw/ + Class::Data::Inheritable + Catalyst::Plugin::Session::Store +/; +use MRO::Compat; +use MIME::Base64 qw(encode_base64 decode_base64); +use Redis; +use Storable qw/nfreeze thaw/; +use Try::Tiny; + +our $VERSION = '0.07'; + +__PACKAGE__->mk_classdata(qw/_session_redis_storage/); + +sub get_session_data { + my ($c, $key) = @_; + + $c->_verify_redis_connection; + + if(my ($sid) = $key =~ /^expires:(.*)/) { + $c->log->debug("Getting expires key for $sid"); + return $c->_session_redis_storage->get($key); + } else { + $c->log->debug("Getting $key"); + my $data = $c->_session_redis_storage->get($key); + if(defined($data)) { + return thaw( decode_base64($data) ) + } + } + + return; +} + +sub store_session_data { + my ($c, $key, $data) = @_; + + $c->_verify_redis_connection; + + if(my ($sid) = $key =~ /^expires:(.*)/) { + $c->log->debug("Setting expires key for $sid: $data"); + $c->_session_redis_storage->set($key, $data); + } else { + $c->log->debug("Setting $key"); + $c->_session_redis_storage->set($key, encode_base64(nfreeze($data))); + } + + # We use expire, not expireat because it's a 1.2 feature and as of this + # release, 1.2 isn't done yet. + my $exp = $c->session_expires; + my $duration = $exp - time; + $c->_session_redis_storage->expire($key, $duration); + # $c->_session_redis_storage->expireat($key, $exp); + + return; +} + +sub delete_session_data { + my ($c, $key) = @_; + + $c->_verify_redis_connection; + + $c->log->debug("Deleting: $key"); + $c->_session_redis_storage->del($key); + + return; +} + +sub delete_expired_sessions { + my ($c) = @_; + + # Null op, Redis handles this for us! +} + +sub setup_session { + my ($c) = @_; + + $c->maybe::next::method(@_); +} + +sub _verify_redis_connection { + my ($c) = @_; + + my $cfg = $c->_session_plugin_config; + + try { + $c->_session_redis_storage->ping; + } catch { + $c->_session_redis_storage( + Redis->new( + server => $cfg->{redis_server} || '127.0.0.1:6379', + debug => $cfg->{redis_debug} || 0, + reconnect => $cfg->{redis_reconnect} || 0 + ) + ); + if ($c->_session_redis_storage && $cfg->{redis_db}) { + $c->_session_redis_storage->select($cfg->{redis_db}); + } + }; +} + +1; + +__END__ + +=pod + +=encoding UTF-8 + +=head1 NAME + +Catalyst::Plugin::Session::Store::Redis - Redis Session store for Catalyst + +=head1 VERSION + +version 0.07 + +=head1 SYNOPSIS + + use Catalyst qw/ + Session + Session::Store::Redis + Session::State::Foo + /; + + MyApp->config->{Plugin::Session} = { + expires => 3600, + redis_server => '127.0.0.1:6379', + redis_debug => 0, # or 1! + redis_reconnect => 0, # or 1 + redis_db => 5, # or 0 by default + }; + + # ... in an action: + $c->session->{foo} = 'bar'; # will be saved + +=head1 DESCRIPTION + +C is a session storage plugin for +Catalyst that uses the Redis (L) key-value +database. + +=head2 CONFIGURATION + +=head3 redis_server + +The IP address and port where your Redis is running. Default: 127.0.0.1:6379 + +=head3 redis_debug + +Boolean flag to turn Redis debug messages on/off. Default: 0, i.e. off + +Turing this on will cause the Redis Perl bindings to output debug +messages to STDOUT. This setting does not influence the logging this +module does via C<< $c->log >> + +=head3 redis_reconnect + +Boolean flag. Default: 0, i.e. off. + +It is highly recommended that you enable this setting. If set to C<0>, +your app might not be able to reconnect to C if the C +server was restarted. + +I leave the default of setting at C<0> for now because changing it +might break existing apps. + +=head1 NOTES + +=over 4 + +=item B + +This store does B automatically expires sessions. There is no need to +call C to clear any expired sessions. + +domm: No idea what this means. + +=item B + +Currently this module does not use C Expiry to clean out old +session. I might look into this in the future. But patches are welcome! + +=back + +=head1 AUTHORS + +Cory G Watson, C<< >> + +Thomas Klausner C<< domm@cpan.org >> + +=head1 AUTHOR + +Thomas Klausner + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 2016 by Thomas Klausner. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut diff --git a/lib/NGCP/Panel.pm b/lib/NGCP/Panel.pm index bda63a5b4a..c68531133c 100644 --- a/lib/NGCP/Panel.pm +++ b/lib/NGCP/Panel.pm @@ -24,7 +24,7 @@ use Catalyst qw/ Authentication Authorization::Roles Session - Session::Store::FastMmap + Session::Store::Redis Session::State::Cookie I18N /;