File Coverage

lib/Concierge/User.pm
Criterion Covered Total %
statement 107 115 93.0
branch 20 26 76.9
condition 13 17 76.4
subroutine 21 23 91.3
pod 17 17 100.0
total 178 198 89.9


line stmt bran cond sub pod time code
1             package Concierge::User v0.6.1;
2 7     7   92 use v5.36;
  7         34  
3              
4             our $VERSION = 'v0.6.1';
5              
6             # ABSTRACT: User object enabled by Concierge
7              
8 7     7   63 use File::Spec;
  7         14  
  7         246  
9 7     7   95 use File::Path qw/make_path/;
  7         73  
  7         469  
10              
11             # === COMPONENT MODULES ===
12 7     7   36 use Concierge::Auth;
  7         9  
  7         251  
13 7     7   44 use Concierge::Sessions;
  7         13  
  7         183  
14 7     7   28 use Concierge::Users;
  7         12  
  7         6352  
15              
16             sub enable_user {
17 24     24 1 123 my ($class, $user_id, $options) = @_;
18 24   50     82 $options //= {}; # Default to empty hashref if not provided
19              
20             # $options = {
21             # session => $session_obj, # optional - for guest/logged-in
22             # user_data => $user_data_hash, # optional - for logged-in only
23             # user_key => $external_key, # optional - reuse existing or generate new
24             # _get_user_data => $closure, # optional - for logged-in users
25             # _update_user_data => $closure, # optional - for logged-in users
26             # }
27              
28             my $self = bless {
29             user_id => $user_id,
30 24   100     295 user_key => $options->{user_key} || scalar(Concierge::Auth->gen_random_string(13)),
31             }, $class;
32              
33             # Store session reference and ID if provided
34 24 100       4467 if ($options->{session}) {
35 23         79 $self->{session} = $options->{session};
36 23         126 $self->{session_id} = $options->{session}->session_id();
37             }
38              
39             # Store user_data snapshot in memory if provided (logged-in users)
40 24 100       206 $self->{user_data} = $options->{user_data} if $options->{user_data};
41              
42             # Store closures for backend access (if logged-in user)
43 24 100       119 $self->{_get_user_data} = $options->{_get_user_data} if $options->{_get_user_data};
44 24 100       124 $self->{_update_user_data} = $options->{_update_user_data} if $options->{_update_user_data};
45              
46             # Determine user type (for status methods)
47 24   66     124 $self->{is_visitor} = !$options->{session} && !$options->{user_data};
48 24   100     142 $self->{is_guest} = $options->{session} && !$options->{user_data};
49 24   100     149 $self->{is_logged_in} = $options->{session} && $options->{user_data};
50              
51 24         98 return $self; # Return blessed object directly (not wrapped)
52             }
53              
54             # =============================================================================
55             # IDENTITY & METADATA - Direct scalar returns
56             # =============================================================================
57              
58 6     6 1 5191 sub user_id ($self) {
  6         10  
  6         10  
59 6         91 return $self->{user_id};
60             }
61              
62 35     35 1 142 sub user_key ($self) {
  35         55  
  35         44  
63 35         190 return $self->{user_key};
64             }
65              
66 14     14 1 2744 sub session_id ($self) {
  14         24  
  14         17  
67 14         55 return $self->{session_id}; # undef if visitor/no session
68             }
69              
70             # =============================================================================
71             # STATUS METHODS - Direct boolean returns
72             # =============================================================================
73              
74 3     3 1 5 sub is_visitor ($self) {
  3         4  
  3         13  
75 3 100       18 return $self->{is_visitor} ? 1 : 0;
76             }
77              
78 5     5 1 1011 sub is_guest ($self) {
  5         8  
  5         6  
79 5 100       70 return $self->{is_guest} ? 1 : 0;
80             }
81              
82 6     6 1 13 sub is_logged_in ($self) {
  6         11  
  6         7  
83 6 100       50 return $self->{is_logged_in} ? 1 : 0;
84             }
85              
86             # =============================================================================
87             # SESSION ACCESS - Returns session object
88             # =============================================================================
89              
90 7     7 1 23 sub session ($self) {
  7         13  
  7         9  
91 7         61 return $self->{session}; # undef if no session (visitor)
92             }
93              
94 4     4 1 557 sub get_session_data ($self) {
  4         14  
  4         8  
95 4 50       19 return undef unless $self->{session};
96 4         27 my $result = $self->{session}->get_data();
97 4   50     96 return $result->{value} // {};
98             }
99              
100 4     4 1 1152 sub update_session_data ($self, $updates) {
  4         20  
  4         7  
  4         8  
101 4 50       17 return undef unless $self->{session};
102              
103 4         21 my $result = $self->{session}->get_data();
104 4   50     43 my $current = $result->{value} // {};
105              
106             # Merge updates into current data
107 4         16 for my $key (keys %$updates) {
108 5         14 $current->{$key} = $updates->{$key};
109             }
110              
111 4         17 $self->{session}->set_data($current);
112 4         47 $self->{session}->save();
113              
114 4         60761 return 1;
115             }
116              
117             # =============================================================================
118             # USER DATA - Quick access from memory snapshot
119             # =============================================================================
120              
121 3     3 1 8 sub moniker ($self) {
  3         6  
  3         3  
122 3         17 return $self->{user_data}{moniker};
123             }
124              
125 1     1 1 2 sub email ($self) {
  1         2  
  1         1  
126 1         5 return $self->{user_data}{email};
127             }
128              
129 0     0 1 0 sub user_status ($self) {
  0         0  
  0         0  
130 0         0 return $self->{user_data}{user_status};
131             }
132              
133 0     0 1 0 sub access_level ($self) {
  0         0  
  0         0  
134 0         0 return $self->{user_data}{access_level};
135             }
136              
137 3     3 1 1325 sub get_user_field ($self, $field) {
  3         9  
  3         6  
  3         6  
138 3         25 return $self->{user_data}{$field};
139             }
140              
141             # =============================================================================
142             # USER DATA - Backend operations via closures
143             # =============================================================================
144              
145 2     2 1 513 sub refresh_user_data ($self) {
  2         6  
  2         5  
146             # Fetch fresh data from backend, update memory snapshot
147 2 50       9 return undef unless $self->{_get_user_data};
148              
149 2         13 my $result = $self->{_get_user_data}->();
150 2 50       7 return undef unless $result->{success};
151              
152 2         5 $self->{user_data} = $result->{user};
153 2         8 return 1;
154             }
155              
156 2     2 1 5 sub update_user_data ($self, $updates) {
  2         4  
  2         4  
  2         3  
157             # Update backend AND memory snapshot
158 2 50       9 return undef unless $self->{_update_user_data};
159              
160 2         26 my $result = $self->{_update_user_data}->($updates);
161 2 50       33968 return undef unless $result->{success};
162              
163             # Update memory snapshot with new values
164 2         10 for my $field (keys %$updates) {
165 2         23 $self->{user_data}{$field} = $updates->{$field};
166             }
167              
168 2         12 return 1;
169             }
170              
171             1;
172              
173             __END__