From a2d54a87eaee14ef8f767ac84e04bd8c9fcbdac8 Mon Sep 17 00:00:00 2001 From: Martin Renvoize Date: Wed, 5 Jun 2024 14:19:54 +0100 Subject: [PATCH] [23.11.x] Bug 37018: Add validation method to Koha::REST::Plugin::Query.pm Signed-off-by: Tomas Cohen Arazi Signed-off-by: Martin Renvoize Signed-off-by: Jonathan Druart --- Koha/REST/Plugin/Query.pm | 67 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/Koha/REST/Plugin/Query.pm b/Koha/REST/Plugin/Query.pm index 7aa092fae25..9fe17156e2a 100644 --- a/Koha/REST/Plugin/Query.pm +++ b/Koha/REST/Plugin/Query.pm @@ -23,6 +23,7 @@ use Scalar::Util qw( reftype ); use JSON qw( decode_json ); use Koha::Exceptions; +use Koha::Exceptions::REST; =head1 NAME @@ -159,6 +160,21 @@ Generates the DBIC prefetch attribute based on embedded relations, and merges in } ); +=head3 dbic_validate_operators + + $attributes = $c->dbic_validate_operators( { filtered_params => $filtered_params } ); + +Validate operators in the passed query. + +=cut + + $app->helper( + 'dbic_validate_operators' => sub { + my ( $c, $args ) = @_; + _validate_query( $args->{filtered_params} ); + } + ); + =head3 _build_query_params_from_api my $params = _build_query_params_from_api( $filtered_params, $reserved_params ); @@ -489,4 +505,55 @@ sub _parse_dbic_query { } +=head3 _validate_operator + +=cut + +sub _validate_operator { + my ($operator) = @_; + my %allowed_operators = map { $_ => 1 } qw(= != < > <= >= like -not_like -in -ident -bool -not_bool -or); + Koha::Exceptions::REST::Query::InvalidOperator->throw( operator => $operator ) + unless exists $allowed_operators{$operator}; + return; +} + +=head3 _validate_query + +=cut + +sub _validate_query { + my ($query) = @_; + + if ( ref $query eq 'HASH' ) { + for my $field ( keys %$query ) { + my $value = $query->{$field}; + + if ( ref $value eq 'HASH' ) { + + # Hash reference with operators + for my $operator ( keys %$value ) { + _validate_operator($operator); + } + } elsif ( ref $value eq 'ARRAY' ) { + + # Array reference with operator as the first element + _validate_query($value); + } else { + + # Simple key-value pairs (no operator to validate) + } + } + } elsif ( ref $query eq 'ARRAY' ) { + + # Top-level OR combination or nested AND combination + for my $element (@$query) { + if ( ref $element eq 'ARRAY' && $element->[0] eq '-and' ) { + _validate_query( $element->[1] ); + } else { + _validate_query($element); + } + } + } +} + 1; -- 2.45.2