From ecd319efe6f23cd860b9443c766f4b169a8e9236 Mon Sep 17 00:00:00 2001 From: Jonathan Druart Date: Fri, 12 Jun 2020 15:20:05 +0200 Subject: [PATCH] Bug 17390: Add /authorised_values endpoint This patch add the different routes for authorised values: * GET /authorised_values * GET /authorised_values/{authorised_value_id} * POST /authorised_values * PUT /authorised_values/{authorised_value_id} * DELETE /authorised_values/{authorised_value_id} Test plan: - Make sure the tests in t/db_dependent/api/v1/authorised_values.t pass - Test the different routes. For instance: GET /authorised_values # list all the avs GET /authorised_values?category=YES_NO # list all the YES_NO avs POST /authorised_values { "category": "YES_NO", "description": "not sure", "opac_description": "something else", "value": "maybe" } DELETE /authorised_values/X # with X the AV id of "maybe" Sponsored-by: Orex Digital --- Koha/AuthorisedValue.pm | 18 + Koha/REST/V1/AuthorisedValues.pm | 139 +++++++ api/v1/swagger/definitions.json | 3 + .../swagger/definitions/authorised_value.json | 30 ++ api/v1/swagger/parameters.json | 3 + .../swagger/parameters/authorised_value.json | 9 + api/v1/swagger/paths.json | 6 + api/v1/swagger/paths/authorised_values.json | 334 +++++++++++++++ api/v1/swagger/x-primitives.json | 5 + t/db_dependent/api/v1/authorised_values.t | 383 ++++++++++++++++++ 10 files changed, 930 insertions(+) create mode 100644 Koha/REST/V1/AuthorisedValues.pm create mode 100644 api/v1/swagger/definitions/authorised_value.json create mode 100644 api/v1/swagger/parameters/authorised_value.json create mode 100644 api/v1/swagger/paths/authorised_values.json create mode 100644 t/db_dependent/api/v1/authorised_values.t diff --git a/Koha/AuthorisedValue.pm b/Koha/AuthorisedValue.pm index 636ce95b3c..a232dba2c1 100644 --- a/Koha/AuthorisedValue.pm +++ b/Koha/AuthorisedValue.pm @@ -47,6 +47,24 @@ sub opac_description { return $self->lib_opac() || $self->lib(); } +=head3 to_api_mapping + +This method returns the mapping for representing a Koha::AuthorisedValue object +on the API. + +=cut + +sub to_api_mapping { + return { + id => 'authorised_value_id', + category => 'category', + authorised_value => 'value', + lib => 'description', + lib_opac => 'opac_description', + imageurl => 'image_url', + }; +} + =head2 Internal methods =head3 _type diff --git a/Koha/REST/V1/AuthorisedValues.pm b/Koha/REST/V1/AuthorisedValues.pm new file mode 100644 index 0000000000..04ab0dbb8e --- /dev/null +++ b/Koha/REST/V1/AuthorisedValues.pm @@ -0,0 +1,139 @@ +package Koha::REST::V1::AuthorisedValues; + +# 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::AuthorisedValues; + +use Try::Tiny; + +=head1 API + +=head2 Methods + +=head3 list + +=cut + +sub list { + my $c = shift->openapi->valid_input or return; + + return try { + my $av_set = Koha::AuthorisedValues->new; + my $avs = $c->objects->search( $av_set ); + return $c->render( status => 200, openapi => $avs ); + } + catch { + $c->unhandled_exception($_); + }; + +} + +=head3 get + +=cut + +sub get { + my $c = shift->openapi->valid_input or return; + + return try { + my $av = Koha::AuthorisedValues->find( $c->validation->param('authorised_value_id') ); + unless ($av) { + return $c->render( status => 404, + openapi => { error => "Authorised value not found" } ); + } + + return $c->render( status => 200, openapi => $av->to_api ); + } + catch { + $c->unhandled_exception($_); + } +} + +=head3 add + +=cut + +sub add { + my $c = shift->openapi->valid_input or return; + + return try { + my $av = Koha::AuthorisedValue->new_from_api( $c->validation->param('body') ); + $av->store; + $c->res->headers->location( $c->req->url->to_string . '/' . $av->id ); + return $c->render( + status => 201, + openapi => $av->to_api + ); + } + catch { + $c->unhandled_exception($_); + }; +} + +=head3 update + +=cut + +sub update { + my $c = shift->openapi->valid_input or return; + + my $av = Koha::AuthorisedValues->find( $c->validation->param('authorised_value_id') ); + + if ( not defined $av ) { + return $c->render( status => 404, + openapi => { error => "Object not found" } ); + } + + return try { + $av->set_from_api( $c->validation->param('body') ); + $av->store(); + return $c->render( status => 200, openapi => $av->to_api ); + } + catch { + $c->unhandled_exception($_); + }; +} + +=head3 delete + +=cut + +sub delete { + my $c = shift->openapi->valid_input or return; + + my $av = Koha::AuthorisedValues->find( $c->validation->param('authorised_value_id') ); + if ( not defined $av ) { + return $c->render( status => 404, + openapi => { error => "Object not found" } ); + } + + return try { + $av->delete; + return $c->render( + status => 204, + openapi => q{} + ); + } + catch { + $c->unhandled_exception($_); + }; +} + +1; diff --git a/api/v1/swagger/definitions.json b/api/v1/swagger/definitions.json index 716e8703b6..dd9fff9d7d 100644 --- a/api/v1/swagger/definitions.json +++ b/api/v1/swagger/definitions.json @@ -2,6 +2,9 @@ "account_line": { "$ref": "definitions/account_line.json" }, + "authorised_value": { + "$ref": "definitions/authorised_value.json" + }, "basket": { "$ref": "definitions/basket.json" }, diff --git a/api/v1/swagger/definitions/authorised_value.json b/api/v1/swagger/definitions/authorised_value.json new file mode 100644 index 0000000000..1870b05be7 --- /dev/null +++ b/api/v1/swagger/definitions/authorised_value.json @@ -0,0 +1,30 @@ +{ + "type": "object", + "properties": { + "authorised_value_id": { + "$ref": "../x-primitives.json#/authorised_value_id" + }, + "category": { + "description": "The category of this authorised value", + "type": "string" + }, + "value": { + "description": "The code for this authorised value", + "type": "string" + }, + "description": { + "description": "The staff interface description for this authorised value", + "type": "string" + }, + "opac_description": { + "description": "The public interface description of this authorised value, if set", + "type": ["string", "null"] + }, + "image_url": { + "description": "The url of the image associated with this authorised value, if any", + "type": ["string", "null"] + } + }, + "additionalProperties": false, + "required": ["category", "value", "description"] +} diff --git a/api/v1/swagger/parameters.json b/api/v1/swagger/parameters.json index cab2d53b47..9acf116928 100644 --- a/api/v1/swagger/parameters.json +++ b/api/v1/swagger/parameters.json @@ -5,6 +5,9 @@ "advancededitormacro_id_pp": { "$ref": "parameters/advancededitormacro.json#/advancededitormacro_id_pp" }, + "authorised_value_id_pp": { + "$ref": "parameters/authorised_value.json#/authorised_value_id_pp" + }, "patron_id_pp": { "$ref": "parameters/patron.json#/patron_id_pp" }, diff --git a/api/v1/swagger/parameters/authorised_value.json b/api/v1/swagger/parameters/authorised_value.json new file mode 100644 index 0000000000..b476653568 --- /dev/null +++ b/api/v1/swagger/parameters/authorised_value.json @@ -0,0 +1,9 @@ +{ + "authorised_value_id_pp": { + "name": "authorised_value_id", + "in": "path", + "description": "Authorised value internal identifier", + "required": true, + "type": "integer" + } +} diff --git a/api/v1/swagger/paths.json b/api/v1/swagger/paths.json index 8f1af595ce..8f75f1b556 100644 --- a/api/v1/swagger/paths.json +++ b/api/v1/swagger/paths.json @@ -17,6 +17,12 @@ "/acquisitions/funds": { "$ref": "paths/acquisitions_funds.json#/~1acquisitions~1funds" }, + "/authorised_values": { + "$ref": "paths/authorised_values.json#/~1authorised_values" + }, + "/authorised_values/{authorised_value_id}": { + "$ref": "paths/authorised_values.json#/~1authorised_values~1{authorised_value_id}" + }, "/checkouts": { "$ref": "paths/checkouts.json#/~1checkouts" }, diff --git a/api/v1/swagger/paths/authorised_values.json b/api/v1/swagger/paths/authorised_values.json new file mode 100644 index 0000000000..f223fddab5 --- /dev/null +++ b/api/v1/swagger/paths/authorised_values.json @@ -0,0 +1,334 @@ +{ + "/authorised_values": { + "get": { + "x-mojo-to": "AuthorisedValues#list", + "operationId": "listAuthorisedValues", + "tags": [ + "authorised", "values" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "category", + "in": "query", + "description": "Search authorised values by category", + "required": false, + "type": "string" + }, + { + "name": "value", + "in": "query", + "description": "Search authorised values by value", + "required": false, + "type": "string" + }, + { + "name": "description", + "in": "query", + "description": "Search authorised values by description", + "required": false, + "type": "string" + }, + { + "name": "opac_description", + "in": "query", + "description": "Search authorised values by opac description", + "required": false, + "type": "string" + }, + { + "name": "image_url", + "in": "query", + "description": "Search authorised values by image url", + "required": false, + "type": "string" + }, + { + "$ref": "../parameters.json#/match" + }, + { + "$ref": "../parameters.json#/order_by" + }, + { + "$ref": "../parameters.json#/page" + }, + { + "$ref": "../parameters.json#/per_page" + }, + { + "$ref": "../parameters.json#/q_param" + }, + { + "$ref": "../parameters.json#/q_body" + }, + { + "$ref": "../parameters.json#/q_header" + } + ], + "responses": { + "200": { + "description": "A list of authorised values", + "schema": { + "type": "array", + "items": { + "$ref": "../definitions.json#/authorised_value" + } + } + }, + "403": { + "description": "Access forbidden", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "500": { + "description": "Internal error", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "503": { + "description": "Under maintenance", + "schema": { + "$ref": "../definitions.json#/error" + } + } + }, + "x-koha-authorization": { + "permissions": { + "catalogue": "1" + } + } + }, + "post": { + "x-mojo-to": "AuthorisedValues#add", + "operationId": "addAuthorisedValue", + "tags": [ + "authorised", "values" + ], + "parameters": [ + { + "name": "body", + "in": "body", + "description": "A JSON object containing informations about the new authorised value", + "required": true, + "schema": { + "$ref": "../definitions.json#/authorised_value" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "201": { + "description": "Authorised value added", + "schema": { + "$ref": "../definitions.json#/authorised_value" + } + }, + "401": { + "description": "Authentication required", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "403": { + "description": "Access forbidden", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "500": { + "description": "Internal error", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "503": { + "description": "Under maintenance", + "schema": { + "$ref": "../definitions.json#/error" + } + } + }, + "x-koha-authorization": { + "permissions": { + "parameters": "manage_auth_values" + } + } + } + }, + "/authorised_values/{authorised_value_id}": { + "get": { + "x-mojo-to": "AuthorisedValues#get", + "operationId": "getAuthorisedValue", + "tags": [ + "authorised", "values" + ], + "parameters": [ + { + "$ref": "../parameters.json#/authorised_value_id_pp" + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "An authorised value", + "schema": { + "$ref": "../definitions.json#/authorised_value" + } + }, + "404": { + "description": "Authorised value not found", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "500": { + "description": "Internal error", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "503": { + "description": "Under maintenance", + "schema": { + "$ref": "../definitions.json#/error" + } + } + }, + "x-koha-authorization": { + "permissions": { + "catalogue": "1" + } + } + }, + "put": { + "x-mojo-to": "AuthorisedValues#update", + "operationId": "updateAuthorisedValue", + "tags": [ + "authorised", "value" + ], + "parameters": [ + { + "$ref": "../parameters.json#/authorised_value_id_pp" + }, + { + "name": "body", + "in": "body", + "description": "An authorised value object", + "required": true, + "schema": { + "$ref": "../definitions.json#/authorised_value" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "An authorised value", + "schema": { + "$ref": "../definitions.json#/authorised_value" + } + }, + "401": { + "description": "Authentication required", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "403": { + "description": "Access forbidden", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "404": { + "description": "Authorised value not found", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "500": { + "description": "Internal error", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "503": { + "description": "Under maintenance", + "schema": { + "$ref": "../definitions.json#/error" + } + } + }, + "x-koha-authorization": { + "permissions": { + "parameters": "manage_auth_values" + } + } + }, + "delete": { + "x-mojo-to": "AuthorisedValues#delete", + "operationId": "deleteAuthorisedValue", + "tags": [ + "authorised", "values" + ], + "parameters": [ + { + "$ref": "../parameters.json#/authorised_value_id_pp" + } + ], + "produces": [ + "application/json" + ], + "responses": { + "204": { + "description": "Authorised value deleted" + }, + "401": { + "description": "Authentication required", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "403": { + "description": "Access forbidden", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "404": { + "description": "Authorised value not found", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "500": { + "description": "Internal error", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "503": { + "description": "Under maintenance", + "schema": { + "$ref": "../definitions.json#/error" + } + } + }, + "x-koha-authorization": { + "permissions": { + "parameters": "manage_auth_values" + } + } + } + } +} diff --git a/api/v1/swagger/x-primitives.json b/api/v1/swagger/x-primitives.json index 0594264be9..27ef69b3dd 100644 --- a/api/v1/swagger/x-primitives.json +++ b/api/v1/swagger/x-primitives.json @@ -8,6 +8,11 @@ "description": "Internal advanced editor macro identifier", "readOnly": true }, + "authorised_value_id": { + "type": "integer", + "description": "internally assigned authorised value identifier", + "readOnly": true + }, "patron_id": { "type": "integer", "description": "Internal patron identifier" diff --git a/t/db_dependent/api/v1/authorised_values.t b/t/db_dependent/api/v1/authorised_values.t new file mode 100644 index 0000000000..a24929924f --- /dev/null +++ b/t/db_dependent/api/v1/authorised_values.t @@ -0,0 +1,383 @@ +#!/usr/bin/env perl + +# 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 Test::More tests => 5; +use Test::Mojo; + +use t::lib::TestBuilder; +use t::lib::Mocks; + +use Koha::AuthorisedValues; +use Koha::Database; + +my $schema = Koha::Database->new->schema; +my $builder = t::lib::TestBuilder->new; + +my $t = Test::Mojo->new('Koha::REST::V1'); +t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 ); + +subtest 'list() tests' => sub { + + plan tests => 20; + + $schema->storage->txn_begin; + + Koha::AuthorisedValues->search->delete; + + my $librarian = $builder->build_object( + { + class => 'Koha::Patrons', + value => { flags => 2 ** 2 } # catalogue flag = 2 + } + ); + my $password = 'thePassword123'; + $librarian->set_password( { password => $password, skip_validation => 1 } ); + my $userid = $librarian->userid; + + my $patron = $builder->build_object( + { + class => 'Koha::Patrons', + value => { flags => 0 } + } + ); + + $patron->set_password( { password => $password, skip_validation => 1 } ); + my $unauth_userid = $patron->userid; + + ## Authorized user tests + # No AVs, so empty array should be returned + $t->get_ok("//$userid:$password@/api/v1/authorised_values") + ->status_is(200) + ->json_is( [] ); + + my $av = $builder->build_object({ class => 'Koha::AuthorisedValues' }); + + # One av created, should get returned + $t->get_ok("//$userid:$password@/api/v1/authorised_values") + ->status_is(200) + ->json_is( [$av->to_api] ); + + my $another_av = $builder->build_object( + { class => 'Koha::AuthorisedValues', value => { lib => $av->lib } } ); + my $av_with_another_lib = $builder->build_object({ class => 'Koha::AuthorisedValues' }); + + # Two avs created, they should both be returned + $t->get_ok("//$userid:$password@/api/v1/authorised_values") + ->status_is(200) + ->json_is([$av->to_api, + $another_av->to_api, + $av_with_another_lib->to_api + ] ); + + # Filtering works, two avs sharing lib + $t->get_ok("//$userid:$password@/api/v1/authorised_values?description=" . $av->lib ) + ->status_is(200) + ->json_is([ $av->to_api, + $another_av->to_api + ]); + + $t->get_ok("//$userid:$password@/api/v1/authorised_values?value=" . $av->authorised_value ) + ->status_is(200) + ->json_is( [$av->to_api] ); + + # Warn on unsupported query parameter + $t->get_ok("//$userid:$password@/api/v1/authorised_values?av_blah=blah" ) + ->status_is(400) + ->json_is( [{ path => '/query/av_blah', message => 'Malformed query string'}] ); + + # Unauthorized access + $t->get_ok("//$unauth_userid:$password@/api/v1/authorised_values") + ->status_is(403); + + $schema->storage->txn_rollback; +}; + +subtest 'get() tests' => sub { + + plan tests => 8; + + $schema->storage->txn_begin; + + my $av = $builder->build_object({ class => 'Koha::AuthorisedValues' }); + my $librarian = $builder->build_object( + { + class => 'Koha::Patrons', + value => { flags => 2**2 } # catalogue flag = 2 + } + ); + my $password = 'thePassword123'; + $librarian->set_password( { password => $password, skip_validation => 1 } ); + my $userid = $librarian->userid; + + my $patron = $builder->build_object( + { + class => 'Koha::Patrons', + value => { flags => 0 } + } + ); + + $patron->set_password( { password => $password, skip_validation => 1 } ); + my $unauth_userid = $patron->userid; + + $t->get_ok( "//$userid:$password@/api/v1/authorised_values/" . $av->id ) + ->status_is(200) + ->json_is($av->to_api); + + $t->get_ok( "//$unauth_userid:$password@/api/v1/authorised_values/" . $av->id ) + ->status_is(403); + + my $av_to_delete = $builder->build_object({ class => 'Koha::AuthorisedValues' }); + my $non_existent_id = $av_to_delete->id; + $av_to_delete->delete; + + $t->get_ok( "//$userid:$password@/api/v1/authorised_values/$non_existent_id" ) + ->status_is(404) + ->json_is( '/error' => 'Authorised value not found' ); + + $schema->storage->txn_rollback; +}; + +subtest 'add() tests' => sub { + + plan tests => 18; + + $schema->storage->txn_begin; + + my $librarian = $builder->build_object( + { + class => 'Koha::Patrons', + value => { flags => 2**3 } # parameters flag = 2 + } + ); + my $password = 'thePassword123'; + $librarian->set_password( { password => $password, skip_validation => 1 } ); + my $userid = $librarian->userid; + + my $patron = $builder->build_object( + { + class => 'Koha::Patrons', + value => { flags => 0 } + } + ); + + $patron->set_password( { password => $password, skip_validation => 1 } ); + my $unauth_userid = $patron->userid; + + my $av_cat = $builder->build_object({ class => 'Koha::AuthorisedValueCategories' }); + my $av = { + category => $av_cat->category_name, + value => "a value", + description => "a lib", + opac_description => "opac lib" + }; + + # Unauthorized attempt to write + $t->post_ok("//$unauth_userid:$password@/api/v1/authorised_values" => json => $av) + ->status_is(403); + + # Authorized attempt to write invalid data + my $av_with_invalid_field = { + blah => "Av Blah", + category => $av_cat->category_name, + value => "a value", + description => "a lib", + opac_description => "opac lib" + }; + + $t->post_ok( "//$userid:$password@/api/v1/authorised_values" => json => $av_with_invalid_field ) + ->status_is(400) + ->json_is( + "/errors" => [ + { + message => "Properties not allowed: blah.", + path => "/body" + } + ] + ); + + # Authorized attempt to write + my $av_id = + $t->post_ok( "//$userid:$password@/api/v1/authorised_values" => json => $av ) + ->status_is( 201, 'SWAGGER3.2.1' ) + ->header_like( + Location => qr|^\/api\/v1\/authorised_values/\d*|, + 'SWAGGER3.4.1' + ) + ->json_is( '/category' => $av->{category} ) + ->json_is( '/value' => $av->{value} ) + ->json_is( '/description' => $av->{description} ) + ->json_is( '/opac_description' => $av->{opac_description} ) + ->tx->res->json->{authorised_value_id}; + + # Authorized attempt to create with null id + $av->{authorised_value_id} = undef; + $t->post_ok( "//$userid:$password@/api/v1/authorised_values" => json => $av ) + ->status_is(400) + ->json_has('/errors'); + + # Authorized attempt to create with existing id + $av->{authorised_value_id} = $av_id; + $t->post_ok( "//$userid:$password@/api/v1/authorised_values" => json => $av ) + ->status_is(400) + ->json_is( + "/errors" => [ + { + message => "Read-only.", + path => "/body/authorised_value_id" + } + ] + ); + + $schema->storage->txn_rollback; +}; + +subtest 'update() tests' => sub { + + plan tests => 15; + + $schema->storage->txn_begin; + + my $librarian = $builder->build_object( + { + class => 'Koha::Patrons', + value => { flags => 2**3 } # parameters flag = 2 + } + ); + my $password = 'thePassword123'; + $librarian->set_password( { password => $password, skip_validation => 1 } ); + my $userid = $librarian->userid; + + my $patron = $builder->build_object( + { + class => 'Koha::Patrons', + value => { flags => 0 } + } + ); + + $patron->set_password( { password => $password, skip_validation => 1 } ); + my $unauth_userid = $patron->userid; + + my $av_id = $builder->build_object({ class => 'Koha::AuthorisedValues' } )->id; + + # Unauthorized attempt to update + $t->put_ok( "//$unauth_userid:$password@/api/v1/authorised_values/$av_id" => json => { name => 'New unauthorized name change' } ) + ->status_is(403); + + my $av_cat = $builder->build_object({ class => 'Koha::AuthorisedValueCategories' }); + + # Attempt partial update on a PUT + my $av_with_missing_field = { + category => $av_cat->category_name, + value => "a value", + }; + + $t->put_ok( "//$userid:$password@/api/v1/authorised_values/$av_id" => json => $av_with_missing_field ) + ->status_is(400) + ->json_is( "/errors" => + [ { message => "Missing property.", path => "/body/description" } ] + ); + + # Full object update on PUT + my $av_with_updated_field = { + category => $av_cat->category_name, + value => "a value", + description => "a lib", + }; + + $t->put_ok( "//$userid:$password@/api/v1/authorised_values/$av_id" => json => $av_with_updated_field ) + ->status_is(200) + ->json_is( '/description' => 'a lib' ); + + # Authorized attempt to write invalid data + my $av_with_invalid_field = { + blah => "Av Blah", + category => $av_cat->category_name, + value => "a value", + description => "a lib", + opac_description => "opac lib" + }; + + $t->put_ok( "//$userid:$password@/api/v1/authorised_values/$av_id" => json => $av_with_invalid_field ) + ->status_is(400) + ->json_is( + "/errors" => [ + { + message => "Properties not allowed: blah.", + path => "/body" + } + ] + ); + + my $av_to_delete = $builder->build_object({ class => 'Koha::AuthorisedValues' }); + my $non_existent_id = $av_to_delete->id; + $av_to_delete->delete; + + $t->put_ok( "//$userid:$password@/api/v1/authorised_values/$non_existent_id" => json => $av_with_updated_field ) + ->status_is(404); + + # Wrong method (POST) + $av_with_updated_field->{authorised_value_id} = 2; + + $t->post_ok( "//$userid:$password@/api/v1/authorised_values/$av_id" => json => $av_with_updated_field ) + ->status_is(404); + + $schema->storage->txn_rollback; +}; + +subtest 'delete() tests' => sub { + + plan tests => 7; + + $schema->storage->txn_begin; + + my $librarian = $builder->build_object( + { + class => 'Koha::Patrons', + value => { flags => 2**3 } # parameters flag = 2 + } + ); + my $password = 'thePassword123'; + $librarian->set_password( { password => $password, skip_validation => 1 } ); + my $userid = $librarian->userid; + + my $patron = $builder->build_object( + { + class => 'Koha::Patrons', + value => { flags => 0 } + } + ); + + $patron->set_password( { password => $password, skip_validation => 1 } ); + my $unauth_userid = $patron->userid; + + my $av_id = $builder->build_object({ class => 'Koha::AuthorisedValues' })->id; + + # Unauthorized attempt to delete + $t->delete_ok( "//$unauth_userid:$password@/api/v1/authorised_values/$av_id" ) + ->status_is(403); + + $t->delete_ok("//$userid:$password@/api/v1/authorised_values/$av_id") + ->status_is(204, 'SWAGGER3.2.4') + ->content_is('', 'SWAGGER3.3.4'); + + $t->delete_ok("//$userid:$password@/api/v1/authorised_values/$av_id") + ->status_is(404); + + $schema->storage->txn_rollback; +}; -- 2.20.1