Bug 37711: (follow-up) Fix AuthClient plugin database upgrade handling

The AuthClient template plugin was causing 500 errors during database
upgrades when the identity_providers schema was out of sync. The plugin
tried to query the new 'auto_register_opac' column before the database
schema was updated, creating a chicken-egg problem.

This patch wraps the database query in Try::Tiny to handle schema
mismatches gracefully during upgrades, allowing the upgrade process
to continue without crashing the authentication interface.

Test plan:
1. On main, apply all bug 37711 patches BUT THIS ONE
2. Simulate an upgrade by:

* Edit Koha.pm so it points to the next version
* Move the atomicupdate file to the right number in db_revs

3. Restart everything:
   $ ktd --shell
  k$ restart_all
4. Access http://kohadev-intra.localhost
=> FAIL: You get a 500! With a stack trace!
5. Apply this patch
6. Repeat 3 and 4
=> SUCCESS: No 500 error, redirects to installer
7. Proceed with the upgrade:
=> SUCCESS: It works as it should
8. Run tests:
  k$ prove -v t/db_dependent/Template/Plugin/AuthClient.t
=> SUCCESS: All tests pass
9. Sign off :-D

Signed-off-by: Tomás Cohen Arazi <tomascohen@theke.io>
Signed-off-by: David Cook <dcook@prosentient.com.au>
Signed-off-by: Laura Escamilla <laura.escamilla@bywatersolutions.com>
This commit is contained in:
Tomás Cohen Arazi 2025-10-13 11:23:04 -03:00 committed by Laura Escamilla
parent 16a5dfe364
commit 1d77c3fdc0
No known key found for this signature in database
GPG Key ID: B5DEB5FD2FCDA5D8
2 changed files with 113 additions and 16 deletions

View File

@ -20,9 +20,11 @@ package Koha::Template::Plugin::AuthClient;
use Modern::Perl;
use Template::Plugin;
use base qw( Template::Plugin );
use base qw( Template::Plugin );
use Try::Tiny qw( catch try );
use Koha::Auth::Identity::Providers;
use Koha::Logger;
=head1 NAME
@ -49,26 +51,35 @@ sub get_providers {
$interface = 'staff'
if $interface eq 'intranet';
my $providers =
Koha::Auth::Identity::Providers->search( { "domains.allow_$interface" => 1 }, { prefetch => 'domains' } );
my $base_url = ( $interface eq 'staff' ) ? "/api/v1/oauth/login" : "/api/v1/public/oauth/login";
my @urls;
while ( my $provider = $providers->next ) {
# Handle database upgrade state where schema might be out of sync
try {
my $providers =
Koha::Auth::Identity::Providers->search( { "domains.allow_$interface" => 1 }, { prefetch => 'domains' } );
my $base_url = ( $interface eq 'staff' ) ? "/api/v1/oauth/login" : "/api/v1/public/oauth/login";
my $code = $provider->code;
while ( my $provider = $providers->next ) {
if ( $provider->protocol eq 'OIDC' || $provider->protocol eq 'OAuth' ) {
push @urls,
{
code => $code,
description => $provider->description,
icon_url => $provider->icon_url,
url => "$base_url/$code/$interface",
};
my $code = $provider->code;
if ( $provider->protocol eq 'OIDC' || $provider->protocol eq 'OAuth' ) {
push @urls,
{
code => $code,
description => $provider->description,
icon_url => $provider->icon_url,
url => "$base_url/$code/$interface",
};
}
}
}
} catch {
# If database query fails (e.g., during upgrade), return empty array
Koha::Logger->get->warn("AuthClient: Unable to load identity providers (database may need upgrade): $_");
@urls = ();
};
return \@urls;
}

View File

@ -0,0 +1,86 @@
#!/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 <https://www.gnu.org/licenses>.
use Modern::Perl;
use Test::More tests => 3;
use Test::Exception;
use Test::MockModule;
use Test::NoWarnings;
use t::lib::TestBuilder;
use t::lib::Mocks::Logger;
BEGIN {
use_ok('Koha::Template::Plugin::AuthClient');
}
my $schema = Koha::Database->new->schema;
my $builder = t::lib::TestBuilder->new;
my $logger = t::lib::Mocks::Logger->new();
subtest 'get_providers() tests' => sub {
plan tests => 2;
subtest 'Normal operation' => sub {
plan tests => 2;
$schema->storage->txn_begin;
my $plugin = Koha::Template::Plugin::AuthClient->new();
my $providers;
lives_ok {
$providers = $plugin->get_providers('staff');
}
'get_providers executes without error';
is( ref($providers), 'ARRAY', 'Returns array reference' );
$schema->storage->txn_rollback;
};
subtest 'Database error handling' => sub {
plan tests => 2;
$schema->storage->txn_begin;
$logger->clear();
# Mock search to simulate database schema mismatch
my $mock = Test::MockModule->new('Koha::Auth::Identity::Providers');
$mock->mock(
'search',
sub {
die "DBD::mysql::st execute failed: Unknown column 'domains.auto_register_opac' in 'field list'";
}
);
my $plugin = Koha::Template::Plugin::AuthClient->new();
my $providers;
lives_ok {
$providers = $plugin->get_providers('staff');
}
'get_providers handles database errors gracefully';
$logger->warn_like( qr/AuthClient: Unable to load identity providers/, 'Logs warning about database issue' );
$schema->storage->txn_rollback;
};
};