ae53e0936d38699df98409b116f54d698183a6f1
[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 (qw/create_requires create_allows update_requires update_allows/)
26 {
27     has $var =>
28     (
29         is => 'ro',
30         isa => ArrayRef[Str|HashRef],
31         traits => ['Array'],
32         default => sub { [] },
33         trigger => sub
34         {
35             my ($self, $new) = @_;
36             $self->check_column_relation($_, 1) for @$new;
37         },
38         handles =>
39         {
40             "get_${var}_column" => 'get',
41             "set_${var}_column" => 'set',
42             "delete_${var}_column" => 'delete',
43             "insert_${var}_column" => 'insert',
44             "count_${var}_column" => 'count',
45             "all_${var}_columns" => 'elements',
46         }
47     );
48
49     before "set_${var}_column" => sub { $_[0]->check_column_relation($_[2], 1) }; #"
50     before "insert_${var}_column" => 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 =>
72     {
73         all_prefetch_allows => 'elements',
74     },
75 );
76
77 has 'prefetch_validator' => (
78     is => 'ro',
79     isa => 'Catalyst::Controller::DBIC::API::Validator',
80     lazy_build => 1,
81 );
82
83 sub _build_prefetch_validator {
84     my $self = shift;
85
86     sub _check_rel {
87         my ($self, $rel, $static, $validator) = @_;
88         if(ArrayRef->check($rel))
89         {
90             foreach my $rel_sub (@$rel)
91             {
92                 _check_rel($self, $rel_sub, $static, $validator);
93             }
94         }
95         elsif(HashRef->check($rel))
96         {
97             while(my($k,$v) = each %$rel)
98             {
99                 $self->check_has_relation($k, $v, undef, $static);
100             }
101             $validator->load($rel);
102         }
103         else
104         {
105             $self->check_has_relation($rel, undef, undef, $static);
106             $validator->load($rel);
107         }
108     }
109
110     my $validator = Catalyst::Controller::DBIC::API::Validator->new;
111
112     foreach my $rel ($self->all_prefetch_allows) {
113         _check_rel($self, $rel, 1, $validator);
114     }
115
116     return $validator;
117 }
118
119 =attribute_public count_arg is: ro, isa: Str, default: 'list_count'
120
121 count_arg controls how to reference 'count' in the the request_data
122
123 =cut
124
125 has 'count_arg' => ( is => 'ro', isa => Str, default => 'list_count' );
126
127 =attribute_public page_arg is: ro, isa: Str, default: 'list_page'
128
129 page_arg controls how to reference 'page' in the the request_data
130
131 =cut
132
133 has 'page_arg' => ( is => 'ro', isa => Str, default => 'list_page' );
134
135 =attribute_public offset_arg is: ro, isa: Str, default: 'offset'
136
137 offset_arg controls how to reference 'offset' in the the request_data
138
139 =cut
140
141 has 'offset_arg' => ( is => 'ro', isa => Str, default => 'list_offset' );
142
143 =attribute_public select_arg is: ro, isa: Str, default: 'list_returns'
144
145 select_arg controls how to reference 'select' in the the request_data
146
147 =cut
148
149 has 'select_arg' => ( is => 'ro', isa => Str, default => 'list_returns' );
150
151 =attribute_public as_arg is: ro, isa: Str, default: 'as'
152
153 as_arg controls how to reference 'as' in the the request_data
154
155 =cut
156
157 has 'as_arg' => ( is => 'ro', isa => Str, default => 'as' );
158
159 =attribute_public search_arg is: ro, isa: Str, default: 'search'
160
161 search_arg controls how to reference 'search' in the the request_data
162
163 =cut
164
165 has 'search_arg' => ( is => 'ro', isa => Str, default => 'search' );
166
167 =attribute_public grouped_by_arg is: ro, isa: Str, default: 'list_grouped_by'
168
169 grouped_by_arg controls how to reference 'grouped_by' in the the request_data
170
171 =cut
172
173 has 'grouped_by_arg' => ( is => 'ro', isa => Str, default => 'list_grouped_by' );
174
175 =attribute_public ordered_by_arg is: ro, isa: Str, default: 'list_ordered_by'
176
177 ordered_by_arg controls how to reference 'ordered_by' in the the request_data
178
179 =cut
180
181 has 'ordered_by_arg' => ( is => 'ro', isa => Str, default => 'list_ordered_by' );
182
183 =attribute_public prefetch_arg is: ro, isa: Str, default: 'list_prefetch'
184
185 prefetch_arg controls how to reference 'prefetch' in the the request_data
186
187 =cut
188
189 has 'prefetch_arg' => ( is => 'ro', isa => Str, default => 'list_prefetch' );
190
191 =attribute_public stash_key is: ro, isa: Str, default: 'response'
192
193 stash_key controls where in stash request_data should be stored
194
195 =cut
196
197 has 'stash_key' => ( is => 'ro', isa => Str, default => 'response');
198
199 =attribute_public data_root is: ro, isa: Str, default: 'list'
200
201 data_root controls how to reference where the data is in the the request_data
202
203 =cut
204
205 has 'data_root' => ( is => 'ro', isa => Str, default => 'list');
206
207 =attribute_public item_root is: ro, isa: Str, default: 'data'
208
209 item_root controls how to reference where the data for single object
210 requests is in the the request_data
211
212 =cut
213
214 has 'item_root' => ( is => 'ro', isa => Str, default => 'data');
215
216 =attribute_public total_entries_arg is: ro, isa: Str, default: 'totalcount'
217
218 total_entries_arg controls how to reference 'total_entries' in the the request_data
219
220 =cut
221
222 has 'total_entries_arg' => ( is => 'ro', isa => Str, default => 'totalcount' );
223
224 =attribute_public use_json_boolean is: ro, isa: Bool, default: 0
225
226 use_json_boolean controls whether JSON boolean types are used in the success parameter of the response or if raw strings are used
227
228 =cut
229
230 has 'use_json_boolean' => ( is => 'ro', isa => Bool, default => 0 );
231
232 =attribute_public return_object is: ro, isa: Bool, default: 0
233
234 return_object controls whether the results of create/update are serialized and returned in the response
235
236 =cut
237
238 has 'return_object' => ( is => 'ro', isa => Bool, default => 0 );
239
240 =head1 DESCRIPTION
241
242 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.
243
244 =cut
245
246 1;