Bugzilla – Attachment 189240 Details for
Bug 39224
Move Shibboleth config from koha-conf to the DB
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 39224: add comprehensive tests for shibboleth configuration
Bug-39224-add-comprehensive-tests-for-shibboleth-c.patch (text/plain), 40.09 KB, created by
Jacob O'Mara
on 2025-11-06 22:11:58 UTC
(
hide
)
Description:
Bug 39224: add comprehensive tests for shibboleth configuration
Filename:
MIME Type:
Creator:
Jacob O'Mara
Created:
2025-11-06 22:11:58 UTC
Size:
40.09 KB
patch
obsolete
>From 510c389c4fc241a7f170e1c85079e46cc36fb01a Mon Sep 17 00:00:00 2001 >From: Jacob O'Mara <Jacob.omara@openfifth.co.uk> >Date: Tue, 4 Nov 2025 15:22:22 +0000 >Subject: [PATCH] Bug 39224: add comprehensive tests for shibboleth > configuration > >Add tests for: >- Koha object models (ShibbolethConfig, ShibbolethFieldMapping) >- REST API endpoints >- Database migration from XML config >--- > t/db_dependent/Auth_with_shibboleth.t | 60 ++- > t/db_dependent/Koha/ShibbolethConfigs.t | 140 +++++++ > t/db_dependent/Koha/ShibbolethFieldMappings.t | 179 +++++++++ > t/db_dependent/Shibboleth/Migration.t | 206 ++++++++++ > t/db_dependent/api/v1/shibboleth_config.t | 121 ++++++ > .../api/v1/shibboleth_field_mappings.t | 356 ++++++++++++++++++ > 6 files changed, 1048 insertions(+), 14 deletions(-) > create mode 100755 t/db_dependent/Koha/ShibbolethConfigs.t > create mode 100755 t/db_dependent/Koha/ShibbolethFieldMappings.t > create mode 100755 t/db_dependent/Shibboleth/Migration.t > create mode 100755 t/db_dependent/api/v1/shibboleth_config.t > create mode 100755 t/db_dependent/api/v1/shibboleth_field_mappings.t > >diff --git a/t/db_dependent/Auth_with_shibboleth.t b/t/db_dependent/Auth_with_shibboleth.t >index 01a229d1929..26cb99fa6f8 100755 >--- a/t/db_dependent/Auth_with_shibboleth.t >+++ b/t/db_dependent/Auth_with_shibboleth.t >@@ -35,6 +35,9 @@ use t::lib::Dates; > use C4::Auth_with_shibboleth qw( shib_ok login_shib_url get_login_shib checkpw_shib ); > use Koha::Database; > use Koha::DateUtils qw( dt_from_string ); >+use Koha::ShibbolethConfig; >+use Koha::ShibbolethConfigs; >+use Koha::ShibbolethFieldMapping; > > BEGIN { > use_ok( >@@ -48,9 +51,7 @@ $schema->storage->txn_begin; > my $builder = t::lib::TestBuilder->new; > my $logger = t::lib::Mocks::Logger->new(); > >-# Mock variables > my $shibboleth; >-change_config( {} ); > my $interface = 'opac'; > > # Mock few preferences >@@ -59,12 +60,13 @@ t::lib::Mocks::mock_preference( 'StaffClientBaseURL', 'teststaff.com' ); > t::lib::Mocks::mock_preference( 'EmailFieldPrimary', '' ); > t::lib::Mocks::mock_preference( 'EmailFieldPrecedence', 'emailpro' ); > >-# Mock Context: config, tz and interface >+# Mock Context: tz and interface > my $context = Test::MockModule->new('C4::Context'); >-$context->mock( 'config', sub { return $shibboleth; } ); # easier than caching by Mocks::mock_config > $context->mock( 'timezone', sub { return 'local'; } ); > $context->mock( 'interface', sub { return $interface; } ); > >+change_config( {} ); >+ > # Mock Letters: GetPreparedLetter, EnqueueLetter and SendQueuedMessages > # We want to test the params > my $mocked_letters = Test::MockModule->new('C4::Letters'); >@@ -97,20 +99,21 @@ $mocked_letters->mock( > # Start testing ---------------------------------------------------------------- > > subtest "shib_ok tests" => sub { >- plan tests => 5; >+ plan tests => 6; > my $result; > > # correct config, no debug > is( shib_ok(), '1', "good config" ); > >- # bad config, no debug >+ # bad config, no debug - clear matchpoint in DB >+ $schema->resultset('ShibbolethFieldMapping')->update( { is_matchpoint => 0 } ); > delete $shibboleth->{matchpoint}; >- warnings_are { $result = shib_ok() } >- [ { carped => 'shibboleth matchpoint not defined' }, ], >- "undefined matchpoint = fatal config, warning given"; >+ $result = shib_ok(); >+ $logger->warn_is( 'No matchpoint configured in Shibboleth field mappings', "matchpoint warning logged" ) >+ ->warn_is( 'shibboleth config could not be loaded', "config could not be loaded warning" )->clear(); > is( $result, '0', "bad config" ); > >- change_config( { matchpoint => 'email' } ); >+ change_config( { matchpoint => 'email', mapping => { email => { content => 'default@example.com' } } } ); > warnings_are { $result = shib_ok() } > [ { carped => 'shibboleth matchpoint not mapped' }, ], > "unmapped matchpoint = fatal config, warning given"; >@@ -273,6 +276,8 @@ subtest "checkpw_shib tests" => sub { > ); > > # sync user >+ my $config = Koha::ShibbolethConfigs->new->get_configuration; >+ $config->sync(1)->store; > $shibboleth->{sync} = 1; > $ENV{'city'} = 'AnotherCity'; > ( $retval, $retcard, $retuserid, $retpatron ) = checkpw_shib($shib_login); >@@ -327,7 +332,7 @@ subtest "checkpw_shib tests" => sub { > $ENV{'emailpro'} = 'me@myemail.com'; > $ENV{branchcode} = $library->branchcode; # needed since T::D::C does no longer hides the FK constraint > >- checkpw($shib_login); >+ ( $retval, $retcard, $retuserid, $retpatron ) = checkpw_shib($shib_login); > ok( > my $new_user_autocreated = Koha::Patrons->find( { userid => 'test43210' } ), > "new user found" >@@ -416,6 +421,19 @@ $schema->storage->txn_rollback; > sub change_config { > my $params = shift; > >+ $schema->resultset('ShibbolethConfig')->delete; >+ $schema->resultset('ShibbolethFieldMapping')->delete; >+ >+ Koha::ShibbolethConfig->new( >+ { >+ force_opac_sso => 0, >+ force_staff_sso => 0, >+ autocreate => $params->{autocreate} // 0, >+ sync => $params->{sync} // 0, >+ welcome => $params->{welcome} // 0, >+ } >+ )->store; >+ > my %mapping = ( > 'userid' => { 'is' => 'uid' }, > 'surname' => { 'is' => 'sn' }, >@@ -429,15 +447,29 @@ sub change_config { > if ( exists $params->{mapping} ) { > $mapping{$_} = $params->{mapping}->{$_} for keys %{ $params->{mapping} }; > } >- $shibboleth = { >+ >+ my $matchpoint = $params->{matchpoint} // 'userid'; >+ >+ foreach my $koha_field ( keys %mapping ) { >+ Koha::ShibbolethFieldMapping->new( >+ { >+ koha_field => $koha_field, >+ idp_field => $mapping{$koha_field}->{is}, >+ is_matchpoint => $koha_field eq $matchpoint ? 1 : 0, >+ default_content => $mapping{$koha_field}->{content}, >+ } >+ )->store; >+ } >+ >+ my $db_config = Koha::ShibbolethConfigs->new->get_configuration; >+ $shibboleth = $db_config ? $db_config->get_combined_config : { > autocreate => $params->{autocreate} // 0, > welcome => $params->{welcome} // 0, > sync => $params->{sync} // 0, >- matchpoint => $params->{matchpoint} // 'userid', >+ matchpoint => $matchpoint, > mapping => \%mapping, > }; > >- # Change environment too > $ENV{'uid'} = "test1234"; > $ENV{'sn'} = undef; > $ENV{'exp'} = undef; >diff --git a/t/db_dependent/Koha/ShibbolethConfigs.t b/t/db_dependent/Koha/ShibbolethConfigs.t >new file mode 100755 >index 00000000000..6ef25ee220e >--- /dev/null >+++ b/t/db_dependent/Koha/ShibbolethConfigs.t >@@ -0,0 +1,140 @@ >+#!/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::NoWarnings; >+use Test::More tests => 6; >+ >+use Koha::ShibbolethConfig; >+use Koha::ShibbolethConfigs; >+use Koha::Database; >+ >+use t::lib::TestBuilder; >+ >+my $schema = Koha::Database->new->schema; >+$schema->storage->txn_begin; >+ >+my $builder = t::lib::TestBuilder->new; >+ >+subtest 'get_configuration' => sub { >+ plan tests => 3; >+ >+ $schema->resultset('ShibbolethConfig')->delete; >+ >+ my $config = Koha::ShibbolethConfigs->new->get_configuration; >+ >+ is( $config->shibboleth_config_id, 1, 'Configuration always has ID 1' ); >+ is( $config->force_opac_sso, 0, 'Default force_opac_sso is 0' ); >+ is( $config->autocreate, 0, 'Default autocreate is 0' ); >+}; >+ >+subtest 'store always updates singleton' => sub { >+ plan tests => 3; >+ >+ $schema->resultset('ShibbolethConfig')->delete; >+ >+ my $config1 = Koha::ShibbolethConfig->new( >+ { >+ force_opac_sso => 1, >+ force_staff_sso => 0, >+ autocreate => 1, >+ sync => 1, >+ welcome => 0 >+ } >+ )->store; >+ >+ is( $config1->shibboleth_config_id, 1, 'First config has ID 1' ); >+ >+ my $config2 = Koha::ShibbolethConfig->new( >+ { >+ force_opac_sso => 0, >+ force_staff_sso => 1, >+ autocreate => 0, >+ sync => 0, >+ welcome => 1 >+ } >+ )->store; >+ >+ is( $config2->shibboleth_config_id, 1, 'Second store still has ID 1' ); >+ is( Koha::ShibbolethConfigs->search->count, 1, 'Only one config exists' ); >+}; >+ >+subtest 'get_value' => sub { >+ plan tests => 3; >+ >+ $schema->resultset('ShibbolethConfig')->delete; >+ >+ my $config = Koha::ShibbolethConfigs->new->get_configuration; >+ $config->force_opac_sso(1)->store; >+ >+ is( $config->get_value('force_opac_sso'), 1, 'get_value returns correct value' ); >+ is( $config->get_value('force_staff_sso'), 0, 'get_value returns correct default' ); >+ is( $config->get_value('nonexistent'), undef, 'get_value returns undef for nonexistent column' ); >+}; >+ >+subtest 'mappings' => sub { >+ plan tests => 1; >+ >+ $schema->resultset('ShibbolethConfig')->delete; >+ >+ my $config = Koha::ShibbolethConfigs->new->get_configuration; >+ my $mappings = $config->mappings; >+ >+ isa_ok( $mappings, 'Koha::ShibbolethFieldMappings', 'mappings returns correct type' ); >+}; >+ >+subtest 'get_combined_config' => sub { >+ plan tests => 4; >+ >+ $schema->resultset('ShibbolethConfig')->delete; >+ $schema->resultset('ShibbolethFieldMapping')->delete; >+ >+ my $config = Koha::ShibbolethConfigs->new->get_configuration; >+ $config->force_opac_sso(1)->store; >+ >+ $builder->build_object( >+ { >+ class => 'Koha::ShibbolethFieldMappings', >+ value => { >+ idp_field => 'eppn', >+ koha_field => 'userid', >+ is_matchpoint => 1 >+ } >+ } >+ ); >+ >+ $builder->build_object( >+ { >+ class => 'Koha::ShibbolethFieldMappings', >+ value => { >+ idp_field => 'mail', >+ koha_field => 'email', >+ is_matchpoint => 0 >+ } >+ } >+ ); >+ >+ my $combined = $config->get_combined_config; >+ >+ is( $combined->{force_opac_sso}, 1, 'Combined config includes base settings' ); >+ is( $combined->{matchpoint}, 'userid', 'Combined config includes matchpoint' ); >+ ok( exists $combined->{mapping}->{userid}, 'Combined config includes userid mapping' ); >+ ok( exists $combined->{mapping}->{email}, 'Combined config includes email mapping' ); >+}; >+ >+$schema->storage->txn_rollback; >diff --git a/t/db_dependent/Koha/ShibbolethFieldMappings.t b/t/db_dependent/Koha/ShibbolethFieldMappings.t >new file mode 100755 >index 00000000000..37abc66c3c9 >--- /dev/null >+++ b/t/db_dependent/Koha/ShibbolethFieldMappings.t >@@ -0,0 +1,179 @@ >+#!/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::NoWarnings; >+use Test::More tests => 6; >+use Test::Exception; >+ >+use Koha::ShibbolethFieldMapping; >+use Koha::ShibbolethFieldMappings; >+use Koha::Database; >+ >+use t::lib::TestBuilder; >+ >+my $schema = Koha::Database->new->schema; >+$schema->storage->txn_begin; >+ >+my $builder = t::lib::TestBuilder->new; >+ >+subtest 'basic CRUD operations' => sub { >+ plan tests => 4; >+ >+ $schema->resultset('ShibbolethFieldMapping')->delete; >+ >+ my $nb_of_mappings = Koha::ShibbolethFieldMappings->search->count; >+ my $new_mapping_1 = Koha::ShibbolethFieldMapping->new( >+ { >+ idp_field => 'eppn', >+ koha_field => 'userid', >+ is_matchpoint => 1, >+ } >+ )->store; >+ >+ like( $new_mapping_1->mapping_id, qr|^\d+$|, 'Adding a new mapping should set the mapping_id' ); >+ is( Koha::ShibbolethFieldMappings->search->count, $nb_of_mappings + 1, 'The mapping should have been added' ); >+ >+ my $retrieved_mapping_1 = Koha::ShibbolethFieldMappings->find( $new_mapping_1->mapping_id ); >+ is( >+ $retrieved_mapping_1->koha_field, $new_mapping_1->koha_field, >+ 'Find a mapping by id should return the correct mapping' >+ ); >+ >+ $retrieved_mapping_1->delete; >+ is( Koha::ShibbolethFieldMappings->search->count, $nb_of_mappings, 'Delete should have deleted the mapping' ); >+}; >+ >+subtest 'store validation' => sub { >+ plan tests => 2; >+ >+ $schema->resultset('ShibbolethFieldMapping')->delete; >+ >+ throws_ok { >+ Koha::ShibbolethFieldMapping->new( >+ { >+ idp_field => 'eppn', >+ } >+ )->store; >+ } >+ 'Koha::Exceptions::MissingParameter', 'Store without koha_field throws exception'; >+ >+ throws_ok { >+ Koha::ShibbolethFieldMapping->new( >+ { >+ koha_field => 'userid', >+ } >+ )->store; >+ } >+ 'Koha::Exceptions::MissingParameter', 'Store without idp_field throws exception'; >+}; >+ >+subtest 'ensure_single_matchpoint' => sub { >+ plan tests => 3; >+ >+ $schema->resultset('ShibbolethFieldMapping')->delete; >+ >+ my $mapping1 = Koha::ShibbolethFieldMapping->new( >+ { >+ idp_field => 'eppn', >+ koha_field => 'userid', >+ is_matchpoint => 1 >+ } >+ )->store; >+ >+ my $mapping2 = Koha::ShibbolethFieldMapping->new( >+ { >+ idp_field => 'mail', >+ koha_field => 'email', >+ is_matchpoint => 1 >+ } >+ )->store; >+ >+ $mapping1->discard_changes; >+ is( $mapping1->is_matchpoint, 0, 'First matchpoint was cleared' ); >+ is( $mapping2->is_matchpoint, 1, 'Second matchpoint remains set' ); >+ >+ my $matchpoint_count = Koha::ShibbolethFieldMappings->search( { is_matchpoint => 1 } )->count; >+ is( $matchpoint_count, 1, 'Only one matchpoint exists' ); >+}; >+ >+subtest 'get_matchpoint' => sub { >+ plan tests => 2; >+ >+ $schema->resultset('ShibbolethFieldMapping')->delete; >+ >+ my $mapping = $builder->build_object( >+ { >+ class => 'Koha::ShibbolethFieldMappings', >+ value => { >+ idp_field => 'eppn', >+ koha_field => 'userid', >+ is_matchpoint => 1 >+ } >+ } >+ ); >+ >+ my $matchpoint = Koha::ShibbolethFieldMappings->new->get_matchpoint; >+ is( $matchpoint->mapping_id, $mapping->mapping_id, 'get_matchpoint returns correct mapping' ); >+ >+ $mapping->is_matchpoint(0)->store; >+ $matchpoint = Koha::ShibbolethFieldMappings->new->get_matchpoint; >+ is( $matchpoint, undef, 'get_matchpoint returns undef when no matchpoint exists' ); >+}; >+ >+subtest 'get_mapping_config' => sub { >+ plan tests => 6; >+ >+ $schema->resultset('ShibbolethFieldMapping')->delete; >+ >+ my ( $success, $config ) = Koha::ShibbolethFieldMappings->new->get_mapping_config; >+ is( $success, 0, 'get_mapping_config returns failure when no matchpoint' ); >+ is( $config, undef, 'get_mapping_config returns undef config when no matchpoint' ); >+ >+ $builder->build_object( >+ { >+ class => 'Koha::ShibbolethFieldMappings', >+ value => { >+ idp_field => 'eppn', >+ koha_field => 'userid', >+ is_matchpoint => 1, >+ default_content => undef >+ } >+ } >+ ); >+ >+ $builder->build_object( >+ { >+ class => 'Koha::ShibbolethFieldMappings', >+ value => { >+ idp_field => 'mail', >+ koha_field => 'email', >+ is_matchpoint => 0, >+ default_content => undef >+ } >+ } >+ ); >+ >+ ( $success, $config ) = Koha::ShibbolethFieldMappings->new->get_mapping_config; >+ is( $success, 1, 'get_mapping_config returns success with valid mappings' ); >+ is( $config->{matchpoint}, 'userid', 'Matchpoint field is correct' ); >+ is( $config->{mapping}->{userid}->{is}, 'eppn', 'userid mapping is correct' ); >+ is( $config->{mapping}->{email}->{is}, 'mail', 'email mapping is correct' ); >+}; >+ >+$schema->storage->txn_rollback; >diff --git a/t/db_dependent/Shibboleth/Migration.t b/t/db_dependent/Shibboleth/Migration.t >new file mode 100755 >index 00000000000..9c46e91b081 >--- /dev/null >+++ b/t/db_dependent/Shibboleth/Migration.t >@@ -0,0 +1,206 @@ >+use Modern::Perl; >+use Test::More tests => 4; >+use Test::NoWarnings; >+ >+use t::lib::TestBuilder; >+use File::Temp qw(tempfile); >+use XML::Simple; >+ >+use C4::Installer qw( TableExists run_atomic_updates ); >+use Koha::Database; >+use Koha::ShibbolethConfigs; >+use Koha::ShibbolethFieldMappings; >+ >+my $schema = Koha::Database->new->schema; >+ >+subtest 'Migration from XML config' => sub { >+ plan tests => 15; >+ >+ $schema->storage->txn_begin; >+ >+ my $dbh = C4::Context->dbh; >+ >+ Koha::ShibbolethConfigs->search()->delete; >+ Koha::ShibbolethFieldMappings->search()->delete; >+ $dbh->do( >+ "DELETE FROM systempreferences WHERE variable IN ('ShibbolethAuthentication', 'staffShibOnly', 'OPACShibOnly')" >+ ); >+ >+ my $xml_content = <<'EOT'; >+<?xml version="1.0" encoding="UTF-8"?> >+<yazgfs> >+ <config> >+ <useshibboleth>1</useshibboleth> >+ <shibboleth> >+ <autocreate>1</autocreate> >+ <sync>1</sync> >+ <welcome>1</welcome> >+ <matchpoint>email</matchpoint> >+ <mapping> >+ <email is="mail"></email> >+ <userid is="userid"></userid> >+ <cardnumber is="id"></cardnumber> >+ <firstname is="givenname"></firstname> >+ <surname is="surname"></surname> >+ <branchcode content="MAIN"></branchcode> >+ <categorycode content="DEFAULT"></categorycode> >+ <password is="digitalid"></password> >+ <borrowernotes content="AUTOMATIC_USER"></borrowernotes> >+ </mapping> >+ </shibboleth> >+ </config> >+</yazgfs> >+EOT >+ >+ my ( $fh, $filename ) = tempfile(); >+ print $fh $xml_content; >+ close $fh; >+ >+ $schema->resultset('Systempreference')->update_or_create( >+ { >+ variable => 'staffShibOnly', >+ value => 1, >+ explanation => 'If ON enables shibboleth only authentication for the staff client', >+ type => 'YesNo' >+ } >+ ); >+ >+ $schema->resultset('Systempreference')->update_or_create( >+ { >+ variable => 'OPACShibOnly', >+ value => 1, >+ explanation => 'If ON enables shibboleth only authentication for the opac', >+ type => 'YesNo' >+ } >+ ); >+ >+ local $ENV{KOHA_CONF} = $filename; >+ >+ run_atomic_updates( ['bug_39224_add_shibboleth_tables.pl'] ); >+ >+ ok( $dbh->selectrow_array(q{SHOW TABLES LIKE 'shibboleth_config'}), "shibboleth_config table exists" ); >+ ok( >+ $dbh->selectrow_array(q{SHOW TABLES LIKE 'shibboleth_field_mappings'}), >+ "shibboleth_field_mappings table exists" >+ ); >+ >+ my ($syspref_value) = >+ $dbh->selectrow_array("SELECT value FROM systempreferences WHERE variable = 'ShibbolethAuthentication'"); >+ is( $syspref_value, 1, "ShibbolethAuthentication syspref created with correct value" ); >+ >+ my $config = $dbh->selectrow_hashref("SELECT * FROM shibboleth_config"); >+ ok( $config, "Config row created" ); >+ is( $config->{force_opac_sso}, 1, "OPACShibOnly migrated correctly" ); >+ is( $config->{force_staff_sso}, 1, "staffShibOnly migrated correctly" ); >+ is( $config->{autocreate}, 1, "autocreate setting migrated" ); >+ is( $config->{sync}, 1, "sync setting migrated" ); >+ is( $config->{welcome}, 1, "welcome setting migrated" ); >+ >+ my $old_prefs = $dbh->selectall_arrayref( >+ "SELECT variable FROM systempreferences WHERE variable IN ('staffShibOnly','OPACShibOnly')"); >+ is( scalar @$old_prefs, 0, "Old sysprefs were removed" ); >+ >+ my @mappings = Koha::ShibbolethFieldMappings->search()->as_list; >+ is( scalar @mappings, 9, "All 9 field mappings migrated" ); >+ >+ my $email_mapping = Koha::ShibbolethFieldMappings->find( { koha_field => 'email' } ); >+ is( $email_mapping->idp_field, 'mail', "email mapping IDP field correct" ); >+ is( $email_mapping->is_matchpoint, 1, "email is matchpoint" ); >+ >+ my $branchcode_mapping = Koha::ShibbolethFieldMappings->find( { koha_field => 'branchcode' } ); >+ is( $branchcode_mapping->default_content, 'MAIN', "branchcode default content correct" ); >+ is( $branchcode_mapping->idp_field, undef, "branchcode has no IDP field" ); >+ >+ $schema->storage->txn_rollback; >+}; >+ >+subtest 'Idempotency - running migration twice' => sub { >+ plan tests => 5; >+ >+ $schema->storage->txn_begin; >+ >+ my $dbh = C4::Context->dbh; >+ Koha::ShibbolethConfigs->search()->delete; >+ Koha::ShibbolethFieldMappings->search()->delete; >+ $dbh->do("DELETE FROM systempreferences WHERE variable = 'ShibbolethAuthentication'"); >+ >+ my $xml_content = <<'EOT'; >+<?xml version="1.0" encoding="UTF-8"?> >+<yazgfs> >+ <config> >+ <useshibboleth>1</useshibboleth> >+ <shibboleth> >+ <autocreate>1</autocreate> >+ <sync>1</sync> >+ <welcome>1</welcome> >+ <matchpoint>email</matchpoint> >+ <mapping> >+ <email is="mail"></email> >+ <userid is="userid"></userid> >+ </mapping> >+ </shibboleth> >+ </config> >+</yazgfs> >+EOT >+ >+ my ( $fh, $filename ) = tempfile(); >+ print $fh $xml_content; >+ close $fh; >+ >+ local $ENV{KOHA_CONF} = $filename; >+ >+ run_atomic_updates( ['bug_39224_add_shibboleth_tables.pl'] ); >+ >+ my $config_count_before = Koha::ShibbolethConfigs->count; >+ my $mapping_count_before = Koha::ShibbolethFieldMappings->count; >+ my ($syspref_count_before) = >+ $dbh->selectrow_array("SELECT COUNT(*) FROM systempreferences WHERE variable = 'ShibbolethAuthentication'"); >+ >+ run_atomic_updates( ['bug_39224_add_shibboleth_tables.pl'] ); >+ >+ my $config_count_after = Koha::ShibbolethConfigs->count; >+ my $mapping_count_after = Koha::ShibbolethFieldMappings->count; >+ my ($syspref_count_after) = >+ $dbh->selectrow_array("SELECT COUNT(*) FROM systempreferences WHERE variable = 'ShibbolethAuthentication'"); >+ >+ is( $config_count_after, $config_count_before, "Config row count unchanged after second run" ); >+ is( $mapping_count_after, $mapping_count_before, "Mapping row count unchanged after second run" ); >+ is( $syspref_count_after, $syspref_count_before, "Syspref count unchanged after second run" ); >+ >+ my $config = Koha::ShibbolethConfigs->search()->single; >+ ok( $config, "Config found after second run" ); >+ is( $config->autocreate, 1, "Config values still correct after second run" ) if $config; >+ >+ $schema->storage->txn_rollback; >+}; >+ >+subtest 'Migration without XML config or old sysprefs' => sub { >+ plan tests => 4; >+ >+ $schema->storage->txn_begin; >+ >+ my $dbh = C4::Context->dbh; >+ Koha::ShibbolethConfigs->search()->delete; >+ Koha::ShibbolethFieldMappings->search()->delete; >+ $dbh->do( >+ "DELETE FROM systempreferences WHERE variable IN ('ShibbolethAuthentication', 'staffShibOnly', 'OPACShibOnly')" >+ ); >+ >+ local $ENV{KOHA_CONF} = '/nonexistent/path.xml'; >+ >+ run_atomic_updates( ['bug_39224_add_shibboleth_tables.pl'] ); >+ >+ ok( $dbh->selectrow_array(q{SHOW TABLES LIKE 'shibboleth_config'}), "Tables created without XML" ); >+ >+ my ($syspref_value) = >+ $dbh->selectrow_array("SELECT value FROM systempreferences WHERE variable = 'ShibbolethAuthentication'"); >+ is( $syspref_value, 0, "ShibbolethAuthentication defaults to 0 without XML" ); >+ >+ my $config_count = Koha::ShibbolethConfigs->count; >+ is( $config_count, 0, "No config row created without XML or old sysprefs" ); >+ >+ my $mapping_count = Koha::ShibbolethFieldMappings->count; >+ is( $mapping_count, 0, "No field mappings created without XML" ); >+ >+ $schema->storage->txn_rollback; >+}; >diff --git a/t/db_dependent/api/v1/shibboleth_config.t b/t/db_dependent/api/v1/shibboleth_config.t >new file mode 100755 >index 00000000000..ebb0b128037 >--- /dev/null >+++ b/t/db_dependent/api/v1/shibboleth_config.t >@@ -0,0 +1,121 @@ >+#!/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 => 3; >+use Test::Mojo; >+ >+use t::lib::TestBuilder; >+use t::lib::Mocks; >+ >+use Koha::ShibbolethConfigs; >+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 'get() tests' => sub { >+ >+ plan tests => 5; >+ >+ $schema->storage->txn_begin; >+ >+ my $librarian = $builder->build_object( >+ { >+ class => 'Koha::Patrons', >+ value => { flags => 2**3 } >+ } >+ ); >+ 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; >+ >+ $schema->resultset('ShibbolethConfig')->delete; >+ >+ my $config = Koha::ShibbolethConfigs->new->get_configuration; >+ >+ $t->get_ok("//$userid:$password@/api/v1/shibboleth/config")->status_is(200)->json_is( $config->to_api ); >+ >+ $t->get_ok("//$unauth_userid:$password@/api/v1/shibboleth/config")->status_is(403); >+ >+ $schema->storage->txn_rollback; >+}; >+ >+subtest 'update() tests' => sub { >+ >+ plan tests => 10; >+ >+ $schema->storage->txn_begin; >+ >+ my $librarian = $builder->build_object( >+ { >+ class => 'Koha::Patrons', >+ value => { flags => 2**3 } >+ } >+ ); >+ 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; >+ >+ $schema->resultset('ShibbolethConfig')->delete; >+ >+ my $config = Koha::ShibbolethConfigs->new->get_configuration; >+ >+ my $updated_config = { >+ force_opac_sso => 1, >+ force_staff_sso => 1, >+ autocreate => 1, >+ sync => 1, >+ welcome => 0 >+ }; >+ >+ $t->put_ok( "//$unauth_userid:$password@/api/v1/shibboleth/config" => json => $updated_config )->status_is(403); >+ >+ $t->put_ok( "//$userid:$password@/api/v1/shibboleth/config" => json => $updated_config )->status_is(200) >+ ->json_is( '/force_opac_sso' => 1 )->json_is( '/force_staff_sso' => 1 )->json_is( '/autocreate' => 1 ) >+ ->json_is( '/sync' => 1 )->json_is( '/welcome' => 0 ); >+ >+ my $updated = Koha::ShibbolethConfigs->find(1); >+ is( $updated->force_opac_sso, 1, 'force_opac_sso updated in database' ); >+ >+ $schema->storage->txn_rollback; >+}; >diff --git a/t/db_dependent/api/v1/shibboleth_field_mappings.t b/t/db_dependent/api/v1/shibboleth_field_mappings.t >new file mode 100755 >index 00000000000..0947f1f4bc6 >--- /dev/null >+++ b/t/db_dependent/api/v1/shibboleth_field_mappings.t >@@ -0,0 +1,356 @@ >+#!/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 => 6; >+use Test::Mojo; >+ >+use t::lib::TestBuilder; >+use t::lib::Mocks; >+ >+use Koha::ShibbolethFieldMappings; >+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 'list() tests' => sub { >+ >+ plan tests => 20; >+ >+ $schema->storage->txn_begin; >+ >+ Koha::ShibbolethFieldMappings->search->delete; >+ >+ my $librarian = $builder->build_object( >+ { >+ class => 'Koha::Patrons', >+ value => { flags => 2**3 } >+ } >+ ); >+ 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/shibboleth/mappings")->status_is(200)->json_is( [] ); >+ >+ my $mapping = $builder->build_object( { class => 'Koha::ShibbolethFieldMappings' } ); >+ >+ $t->get_ok("//$userid:$password@/api/v1/shibboleth/mappings")->status_is(200)->json_is( [ $mapping->to_api ] ); >+ >+ my $another_mapping = $builder->build_object( >+ { >+ class => 'Koha::ShibbolethFieldMappings', >+ value => { idp_field => 'eppn', koha_field => 'userid' } >+ } >+ ); >+ >+ $t->get_ok("//$userid:$password@/api/v1/shibboleth/mappings")->status_is(200)->json_is( >+ [ >+ $mapping->to_api, >+ $another_mapping->to_api, >+ ] >+ ); >+ >+ $mapping->delete; >+ $another_mapping->delete; >+ $t->get_ok(qq~//$userid:$password@/api/v1/shibboleth/mappings?q=[{"me.koha_field":{"like":"%user%"}}]~) >+ ->status_is(200)->json_is( [] ); >+ >+ my $mapping_to_search = $builder->build_object( >+ { >+ class => 'Koha::ShibbolethFieldMappings', >+ value => { >+ koha_field => 'userid', >+ } >+ } >+ ); >+ >+ $t->get_ok(qq~//$userid:$password@/api/v1/shibboleth/mappings?q=[{"me.koha_field":{"like":"%user%"}}]~) >+ ->status_is(200)->json_is( [ $mapping_to_search->to_api ] ); >+ >+ $t->get_ok("//$userid:$password@/api/v1/shibboleth/mappings?blah=blah")->status_is(400) >+ ->json_is( [ { path => '/query/blah', message => 'Malformed query string' } ] ); >+ >+ $t->get_ok("//$unauth_userid:$password@/api/v1/shibboleth/mappings")->status_is(403); >+ >+ $schema->storage->txn_rollback; >+}; >+ >+subtest 'get() tests' => sub { >+ >+ plan tests => 8; >+ >+ $schema->storage->txn_begin; >+ >+ my $mapping = $builder->build_object( { class => 'Koha::ShibbolethFieldMappings' } ); >+ my $librarian = $builder->build_object( >+ { >+ class => 'Koha::Patrons', >+ value => { flags => 2**3 } >+ } >+ ); >+ 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/shibboleth/mappings/" . $mapping->mapping_id )->status_is(200) >+ ->json_is( $mapping->to_api ); >+ >+ $t->get_ok( "//$unauth_userid:$password@/api/v1/shibboleth/mappings/" . $mapping->mapping_id )->status_is(403); >+ >+ my $mapping_to_delete = $builder->build_object( { class => 'Koha::ShibbolethFieldMappings' } ); >+ my $non_existent_id = $mapping_to_delete->mapping_id; >+ $mapping_to_delete->delete; >+ >+ $t->get_ok("//$userid:$password@/api/v1/shibboleth/mappings/$non_existent_id")->status_is(404) >+ ->json_is( '/error' => 'Mapping not found' ); >+ >+ $schema->storage->txn_rollback; >+}; >+ >+subtest 'add() tests' => sub { >+ >+ plan tests => 19; >+ >+ $schema->storage->txn_begin; >+ >+ my $librarian = $builder->build_object( >+ { >+ class => 'Koha::Patrons', >+ value => { flags => 2**3 } >+ } >+ ); >+ 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; >+ >+ my $mapping = { >+ idp_field => "mail", >+ koha_field => "email", >+ is_matchpoint => 0, >+ }; >+ >+ $t->post_ok( "//$unauth_userid:$password@/api/v1/shibboleth/mappings" => json => $mapping )->status_is(403); >+ >+ my $mapping_with_invalid_field = { >+ blah => "Mapping Blah", >+ idp_field => "mail", >+ koha_field => "email", >+ is_matchpoint => 0, >+ }; >+ >+ $t->post_ok( "//$userid:$password@/api/v1/shibboleth/mappings" => json => $mapping_with_invalid_field ) >+ ->status_is(400)->json_is( >+ "/errors" => [ >+ { >+ message => "Properties not allowed: blah.", >+ path => "/body" >+ } >+ ] >+ ); >+ >+ my $mapping_id = >+ $t->post_ok( "//$userid:$password@/api/v1/shibboleth/mappings" => json => $mapping ) >+ ->status_is( 201, 'REST3.2.1' )->header_like( >+ Location => qr|^/api/v1/shibboleth/mappings/\d*|, >+ 'REST3.4.1' >+ )->json_is( '/idp_field' => $mapping->{idp_field} )->json_is( '/koha_field' => $mapping->{koha_field} ) >+ ->tx->res->json->{mapping_id}; >+ >+ $mapping->{mapping_id} = undef; >+ $t->post_ok( "//$userid:$password@/api/v1/shibboleth/mappings" => json => $mapping )->status_is(400) >+ ->json_has('/errors'); >+ >+ $mapping->{mapping_id} = $mapping_id; >+ >+ $t->post_ok( "//$userid:$password@/api/v1/shibboleth/mappings" => json => $mapping )->status_is(400)->json_is( >+ "/errors" => [ >+ { >+ message => "Read-only.", >+ path => "/body/mapping_id" >+ } >+ ] >+ ); >+ >+ my $mapping_without_idp_or_default = { >+ koha_field => "phonepro", >+ is_matchpoint => 0, >+ }; >+ >+ $t->post_ok( "//$userid:$password@/api/v1/shibboleth/mappings" => json => $mapping_without_idp_or_default ) >+ ->status_is(400)->json_is( "/error" => "Either idp_field or default_content must be provided" ); >+ >+ $schema->storage->txn_rollback; >+}; >+ >+subtest 'update() tests' => sub { >+ >+ plan tests => 15; >+ >+ $schema->storage->txn_begin; >+ >+ my $librarian = $builder->build_object( >+ { >+ class => 'Koha::Patrons', >+ value => { flags => 2**3 } >+ } >+ ); >+ 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; >+ >+ my $mapping_id = $builder->build_object( { class => 'Koha::ShibbolethFieldMappings' } )->mapping_id; >+ >+ $t->put_ok( "//$unauth_userid:$password@/api/v1/shibboleth/mappings/$mapping_id" => json => >+ { idp_field => 'New unauthorized name change' } )->status_is(403); >+ >+ my $mapping_without_idp_or_default = { >+ koha_field => 'surname', >+ idp_field => undef, >+ default_content => undef, >+ is_matchpoint => 0, >+ }; >+ >+ $t->put_ok( >+ "//$userid:$password@/api/v1/shibboleth/mappings/$mapping_id" => json => $mapping_without_idp_or_default ) >+ ->status_is(400)->json_is( "/error" => "Either idp_field or default_content must be provided" ); >+ >+ my $mapping_with_updated_field = { >+ idp_field => "sn", >+ koha_field => "surname", >+ is_matchpoint => 0, >+ }; >+ >+ $t->put_ok( "//$userid:$password@/api/v1/shibboleth/mappings/$mapping_id" => json => $mapping_with_updated_field ) >+ ->status_is(200)->json_is( '/idp_field' => 'sn' ); >+ >+ my $mapping_with_invalid_field = { >+ blah => "Mapping Blah", >+ idp_field => "sn", >+ koha_field => "surname", >+ is_matchpoint => 0, >+ }; >+ >+ $t->put_ok( "//$userid:$password@/api/v1/shibboleth/mappings/$mapping_id" => json => $mapping_with_invalid_field ) >+ ->status_is(400)->json_is( >+ "/errors" => [ >+ { >+ message => "Properties not allowed: blah.", >+ path => "/body" >+ } >+ ] >+ ); >+ >+ my $mapping_to_delete = $builder->build_object( { class => 'Koha::ShibbolethFieldMappings' } ); >+ my $non_existent_id = $mapping_to_delete->mapping_id; >+ $mapping_to_delete->delete; >+ >+ $t->put_ok( >+ "//$userid:$password@/api/v1/shibboleth/mappings/$non_existent_id" => json => $mapping_with_updated_field ) >+ ->status_is(404); >+ >+ $mapping_with_updated_field->{mapping_id} = 2; >+ >+ $t->post_ok( "//$userid:$password@/api/v1/shibboleth/mappings/$mapping_id" => json => $mapping_with_updated_field ) >+ ->status_is(404); >+ >+ $schema->storage->txn_rollback; >+}; >+ >+subtest 'delete() tests' => sub { >+ >+ plan tests => 7; >+ >+ $schema->storage->txn_begin; >+ >+ my $librarian = $builder->build_object( >+ { >+ class => 'Koha::Patrons', >+ value => { flags => 2**3 } >+ } >+ ); >+ 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; >+ >+ my $mapping_id = $builder->build_object( { class => 'Koha::ShibbolethFieldMappings' } )->mapping_id; >+ >+ $t->delete_ok("//$unauth_userid:$password@/api/v1/shibboleth/mappings/$mapping_id")->status_is(403); >+ >+ $t->delete_ok("//$userid:$password@/api/v1/shibboleth/mappings/$mapping_id")->status_is( 204, 'REST3.2.4' ) >+ ->content_is( '', 'REST3.3.4' ); >+ >+ $t->delete_ok("//$userid:$password@/api/v1/shibboleth/mappings/$mapping_id")->status_is(404); >+ >+ $schema->storage->txn_rollback; >+}; >-- >2.39.5
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 39224
:
189234
|
189235
|
189236
|
189237
|
189238
|
189239
| 189240 |
189241
|
189242
|
189243
|
189244