File Coverage

blib/lib/WWW/Suffit/AuthDB/User.pm
Criterion Covered Total %
statement 36 63 57.1
branch 10 38 26.3
condition 8 63 12.7
subroutine 9 15 60.0
pod 10 10 100.0
total 73 189 38.6


line stmt bran cond sub pod time code
1             package WWW::Suffit::AuthDB::User;
2 3     3   25 use strict;
  3         8  
  3         135  
3 3     3   19 use utf8;
  3         6  
  3         26  
4              
5             =encoding utf8
6              
7             =head1 NAME
8              
9             WWW::Suffit::AuthDB::User - WWW::Suffit::AuthDB user class
10              
11             =head1 SYNOPSIS
12              
13             use WWW::Suffit::AuthDB::User;
14              
15             =head1 DESCRIPTION
16              
17             This module provides AuthDB user methods
18              
19             =head1 ATTRIBUTES
20              
21             This class implements the following attributes
22              
23             =head2 address
24              
25             address => '127.0.0.1'
26              
27             The remote client IP address (IPv4 or IPv6)
28              
29             $user = $user->address("::1");
30             my $address = $user->address;
31              
32             Default: '127.0.0.1'
33              
34             =head2 algorithm
35              
36             $user = $user->algorithm( 'SHA256' );
37             my $algorithm = $user->algorithm;
38              
39             Sets or returns algorithm of hash function for password store.
40             See L attribute
41              
42             Default: 'SHA256'
43              
44             =head2 attributes
45              
46             $user = $user->attributes( '{"foo": 123, "disabled": 0}' );
47             my $attributes = $user->attributes;
48              
49             Sets or returns additional attributes of the user in JSON format
50              
51             Default: none
52              
53             =head2 cached
54              
55             $user = $user->cached( 12345.123456789 );
56             my $cached = $user->cached;
57              
58             Sets or returns time of caching user data
59              
60             Default: 0
61              
62             =head2 cachekey
63              
64             $user = $user->cachekey( 'abcdef1234567890' );
65             my $cachekey = $user->cachekey;
66              
67             Sets or returns the cache key string
68              
69             =head2 comment
70              
71             $user = $user->comment( 'Blah-Blah-Blah' );
72             my $comment = $user->comment;
73              
74             Sets or returns comment for selected user
75              
76             Default: undef
77              
78             =head2 created
79              
80             $user = $user->created( time() );
81             my $comment = $user->created;
82              
83             Sets or returns time of user create
84              
85             Default: 0
86              
87             =head2 disabled
88              
89             $user = $user->disabled( 1 );
90             my $disabled = $user->disabled;
91              
92             Sets and returns boolean ban-status of the user
93              
94             Since C<1.01> this method is deprecated! See L
95              
96             =head2 email
97              
98             $user = $user->email('alice@example.com');
99             my $email = $user->email;
100              
101             Sets and returns email address of user
102              
103             =head2 error
104              
105             $user = $user->error( 'Oops' );
106             my $error = $user->error;
107              
108             Sets or returns error string
109              
110             =head2 expires
111              
112             $user = $user->expires( 300 );
113             my $expires = $user->expires;
114              
115             Sets or returns cache/object expiration time in seconds
116              
117             Default: 300 (5 min)
118              
119             =head2 flags
120              
121             $user = $user->flags( 123 );
122             my $flags = $user->flags;
123              
124             Sets or returns flags of user
125              
126             Default: 0
127              
128             =head2 groups
129              
130             $user = $user->groups([qw/ administrator wheel /]);
131             my $groups = $user->groups; # ['administrator', 'wheel']
132              
133             Sets and returns groups of user (array of groups)
134              
135             =head2 id
136              
137             $user = $user->id( 2 );
138             my $id = $user->id;
139              
140             Sets or returns id of user
141              
142             Default: 0
143              
144             =head2 is_authorized
145              
146             This attribute returns true if the user is authorized
147              
148             Default: false
149              
150             =head2 is_cached
151              
152             This attribute returns true if the user data was cached
153              
154             Default: false
155              
156             =head2 name
157              
158             $user = $user->name('Mark Miller');
159             my $name = $user->name;
160              
161             Sets and returns full name of user
162              
163             =head2 not_after
164              
165             $user = $user->not_after( time() );
166             my $not_after = $user->not_after;
167              
168             Sets or returns the time after which user data is considered invalid
169              
170             =head2 not_before
171              
172             $user = $user->not_before( time() );
173             my $not_before = $user->not_before;
174              
175             Sets or returns the time before which user data is considered invalid
176              
177             =head2 password
178              
179             $user = $user->password(sha256_hex('MyNewPassphrase'));
180             my $password = $user->password;
181              
182             Sets and returns hex notation of user password digest (sha256, eg.).
183             See L attribute
184              
185             =head2 private_key
186              
187             $user = $user->private_key('...');
188             my $private_key = $user->private_key;
189              
190             Sets and returns private key of user
191              
192             =head2 public_key
193              
194             $user = $user->public_key('...');
195             my $public_key = $user->public_key;
196              
197             Sets and returns public key of user
198              
199             =head2 role
200              
201             $user = $user->role('Regular user');
202             my $role = $user->role;
203              
204             Sets and returns role of user
205              
206             =head2 username
207              
208             $user = $user->username('new_username');
209             my $username = $user->username;
210              
211             Sets and returns username
212              
213             =head1 METHODS
214              
215             This class inherits all methods from L and implements the following new ones
216              
217             =head2 allow_ext
218              
219             say "yes" if $user->allow_ext;
220              
221             Returns true if user has access to external routes
222              
223             =head2 allow_int
224              
225             say "yes" if $user->allow_int;
226              
227             Returns true if user has access to internal routes
228              
229             =head2 forever
230              
231             say "yes" if $user->forever;
232              
233             Returns true if user can use endless API tokens
234              
235             =head2 is_admin
236              
237             say "yes" if $user->is_admin;
238              
239             If user is admin then returns true
240              
241             =head2 is_enabled
242              
243             say "yes" if $user->is_enabled;
244              
245             Returns status of user - enabled (true) or disabled (false)
246              
247             =head2 is_valid
248              
249             $user->is_valid or die "Incorrect user";
250              
251             Returns boolean status of user's data
252              
253             =head2 mark
254              
255             Marks object as cached
256              
257             =head2 to_hash
258              
259             my $short = $user->to_hash();
260             my $full = $user->to_hash(1);
261              
262             Returns user data as hash in short or full view
263              
264             =head2 uid
265              
266             $uid = $user->uid;
267              
268             Returns the ID of the user.
269             This method is an alias for calling $user->id without arguments
270              
271             Default: 0
272              
273             =head2 use_flags
274              
275             say "yes" if $user->use_flags;
276              
277             This method returns a binary indicator - whether flags should be used or not
278              
279             =head1 HISTORY
280              
281             See C file
282              
283             =head1 TO DO
284              
285             See C file
286              
287             =head1 SEE ALSO
288              
289             L, L
290              
291             =head1 AUTHOR
292              
293             Serż Minus (Sergey Lepenkov) L Eabalama@cpan.orgE
294              
295             =head1 COPYRIGHT
296              
297             Copyright (C) 1998-2026 D&D Corporation
298              
299             =head1 LICENSE
300              
301             This program is distributed under the terms of the Artistic License Version 2.0
302              
303             See the C file or L for details
304              
305             =cut
306              
307 3     3   401 use Mojo::Base -base;
  3         6  
  3         36  
