@@ -, +, @@ --- Koha/Object.pm | 38 ++++++++++++++++++++++++++++++++---- Koha/Patron.pm | 13 +++++++++++- t/db_dependent/Koha/Object.t | 8 +++++--- 3 files changed, 51 insertions(+), 8 deletions(-) --- a/Koha/Object.pm +++ a/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; --- a/Koha/Patron.pm +++ a/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; --- a/t/db_dependent/Koha/Object.t +++ a/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; }; --