From: Alexander Hartmaier Date: Thu, 5 May 2011 14:12:09 +0000 (+0200) Subject: moved prefetch_allows to StaticArguments to fix controller instantiation failures... X-Git-Tag: 2.003002~2 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=4e5983f2a904f894762e61c2dff962a37da5ef92;p=catagits%2FCatalyst-Controller-DBIC-API.git moved prefetch_allows to StaticArguments to fix controller instantiation failures with Moose 2 where the validator template wasn't loaded before used by the prefetch trigger --- diff --git a/Changes b/Changes index 6b9e2a6..e1f5098 100644 --- a/Changes +++ b/Changes @@ -4,6 +4,7 @@ Revision history for Catalyst-Controller-DBIC-API: {{ $dist->version }} - Added has_errors method - Fixed tests to succeed with newer DBIx::Class versions +- Fixed controller instantiation failures with Moose 2 in relation to prefetch 2.003001 2011-02-16 17:52:37 Europe/Vienna diff --git a/lib/Catalyst/Controller/DBIC/API.pm b/lib/Catalyst/Controller/DBIC/API.pm index b9a53d0..aa75619 100644 --- a/lib/Catalyst/Controller/DBIC/API.pm +++ b/lib/Catalyst/Controller/DBIC/API.pm @@ -27,8 +27,9 @@ sub _build__json { } with 'Catalyst::Controller::DBIC::API::StoredResultSource', - 'Catalyst::Controller::DBIC::API::StaticArguments', - 'Catalyst::Controller::DBIC::API::RequestArguments' => { static => 1 }; + 'Catalyst::Controller::DBIC::API::StaticArguments'; + +with 'Catalyst::Controller::DBIC::API::RequestArguments' => { static => 1 }; __PACKAGE__->config(); diff --git a/lib/Catalyst/Controller/DBIC/API/Request.pm b/lib/Catalyst/Controller/DBIC/API/Request.pm index af7cff6..71aceb2 100644 --- a/lib/Catalyst/Controller/DBIC/API/Request.pm +++ b/lib/Catalyst/Controller/DBIC/API/Request.pm @@ -34,12 +34,13 @@ has '_controller' => $self->_set_class($new->class) if defined($new->class); $self->_set_application($new->_application); - $self->_set_prefetch_allows($new->prefetch_allows); $self->_set_search_exposes($new->search_exposes); $self->_set_select_exposes($new->select_exposes); - } + }, + handles => ['prefetch_validator'], ); + with 'Catalyst::Controller::DBIC::API::StoredResultSource', 'Catalyst::Controller::DBIC::API::RequestArguments', 'Catalyst::Controller::DBIC::API::Request::Context'; diff --git a/lib/Catalyst/Controller/DBIC/API/RequestArguments.pm b/lib/Catalyst/Controller/DBIC/API/RequestArguments.pm index a6939f2..523c07f 100644 --- a/lib/Catalyst/Controller/DBIC/API/RequestArguments.pm +++ b/lib/Catalyst/Controller/DBIC/API/RequestArguments.pm @@ -29,7 +29,7 @@ A Catalyst::Controller::DBIC::API::Validator instance used solely to validate pr =cut -has [qw( search_validator select_validator prefetch_validator )] => ( +has [qw( search_validator select_validator )] => ( is => 'ro', isa => 'Catalyst::Controller::DBIC::API::Validator', lazy => 1, @@ -48,7 +48,7 @@ role { if($p->static) { - requires qw/check_has_relation check_column_relation/; + requires qw/check_has_relation check_column_relation prefetch_allows /; } else { @@ -145,80 +145,20 @@ prefetch is passed to ->search to optimize the number of database fetches for jo trigger => sub { my ($self, $new) = @_; - if($self->has_prefetch_allows and @{$self->prefetch_allows}) - { - foreach my $pf (@$new) - { - if(HashRef->check($pf)) - { - die qq|'${\Dumper($pf)}' is not an allowed prefetch in: ${\join("\n", @{$self->prefetch_validator->templates})}| - unless $self->prefetch_validator->validate($pf)->[0]; - } - else - { - die qq|'$pf' is not an allowed prefetch in: ${\join("\n", @{$self->prefetch_validator->templates})}| - unless $self->prefetch_validator->validate({$pf => 1})->[0]; - } - } - } - else - { - return if not defined($new); - die 'Prefetching is not allowed' if @$new; - } - }, - ); - -=attribute_public prefetch_allows is: ro, isa: ArrayRef[ArrayRef|Str|HashRef] - -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. -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. - - prefetch_allows => [ 'cds', { cds => tracks }, { cds => producers } ] # to be explicit - prefetch_allows => [ 'cds', { cds => '*' } ] # wildcard means the same thing - -=cut - - has prefetch_allows => - ( - is => 'ro', - writer => '_set_prefetch_allows', - isa => ArrayRef[ArrayRef|Str|HashRef], - default => sub { [ ] }, - predicate => 'has_prefetch_allows', - trigger => sub - { - my ($self, $new) = @_; - - sub _check_rel { - my ($self, $rel, $static) = @_; - if(ArrayRef->check($rel)) - { - foreach my $rel_sub (@$rel) - { - $self->_check_rel($rel_sub, $static); - } - } - elsif(HashRef->check($rel)) + foreach my $pf (@$new) + { + if(HashRef->check($pf)) { - while(my($k,$v) = each %$rel) - { - $self->check_has_relation($k, $v, undef, $static); - } - $self->prefetch_validator->load($rel); + die qq|'${\Dumper($pf)}' is not an allowed prefetch in: ${\join("\n", @{$self->prefetch_validator->templates})}| + unless $self->prefetch_validator->validate($pf)->[0]; } else { - $self->check_has_relation($rel, undef, undef, $static); - $self->prefetch_validator->load($rel); + die qq|'$pf' is not an allowed prefetch in: ${\join("\n", @{$self->prefetch_validator->templates})}| + unless $self->prefetch_validator->validate({$pf => 1})->[0]; } } - - foreach my $rel (@$new) - { - $self->_check_rel($rel, $p->static); - } }, ); diff --git a/lib/Catalyst/Controller/DBIC/API/StaticArguments.pm b/lib/Catalyst/Controller/DBIC/API/StaticArguments.pm index e2c2c90..ae53e09 100644 --- a/lib/Catalyst/Controller/DBIC/API/StaticArguments.pm +++ b/lib/Catalyst/Controller/DBIC/API/StaticArguments.pm @@ -50,6 +50,72 @@ foreach my $var (qw/create_requires create_allows update_requires update_allows/ before "insert_${var}_column" => sub { $_[0]->check_column_relation($_[2], 1) }; #" } +=attribute_public prefetch_allows is: ro, isa: ArrayRef[ArrayRef|Str|HashRef] + +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. + +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. + + prefetch_allows => [ 'cds', { cds => tracks }, { cds => producers } ] # to be explicit + prefetch_allows => [ 'cds', { cds => '*' } ] # wildcard means the same thing + +=cut + +has 'prefetch_allows' => ( + is => 'ro', + writer => '_set_prefetch_allows', + isa => ArrayRef[ArrayRef|Str|HashRef], + default => sub { [ ] }, + predicate => 'has_prefetch_allows', + traits => ['Array'], + handles => + { + all_prefetch_allows => 'elements', + }, +); + +has 'prefetch_validator' => ( + is => 'ro', + isa => 'Catalyst::Controller::DBIC::API::Validator', + lazy_build => 1, +); + +sub _build_prefetch_validator { + my $self = shift; + + sub _check_rel { + my ($self, $rel, $static, $validator) = @_; + if(ArrayRef->check($rel)) + { + foreach my $rel_sub (@$rel) + { + _check_rel($self, $rel_sub, $static, $validator); + } + } + elsif(HashRef->check($rel)) + { + while(my($k,$v) = each %$rel) + { + $self->check_has_relation($k, $v, undef, $static); + } + $validator->load($rel); + } + else + { + $self->check_has_relation($rel, undef, undef, $static); + $validator->load($rel); + } + } + + my $validator = Catalyst::Controller::DBIC::API::Validator->new; + + foreach my $rel ($self->all_prefetch_allows) { + _check_rel($self, $rel, 1, $validator); + } + + return $validator; +} + =attribute_public count_arg is: ro, isa: Str, default: 'list_count' count_arg controls how to reference 'count' in the the request_data