From a06917369c7fe463c1dae9d59dc98cbbd350cd82 Mon Sep 17 00:00:00 2001 From: Tomas Cohen Arazi Date: Thu, 18 Mar 2021 15:15:13 -0300 Subject: [PATCH] Bug 23666: Add extended attributes routes This patch adds routes to handle patron's extended attributes: GET /patrons/:patron_id/extended_attributes POST /patrons/:patron_id/extended_attributes PUT /patrons/:patron_id/extended_attributes <- to overwrite them all DELETE /patrons/:patron_id/extended_attributes/:extended_attribute_id Controllers rely on the Koha::Patron methods for retrieving/adding extended attributes. Exceptions are correctly catch and handled in the responses. This is all covered by tests as well. Note: I decidedto override the default sorting on the PUT response, because the overloaded search sorting it felt a bit wrong on the API. To test: 1. Apply this patches 2. Run: $ kshell k$ prove t/db_dependent/api/v1/patrons_extended_attributes.t => SUCCESS: Tests pass! 3. Play with your favourite tool and this routes => SUCCESS: They work well! 4. Sign off :-D --- Koha/REST/V1/Patrons/Attributes.pm | 270 +++++++++++++++++++++++++++++ 1 file changed, 270 insertions(+) create mode 100644 Koha/REST/V1/Patrons/Attributes.pm diff --git a/Koha/REST/V1/Patrons/Attributes.pm b/Koha/REST/V1/Patrons/Attributes.pm new file mode 100644 index 00000000000..2132ec0a047 --- /dev/null +++ b/Koha/REST/V1/Patrons/Attributes.pm @@ -0,0 +1,270 @@ +package Koha::REST::V1::Patrons::Attributes; + +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# Koha is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Koha; if not, see . + +use Modern::Perl; + +use Mojo::Base 'Mojolicious::Controller'; + +use Koha::Patron::Attributes; +use Koha::Patrons; + +use Scalar::Util qw(blessed); +use Try::Tiny; + +=head1 NAME + +Koha::REST::V1::Patrons::Attributes + +=head1 API + +=head2 Methods + +=head3 list_patron_attributes + +Controller method that handles listing the Koha::Patron::Attribute objects that belong +to a given patron. + +=cut + +sub list_patron_attributes { + my $c = shift->openapi->valid_input or return; + + my $patron = Koha::Patrons->find( $c->validation->param('patron_id') ); + + unless ($patron) { + return $c->render( + status => 404, + openapi => { + error => 'Patron not found' + } + ); + } + + return try { + + my $attributes_rs = $patron->extended_attributes; + my $attributes = $c->objects->search($attributes_rs); + + return $c->render( + status => 200, + openapi => $attributes + ); + } + catch { + $c->unhandled_exception($_); + }; +} + +=head3 add + +Controller method that handles adding a Koha::Patron::Attribute to a given patron. + +=cut + +sub add { + my $c = shift->openapi->valid_input or return; + + my $patron = Koha::Patrons->find( $c->validation->param('patron_id') ); + + unless ($patron) { + return $c->render( + status => 404, + openapi => { + error => 'Patron not found' + } + ); + } + + return try { + + my $attribute = $patron->add_extended_attribute( + Koha::Patron::Attribute->new_from_api( # new_from_api takes care of mapping attributes + $c->validation->param('body') + )->unblessed + ); + + $c->res->headers->location( $c->req->url->to_string . '/' . $attribute->id ); + return $c->render( + status => 201, + openapi => $attribute->to_api + ); + } + catch { + if ( blessed $_ ) { + if ( + $_->isa( + 'Koha::Exceptions::Patron::Attribute::UniqueIDConstraint') + ) + { + return $c->render( + status => 409, + openapi => { + error => "$_" + } + ); + } + elsif ( + $_->isa('Koha::Exceptions::Patron::Attribute::NonRepeatable') ) + { + return $c->render( + status => 409, + openapi => { + error => "$_" + } + ); + } + elsif ( + $_->isa('Koha::Exceptions::Patron::Attribute::InvalidType') ) + { + return $c->render( + status => 400, + openapi => { error => "$_" } + ); + } + } + + $c->unhandled_exception($_); + }; +} + +=head3 overwrite + +Controller method that handles overwriting extended attributes for a given patron. + +=cut + +sub overwrite { + my $c = shift->openapi->valid_input or return; + + my $patron = Koha::Patrons->find( $c->validation->param('patron_id') ); + + unless ($patron) { + return $c->render( + status => 404, + openapi => { + error => 'Patron not found' + } + ); + } + + return try { + + my $body = $c->validation->every_param('body'); + + my @attrs; + + foreach my $attr ( @{$body} ) { + push @attrs, { code => $attr->{type}, attribute => $attr->{value} }; + } + + # Fetch the attributes, sorted by id + my $attributes = $patron->extended_attributes( \@attrs )->search( undef, { order_by => 'id' }); + + return $c->render( + status => 200, + openapi => $attributes->to_api + ); + } + catch { + if ( blessed $_ ) { + if ( $_->isa('Koha::Exceptions::Patron::Attribute::InvalidType') ) { + return $c->render( + status => 400, + openapi => { error => "$_" } + ); + + } + elsif ( + $_->isa( + 'Koha::Exceptions::Patron::Attribute::UniqueIDConstraint') + ) + { + return $c->render( + status => 409, + openapi => { error => "$_" } + ); + } + elsif ( + $_->isa('Koha::Exceptions::Patron::Attribute::NonRepeatable') ) + { + return $c->render( + status => 409, + openapi => { error => "$_" } + ); + } + elsif ( $_->isa('Koha::Exceptions::Object::FKConstraint') ) { + return $c->render( + status => 400, + openapi => { + error => 'Missing mandatory attribute of type "' + . $_->value . '".' + } + ); + + } + } + + $c->unhandled_exception($_); + }; +} + +=head3 delete + +Controller method that handling removing an extended patron attribute + +=cut + +sub delete { + my $c = shift->openapi->valid_input or return; + + my $patron = Koha::Patrons->find( $c->validation->param('patron_id') ); + + unless ($patron) { + return $c->render( + status => 404, + openapi => { + error => 'Patron not found' + } + ); + } + + return try { + + my $attribute = $patron->extended_attributes->find( + $c->validation->param('extended_attribute_id') ); + + unless ($attribute) { + return $c->render( + status => 404, + openapi => { + error => 'Attribute not found' + } + ); + } + + $attribute->delete; + return $c->render( + status => 204, + openapi => q{} + ); + } + catch { + $c->unhandled_exception($_); + }; +} + +1; -- 2.31.0