From 6fc014670d32915a485b45d05967665d4c917307 Mon Sep 17 00:00:00 2001 From: Agustin Moyano Date: Tue, 20 Dec 2022 15:28:04 -0300 Subject: [PATCH] Bug 31796: Add REST endpoint to modify an authority To test: 1. Apply patch 2. Set RESTBasicAuth preference to true 3. Pick an authority to modify, and modify it's marc record 4. Make a PUT request to /api/v1/authorities/:authid with one of the following content type header - application/json - application/marcxml+xml - application/marc-in-json - application/marc 5. If content type is other than 'application/json' place the following header in the request 'x-authority-type: ' 5. Check that the authority was modified 6. Sign off Signed-off-by: David Nind --- Koha/REST/V1/Authorities.pm | 62 ++++++++++++++++++- api/v1/swagger/paths/authorities.yaml | 51 ++++++++++++++++ t/db_dependent/api/v1/authorities.t | 88 ++++++++++++++++++++++++++- 3 files changed, 199 insertions(+), 2 deletions(-) mode change 100755 => 100644 t/db_dependent/api/v1/authorities.t diff --git a/Koha/REST/V1/Authorities.pm b/Koha/REST/V1/Authorities.pm index b46be125b7..2bbab6a6a3 100644 --- a/Koha/REST/V1/Authorities.pm +++ b/Koha/REST/V1/Authorities.pm @@ -20,7 +20,7 @@ use Modern::Perl; use Mojo::Base 'Mojolicious::Controller'; use Koha::Authorities; -use C4::AuthoritiesMarc qw( DelAuthority AddAuthority FindDuplicateAuthority); +use C4::AuthoritiesMarc qw( DelAuthority AddAuthority FindDuplicateAuthority ModAuthority); use List::MoreUtils qw( any ); use MARC::Record::MiJ; @@ -193,4 +193,64 @@ sub add { }; } + +=head3 update + +Controller function that handles modifying an authority object + +=cut + +sub update { + my $c = shift->openapi->valid_input or return; + + my $authid = $c->validation->param('authority_id'); + my $authority = Koha::Authorities->find( { authid => $authid } ); + + if ( not defined $authority ) { + return $c->render( + status => 404, + openapi => { error => "Object not found" } + ); + } + + try { + my $headers = $c->req->headers; + + my $flavour = + C4::Context->preference('marcflavour') eq 'UNIMARC' + ? 'UNIMARCAUTH' + : 'MARC21'; + + my $record; + my $authtypecode = $headers->header('x-authority-type') || $authority->authtypecode; + if ( $c->req->headers->content_type =~ m/application\/marcxml\+xml/ ) { + $record = MARC::Record->new_from_xml( $c->req->body, 'UTF-8', $flavour ); + } elsif ( $c->req->headers->content_type =~ m/application\/marc-in-json/ ) { + $record = MARC::Record->new_from_mij_structure( $c->req->json ); + } elsif ( $c->req->headers->content_type =~ m/application\/marc/ ) { + $record = MARC::Record->new_from_usmarc( $c->req->body ); + } else { + return $c->render( + status => 406, + openapi => [ + "application/json", + "application/marcxml+xml", + "application/marc-in-json", + "application/marc" + ] + ); + } + + my $authid = ModAuthority( $authid, $record, $authtypecode ); + + $c->render( + status => 200, + openapi => { id => $authid } + ); + } + catch { + $c->unhandled_exception($_); + }; +} + 1; diff --git a/api/v1/swagger/paths/authorities.yaml b/api/v1/swagger/paths/authorities.yaml index 45a18cc217..b2a3b7f334 100644 --- a/api/v1/swagger/paths/authorities.yaml +++ b/api/v1/swagger/paths/authorities.yaml @@ -163,3 +163,54 @@ x-koha-authorization: permissions: editauthorities: "1" + put: + x-mojo-to: Authorities#update + operationId: updateAuthority + tags: + - authorities + summary: Update authority + parameters: + - $ref: "../swagger.yaml#/parameters/authority_id_pp" + - $ref: "../swagger.yaml#/parameters/authority_type_header" + produces: + - application/json + responses: + "200": + description: An authority id + "400": + description: Bad request + schema: + $ref: "../swagger.yaml#/definitions/error" + "401": + description: Authentication required + schema: + $ref: "../swagger.yaml#/definitions/error" + "403": + description: Access forbidden + schema: + $ref: "../swagger.yaml#/definitions/error" + "404": + description: Authority not found + schema: + $ref: "../swagger.yaml#/definitions/error" + "406": + description: Not acceptable + schema: + type: array + description: Accepted content-types + items: + type: string + "500": + description: | + Internal server error. Possible `error_code` attribute values: + + * `internal_server_error` + schema: + $ref: "../swagger.yaml#/definitions/error" + "503": + description: Under maintenance + schema: + $ref: "../swagger.yaml#/definitions/error" + x-koha-authorization: + permissions: + editauthorities: "1" diff --git a/t/db_dependent/api/v1/authorities.t b/t/db_dependent/api/v1/authorities.t old mode 100755 new mode 100644 index 8c8056323b..9524d53614 --- a/t/db_dependent/api/v1/authorities.t +++ b/t/db_dependent/api/v1/authorities.t @@ -20,7 +20,7 @@ use Modern::Perl; use utf8; use Encode; -use Test::More tests => 3; +use Test::More tests => 4; use Test::MockModule; use Test::Mojo; use Test::Warn; @@ -228,3 +228,89 @@ subtest 'post() tests' => sub { $schema->storage->txn_rollback; }; + +subtest 'put() tests' => sub { + + plan tests => 14; + + $schema->storage->txn_begin; + + Koha::Authorities->delete; + + my $record; + my $subfield_a; + + my $patron = $builder->build_object( + { + class => 'Koha::Patrons', + value => { flags => 0 } # no permissions + } + ); + my $password = 'thePassword123'; + $patron->set_password( { password => $password, skip_validation => 1 } ); + my $userid = $patron->userid; + + my $authority = $builder->build_object({ 'class' => 'Koha::Authorities', value => { + marcxml => q| + + 1001 + + 102 + My Corporation + +| + } }); + + my $authid = $authority->authid; + my $authtypecode = $authority->authtypecode; + + my $marcxml = q| + + 1001 + + 102 + MARCXML + +|; + + my $mij = '{"fields":[{"001":"1001"},{"110":{"subfields":[{"9":"102"},{"a":"MIJ"}],"ind1":" ","ind2":" "}}],"leader":" "}'; + my $marc = '00079 2200049 45000010005000001100024000051001 9102aUSMARCFormated'; + + $t->put_ok("//$userid:$password@/api/v1/authorities/$authid") + ->status_is(403, 'Not enough permissions makes it return the right code'); + + # Add permissions + $patron->flags( 2 ** 14 )->store; # 14 => editauthorities userflag + + $t->put_ok("//$userid:$password@/api/v1/authorities/$authid" => {'Content-Type' => 'application/marcxml+xml', 'x-authority-type' => $authtypecode} => $marcxml) + ->status_is(200) + ->json_has('/id'); + + $authority = Koha::Authorities->find($authid); + $record = $authority->record; + $subfield_a = $record->subfield('110', 'a'); + + is($subfield_a, 'MARCXML'); + + $t->put_ok("//$userid:$password@/api/v1/authorities/$authid" => {'Content-Type' => 'application/marc-in-json', 'x-authority-type' => $authtypecode} => $mij) + ->status_is(200) + ->json_has('/id'); + + $authority = Koha::Authorities->find($authid); + $record = $authority->record; + $subfield_a = $record->subfield('110', 'a'); + + is($subfield_a, 'MIJ'); + + $t->put_ok("//$userid:$password@/api/v1/authorities/$authid" => {'Content-Type' => 'application/marc', 'x-authority-type' => $authtypecode} => $marc) + ->status_is(200) + ->json_has('/id'); + + $authority = Koha::Authorities->find($authid); + $record = $authority->record; + $subfield_a = $record->subfield('110', 'a'); + + is($subfield_a, 'USMARCFormated'); + + $schema->storage->txn_rollback; +}; -- 2.25.1