File Coverage

blib/lib/XML/EPP/DCP.pm
Criterion Covered Total %
statement 1 3 33.3
branch n/a
condition n/a
subroutine 1 1 100.0
pod n/a
total 2 4 50.0


line stmt bran cond sub pod time code
1              
2             package XML::EPP::DCP::Expiry;
3              
4 1     1   2861 use Moose;
  0            
  0            
5             use MooseX::Method::Signatures;
6             use Moose::Util::TypeConstraints;
7             use PRANG::Graph;
8             use PRANG::XMLSchema::Types;
9              
10             our $SCHEMA_PKG = "XML::EPP";
11              
12             # hmm, choice with simpleTypes can't be mapped quite the same..
13             has 'absolute' =>
14             is => "rw",
15             isa => "PRANG::XMLSchema::dateTime",
16             predicate => "has_absolute",
17             clearer => "clear_absolute",
18             ;
19              
20             has 'relative' =>
21             is => "rw",
22             isa => "PRANG::XMLSchema::duration",
23             predicate => "has_relative",
24             clearer => "clear_relative",
25             ;
26              
27             has_element 'abs_or_rel' =>
28             is => "rw",
29             isa => "PRANG::XMLSchema::duration|PRANG::XMLSchema::dateTime",
30             xml_nodeName => {
31             "absolute" => "PRANG::XMLSchema::dateTime",
32             "relative" => "PRANG::XMLSchema::duration",
33             },
34             xml_nodeName_attr => "is_abs_or_rel",
35             lazy => 1,
36             default => sub {
37             my $self = shift;
38             $self->has_absolute ? $self->absolute : $self->relative
39             },
40             trigger => sub {
41             my $self = shift;
42             my $val = shift;
43             if ( $self->is_abs_or_rel eq "relative" ) {
44             $self->clear_absolute;
45             $self->relative($val);
46             }
47             else {
48             $self->clear_relative;
49             $self->absolute($val);
50             }
51             },
52             ;
53              
54             method is_abs_or_rel( Str $abs_or_rel? where { m{^(relative|absolute)$} } ) {
55             if ( defined $abs_or_rel ) {
56             if ( $abs_or_rel eq "relative" ) {
57             $self->clear_absolute;
58             }
59             else {
60             $self->clear_relative;
61             }
62             }
63             else {
64             if ( $self->has_relative ) {
65             "relative";
66             }
67             elsif ( $self->has_absolute ) {
68             "absolute";
69             }
70             else {
71             die "neither absolute nor relative time in $self";
72             }
73             }
74             }
75              
76             with 'XML::EPP::Node';
77              
78             subtype "${SCHEMA_PKG}::dcpExpiryType"
79             => as __PACKAGE__;
80             coerce "${SCHEMA_PKG}::dcpExpiryType"
81             => from "PRANG::XMLSchema::duration"
82             => via {
83             __PACKAGE__->new(relative => $_);
84             };
85             coerce "${SCHEMA_PKG}::dcpExpiryType"
86             => from "PRANG::XMLSchema::dateTime"
87             => via {
88             __PACKAGE__->new(absolute => $_);
89             };
90              
91             package XML::EPP::DCP::Ours;
92              
93             use Moose;
94             use Moose::Util::TypeConstraints;
95             use MooseX::Method::Signatures;
96             use PRANG::Graph;
97             our $SCHEMA_PKG = "XML::EPP";
98              
99             subtype "${SCHEMA_PKG}::dcpRecDescType"
100             => as "PRANG::XMLSchema::token"
101             => where {
102             length($_) and length($_) <= 255;
103             };
104              
105             has_element 'name' =>
106             is => "rw",
107             isa => "${SCHEMA_PKG}::dcpRecDescType",
108             predicate => "has_name",
109             xml_nodeName => "recDesc",
110             ;
111              
112             with 'XML::EPP::Node';
113              
114             subtype "${SCHEMA_PKG}::dcpOursType"
115             => as __PACKAGE__;
116              
117              
118             package XML::EPP::DCP::Recipient;
119              
120             use Moose;
121             use Moose::Util::TypeConstraints;
122             use MooseX::Method::Signatures;
123             use PRANG::Graph;
124             our $SCHEMA_PKG = "XML::EPP";
125              
126             our @valid_recipients = qw(other ours public same unrelated);
127             for my $recipient ( @valid_recipients ) {
128              
129             my $type = $recipient eq "ours" ?
130             "ArrayRef[${SCHEMA_PKG}::dcpOursType]" : "Bool";
131              
132             has_element $recipient =>
133             (is => "rw",
134             isa => $type,
135             predicate => "has_$recipient",
136             );
137             }
138              
139             with 'XML::EPP::Node';
140              
141             subtype "${SCHEMA_PKG}::dcpRecipientType"
142             => as __PACKAGE__;
143              
144             coerce "${SCHEMA_PKG}::dcpRecipientType"
145             => from "Str|ArrayRef[Str]"
146             => via {
147             my @recipient = (ref $_ ? @$_ : $_);
148             my %recipients = map { $_ => 1 } @recipient;
149             my @init_args;
150             my @ours;
151             for my $recipient ( @valid_recipients ) {
152             if (delete $recipients{$recipient}) {
153             if ( $recipient eq "ours") {
154             push @ours, XML::EPP::DCP::Ours->new;
155             }
156             else {
157             push @init_args, $recipient => 1;
158             }
159             }
160             }
161             push @ours, map {
162             XML::EPP::DCP::Ours->new( name => $_ );
163             } keys %recipients;
164              
165             push @init_args, ours => \@ours
166             if @ours;
167              
168             __PACKAGE__->new(@init_args);
169             };
170              
171             package XML::EPP::DCP::Access;
172              
173             use Moose;
174             use MooseX::Method::Signatures;
175             use Moose::Util::TypeConstraints;
176             use PRANG::Graph;
177             our $SCHEMA_PKG = "XML::EPP";
178              
179             my @access_enum = qw(all none null other personal personalAndOther);
180             enum "${SCHEMA_PKG}::dcpAccessType::enum" => @access_enum;
181              
182             has 'access' =>
183             is => "rw",
184             isa => "${SCHEMA_PKG}::dcpAccessType::enum",
185             trigger => sub { $_[0]->access_node(1) },
186             ;
187              
188             has_element 'access_node' =>
189             is => "rw",
190             isa => "Bool",
191             xml_nodeName => { map { $_ => "Bool" } @access_enum },
192             xml_nodeName_attr => "access",
193             ;
194              
195             with "${SCHEMA_PKG}::Node";
196              
197             subtype "${SCHEMA_PKG}::dcpAccessType"
198             => as __PACKAGE__;
199              
200             coerce "${SCHEMA_PKG}::dcpAccessType"
201             => from "Str"
202             => via {
203             __PACKAGE__->new($_ => 1);
204             };
205              
206              
207             package XML::EPP::DCP;
208              
209             use Moose;
210             use MooseX::Method::Signatures;
211             use Moose::Util::TypeConstraints;
212             use PRANG::Graph;
213             our $SCHEMA_PKG = "XML::EPP";
214              
215             has_element 'access' =>
216             is => "rw",
217             isa => "XML::EPP::dcpAccessType",
218             coerce => 1,
219             required => 1,
220             ;
221              
222             has_element 'statement' =>
223             is => "rw",
224             isa => "ArrayRef[XML::EPP::DCP::Statement]",
225             coerce => 1,
226             required => 1,
227             ;
228              
229             coerce "ArrayRef[XML::EPP::DCP::Statement]"
230             => from "ArrayRef[HashRef]"
231             => via {
232             my @x = @$_;
233             [ map { XML::EPP::DCP::Statement->new(%$_) }
234             @x ];
235             };
236              
237             coerce "ArrayRef[XML::EPP::DCP::Statement]"
238             => from "HashRef"
239             => via {
240             [ XML::EPP::DCP::Statement->new(%$_) ];
241             };
242              
243             has_element 'expiry' =>
244             is => "rw",
245             predicate => "has_expiry",
246             isa => "${SCHEMA_PKG}::dcpExpiryType",
247             coerce => 1,
248             ;
249              
250             with "${SCHEMA_PKG}::Node";
251              
252             subtype "${SCHEMA_PKG}::dcpType"
253             => as __PACKAGE__;
254              
255             coerce __PACKAGE__
256             => from "HashRef"
257             => via {
258             __PACKAGE__->new(%$_);
259             };
260              
261             package XML::EPP::DCP::Purpose;
262              
263             use Moose;
264             our $SCHEMA_PKG = "XML::EPP";
265             use Moose::Util::TypeConstraints;
266             use MooseX::Method::Signatures;
267             use PRANG::Graph;
268              
269             my @valid_purposes = qw(admin contact other prov);
270             has_element $_ =>
271             is => "rw",
272             isa => "Bool"
273             for @valid_purposes;
274              
275             with "${SCHEMA_PKG}::Node";
276              
277             subtype "${SCHEMA_PKG}::dcpPurposeType"
278             => as __PACKAGE__;
279              
280             coerce "${SCHEMA_PKG}::dcpPurposeType"
281             => from "Str|ArrayRef[Str]"
282             => via {
283             my @purposes = ref $_ ? @$_ : $_;
284             my %purposes = map { $_ => 1 } @purposes;
285             my @init_args;
286             for my $purpose ( @valid_purposes ) {
287             if ( delete $purposes{$purpose} ) {
288             push @init_args, $purpose => 1,
289             }
290             }
291             if ( keys %purposes ) {
292             die "invalid purpose(s): @{[keys %purposes]}";
293             }
294             __PACKAGE__->new(@init_args);
295             };
296              
297             package XML::EPP::DCP::Retention;
298              
299             use Moose;
300             our $SCHEMA_PKG = "XML::EPP";
301             use Moose::Util::TypeConstraints;
302             use MooseX::Method::Signatures;
303             use PRANG::Graph;
304              
305             my @retention_types = qw(business indefinite legal none stated);
306             enum "${SCHEMA_PKG}::dcpRetentionType::enum"
307             => @retention_types;
308              
309             with "${SCHEMA_PKG}::Node";
310              
311             has 'retention' =>
312             is => "rw",
313             isa => "${SCHEMA_PKG}::dcpRetentionType::enum",
314             trigger => sub {
315             $_[0]->has_retention(1);
316             };
317              
318             has_element 'has_retention' =>
319             is => "rw",
320             isa => "Bool",
321             xml_nodeName => { map { $_ => "Bool" } @retention_types },
322             xml_nodeName_attr => "retention",
323             ;
324              
325             subtype "${SCHEMA_PKG}::dcpRetentionType"
326             => as __PACKAGE__;
327             coerce "${SCHEMA_PKG}::dcpRetentionType"
328             => from "Str"
329             => via {
330             __PACKAGE__->new(retention => $_);
331             };
332              
333             package XML::EPP::DCP::Statement;
334              
335             use Moose;
336             our $SCHEMA_PKG = "XML::EPP";
337             use Moose::Util::TypeConstraints;
338             use MooseX::Method::Signatures;
339             use PRANG::Graph;
340              
341             has_element 'purpose' =>
342             is => "rw",
343             isa => "${SCHEMA_PKG}::dcpPurposeType",
344             required => 1,
345             coerce => 1,
346             ;
347              
348             has_element 'recipient' =>
349             is => "rw",
350             isa => "${SCHEMA_PKG}::dcpRecipientType",
351             required => 1,
352             coerce => 1,
353             ;
354              
355             has_element 'retention' =>
356             is => "rw",
357             isa => "${SCHEMA_PKG}::dcpRetentionType",
358             required => 1,
359             coerce => 1,
360             ;
361              
362             with "${SCHEMA_PKG}::Node";
363              
364             subtype "${SCHEMA_PKG}::dcpStatementType"
365             => as __PACKAGE__;
366              
367             1;
368              
369             __END__
370              
371             =head1 NAME
372              
373             XML::EPP::DCP - Data Collection Policy object
374              
375             =head1 SYNOPSIS
376              
377             my $DCP = XML::EPP::DCP->new(
378             access => "personalAndOther", # only one value allowed
379             statement => { # array of hash refs OK
380             purpose => "prov", # array of str OK
381             recipient => "ours", # array of str OK; see notes
382             retention => "business", # only one value allowed
383             },
384             expiry => "PY1", # optional; specify policy expiry
385             );
386              
387             =head1 DESCRIPTION
388              
389             This module represents a Data Collection Policy, a part of the EPP
390             Greeting format. The DCP is
391              
392             used to describe the server's privacy policy for data
393             collection and management.
394              
395             The RFC also notes;
396              
397             Policy implications usually extend
398             beyond the client-server relationship. Both clients and
399             servers can have relationships with other entities that need to
400             know the server operator's data collection policy to make
401             informed provisioning decisions. Policy information MUST be
402             disclosed to provisioning entities, though the method of
403             disclosing policy data outside of direct protocol interaction
404             is beyond the scope of this specification.
405              
406             The following classes and properties are defined; once the object
407             structure is created, or if you are dealing with a DCP from a server
408             greeting, this API is how you must access the object.
409              
410             They are concisely described here; note there are many coercion rules
411             for convenience and these are summaried in the L</SYNOPSIS>.
412              
413             =head2 XML::EPP::DCP
414              
415             This is the top-level object; there is exactly one of these in each
416             greeting.
417              
418             Properties: B<access> (see L</XML::EPP::DCP::Access>), B<statement>
419             (array; see L</XML::EPP::DCP::Statement>), B<expiry> (See
420             L</XML::EPP::DCP::Expiry>)
421              
422             =head2 XML::EPP::DCP::Access
423              
424             This object;
425              
426             describes the access provided by
427             the server to the client on behalf of the originating data
428             source.
429              
430             It may have only one of its 6 boolean properties set; is is
431             essentially an enumerated value (this is not currently enforced). It
432             is not implemented as a simple enum due to its structure in the XML
433             Schema.
434              
435             Here are the values and description from RFC5730; these are all
436             available as properties from the B<XML::EPP::DCP::Access> object;
437              
438             =over
439              
440             =item B<all>
441              
442             Access is given to all identified data.
443              
444             =item B<none>
445              
446             No access is provided to identified data.
447              
448             =item B<null>
449              
450             Data is not persistent, so no access is possible.
451              
452             =item B<personal>
453              
454             Access is given to identified data relating to individuals and
455             organizational entities.
456              
457             =item B<personalAndOther>
458              
459             Access is given to identified data relating to individuals,
460             organizational entities, and other data of a non-personal nature.
461              
462             =item B<other>
463              
464             Access is given to other identified data of a non-personal nature.
465              
466             =back
467              
468             =head2 XML::EPP::DCP::Statement
469              
470             These objects
471              
472             describe data
473             collection purposes, data recipients, and data retention.
474              
475             There can be more than one of these for each DCP.
476              
477             Properties: B<purpose> (see L</XML::EPP::DCP::Purpose>), B<recipient>
478             (see L</XML::EPP::DCP::Recipient>), B<retention> (see
479             L</XML::EPP::DCP::Retention>)
480              
481             =head2 XML::EPP::DCP::Purpose
482              
483             A set of values describing "the purposes for which data is collected"
484              
485             Like B<XML::EPP::DCP::Access>, this object has a bunch of boolean
486             properties. At least one must be set, but any number can be set at
487             once. They are (the following text is from RFC5730):
488              
489             =over
490              
491             =item B<admin>
492              
493             Administrative purposes. Information can be used for administrative
494             and technical support of the provisioning system.
495              
496             =item B<contact>
497              
498             Contact for marketing purposes. Information can be used to contact
499             individuals, through a communications channel other than the protocol,
500             for the promotion of a product or service.
501              
502             =item B<prov>
503              
504             Object-provisioning purposes. Information can be used to identify
505             objects and inter-object relationships.
506              
507             =item B<other>
508              
509             Other purposes. Information may be used in other ways not captured by
510             the above definitions.
511              
512             =back
513              
514             =head2 XML::EPP::DCP::Recipient
515              
516             For the most part, this object is like the other quasi-enum types,
517             B<XML::EPP::DCP::Access> and B<XML::EPP::DCP::Purpose>. This field
518              
519             describes the recipients of collected data
520              
521             This object has a collection of properties, most of which are boolean
522             like the other two classes. Like B<::Purpose> (but I<unlike>
523             B<::Access>), more than one may be set simultaneously. However, the
524             B<ours> property is an array of B<XML::EPP::DCP::Ours> objects, which
525             may be named entities, and appear multiple times.
526              
527             As such, there is a special case for the rule for this type when
528             coercing from C<ArrayRef[Str]> (ie, a list of strings); if an unknown
529             string appears, it is converted to a B<XML::EPP::DCP::Ours> object
530             with the B<name> property set to the passed-in value.
531              
532             Valid types of recipient (and hence, property names of this object)
533             are;
534              
535             =over
536              
537             =item B<other>
538              
539             Other entities following unknown practices.
540              
541             =item B<ours>
542              
543             Server operator and/or entities acting as agents or entities for whom
544             the server operator is acting as an agent. This property is an Array
545             Reference of L</XML::EPP::DCP::Ours> objects.
546              
547             =item B<public>
548              
549             Public forums.
550              
551             =item B<same>
552              
553             Other entities following server practices.
554              
555             =item B<unrelated>
556              
557             Unrelated third parties.
558              
559             =back
560              
561             =head2 XML::EPP::DCP::Ours
562              
563             As described in the previous section, an entry in the C<ours> array
564             property of a B<XML::EPP::DCP::Recipient> object.
565              
566             An agent in this instance is defined as
567             a third party that processes data only on behalf of the service
568             provider for the completion of the stated purposes.
569              
570             Properties: B<name> (optional Str; "used to describe the recipient")
571              
572             =head2 XML::EPP::DCP::Retention
573              
574             Another quasi-enum type, only a single property may be set at once for
575             this type. It specifies
576              
577             data retention practices
578              
579             So there you have it. The allowed types of practices, and hence
580             properties of this class, are:
581              
582             =over
583              
584             =item B<business>
585              
586             Data persists per business practices.
587              
588             =item B<indefinite>
589              
590             Data persists indefinitely.
591              
592             =item B<legal>
593              
594             Data persists per legal requirements.
595              
596             =item B<none>
597              
598             Data is not persistent and is not retained for more than a brief
599             period of time necessary to make use of it during the course of a
600             single online interaction.
601              
602             =item B<stated>
603              
604             Data persists to meet the stated purpose.
605              
606             =back
607              
608             =head2 XML::EPP::DCP::Expiry
609              
610             This specifies "the lifetime of the policy" and is optional.
611              
612             Properties: B<absolute> (an ISO-8601 dateTime eg
613             C<20100426T19:52+12>), B<relative> (an ISO-8601 duration eg C<PY2M52m>
614             for 2 years, 5 months, 2 minutes - mutually exclusive with
615             absolute)
616              
617             The subtype C<XML::EPP::dcpExpiryType> will happily co-erce from a
618             valid C<Str> which is already a valid ISO-8601 dateTime (the precise
619             subset of which is defined in the XML Schema specification). Values
620             accepted by L<MooseX::TimestampTZ> are also accepted.
621              
622             =head1 SEE ALSO
623              
624             L<XML::EPP>, L<XML::EPP::Greeting>
625              
626             =head1 AUTHOR AND LICENSE
627              
628             Development commissioned by NZ Registry Services, and carried out by
629             Catalyst IT - L<http://www.catalyst.net.nz/>
630              
631             Copyright 2009, 2010, NZ Registry Services. This module is licensed
632             under the Artistic License v2.0, which permits relicensing under other
633             Free Software licenses.
634              
635             =cut