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