From 2f67d4c5179c209375fd6c0117f0b36baa50034b Mon Sep 17 00:00:00 2001 From: Martin Renvoize Date: Thu, 31 Aug 2023 14:13:54 +0200 Subject: [PATCH] Bug 29523: Add redaction for inaccessible objects Content-Type: text/plain; charset=utf-8 This patch switches from removing inaccessible items from the responses to instead redacting fields in innaccessible responses. This allows for embed traversal and keeps counts etc correct but also hides the data we want to hide. We add support for an 'unredact_list' method at the Koha::* class level allowing for individual classes to specify which fields they wish to expose to restricted users regardless of their restriction. It is to be used in combination with the is_accessible method introduced earlier in this patchset which is used to denote whether the current user should be allowed to see the full record or only a subset of it as defined in the unredacted_list. We undefine any fields not listed in the unredact_list for the API response. This has the effect of still returning the full object of keys, but setting most fields to a JSON null. Signed-off-by: Jonathan Druart Signed-off-by: Marcel de Rooy --- Koha/Object.pm | 38 ++++++++++++++++++++++++++++++++---- Koha/Patron.pm | 13 +++++++++++- t/db_dependent/Koha/Object.t | 8 +++++--- 3 files changed, 51 insertions(+), 8 deletions(-) diff --git a/Koha/Object.pm b/Koha/Object.pm index c05a923cfe..560dccaff2 100644 --- a/Koha/Object.pm +++ b/Koha/Object.pm @@ -405,7 +405,6 @@ sub TO_JSON { elsif ( _numeric_column_type( $columns_info->{$col}->{data_type} ) and looks_like_number( $unblessed->{$col} ) ) { - # TODO: Remove once the solution for # https://github.com/perl5-dbi/DBD-mysql/issues/212 # is ported to whatever distro we support by that time @@ -415,7 +414,6 @@ sub TO_JSON { elsif ( _decimal_column_type( $columns_info->{$col}->{data_type} ) and looks_like_number( $unblessed->{$col} ) ) { - # TODO: Remove once the solution for # https://github.com/perl5-dbi/DBD-mysql/issues/212 # is ported to whatever distro we support by that time @@ -552,8 +550,6 @@ Returns a representation of the object, suitable for API output. sub to_api { my ( $self, $params ) = @_; - return unless $self->is_accessible($params); - my $json_object = $self->TO_JSON; # Make sure we duplicate the $params variable to avoid @@ -585,6 +581,23 @@ sub to_api { } } + # Remove forbidden attributes if required (including their coded values) + if ( !$self->is_accessible($params) ) { + for my $field ( keys %{$json_object} ) { + unless ( any { $_ eq $field } @{ $self->unredact_list } ) { + $json_object->{$field} = undef; + } + } + + if ($strings) { + foreach my $field ( keys %{$string_map} ) { + unless ( any { $_ eq $field } @{ $self->unredact_list } ) { + $string_map->{$field} = undef; + } + } + } + } + my $to_api_mapping = $self->to_api_mapping; # Rename attributes and coded values if there's a mapping @@ -717,6 +730,23 @@ sub public_read_list return []; } +=head3 unredact_list + + my @unredact_list = @{$object->unredact_list}; + +Generic method that returns the list of database columns that are allowed to +be passed to render objects on the API when the user making the request should +not ordinarily have unrestricted access to the data (as returned by the is_accesible method). + +Note: this only returns an empty I. Each class should have its +own implementation. + +=cut + +sub unredact_list { + return []; +} + =head3 from_api_mapping my $mapping = $object->from_api_mapping; diff --git a/Koha/Patron.pm b/Koha/Patron.pm index 102ac9e4f6..b466276ff0 100644 --- a/Koha/Patron.pm +++ b/Koha/Patron.pm @@ -2279,7 +2279,7 @@ sub set_default_messaging_preferences { if ( $patron->is_accessible({ user => $logged_in_user }) ) { ... } -This overloaded method validates wether the current I object can be accessed +This overloaded method validates whether the current I object can be accessed by the logged in user. Returns 0 if the I parameter is missing. @@ -2297,6 +2297,17 @@ sub is_accessible { return $consumer->can_see_patron_infos($self); } +=head3 unredact_list + +This method returns the list of database fields that should be visible, even for restricted users, +for both API and UI output purposes + +=cut + +sub unredact_list { + return ['branchcode']; +} + =head3 to_api my $json = $patron->to_api; diff --git a/t/db_dependent/Koha/Object.t b/t/db_dependent/Koha/Object.t index f890c22f74..ecf0bed621 100755 --- a/t/db_dependent/Koha/Object.t +++ b/t/db_dependent/Koha/Object.t @@ -554,7 +554,6 @@ subtest "to_api() tests" => sub { } ); - my $patron_1 = $builder->build_object( { class => 'Koha::Patrons', value => { branchcode => $library_1->id } } ); @@ -564,8 +563,11 @@ subtest "to_api() tests" => sub { t::lib::Mocks::mock_userenv( { patron => $patron } ); - is( ref($patron_1->to_api({ user => $patron })), 'HASH', 'Returns the object hash' ); - is( $patron_2->to_api({ user => $patron }), undef, 'Not accessible, returns undef' ); + is( + $patron_1->to_api( { user => $patron } )->{firstname}, $patron_1->firstname, + 'Returns unredacted object hash' + ); + is( $patron_2->to_api( { user => $patron } )->{firstname}, undef, 'Returns redacted object hash' ); $schema->storage->txn_rollback; }; -- 2.30.2