use MooseX::Types::Moose(':all');
use Scalar::Util('reftype');
use Data::Dumper;
+use Catalyst::Controller::DBIC::API::Validator;
use namespace::autoclean;
use Catalyst::Controller::DBIC::API::JoinBuilder;
=cut
-with 'MooseX::Role::BuildInstanceOf' =>
-{
- 'target' => 'Catalyst::Controller::DBIC::API::Validator',
- 'prefix' => 'search_validator',
-};
-
=attribute_private select_validator
A Catalyst::Controller::DBIC::API::Validator instance used solely to validate select parameters
=cut
-with 'MooseX::Role::BuildInstanceOf' =>
-{
- 'target' => 'Catalyst::Controller::DBIC::API::Validator',
- 'prefix' => 'select_validator',
-};
-
=attribute_private prefetch_validator
A Catalyst::Controller::DBIC::API::Validator instance used solely to validate prefetch parameters
=cut
-with 'MooseX::Role::BuildInstanceOf' =>
-{
- 'target' => 'Catalyst::Controller::DBIC::API::Validator',
- 'prefix' => 'prefetch_validator',
-};
+has [qw( search_validator select_validator )] => (
+ is => 'ro',
+ isa => 'Catalyst::Controller::DBIC::API::Validator',
+ lazy => 1,
+ builder => '_build_validator',
+);
+
+sub _build_validator {
+ return Catalyst::Controller::DBIC::API::Validator->new;
+}
parameter static => ( isa => Bool, default => 0 );
if($p->static)
{
- requires qw/check_has_relation check_column_relation/;
+ requires qw/check_has_relation check_column_relation prefetch_allows /;
}
else
{
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);
- }
},
);