From a5286b982952bd3130681a16f9ec7db1805f88d7 Mon Sep 17 00:00:00 2001 From: Lari Taskula Date: Fri, 19 Feb 2021 01:17:38 +0000 Subject: [PATCH] Bug 20028: Add OpenAPI spec Includes a test that validates the existence of all related properties. To test: 1. prove t/db_dependent/api/v1/patrons_export.t Sponsored-by: The National Library of Finland --- api/v1/swagger/definitions.json | 3 + api/v1/swagger/definitions/patron_export.json | 198 ++++++++++++++++++ api/v1/swagger/paths.json | 6 + api/v1/swagger/paths/patrons_export.json | 62 ++++++ api/v1/swagger/paths/public_patrons.json | 63 +++++- t/db_dependent/api/v1/patrons_export.t | 80 +++++++ 6 files changed, 411 insertions(+), 1 deletion(-) create mode 100644 api/v1/swagger/definitions/patron_export.json create mode 100644 api/v1/swagger/paths/patrons_export.json create mode 100755 t/db_dependent/api/v1/patrons_export.t diff --git a/api/v1/swagger/definitions.json b/api/v1/swagger/definitions.json index bc844bdc8f..1672a483ef 100644 --- a/api/v1/swagger/definitions.json +++ b/api/v1/swagger/definitions.json @@ -65,6 +65,9 @@ "patron_balance": { "$ref": "definitions/patron_balance.json" }, + "patron_export": { + "$ref": "definitions/patron_export.json" + }, "quote": { "$ref": "definitions/quote.json" }, diff --git a/api/v1/swagger/definitions/patron_export.json b/api/v1/swagger/definitions/patron_export.json new file mode 100644 index 0000000000..010df6da27 --- /dev/null +++ b/api/v1/swagger/definitions/patron_export.json @@ -0,0 +1,198 @@ +{ + "type": "object", + "properties": { + "Accountline": { + "type": "array" + }, + "Accountline": { + "type": "array" + }, + "AdvancedEditorMacro": { + "type": "array" + }, + "Alert": { + "type": "array" + }, + "ApiKey": { + "type": "array" + }, + "Aqbasketuser": { + "type": "array" + }, + "Aqbudgetborrower": { + "type": "array" + }, + "AqorderUser": { + "type": "array" + }, + "Aqorder": { + "type": "array" + }, + "ArticleRequest": { + "type": "array" + }, + "Borrower": { + "type": "object" + }, + "BorrowerAttribute": { + "type": "array" + }, + "BorrowerDebarment": { + "type": "array" + }, + "BorrowerFile": { + "type": "array" + }, + "BorrowerMessagePreference": { + "type": "array" + }, + "BorrowerRelationship": { + "type": "array" + }, + "BorrowerRelationship": { + "type": "array" + }, + "CashRegisterAction": { + "type": "array" + }, + "ClubEnrollment": { + "type": "array" + }, + "ClubHoldsToPatronHold": { + "type": "array" + }, + "CourseInstructor": { + "type": "array" + }, + "CreatorBatch": { + "type": "array" + }, + "Discharge": { + "type": "array" + }, + "HoldFillTarget": { + "type": "array" + }, + "HouseboundProfile": { + "type": "array" + }, + "HouseboundRole": { + "type": "array" + }, + "HouseboundVisit": { + "type": "array" + }, + "HouseboundVisit": { + "type": "array" + }, + "Illcomment": { + "type": "array" + }, + "Illrequest": { + "type": "array" + }, + "Issue": { + "type": "array" + }, + "Issue": { + "type": "array" + }, + "ItemsLastBorrower": { + "type": "array" + }, + "MessageQueue": { + "type": "array" + }, + "Message": { + "type": "array" + }, + "Message": { + "type": "array" + }, + "OldIssue": { + "type": "array" + }, + "OldIssue": { + "type": "array" + }, + "OldReserve": { + "type": "array" + }, + "OpacNews": { + "type": "array" + }, + "PatronConsent": { + "type": "array" + }, + "PatronListPatron": { + "type": "array" + }, + "PatronList": { + "type": "array" + }, + "Patronimage": { + "type": "array" + }, + "ProblemReport": { + "type": "array" + }, + "Rating": { + "type": "array" + }, + "Reserve": { + "type": "array" + }, + "ReturnClaim": { + "type": "array" + }, + "ReturnClaim": { + "type": "array" + }, + "ReturnClaim": { + "type": "array" + }, + "ReturnClaim": { + "type": "array" + }, + "Review": { + "type": "array" + }, + "Subscriptionroutinglist": { + "type": "array" + }, + "Suggestion": { + "type": "array" + }, + "Suggestion": { + "type": "array" + }, + "Suggestion": { + "type": "array" + }, + "Suggestion": { + "type": "array" + }, + "Suggestion": { + "type": "array" + }, + "TagAll": { + "type": "array" + }, + "TagsApproval": { + "type": "array" + }, + "UserPermission": { + "type": "array" + }, + "Virtualshelfcontent": { + "type": "array" + }, + "Virtualshelfshare": { + "type": "array" + }, + "Virtualshelve": { + "type": "array" + } + }, + "additionalProperties": false +} diff --git a/api/v1/swagger/paths.json b/api/v1/swagger/paths.json index df30f36459..42ef014eff 100644 --- a/api/v1/swagger/paths.json +++ b/api/v1/swagger/paths.json @@ -104,6 +104,9 @@ "/patrons/{patron_id}/account/credits": { "$ref": "paths/patrons_account.json#/~1patrons~1{patron_id}~1account~1credits" }, + "/patrons/{patron_id}/export": { + "$ref": "paths/patrons_export.json#/~1patrons~1{patron_id}~1export" + }, "/patrons/{patron_id}/password": { "$ref": "paths/patrons_password.json#/~1patrons~1{patron_id}~1password" }, @@ -128,6 +131,9 @@ "/public/biblios/{biblio_id}": { "$ref": "paths/biblios.json#/~1public~1biblios~1{biblio_id}" }, + "/public/patrons/{patron_id}/export": { + "$ref": "paths/public_patrons.json#/~1public~1patrons~1{patron_id}~1export" + }, "/public/patrons/{patron_id}/password": { "$ref": "paths/public_patrons.json#/~1public~1patrons~1{patron_id}~1password" }, diff --git a/api/v1/swagger/paths/patrons_export.json b/api/v1/swagger/paths/patrons_export.json new file mode 100644 index 0000000000..cb07b5a3d8 --- /dev/null +++ b/api/v1/swagger/paths/patrons_export.json @@ -0,0 +1,62 @@ +{ + "/patrons/{patron_id}/export": { + "get": { + "x-mojo-to": "Patrons::Export#get", + "operationId": "getPatronExport", + "tags": [ + "patron" + ], + "parameters": [ + { + "$ref": "../parameters.json#/patron_id_pp" + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "Patron's data export", + "schema": { + "$ref": "../definitions.json#/patron_export" + } + }, + "401": { + "description": "Authentication required", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "403": { + "description": "Access forbidden", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "404": { + "description": "Patron not found", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "500": { + "description": "Internal server error", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "503": { + "description": "Under maintenance", + "schema": { + "$ref": "../definitions.json#/error" + } + } + }, + "x-koha-authorization": { + "permissions": { + "borrowers": "edit_borrowers" + } + } + } + } +} diff --git a/api/v1/swagger/paths/public_patrons.json b/api/v1/swagger/paths/public_patrons.json index 5db073c4eb..c2468d3c89 100644 --- a/api/v1/swagger/paths/public_patrons.json +++ b/api/v1/swagger/paths/public_patrons.json @@ -1,4 +1,65 @@ { + "/public/patrons/{patron_id}/export": { + "get": { + "x-mojo-to": "Patrons::Export#get_public", + "operationId": "getPublicPatronExport", + "tags": [ + "patron" + ], + "parameters": [ + { + "$ref": "../parameters.json#/patron_id_pp" + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "Patron's data export", + "schema": { + "$ref": "../definitions.json#/patron_export" + } + }, + "401": { + "description": "Authentication required", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "403": { + "description": "Access forbidden", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "404": { + "description": "Patron not found", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "500": { + "description": "Internal server error", + "schema": { + "$ref": "../definitions.json#/error" + } + }, + "503": { + "description": "Under maintenance", + "schema": { + "$ref": "../definitions.json#/error" + } + } + }, + "x-koha-authorization": { + "permissions": { + "borrowers": "edit_borrowers" + }, + "allow-owner": true + } + } + }, "/public/patrons/{patron_id}/password": { "post": { "x-mojo-to": "Patrons::Password#set_public", @@ -237,4 +298,4 @@ } } } -} \ No newline at end of file +} diff --git a/t/db_dependent/api/v1/patrons_export.t b/t/db_dependent/api/v1/patrons_export.t new file mode 100755 index 0000000000..3e5e35e5b1 --- /dev/null +++ b/t/db_dependent/api/v1/patrons_export.t @@ -0,0 +1,80 @@ +#!/usr/bin/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 => 1; + +use Test::Mojo; + +use t::lib::TestBuilder; +use t::lib::Mocks; + +my $schema = Koha::Database->new->schema; +my $builder = t::lib::TestBuilder->new; + +t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 ); + +my $t = Test::Mojo->new('Koha::REST::V1'); + +subtest 'validate patrons_export OpenAPI definition' => sub { + + my @related_sources = _get_related_sources(); + plan tests => scalar @related_sources; + + $schema->storage->txn_begin; + + # Load OpenAPI schema + my $validator = JSON::Validator::OpenAPI::Mojolicious->new; + my $intradir = C4::Context->config('intranetdir'); + my $swagger_schema = "$intradir/api/v1/swagger/swagger.json"; + my $api_spec = $validator->bundle( + { + replace => 1, + schema => $swagger_schema + } + ); + # Get patron export properties + my $objs = $api_spec->{definitions}->{patron_export}->{properties}; + + # Test OpenAPI property existence for all related sources + my $result_source = Koha::Patron->new->_result()->result_source; + foreach my $rel ( _get_related_sources() ) { + my $related_source = $schema->source($rel); + ok( + exists $objs->{$related_source->source_name}, + $related_source->source_name + ); + } + + $schema->storage->txn_rollback; +}; + +sub _get_related_sources { + my $sources = {}; + my $res_source = Koha::Patron->new->_result()->result_source; + foreach my $rel ( Koha::Patron->new->_result()->relationships() ) { + my $related_source = $res_source->related_source($rel); + my $info = $res_source->relationship_info( $rel ); + next if $info->{'attrs'}->{'is_depends_on'}; + next if $sources->{$related_source->source_name}; + $sources->{$related_source->source_name} = 1; + } + $sources->{'Borrower'} = 1; # add Borrower itself + my @sorted = sort keys %$sources; + return @sorted; +} -- 2.25.1