From a1782ab3d85a5ecc47cc7ba3e53ab241d809e741 Mon Sep 17 00:00:00 2001 From: Martin Renvoize Date: Wed, 11 Mar 2026 10:05:16 +0000 Subject: [PATCH] Bug 40596: DB atomicupdate - add CAS to identity providers, migrate config Adds 'CAS' to the identity_providers.protocol enum and migrates any existing CAS configuration into the identity_providers table: - If Auth_cas_servers.yaml exists, each server becomes a separate identity provider record. - Otherwise, casServerUrl/casServerVersion system preferences are used to create a single provider (code: 'cas'). The casServerUrl and casServerVersion preferences are superseded by the Identity Providers configuration after migration. --- .../data/mysql/atomicupdate/bug_40596.pl | 102 ++++++++++++++++++ installer/data/mysql/kohastructure.sql | 2 +- 2 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 installer/data/mysql/atomicupdate/bug_40596.pl diff --git a/installer/data/mysql/atomicupdate/bug_40596.pl b/installer/data/mysql/atomicupdate/bug_40596.pl new file mode 100644 index 00000000000..e3e0e63b97b --- /dev/null +++ b/installer/data/mysql/atomicupdate/bug_40596.pl @@ -0,0 +1,102 @@ +use Modern::Perl; +use Koha::Installer::Output qw(say_warning say_success say_info); +use JSON; + +return { + bug_number => "40596", + description => "Migrate CAS authentication to identity providers", + up => sub { + my ($args) = @_; + my ( $dbh, $out ) = @$args{qw(dbh out)}; + + # ── 1. Add CAS to identity_providers.protocol enum ───────────────────── + + if ( column_exists( 'identity_providers', 'protocol' ) ) { + my ($current_type) = $dbh->selectrow_array( + "SELECT COLUMN_TYPE FROM INFORMATION_SCHEMA.COLUMNS + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = 'identity_providers' + AND COLUMN_NAME = 'protocol'" + ); + + unless ( $current_type && $current_type eq "enum('CAS','OAuth','OIDC','SAML2')" ) { + $dbh->do( + q{ + ALTER TABLE identity_providers + MODIFY COLUMN `protocol` + enum('CAS','OAuth','OIDC','SAML2') + COLLATE utf8mb4_unicode_ci NOT NULL + COMMENT 'Protocol provider speaks' + } + ); + say_success( $out, "Added CAS to identity_providers.protocol enum" ); + } + } + + # ── 2. Migrate existing CAS configuration to identity providers ──────── + + my $version = C4::Context->preference('casServerVersion') || '2'; + + # Check for a multi-server YAML config file first + my $yamlauthfile = C4::Context->config('intranetdir') . "/C4/Auth_cas_servers.yaml"; + + if ( -e $yamlauthfile ) { + require YAML::XS; + my ( $default_hash, $servers ) = YAML::XS::LoadFile($yamlauthfile); + + for my $code ( sort keys %$servers ) { + my $server_url = $servers->{$code}; + next unless $server_url; + + my ($exists) = $dbh->selectrow_array( + "SELECT COUNT(*) FROM identity_providers WHERE code = ? AND protocol = 'CAS'", + undef, $code + ); + if ($exists) { + say_info( $out, "CAS provider '$code' already exists - skipping" ); + next; + } + + $dbh->do( + "INSERT INTO identity_providers (code, description, protocol, config, enabled) + VALUES (?, ?, 'CAS', ?, 1)", + undef, + $code, + $code, + encode_json( { server_url => $server_url, version => $version } ) + ); + say_success( $out, "Migrated CAS server '$code' ($server_url) to identity providers" ); + } + + say_info( + $out, + "CAS servers migrated from $yamlauthfile - " + . "the file can be removed once you have verified the configuration" + ); + + } elsif ( C4::Context->preference('casAuthentication') && C4::Context->preference('casServerUrl') ) { + + # Single CAS server from system preferences + my $server_url = C4::Context->preference('casServerUrl'); + + my ($exists) = $dbh->selectrow_array("SELECT COUNT(*) FROM identity_providers WHERE protocol = 'CAS'"); + + if ($exists) { + say_info( $out, "CAS identity provider already exists - skipping syspref migration" ); + } else { + $dbh->do( + "INSERT INTO identity_providers (code, description, protocol, config, enabled) + VALUES ('cas', 'CAS', 'CAS', ?, 1)", + undef, + encode_json( { server_url => $server_url, version => $version } ) + ); + say_success( $out, "Migrated CAS server ($server_url) to identity providers (code: 'cas')" ); + say_info( + $out, + "The casServerUrl and casServerVersion system preferences are now superseded " + . "by the Identity Providers configuration (Admin > Identity providers)" + ); + } + } + }, +}; diff --git a/installer/data/mysql/kohastructure.sql b/installer/data/mysql/kohastructure.sql index 2421df3d95c..a47faff99c4 100644 --- a/installer/data/mysql/kohastructure.sql +++ b/installer/data/mysql/kohastructure.sql @@ -3742,7 +3742,7 @@ CREATE TABLE `identity_providers` ( `identity_provider_id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'unique key, used to identify the provider', `code` varchar(20) NOT NULL COMMENT 'Provider code', `description` varchar(255) NOT NULL COMMENT 'Description for the provider', - `protocol` enum('OAuth','OIDC','SAML2') NOT NULL COMMENT 'Protocol provider speaks', + `protocol` enum('CAS','OAuth','OIDC','SAML2') NOT NULL COMMENT 'Protocol provider speaks', `config` longtext NOT NULL COMMENT 'Configuration of the provider in JSON format', `enabled` tinyint(1) NOT NULL DEFAULT 1 COMMENT 'Whether this provider is active', `icon_url` varchar(255) DEFAULT NULL COMMENT 'Provider icon URL', -- 2.53.0