308              
309 3     3   1124 use Mojo::Util qw/md5_sum deprecated steady_time/;
  3         10  
  3         446  
310              
311             use constant {
312             # User Flags (See main.js too!)
313             # Set: VAL = VAL | UFLAG_*
314             # Get: VAL & UFLAG_*
315 3         5343 DEFAULT_ADDRESS => '127.0.0.1',
316             UFLAG_USING => 1, # 0 Use rules of flags
317             UFLAG_ENABLED => 2, # 1 User is enabled
318             UFLAG_IS_ADMIN => 4, # 2 User is admin
319             UFLAG_ALLOW_INT => 8, # 3 User has access to internal routes
320             UFLAG_ALLOW_EXT => 16, # 4 User has access to external routes
321             UFLAG_FOREVER => 32, # 5 User can use endless tokens
322 3     3   25 };
  3         99  
323              
324             has address => DEFAULT_ADDRESS;
325             has algorithm => 'SHA256';
326             has attributes => '';
327             has comment => '';
328             has created => 0;
329             has disabled => sub { deprecated 'The "disabled" method is deprecated! Use "is_enabled"'; 0; };
330             has email => '';
331             has error => '';
332             has expires => 0;
333             has flags => 0;
334             has groups => sub { return [] };
335             has id => 0;
336             has name => '';
337             has not_after => undef;
338             has not_before => undef;
339             has password => '';
340             has private_key => '';
341             has public_key => '';
342             has role => 'Regular user';
343             has username => undef;
344             has is_cached => 0; # 0 or 1
345             has cached => 0; # steady_time() of cached
346             has cachekey => '';
347             has is_authorized => 0;
348              
349             sub is_valid {
350 7     7 1 51 my $self = shift;
351              
352 7 100       27 unless ($self->id) {
353 3         26 $self->error("E1310: User not found");
354 3         32 return 0;
355             }
356 4 50 33     42 unless (defined($self->username) && length($self->username)) {
357 0         0 $self->error("E1311: Incorrect username stored");
358 0         0 return 0;
359             }
360 4 50 33     62 unless (defined($self->password) && length($self->password)) {
361 0         0 $self->error("E1312: Incorrect password stored");
362 0         0 return 0;
363             }
364 4 50 33     54 if ($self->expires && $self->expires < time) {
365 0         0 $self->error("E1313: The user data is expired");
366 0         0 return 0;
367             }
368              
369 4         36 return 1;
370             }
371             sub mark {
372 0     0 1 0 my $self = shift;
373 0   0     0 return $self->is_cached(1)->cached(shift || steady_time);
374             }
375             sub to_hash {
376 0     0 1 0 my $self = shift;
377 0   0     0 my $all = shift || 0;
378             return (
379 0 0 0     0 uid => $self->id || 0,
    0 0        
      0        
      0        
      0        
      0        
      0        
      0        
      0        
      0        
      0        
      0        
      0        
      0        
      0        
380             username => $self->username // '',
381             name => $self->name // '',
382             email => $self->email // '',
383             email_md5=> $self->email ? md5_sum(lc($self->email)) : '',
384             role => $self->role // '',
385             groups => $self->groups || [],
386             expires => $self->expires || 0,
387             $all ? (
388             algorithm => $self->algorithm // '',
389             attributes => $self->attributes // '',
390             comment => $self->comment // '',
391             created => $self->created || 0,
392             flags => $self->flags || 0,
393             not_after => $self->not_after || 0,
394             not_before => $self->not_before || 0,
395             public_key => $self->public_key // '',
396             ) : (),
397             );
398             }
399 0     0 1 0 sub uid { shift->id }
400             sub use_flags {
401 2     2 1 5 my $self = shift;
402 2   50     6 my $flags = ($self->flags || 0) * 1;
403 2 50       24 return ($flags & UFLAG_USING) ? 1 : 0;
404             }
405             sub is_enabled {
406 1     1 1 3 my $self = shift;
407 1   50     5 my $flags = ($self->flags || 0) * 1;
408 1         11 my $now = time;
409              
410             # Check dates first
411 1   50     5 my $not_before = ($self->not_before || 0) * 1;
412 1   50     9 my $not_after = ($self->not_after || 0) * 1;
413 1 50 33     16 my $status = (
414             ($not_before ? (($not_before >= $now) ? 0 : 1) : 1)
415             && ($not_after ? (($not_after <= $now) ? 0 : 1) : 1)
416             ) ? 1 : 0;
417 1 50       4 return 0 unless $status; # Disabled by dates
418              
419             # Check flags?
420 1 50       5 return $status unless $self->use_flags;
421 0 0       0 return ($flags & UFLAG_ENABLED) ? 1 : 0;
422             }
423             sub is_admin {
424 0     0 1 0 my $self = shift;
425 0 0       0 return 1 unless $self->use_flags; # Returns true by default if not using flags
426 0   0     0 my $flags = ($self->flags || 0) * 1;
427 0 0       0 return ($flags & UFLAG_IS_ADMIN) ? 1 : 0;
428             }
429             sub allow_int {
430 1     1 1 3 my $self = shift;
431 1 50       3 return 1 unless $self->use_flags; # Returns true by default if not using flags
432 0   0       my $flags = ($self->flags || 0) * 1;
433 0 0         return ($flags & UFLAG_ALLOW_INT) ? 1 : 0;
434             }
435             sub allow_ext {
436 0     0 1   my $self = shift;
437 0 0         return 1 unless $self->use_flags; # Returns true by default if not using flags
438 0   0       my $flags = ($self->flags || 0) * 1;
439 0 0         return ($flags & UFLAG_ALLOW_EXT) ? 1 : 0;
440             }
441             sub forever {
442 0     0 1   my $self = shift;
443 0 0         return 1 unless $self->use_flags; # Returns true by default if not using flags
444 0   0       my $flags = ($self->flags || 0) * 1;
445 0 0         return ($flags & UFLAG_FOREVER) ? 1 : 0;
446             }
447              
448             1;
449              
450             __END__