1a20acf7dc7d02015570501d1749cf967a672251
[catagits/Catalyst-Controller-DBIC-API.git] / lib / Catalyst / Controller / DBIC / API / StaticArguments.pm
1 package Catalyst::Controller::DBIC::API::StaticArguments;
2
3 #ABSTRACT: Provides controller level configuration arguments
4 use Moose::Role;
5 use MooseX::Types::Moose(':all');
6 use namespace::autoclean;
7
8 requires 'check_column_relation';
9
10 =attribute_public create_requires create_allows update_requires update_allows
11
12 These attributes control requirements and limits to columns when creating or updating objects.
13
14 Each provides a number of handles:
15
16     "get_${var}_column" => 'get'
17     "set_${var}_column" => 'set'
18     "delete_${var}_column" => 'delete'
19     "insert_${var}_column" => 'insert'
20     "count_${var}_column" => 'count'
21     "all_${var}_columns" => 'elements'
22
23 =cut
24
25 foreach my $var (
26     qw( create_requires create_allows update_requires update_allows ))
27 {
28     has $var => (
29         is      => 'ro',
30         isa     => ArrayRef [ Str | HashRef ],
31         traits  => ['Array'],
32         default => sub { [] },
33         trigger => sub {
34             my ( $self, $new ) = @_;
35             $self->check_column_relation( $_, 1 ) for @$new;
36         },
37         handles => {
38             "get_${var}_column"    => 'get',
39             "set_${var}_column"    => 'set',
40             "delete_${var}_column" => 'delete',
41             "insert_${var}_column" => 'insert',
42             "count_${var}_column"  => 'count',
43             "all_${var}_columns"   => 'elements',
44         }
45     );
46
47     before "set_${var}_column" =>
48         sub { $_[0]->check_column_relation( $_[2], 1 ) };
49     before "insert_${var}_column" =>
50         sub { $_[0]->check_column_relation( $_[2], 1 ) };
51 }
52
53 =attribute_public prefetch_allows is: ro, isa: ArrayRef[ArrayRef|Str|HashRef]
54
55 prefetch_allows limits what relations may be prefetched when executing searches with joins. This is necessary to avoid denial of service attacks in form of queries which would return a large number of data and unwanted disclosure of data.
56
57 Like the synopsis in DBIC::API shows, you can declare a "template" of what is allowed (by using an '*'). Each element passed in, will be converted into a Data::DPath and added to the validator.
58
59     prefetch_allows => [ 'cds', { cds => tracks }, { cds => producers } ] # to be explicit
60     prefetch_allows => [ 'cds', { cds => '*' } ] # wildcard means the same thing
61
62 =cut
63
64 has 'prefetch_allows' => (
65     is        => 'ro',
66     writer    => '_set_prefetch_allows',
67     isa       => ArrayRef [ ArrayRef | Str | HashRef ],
68     default   => sub { [] },
69     predicate => 'has_prefetch_allows',
70     traits    => ['Array'],
71     handles   => { all_prefetch_allows => 'elements', },
72 );
73
74 has 'prefetch_validator' => (
75     is         => 'ro',
76     isa        => 'Catalyst::Controller::DBIC::API::Validator',
77     lazy_build => 1,
78 );
79
80 sub _build_prefetch_validator {
81     my $self = shift;
82
83     sub _check_rel {
84         my ( $self, $rel, $static, $validator ) = @_;
85         if ( ArrayRef->check($rel) ) {
86             foreach my $rel_sub (@$rel) {
87                 _check_rel( $self, $rel_sub, $static, $validator );
88             }
89         }
90         elsif ( HashRef->check($rel) ) {
91             while ( my ( $k, $v ) = each %$rel ) {
92                 $self->check_has_relation( $k, $v, undef, $static );
93             }
94             $validator->load($rel);
95         }
96         else {
97             $self->check_has_relation( $rel, undef, undef, $static );
98             $validator->load($rel);
99         }
100     }
101
102     my $validator = Catalyst::Controller::DBIC::API::Validator->new;
103
104     foreach my $rel ( $self->all_prefetch_allows ) {
105         _check_rel( $self, $rel, 1, $validator );
106     }
107
108     return $validator;
109 }
110
111 =attribute_public count_arg is: ro, isa: Str, default: 'list_count'
112
113 count_arg controls how to reference 'count' in the the request_data
114
115 =cut
116
117 has 'count_arg' => ( is => 'ro', isa => Str, default => 'list_count' );
118
119 =attribute_public page_arg is: ro, isa: Str, default: 'list_page'
120
121 page_arg controls how to reference 'page' in the the request_data
122
123 =cut
124
125 has 'page_arg' => ( is => 'ro', isa => Str, default => 'list_page' );
126
127 =attribute_public offset_arg is: ro, isa: Str, default: 'list_offset'
128
129 offset_arg controls how to reference 'offset' in the the request_data
130
131 =cut
132
133 has 'offset_arg' => ( is => 'ro', isa => Str, default => 'list_offset' );
134
135 =attribute_public select_arg is: ro, isa: Str, default: 'list_returns'
136
137 select_arg controls how to reference 'select' in the the request_data
138
139 =cut
140
141 has 'select_arg' => ( is => 'ro', isa => Str, default => 'list_returns' );
142
143 =attribute_public as_arg is: ro, isa: Str, default: 'as'
144
145 as_arg controls how to reference 'as' in the the request_data
146
147 =cut
148
149 has 'as_arg' => ( is => 'ro', isa => Str, default => 'as' );
150
151 =attribute_public search_arg is: ro, isa: Str, default: 'search'
152
153 search_arg controls how to reference 'search' in the the request_data
154
155 =cut
156
157 has 'search_arg' => ( is => 'ro', isa => Str, default => 'search' );
158
159 =attribute_public grouped_by_arg is: ro, isa: Str, default: 'list_grouped_by'
160
161 grouped_by_arg controls how to reference 'grouped_by' in the the request_data
162
163 =cut
164
165 has 'grouped_by_arg' =>
166     ( is => 'ro', isa => Str, default => 'list_grouped_by' );
167
168 =attribute_public ordered_by_arg is: ro, isa: Str, default: 'list_ordered_by'
169
170 ordered_by_arg controls how to reference 'ordered_by' in the the request_data
171
172 =cut
173
174 has 'ordered_by_arg' =>
175     ( is => 'ro', isa => Str, default => 'list_ordered_by' );
176
177 =attribute_public prefetch_arg is: ro, isa: Str, default: 'list_prefetch'
178
179 prefetch_arg controls how to reference 'prefetch' in the the request_data
180
181 =cut
182
183 has 'prefetch_arg' => ( is => 'ro', isa => Str, default => 'list_prefetch' );
184
185 =attribute_public stash_key is: ro, isa: Str, default: 'response'
186
187 stash_key controls where in stash request_data should be stored
188
189 =cut
190
191 has 'stash_key' => ( is => 'ro', isa => Str, default => 'response' );
192
193 =attribute_public data_root is: ro, isa: Str, default: 'list'
194
195 data_root controls how to reference where the data is in the the request_data
196
197 =cut
198
199 has 'data_root' => ( is => 'ro', isa => Str, default => 'list' );
200
201 =attribute_public item_root is: ro, isa: Str, default: 'data'
202
203 item_root controls how to reference where the data for single object
204 requests is in the the request_data
205
206 =cut
207
208 has 'item_root' => ( is => 'ro', isa => Str, default => 'data' );
209
210 =attribute_public total_entries_arg is: ro, isa: Str, default: 'totalcount'
211
212 total_entries_arg controls how to reference 'total_entries' in the the request_data
213
214 =cut
215
216 has 'total_entries_arg' =>
217     ( is => 'ro', isa => Str, default => 'totalcount' );
218
219 =attribute_public use_json_boolean is: ro, isa: Bool, default: 0
220
221 use_json_boolean controls whether JSON boolean types are used in the success parameter of the response or if raw strings are used
222
223 =cut
224
225 has 'use_json_boolean' => ( is => 'ro', isa => Bool, default => 0 );
226
227 =attribute_public return_object is: ro, isa: Bool, default: 0
228
229 return_object controls whether the results of create/update are serialized and returned in the response
230
231 =cut
232
233 has 'return_object' => ( is => 'ro', isa => Bool, default => 0 );
234
235 =head1 DESCRIPTION
236
237 StaticArguments is a Role that is composed by the controller to provide configuration parameters such as how where in the request data to find specific elements, and if to use JSON boolean types.
238
239 =cut
240
241 1;