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