File Coverage

lib/OAuthomatic/Types.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             ## no critic (ProhibitMultiplePackages, RequireFilenameMatchesPackage, RequireUseWArnings, RequireUseStrict, RequireExplicitPackage)
3              
4             =head1 NAME
5              
6             OAuthomatic::Types - few helper types to make code more readable and less error-prone
7              
8             =head1 DESCRIPTION
9              
10             Types below are defined to make code a bit more readable and less error prone.
11              
12             =cut
13              
14             =head1 OAuthomatic::Types::StructBase
15              
16             Role composed into types defined below. Handles a few common
17             conventions.
18              
19             =head2 METHODS
20              
21             =head3 new
22              
23             Adds two conventions to usual parameter handling:
24              
25             =over 4
26              
27             =item *
28              
29             Any empty or undef'ed values given to the constructor are dropped as
30             if they were not specified at all.
31              
32             =item *
33              
34             If args C<data> and C<remap> are given to the constructor, they are
35             used to translate field names, for example:
36              
37             Something->new(data=>{aaa=>'x', bbb=>'y'},
38             remap=>{aaa=>'token', 'bbb'=>'secret');
39              
40             is equivalent to:
41              
42             Something->new(token=>'x', secret=>'y');
43              
44             Partial replacements are possible too:
45              
46             Something->new(data=>{token=>'x', bbb=>'y'},
47             remap=>{'bbb'=>'secret');
48              
49             =back
50              
51             =head3 Class->of_my_type(obj)
52              
53             Checks whether given object is of given structure type. Returns 1 if so, 0 if it is undef,
54             throws if it is of another type.
55              
56             =head2 Class->equal(obj1, obj2)
57              
58             Compares two objects, allowing undef-s but raises on wrong type.
59              
60             =cut
61              
62             {
63             package OAuthomatic::Types::StructBase;
64 1     1   827 use Moose::Role;
  0            
  0            
65             use OAuthomatic::Error;
66             use Scalar::Util qw(blessed);
67             use namespace::sweep;
68              
69             around BUILDARGS => sub {
70             my $orig = shift;
71             my $class = shift;
72             my $ret = $class->$orig(@_);
73              
74             # Drop empty values (FIXME: this is close to MooseX::UndefTolerant)
75             foreach my $key (keys %$ret) {
76             my $val = $ret->{$key};
77             unless(defined($val) && $val =~ /./x) {
78             delete $ret->{$key};
79             }
80             }
81              
82             # Remap names
83             if(exists $ret->{remap}) {
84             my $remap = $ret->{remap};
85             my $data = $ret->{data} or
86             OAuthomatic::Error::Generic->throw(
87             ident => "Bad call",
88             extra => "No data given in spite remap is specified");
89             delete $ret->{remap};
90             delete $ret->{data};
91             my %data_unconsumed = %$data; # To delete consumed keys
92             foreach my $mapped (keys %$remap) {
93             my $mapped_to = $remap->{$mapped};
94             my $value = $data->{$mapped}
95             or OAuthomatic::Error::Generic->throw(
96             ident => "Missing parameter",
97             extra => "Missing $mapped (while constructing $class). Known keys: ") . join(", ", keys %$data) . "\n";
98             delete $data_unconsumed{$mapped};
99             $ret->{$mapped_to} = $value;
100             }
101             # Copy unmapped data verbatim
102             while (my ($k, $v) = each %data_unconsumed) {
103             $ret->{$k} = $v;
104             }
105             }
106             return $ret;
107             };
108              
109             sub of_my_type {
110             my ($class, $obj) = @_;
111             return '' if ! defined($obj);
112             my $pkg = blessed($obj);
113             unless( $pkg ) {
114             OAuthomatic::Error::Generic->throw(
115             ident => "Bad parameter", extra => "Wrong object type (expected $class, got non-blessed scalar)");
116             }
117             return 1 if $obj->isa($class);
118             return OAuthomatic::Error::Generic->throw(
119             ident => "Bad parameter", extra => "Wrong object type (expected $class, got $pkg)");
120             }
121             };
122              
123             =head1 OAuthomatic::Types::ClientCred
124              
125             Client (application) credentials. Fixed key and secret allocated manually
126             using server web interface (usually after filling some form with various
127             details) which identify the application.
128              
129             =head2 ATTRIBUTES
130              
131             =over 4
132              
133             =item key
134              
135             Client key - the application identifier.
136              
137             =item secret
138              
139             Client secret - confidential value used to sign requests, to prove key
140             is valid.
141              
142             =back
143              
144             =cut
145              
146             {
147             package OAuthomatic::Types::ClientCred;
148             use Moose;
149             with 'OAuthomatic::Types::StructBase';
150              
151             has 'key' => (is => 'ro', isa => 'Str', required => 1);
152             has 'secret' => (is => 'ro', isa => 'Str', required => 1);
153              
154             sub as_hash {
155             my ($self, $prefix) = @_;
156             return (
157             $prefix . '_key' => $self->key,
158             $prefix . '_secret' => $self->secret,
159             );
160             }
161              
162             sub equal {
163             my ($class, $left, $right) = @_;
164             # Croaks of mismatches, false on undefs
165             return '' unless $class->of_my_type($left) && $class->of_my_type($right);
166             # Compare all fields
167             return ($left->key eq $right->key) && ($left->secret eq $right->secret);
168             }
169              
170             };
171              
172             # Common implementation for two classes below
173             {
174             package OAuthomatic::Types::GenericTokenCred;
175             use Moose;
176             with 'OAuthomatic::Types::StructBase';
177              
178             has 'token' => (is => 'ro', isa => 'Str', required => 1);
179             has 'secret' => (is => 'ro', isa => 'Str', required => 1);
180              
181             sub as_hash {
182             my $self = shift;
183             return (
184             token => $self->token,
185             token_secret => $self->secret,
186             );
187             }
188              
189             sub equal {
190             my ($class, $left, $right) = @_;
191             # Croaks of mismatches, 0 on undefs
192             return '' unless $class->of_my_type($left) && $class->of_my_type($right);
193             # Compare all fields
194             return ($left->token eq $right->token) && ($left->secret eq $right->secret);
195             }
196             };
197              
198             =head1 OAuthomatic::Types::TemporaryCred
199              
200             Temporary (request) credentials. Used during process of allocating
201             token credentials.
202              
203             =head2 ATTRIBUTES
204              
205             =over 4
206              
207             =item token
208              
209             Actual token - identifier quoted in requests.
210              
211             =item secret
212              
213             Associated secret - confidential value used to sign requests, to prove they
214             are valid.
215              
216             =item authorize_page
217              
218             Full URL of the page end user should use to spend this temporary credential
219             and generate access token. Already contains the token.
220              
221             =back
222              
223             =cut
224             {
225             package OAuthomatic::Types::TemporaryCred;
226             use Moose;
227             extends 'OAuthomatic::Types::GenericTokenCred';
228              
229             # This is rw and not required as we append it after initial object creation
230             has 'authorize_page' => (is => 'rw', isa => 'URI', required => 0);
231             };
232              
233              
234             =head1 OAuthomatic::Types::TokenCred
235              
236             Token (access) credentials. Those are used to sign actual API calls.
237              
238             =cut
239              
240             {
241             package OAuthomatic::Types::TokenCred;
242             use Moose;
243             extends 'OAuthomatic::Types::GenericTokenCred';
244             };
245              
246             =head1 OAuthomatic::Types::Verifier
247              
248             Verifier info, returned from authorization.
249              
250             =cut
251              
252             {
253             package OAuthomatic::Types::Verifier;
254             use Moose;
255             with 'OAuthomatic::Types::StructBase';
256              
257             has 'token' => (is => 'ro', isa => 'Str', required => 1);
258             has 'verifier' => (is => 'ro', isa => 'Str', required => 1);
259              
260             sub equal {
261             my ($class, $left, $right) = @_;
262             # Croaks of mismatches, 0 on undefs
263             return '' unless $class->of_my_type($left) && $class->of_my_type($right);
264             # Compare all fields
265             return ($left->token eq $right->token) && ($left->verifier eq $right->verifier);
266             }
267             };
268              
269             1;