File Coverage

blib/lib/Data/Login.pm
Criterion Covered Total %
statement 39 39 100.0
branch 2 2 100.0
condition 3 3 100.0
subroutine 9 9 100.0
pod 0 1 0.0
total 53 54 98.1


line stmt bran cond sub pod time code
1             package Data::Login;
2              
3 10     10   5494690 use strict;
  10         27  
  10         406  
4 10     10   82 use warnings;
  10         30  
  10         568  
5              
6 10     10   1863 use DateTime;
  10         1181528  
  10         411  
7 10     10   1567 use Error::Pure qw(err);
  10         29129  
  10         602  
8 10     10   1458 use Mo qw(build default is);
  10         1317  
  10         67  
9 10     10   17819 use Mo::utils 0.28 qw(check_isa check_length check_required);
  10         5617  
  10         661  
10 10     10   6497 use Mo::utils::Array qw(check_array_object);
  10         28389  
  10         358  
11 10     10   2348 use Mo::utils::Number qw(check_positive_natural);
  10         6745  
  10         3380  
12              
13             our $VERSION = 0.05;
14              
15             has hash_type => (
16             is => 'ro',
17             );
18              
19             has id => (
20             is => 'ro',
21             );
22              
23             has login_name => (
24             is => 'ro',
25             );
26              
27             has password_hash => (
28             is => 'ro',
29             );
30              
31             has roles => (
32             default => [],
33             is => 'ro',
34             );
35              
36             has valid_from => (
37             is => 'ro',
38             );
39              
40             has valid_to => (
41             is => 'ro',
42             );
43              
44             sub BUILD {
45 18     18 0 3143881 my $self = shift;
46              
47             # Check hash type.
48 18         97 check_isa($self, 'hash_type', 'Data::HashType');
49 18         543 check_required($self, 'hash_type');
50              
51             # Check id.
52 17         169 check_positive_natural($self, 'id');
53              
54             # Check login_name.
55 16         195 check_length($self, 'login_name', 50);
56 16         212 check_required($self, 'login_name');
57              
58             # Check password_hash.
59 15         143 check_length($self, 'password_hash', 128);
60 15         218 check_required($self, 'password_hash');
61              
62             # Check roles.
63 14         133 check_array_object($self, 'roles', 'Data::Login::Role');
64              
65             # Check valid_from.
66 14         185 check_required($self, 'valid_from');
67 13         113 check_isa($self, 'valid_from', 'DateTime');
68              
69             # Check valid_to.
70 13         279 check_isa($self, 'valid_to', 'DateTime');
71 13 100 100     235 if (defined $self->{'valid_to'}
72             && DateTime->compare($self->{'valid_from'}, $self->{'valid_to'}) != -1) {
73              
74             err "Parameter 'valid_to' must be older than 'valid_from' parameter.",
75             'Value', $self->{'valid_to'},
76 1         113 'Valid from', $self->{'valid_from'},
77             ;
78             }
79              
80 12         122 return;
81             }
82              
83             1;
84              
85             __END__
86              
87             =pod
88              
89             =encoding utf8
90              
91             =head1 NAME
92              
93             Data::Login - Data object for login.
94              
95             =head1 SYNOPSIS
96              
97             use Data::Login;
98              
99             my $obj = Data::Login->new(%params);
100             my $hash_type = $obj->hash_type;
101             my $id = $obj->id;
102             my $login_name = $obj->login_name;
103             my $password_hash = $obj->password_hash;
104             my $roles_ar = $obj->roles;
105             my $valid_from = $obj->valid_from;
106             my $valid_to = $obj->valid_to;
107              
108             =head1 DESCRIPTION
109              
110             The intention of this module is to store information about the user logins.
111             User logins are active only within a certain time range, and we need a mechanism to
112             transition to others.
113              
114             A real-world example is a database table that follows the same format as this data object,
115             with multiple records being valid at different times, e.g. for transfering of Digest from
116             obsolete version to new. Or planning of access to system from concrete date.
117              
118             =head1 METHODS
119              
120             =head2 C<new>
121              
122             my $obj = Data::Login->new(%params);
123              
124             Constructor.
125              
126             =over 8
127              
128             =item * C<hash_type>
129              
130             Hash type object.
131             Possible value is L<Data::HashType> object.
132             Parameter is required.
133             Default value is undef.
134              
135             =item * C<id>
136              
137             Id of record.
138             Id could be number.
139             It's optional.
140             Default value is undef.
141              
142             =item * C<login_name>
143              
144             Login name.
145             Maximal length of value is 50 characters.
146             It's required.
147              
148             =item * C<password_hash>
149              
150             Password hash.
151             Maximal length of value is 128 characters.
152             It's required.
153              
154             =item * C<roles>
155              
156             Login roles list.
157             Possible value is reference to array with L<Data::Login::Role> objects.
158             Parameter is optional.
159             Default value is [].
160              
161             =item * C<valid_from>
162              
163             Date and time of start of use.
164             Must be a L<DateTime> object.
165             It's required.
166              
167             =item * C<valid_to>
168              
169             Date and time of end of use. An undefined value means it is in use.
170             Must be a L<DateTime> object.
171             It's optional.
172              
173             =back
174              
175             Returns instance of object.
176              
177             =head2 C<hash_type>
178              
179             my $hash_type = $obj->hash_type;
180              
181             Get hash type.
182              
183             Returns 0/1.
184              
185             =head2 C<id>
186              
187             my $id = $obj->id;
188              
189             Get hash type record id.
190              
191             Returns number.
192              
193             =head2 C<login_name>
194              
195             my $login_name = $obj->login_name;
196              
197             Get login name.
198              
199             Returns string.
200              
201             =head2 C<password_hash>
202              
203             my $password_hash = $obj->password_hash;;
204              
205             Get password hash.
206              
207             Returns string.
208              
209             =head2 C<roles>
210              
211             my $roles_ar = $obj->roles;
212              
213             Get roles.
214              
215             Returns reference to array with L<Data::Login::Role> objects.
216              
217             =head2 C<valid_from>
218              
219             my $valid_from = $obj->valid_from;
220              
221             Get date and time of start of use.
222              
223             Returns L<DateTime> object.
224              
225             =head2 C<valid_to>
226              
227             my $valid_to = $obj->valid_to;
228              
229             Get date and time of end of use.
230              
231             Returns L<DateTime> object or undef.
232              
233             =head1 ERRORS
234              
235             new():
236             From Mo::utils:
237             Parameter 'hash_type' is required.
238             Parameter 'hash_type' must be a 'Data::HashType' object.
239             Value: %s
240             Reference: %s
241             Parameter 'login_name' has length greater than '50'.
242             Value: %s
243             Parameter 'login_name' is required.
244             Parameter 'password_hash' has length greater than '128'.
245             Value: %s
246             Parameter 'password_hash' is required.
247             Parameter 'valid_from' is required.
248             Parameter 'valid_from' must be a 'DateTime' object.
249             Value: %s
250             Reference: %s
251             Parameter 'valid_to' must be a 'DateTime' object.
252             Value: %s
253             Reference: %s
254             Parameter 'valid_to' must be older than 'valid_from' parameter.
255             Value: %s
256             Valid from: %s
257              
258             From Mo::utils::Array::check_array_object():
259             Parameter 'roles' must be a array.
260             Value: %s
261             Reference: %s
262             Parameter 'roles' with array must contain 'Data::Login::Role' objects.
263             Value: %s
264             Reference: %s
265              
266             From Mo::utils::Number::check_positive_natural():
267             Parameter 'id' must be a positive natural number.
268             Value: %s
269              
270              
271             =head1 EXAMPLE
272              
273             =for comment filename=create_and_print_login.pl
274              
275             use strict;
276             use warnings;
277              
278             use Data::HashType;
279             use Data::Login;
280             use Data::Login::Role;
281             use Data::Random::Utils 0.02 qw(is_object_currently_valid);
282             use DateTime;
283              
284             my $obj = Data::Login->new(
285             'hash_type' => Data::HashType->new(
286             'id' => 1,
287             'name' => 'SHA-512',
288             'valid_from' => DateTime->new(
289             'day' => 1,
290             'month' => 1,
291             'year' => 2024,
292             ),
293             ),
294             'id' => 2,
295             'login_name' => 'michal.josef.spacek',
296             'password_hash' => '24ea354ebd9198257b8837fd334ac91663bf52c05658eae3c9e6ad0c87c659c62e43a2e1e5a1e573962da69c523bf1f680c70aedd748cd2b71a6d3dbe42ae972',
297             'roles' => [
298             Data::Login::Role->new(
299             'id' => 1,
300             'role' => 'Admin',
301             'valid_from' => DateTime->new(
302             'day' => 1,
303             'month' => 1,
304             'year' => 2024,
305             ),
306             ),
307             Data::Login::Role->new(
308             'id' => 2,
309             'role' => 'User',
310             'valid_from' => DateTime->new(
311             'day' => 1,
312             'month' => 1,
313             'year' => 2024,
314             ),
315             ),
316             Data::Login::Role->new(
317             'id' => 3,
318             'role' => 'Bad',
319             'valid_from' => DateTime->new(
320             'day' => 1,
321             'month' => 1,
322             'year' => 2024,
323             ),
324             'valid_to' => DateTime->new(
325             'day' => 1,
326             'month' => 2,
327             'year' => 2024,
328             ),
329             ),
330             ],
331             'valid_from' => DateTime->new(
332             'day' => 1,
333             'month' => 1,
334             'year' => 2024,
335             ),
336             );
337              
338             # Print out.
339             print 'Hash type: '.$obj->hash_type->name."\n";
340             print 'Id: '.$obj->id."\n";
341             print 'Login name: '.$obj->login_name."\n";
342             print 'Password hash: '.$obj->password_hash."\n";
343             print "Active roles:\n";
344             print join "\n", map { is_object_currently_valid($_) ? ' - '.$_->role : () } @{$obj->roles};
345             print "\n";
346             print 'Valid from: '.$obj->valid_from->ymd."\n";
347              
348             # Output:
349             # Hash type: SHA-512
350             # Id: 2
351             # Login name: michal.josef.spacek
352             # Password hash: 24ea354ebd9198257b8837fd334ac91663bf52c05658eae3c9e6ad0c87c659c62e43a2e1e5a1e573962da69c523bf1f680c70aedd748cd2b71a6d3dbe42ae972
353             # Active roles:
354             # - Admin
355             # - User
356             # Valid from: 2024-01-01
357              
358             =head1 DEPENDENCIES
359              
360             L<DateTime>,
361             L<Error::Pure>,
362             L<Mo>,
363             L<Mo::utils>,
364             L<Mo::utils::Array>,
365             L<Mo::utils::Number>.
366              
367             =head1 REPOSITORY
368              
369             L<https://github.com/michal-josef-spacek/Data-Login>
370              
371             =head1 AUTHOR
372              
373             Michal Josef Špaček L<mailto:skim@cpan.org>
374              
375             L<http://skim.cz>
376              
377             =head1 LICENSE AND COPYRIGHT
378              
379             © 2023-2025 Michal Josef Špaček
380              
381             BSD 2-Clause License
382              
383             =head1 VERSION
384              
385             0.05
386              
387             =cut