From c50975c790da7a8d0a0e5556a54ff041d6ccedd6 Mon Sep 17 00:00:00 2001 From: Pedro Amorim Date: Wed, 15 Oct 2025 09:09:28 +0000 Subject: [PATCH] Bug 40504: Add ill/users API endpoint Required to get users filtered by 'ill' permission for patron search modal prove t/db_dependent/api/v1/ill_users.t Signed-off-by: Jeremy Evans --- Koha/REST/V1/ILL.pm | 57 ++++++++++ api/v1/swagger/paths/ill_users.yaml | 61 ++++++++++ api/v1/swagger/swagger.yaml | 5 + .../prog/en/includes/patron-search.inc | 6 +- t/db_dependent/api/v1/ill_users.t | 107 ++++++++++++++++++ 5 files changed, 235 insertions(+), 1 deletion(-) create mode 100644 Koha/REST/V1/ILL.pm create mode 100644 api/v1/swagger/paths/ill_users.yaml create mode 100755 t/db_dependent/api/v1/ill_users.t diff --git a/Koha/REST/V1/ILL.pm b/Koha/REST/V1/ILL.pm new file mode 100644 index 00000000000..b3eb07e5f3c --- /dev/null +++ b/Koha/REST/V1/ILL.pm @@ -0,0 +1,57 @@ +package Koha::REST::V1::ILL; + +# 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::Patrons; + +use Try::Tiny qw( catch try ); + +=head1 NAME + +Koha::REST::V1::ILL + +=head1 API + +=head2 Class methods + +=head3 list_users + +Return the list of possible ILL users + +=cut + +sub list_users { + my $c = shift->openapi->valid_input or return; + + return try { + + my $patrons_rs = Koha::Patrons->search->filter_by_have_permission('ill'); + my $patrons = $c->objects->search($patrons_rs); + + return $c->render( + status => 200, + openapi => $patrons + ); + } catch { + $c->unhandled_exception($_); + }; +} + +1; diff --git a/api/v1/swagger/paths/ill_users.yaml b/api/v1/swagger/paths/ill_users.yaml new file mode 100644 index 00000000000..202f9856a64 --- /dev/null +++ b/api/v1/swagger/paths/ill_users.yaml @@ -0,0 +1,61 @@ +--- +/ill/users: + get: + x-mojo-to: ILL#list_users + operationId: listILLUsers + description: This resource returns a list of patron allowed to be users of the ILL module + summary: List possibe users for ILL + tags: + - ill_users + parameters: + - $ref: "../swagger.yaml#/parameters/match" + - $ref: "../swagger.yaml#/parameters/order_by" + - $ref: "../swagger.yaml#/parameters/page" + - $ref: "../swagger.yaml#/parameters/per_page" + - $ref: "../swagger.yaml#/parameters/q_param" + - $ref: "../swagger.yaml#/parameters/q_body" + - name: x-koha-embed + in: header + required: false + description: Embed list sent as a request header + type: array + items: + type: string + enum: + - extended_attributes + - library + collectionFormat: csv + produces: + - application/json + responses: + 200: + description: A list of ILL' users + schema: + type: array + items: + $ref: "../swagger.yaml#/definitions/patron" + "400": + description: | + Bad request. Possible `error_code` attribute values: + + * `invalid_query` + schema: + $ref: "../swagger.yaml#/definitions/error" + 403: + description: Access forbidden + schema: + $ref: "../swagger.yaml#/definitions/error" + 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: + ill: 1 diff --git a/api/v1/swagger/swagger.yaml b/api/v1/swagger/swagger.yaml index 9be774eace6..07f640a4f44 100644 --- a/api/v1/swagger/swagger.yaml +++ b/api/v1/swagger/swagger.yaml @@ -439,6 +439,8 @@ paths: $ref: ./paths/ill_batchstatuses.yaml#/~1ill~1batchstatuses "/ill/batchstatuses/{ill_batchstatus_code}": $ref: "./paths/ill_batchstatuses.yaml#/~1ill~1batchstatuses~1{ill_batchstatus_code}" + /ill/users: + $ref: ./paths/ill_users.yaml#/~1ill~1users "/import_batches/{import_batch_id}/records/{import_record_id}/matches/chosen": $ref: "./paths/import_batches.yaml#/~1import_batches~1{import_batch_id}~1records~1{import_record_id}~1matches~1chosen" /import_batch_profiles: @@ -1278,6 +1280,9 @@ tags: - description: "Manage item groups\n" name: item_groups x-displayName: Item groups + - description: "Manage ILL users\n" + name: ill_users + x-displayName: ILL users - description: "Manage record sources\n" name: record_sources x-displayName: Record source diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/patron-search.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/patron-search.inc index 8521528b9df..5d2627b8f5d 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/patron-search.inc +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/patron-search.inc @@ -117,7 +117,7 @@ [%# - Browse by last name %] [%# - The table %] [%# Get the following parameters: %] -[%# - filter: can be 'suggestions_managers', 'orders_managers', 'funds_owners', 'funds_users' or 'erm_users' to filter patrons on their permissions %] +[%# - filter: can be 'suggestions_managers', 'orders_managers', 'funds_owners', 'funds_users', 'erm_users' or 'ill_users' to filter patrons on their permissions %] [%# - table_id: the ID of the table %] [%# open_on_row_click: See patron_search_js %] [%# columns: See patron_search_js %] @@ -135,6 +135,8 @@
Only staff with superlibrarian or acquisitions permissions (or budget_modify permission if granular permissions are enabled) are returned in the search results
[% ELSIF filter == 'erm_users' %]
Only staff with superlibrarian or ERM permissions are returned in the search results
+ [% ELSIF filter == 'ill_users' %] +
Only staff with superlibrarian or ILL permissions are returned in the search results
[% END %]
@@ -341,6 +343,8 @@ let patron_search_url = '/api/v1/acquisitions/funds/users'; [% CASE 'erm_users' %] let patron_search_url = '/api/v1/erm/users'; + [% CASE 'ill_users' %] + let patron_search_url = '/api/v1/ill/users'; [% CASE %] let patron_search_url = '/api/v1/patrons'; [% END %] diff --git a/t/db_dependent/api/v1/ill_users.t b/t/db_dependent/api/v1/ill_users.t new file mode 100755 index 00000000000..c528fc80996 --- /dev/null +++ b/t/db_dependent/api/v1/ill_users.t @@ -0,0 +1,107 @@ +#!/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::NoWarnings; +use Test::More tests => 2; +use Test::Mojo; + +use t::lib::TestBuilder; +use t::lib::Mocks; + +use Koha::Patron::Attributes; +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 ); +t::lib::Mocks::mock_preference( 'ChildNeedsGuarantor', 0 ); + +subtest 'list() tests' => sub { + + plan tests => 14; + + $schema->storage->txn_begin; + + my $patron_category = + $builder->build( { source => 'Category', value => { category_type => 'A', can_be_guarantee => 0 } } ) + ->{categorycode}; + + Koha::Patrons->search->update( { flags => 0, categorycode => $patron_category } ); + $schema->resultset('UserPermission')->delete; + + my $librarian = $builder->build_object( + { + class => 'Koha::Patrons', + value => { flags => 2**22 } + } + ); + + my $password = 'thePassword123'; + $librarian->set_password( { password => $password, skip_validation => 1 } ); + my $userid = $librarian->userid; + + ## Authorized user tests + # One erm_user created, should get returned + $librarian->discard_changes; + $t->get_ok("//$userid:$password@/api/v1/ill/users")->status_is(200) + ->json_is( [ $librarian->to_api( { user => $librarian } ) ] ); + + my $another_erm_user = $builder->build_object( + { + class => 'Koha::Patrons', + value => { flags => 2**22 } + } + ); + + # Two erm_users created, only self is returned without permission to view_any_borrower + $t->get_ok("//$userid:$password@/api/v1/ill/users")->status_is(200) + ->json_is( [ $librarian->to_api( { user => $librarian } ) ] ); + + my $dbh = C4::Context->dbh; + $dbh->do( + q{INSERT INTO user_permissions( borrowernumber, module_bit, code ) VALUES (?, ?, ?)}, undef, + ( $librarian->borrowernumber, 4, 'view_borrower_infos_from_any_libraries' ) + ); + + # Two erm_users created, they should both be returned + $t->get_ok("//$userid:$password@/api/v1/ill/users")->status_is(200) + ->json_is( + [ $librarian->to_api( { user => $librarian } ), $another_erm_user->to_api( { user => $another_erm_user } ) ] ); + + # Warn on unsupported query parameter + $t->get_ok("//$userid:$password@/api/v1/ill/users?blah=blah")->status_is(400) + ->json_is( [ { path => '/query/blah', message => 'Malformed query string' } ] ); + + my $patron = $builder->build_object( + { + class => 'Koha::Patrons', + value => { flags => 0 } + } + ); + + $patron->set_password( { password => $password, skip_validation => 1 } ); + my $unauth_userid = $patron->userid; + + # Unauthorized access + $t->get_ok("//$unauth_userid:$password@/api/v1/ill/users")->status_is(403); + + $schema->storage->txn_rollback; +}; -- 2.39.5