Bug 42845: Add ILL config endpoint for Vue app

The ILL Vue app currently reads ILLModule and ILLPartnerCode through the system preferences service. That service requires parameters/manage_sysprefs, so a staff user with ILL permissions but without system preference administration permissions cannot load the ILL module.

Add an ILL-specific /ill/config REST endpoint protected by the ill permission, and switch the ILL Vue app to load its configuration from that endpoint. This follows the module-specific configuration endpoint pattern introduced by bug 33606 for the same manage_sysprefs problem in the ERM Vue app.

Security/compatibility considerations: the endpoint returns only allow-listed, non-secret ILL configuration values needed by the ILL Vue app. It does not expose the generic system preferences API, and /api/v1/sysprefs remains restricted to parameters/manage_sysprefs.

Regression test coverage: the new API test verifies that a staff user with the ill permission can read /ill/config, that a staff user without the ill permission cannot read it, and that the same ILL-only user still cannot access /api/v1/sysprefs.

Test plan:

1. prove -I. -It/lib t/db_dependent/api/v1/ill_config.t

2. prove -I. -It/lib t/db_dependent/api/v1/ill_users.t

Signed-off-by: David Nind <david@davidnind.com>

Amended-by: Jonathan Druart
chmod +x t/db_dependent/api/v1/ill_config.t

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
This commit is contained in:
Andrii Nugged 2026-06-15 08:25:32 +03:00 committed by Pedro Amorim
parent 769e565890
commit a445bb0ab3
No known key found for this signature in database
GPG Key ID: 06B75BA7F3894D55
7 changed files with 171 additions and 19 deletions

View File

@ -19,6 +19,7 @@ use Modern::Perl;
use Mojo::Base 'Mojolicious::Controller';
use C4::Context;
use Koha::Patrons;
use Try::Tiny qw( catch try );
@ -31,6 +32,26 @@ Koha::REST::V1::ILL
=head2 Class methods
=head3 config
Return the configuration options needed for the ILL Vue app
=cut
sub config {
my $c = shift->openapi->valid_input or return;
return $c->render(
status => 200,
openapi => {
settings => {
ILLModule => C4::Context->preference('ILLModule'),
ILLPartnerCode => C4::Context->preference('ILLPartnerCode'),
},
},
);
}
=head3 list_users
Return the list of possible ILL users

View File

@ -0,0 +1,7 @@
---
type: object
properties:
settings:
type: object
description: List of sysprefs used for the ILL module
additionalProperties: false

View File

@ -0,0 +1,38 @@
---
/ill/config:
get:
x-mojo-to: ILL#config
operationId: getILLconfig
description: This resource returns a list of options needed for the ILL Vue app. EXPERIMENTAL - DO NOT RELY on this, it is subject to change!
summary: get the ILL config
tags:
- ill_config
produces:
- application/json
responses:
200:
description: The ILL config
schema:
$ref: "../swagger.yaml#/definitions/ill_config"
400:
description: Bad request
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

View File

@ -108,6 +108,8 @@ definitions:
$ref: ./definitions/ill_backend.yaml
ill_backends:
$ref: ./definitions/ill_backends.yaml
ill_config:
$ref: ./definitions/ill_config.yaml
ill_status:
$ref: ./definitions/ill_status.yaml
ill_request:
@ -471,6 +473,8 @@ paths:
$ref: "./paths/holds.yaml#/~1holds~1{hold_id}~1suspension"
"/holds/{hold_id}/lowest_priority":
$ref: "./paths/holds.yaml#/~1holds~1{hold_id}~1lowest_priority"
/ill/config:
$ref: ./paths/ill_config.yaml#/~1ill~1config
/ill/backends:
$ref: ./paths/ill_backends.yaml#/~1ill~1backends
"/ill/backends/{ill_backend_id}":
@ -1403,6 +1407,9 @@ tags:
- description: "Manage ILL module batch statuses\n"
name: ill_batchstatuses
x-displayName: ILL batch statuses
- description: "Manage ILL configuration\n"
name: ill_config
x-displayName: ILL configuration
- description: "Manage ILL requests\n"
name: ill_requests
x-displayName: ILL requests

View File

@ -5,6 +5,15 @@ export class ILLAPIClient {
});
}
get config() {
return {
get: () =>
this.httpClient.get({
endpoint: "config",
}),
};
}
get supplying() {
return {
get: id =>

View File

@ -49,26 +49,21 @@ export default {
onBeforeMount(() => {
loading();
const client = APIClient.sysprefs;
client.sysprefs
.getAll(["ILLPartnerCode", "ILLModule"])
.then(pref_values => {
config.value.settings.ILLPartnerCode =
pref_values.value.ILLPartnerCode;
config.value.settings.ILLModule =
pref_values.value.ILLModule;
if (config.value.settings.ILLModule != 1) {
loaded();
return setError(
$__(
"The ILL module is disabled, turn on <a href='/cgi-bin/koha/admin/preferences.pl?tab=&op=search&searchfield=ILLModule'>ILLModule</a> to use it"
),
false
);
}
const client = APIClient.ill;
client.config.get().then(result => {
config.value = result;
if (config.value.settings.ILLModule != 1) {
loaded();
});
initialized.value = true;
return setError(
$__(
"The ILL module is disabled, turn on <a href='/cgi-bin/koha/admin/preferences.pl?tab=&op=search&searchfield=ILLModule'>ILLModule</a> to use it"
),
false
);
}
loaded();
initialized.value = true;
});
});
return {

View File

@ -0,0 +1,75 @@
#!/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 <https://www.gnu.org/licenses>.
use Modern::Perl;
use Test::NoWarnings;
use Test::More tests => 2;
use Test::Mojo;
use t::lib::Mocks;
use t::lib::TestBuilder;
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 'config() tests' => sub {
plan tests => 8;
$schema->storage->txn_begin;
t::lib::Mocks::mock_preference( 'ILLModule', 1 );
t::lib::Mocks::mock_preference( 'ILLPartnerCode', 'IL' );
my $librarian = $builder->build_object(
{
class => 'Koha::Patrons',
value => { flags => 2**22 } # 22 => ill
}
);
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/ill/config")
->status_is(200)
->json_is( '/settings/ILLModule' => '1' )
->json_is( '/settings/ILLPartnerCode' => 'IL' );
$t->get_ok("//$userid:$password@/api/v1/sysprefs")->status_is(403);
$t->get_ok("//$unauth_userid:$password@/api/v1/ill/config")->status_is(403);
$schema->storage->txn_rollback;
};