File Coverage

lib/Concierge/Sessions.pm
Criterion Covered Total %
statement 53 57 92.9
branch 16 18 88.8
condition 4 6 66.6
subroutine 10 11 90.9
pod 6 6 100.0
total 89 98 90.8


line stmt bran cond sub pod time code
1             package Concierge::Sessions v0.11.0;
2 4     4   927497 use v5.36;
  4         13  
3              
4             # ABSTRACT: Session manager with flexible session information storage
5              
6 4     4   23 use Carp qw/croak/;
  4         7  
  4         219  
7              
8 4     4   1984 use Concierge::Sessions::Session;
  4         11  
  4         172  
9 4     4   1818 use Concierge::Sessions::SQLite;
  4         14  
  4         214  
10 4     4   2087 use Concierge::Sessions::File;
  4         11  
  4         2363  
11              
12             # Default backend
13             our $DEFAULT_BACKEND = 'Concierge::Sessions::SQLite';
14             our $DEFAULT_SESSION_TIMEOUT = 3600;
15              
16             # Sessions manager
17             sub new {
18 68     68 1 775955 my ($class, %args) = @_;
19              
20             # Determine backend class (can be specified as 'database' or 'file')
21             # database (default): SQLite creates and updates session records
22             # file: File creates and overwrites session files as JSON
23 68   66     384 my $backend_param = $args{backend} || $DEFAULT_BACKEND;
24              
25             # Handle case-insensitive backend names and map to module names
26 68 100       248 unless ($backend_param =~ /^Concierge::Sessions::/) {
27 67         183 my $backend_lc = lc($backend_param);
28 67 100       237 if ($backend_lc eq 'database') {
    100          
29 29         61 $backend_param = 'Concierge::Sessions::SQLite';
30             } elsif ($backend_lc eq 'file') {
31 5         10 $backend_param = 'Concierge::Sessions::File';
32             } else {
33             # For backwards compatibility, still support module name suffixes
34 33         70 $backend_param = "Concierge::Sessions::$backend_param";
35             }
36             }
37              
38 68         121 my $backend_class = $backend_param;
39              
40             # Create backend instance
41 68         106 my $backend;
42 68         97 eval {
43 68         515 $backend = $backend_class->new(%args);
44             };
45 68 100       199 if ($@) {
46 1         221 croak "Failed to initialize backend $backend_class: $@";
47             }
48              
49 67         354 my $self = bless {
50             storage => $backend,
51             }, $class;
52              
53 67         277 return $self;
54             }
55              
56             # Session object
57             sub new_session {
58 65     65 1 1037 my ($self, %args) = @_;
59              
60 65 100       213 unless ($args{user_id}) {
61 3         20 return { success => 0, message => "user_id required to create a new session" };
62             }
63              
64 62   66     371 $args{session_timeout} ||= $DEFAULT_SESSION_TIMEOUT;
65 62         174 $args{storage} = $self->{storage};
66              
67 62         574 my $session_result = Concierge::Sessions::Session->new( %args );
68              
69 62         426 return $session_result;
70             }
71              
72             sub get_session {
73 26     26 1 34921 my ($self, $session_id) = @_;
74              
75 26 100       90 unless ($session_id) {
76 1         7 return { success => 0, message => "Session ID required to retrieve a session" };
77             }
78              
79             # Load session info from backend
80 25         150 my $result = $self->{storage}->get_session_info($session_id);
81              
82 25 100       132 unless ($result->{success}) {
83 8         58 return { success => 0, message => "get_session_info: " . $result->{message} };
84             }
85              
86 17         140 my %ses_args = $result->{info}->%*;
87 17         56 $ses_args{storage} = $self->{storage};
88              
89             # Instantiate Refreshed Session object
90 17         122 my $session = bless { %ses_args }, 'Concierge::Sessions::Session';
91              
92 17         146 return { success => 1, session => $session };
93             }
94              
95             # Administrative methods - handled by backends
96              
97             # delete sessions that have expired
98             sub cleanup_sessions {
99 3     3 1 21 my ($self) = @_;
100 3         18 return $self->{storage}->cleanup_sessions();
101             }
102              
103             # delete session by session_id
104             sub delete_session {
105 6     6 1 1976 my ($self, $session_id) = @_;
106              
107 6 100       20 unless ($session_id) {
108 1         4 return { success => 0, message => "Session ID required to delete a session" };
109             }
110              
111 5         29 return $self->{storage}->delete_session($session_id);
112             }
113              
114             # delete session by user_id
115             # sub delete_user_sessions {
116             sub delete_user_session {
117 0     0 1   my ($self, $user_id) = @_;
118              
119 0 0         unless ($user_id) {
120 0           return { success => 0, message => "user_id required to delete user sessions" };
121             }
122              
123 0           return $self->{storage}->delete_user_session($user_id);
124             }
125              
126              
127             1;
128              
129             __END__