View | Details | Raw Unified | Return to bug 39224
Collapse All | Expand All

(-)a/t/db_dependent/Auth_with_shibboleth.t (-14 / +46 lines)
Lines 35-40 use t::lib::Dates; Link Here
35
use C4::Auth_with_shibboleth qw( shib_ok login_shib_url get_login_shib checkpw_shib );
35
use C4::Auth_with_shibboleth qw( shib_ok login_shib_url get_login_shib checkpw_shib );
36
use Koha::Database;
36
use Koha::Database;
37
use Koha::DateUtils qw( dt_from_string );
37
use Koha::DateUtils qw( dt_from_string );
38
use Koha::ShibbolethConfig;
39
use Koha::ShibbolethConfigs;
40
use Koha::ShibbolethFieldMapping;
38
41
39
BEGIN {
42
BEGIN {
40
    use_ok(
43
    use_ok(
Lines 48-56 $schema->storage->txn_begin; Link Here
48
my $builder = t::lib::TestBuilder->new;
51
my $builder = t::lib::TestBuilder->new;
49
my $logger  = t::lib::Mocks::Logger->new();
52
my $logger  = t::lib::Mocks::Logger->new();
50
53
51
# Mock variables
52
my $shibboleth;
54
my $shibboleth;
53
change_config( {} );
54
my $interface = 'opac';
55
my $interface = 'opac';
55
56
56
# Mock few preferences
57
# Mock few preferences
Lines 59-70 t::lib::Mocks::mock_preference( 'StaffClientBaseURL', 'teststaff.com' ); Link Here
59
t::lib::Mocks::mock_preference( 'EmailFieldPrimary',    '' );
60
t::lib::Mocks::mock_preference( 'EmailFieldPrimary',    '' );
60
t::lib::Mocks::mock_preference( 'EmailFieldPrecedence', 'emailpro' );
61
t::lib::Mocks::mock_preference( 'EmailFieldPrecedence', 'emailpro' );
61
62
62
# Mock Context: config, tz and interface
63
# Mock Context: tz and interface
63
my $context = Test::MockModule->new('C4::Context');
64
my $context = Test::MockModule->new('C4::Context');
64
$context->mock( 'config',    sub { return $shibboleth; } );    # easier than caching by Mocks::mock_config
65
$context->mock( 'timezone',  sub { return 'local'; } );
65
$context->mock( 'timezone',  sub { return 'local'; } );
66
$context->mock( 'interface', sub { return $interface; } );
66
$context->mock( 'interface', sub { return $interface; } );
67
67
68
change_config( {} );
69
68
# Mock Letters: GetPreparedLetter, EnqueueLetter and SendQueuedMessages
70
# Mock Letters: GetPreparedLetter, EnqueueLetter and SendQueuedMessages
69
# We want to test the params
71
# We want to test the params
70
my $mocked_letters = Test::MockModule->new('C4::Letters');
72
my $mocked_letters = Test::MockModule->new('C4::Letters');
Lines 97-116 $mocked_letters->mock( Link Here
97
# Start testing ----------------------------------------------------------------
99
# Start testing ----------------------------------------------------------------
98
100
99
subtest "shib_ok tests" => sub {
101
subtest "shib_ok tests" => sub {
100
    plan tests => 5;
102
    plan tests => 6;
101
    my $result;
103
    my $result;
102
104
103
    # correct config, no debug
105
    # correct config, no debug
104
    is( shib_ok(), '1', "good config" );
106
    is( shib_ok(), '1', "good config" );
105
107
106
    # bad config, no debug
108
    # bad config, no debug - clear matchpoint in DB
109
    $schema->resultset('ShibbolethFieldMapping')->update( { is_matchpoint => 0 } );
107
    delete $shibboleth->{matchpoint};
110
    delete $shibboleth->{matchpoint};
108
    warnings_are { $result = shib_ok() }
111
    $result = shib_ok();
109
    [ { carped => 'shibboleth matchpoint not defined' }, ],
112
    $logger->warn_is( 'No matchpoint configured in Shibboleth field mappings', "matchpoint warning logged" )
110
        "undefined matchpoint = fatal config, warning given";
113
        ->warn_is( 'shibboleth config could not be loaded', "config could not be loaded warning" )->clear();
111
    is( $result, '0', "bad config" );
114
    is( $result, '0', "bad config" );
112
115
113
    change_config( { matchpoint => 'email' } );
116
    change_config( { matchpoint => 'email', mapping => { email => { content => 'default@example.com' } } } );
114
    warnings_are { $result = shib_ok() }
117
    warnings_are { $result = shib_ok() }
115
    [ { carped => 'shibboleth matchpoint not mapped' }, ],
118
    [ { carped => 'shibboleth matchpoint not mapped' }, ],
116
        "unmapped matchpoint = fatal config, warning given";
119
        "unmapped matchpoint = fatal config, warning given";
Lines 273-278 subtest "checkpw_shib tests" => sub { Link Here
273
    );
276
    );
274
277
275
    # sync user
278
    # sync user
279
    my $config = Koha::ShibbolethConfigs->new->get_configuration;
280
    $config->sync(1)->store;
276
    $shibboleth->{sync} = 1;
281
    $shibboleth->{sync} = 1;
277
    $ENV{'city'} = 'AnotherCity';
282
    $ENV{'city'} = 'AnotherCity';
278
    ( $retval, $retcard, $retuserid, $retpatron ) = checkpw_shib($shib_login);
283
    ( $retval, $retcard, $retuserid, $retpatron ) = checkpw_shib($shib_login);
Lines 327-333 subtest "checkpw_shib tests" => sub { Link Here
327
    $ENV{'emailpro'} = 'me@myemail.com';
332
    $ENV{'emailpro'} = 'me@myemail.com';
328
    $ENV{branchcode} = $library->branchcode;      # needed since T::D::C does no longer hides the FK constraint
333
    $ENV{branchcode} = $library->branchcode;      # needed since T::D::C does no longer hides the FK constraint
329
334
330
    checkpw($shib_login);
335
    ( $retval, $retcard, $retuserid, $retpatron ) = checkpw_shib($shib_login);
331
    ok(
336
    ok(
332
        my $new_user_autocreated = Koha::Patrons->find( { userid => 'test43210' } ),
337
        my $new_user_autocreated = Koha::Patrons->find( { userid => 'test43210' } ),
333
        "new user found"
338
        "new user found"
Lines 416-421 $schema->storage->txn_rollback; Link Here
416
sub change_config {
421
sub change_config {
417
    my $params = shift;
422
    my $params = shift;
418
423
424
    $schema->resultset('ShibbolethConfig')->delete;
425
    $schema->resultset('ShibbolethFieldMapping')->delete;
426
427
    Koha::ShibbolethConfig->new(
428
        {
429
            force_opac_sso  => 0,
430
            force_staff_sso => 0,
431
            autocreate      => $params->{autocreate} // 0,
432
            sync            => $params->{sync}       // 0,
433
            welcome         => $params->{welcome}    // 0,
434
        }
435
    )->store;
436
419
    my %mapping = (
437
    my %mapping = (
420
        'userid'       => { 'is' => 'uid' },
438
        'userid'       => { 'is' => 'uid' },
421
        'surname'      => { 'is' => 'sn' },
439
        'surname'      => { 'is' => 'sn' },
Lines 429-443 sub change_config { Link Here
429
    if ( exists $params->{mapping} ) {
447
    if ( exists $params->{mapping} ) {
430
        $mapping{$_} = $params->{mapping}->{$_} for keys %{ $params->{mapping} };
448
        $mapping{$_} = $params->{mapping}->{$_} for keys %{ $params->{mapping} };
431
    }
449
    }
432
    $shibboleth = {
450
451
    my $matchpoint = $params->{matchpoint} // 'userid';
452
453
    foreach my $koha_field ( keys %mapping ) {
454
        Koha::ShibbolethFieldMapping->new(
455
            {
456
                koha_field      => $koha_field,
457
                idp_field       => $mapping{$koha_field}->{is},
458
                is_matchpoint   => $koha_field eq $matchpoint ? 1 : 0,
459
                default_content => $mapping{$koha_field}->{content},
460
            }
461
        )->store;
462
    }
463
464
    my $db_config = Koha::ShibbolethConfigs->new->get_configuration;
465
    $shibboleth = $db_config ? $db_config->get_combined_config : {
433
        autocreate => $params->{autocreate} // 0,
466
        autocreate => $params->{autocreate} // 0,
434
        welcome    => $params->{welcome}    // 0,
467
        welcome    => $params->{welcome}    // 0,
435
        sync       => $params->{sync}       // 0,
468
        sync       => $params->{sync}       // 0,
436
        matchpoint => $params->{matchpoint} // 'userid',
469
        matchpoint => $matchpoint,
437
        mapping    => \%mapping,
470
        mapping    => \%mapping,
438
    };
471
    };
439
472
440
    # Change environment too
441
    $ENV{'uid'}      = "test1234";
473
    $ENV{'uid'}      = "test1234";
442
    $ENV{'sn'}       = undef;
474
    $ENV{'sn'}       = undef;
443
    $ENV{'exp'}      = undef;
475
    $ENV{'exp'}      = undef;
(-)a/t/db_dependent/Koha/ShibbolethConfigs.t (+140 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
# This file is part of Koha
4
#
5
# Koha is free software; you can redistribute it and/or modify it
6
# under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 3 of the License, or
8
# (at your option) any later version.
9
#
10
# Koha is distributed in the hope that it will be useful, but
11
# WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
14
#
15
# You should have received a copy of the GNU General Public License
16
# along with Koha; if not, see <https://www.gnu.org/licenses>.
17
18
use Modern::Perl;
19
20
use Test::NoWarnings;
21
use Test::More tests => 6;
22
23
use Koha::ShibbolethConfig;
24
use Koha::ShibbolethConfigs;
25
use Koha::Database;
26
27
use t::lib::TestBuilder;
28
29
my $schema = Koha::Database->new->schema;
30
$schema->storage->txn_begin;
31
32
my $builder = t::lib::TestBuilder->new;
33
34
subtest 'get_configuration' => sub {
35
    plan tests => 3;
36
37
    $schema->resultset('ShibbolethConfig')->delete;
38
39
    my $config = Koha::ShibbolethConfigs->new->get_configuration;
40
41
    is( $config->shibboleth_config_id, 1, 'Configuration always has ID 1' );
42
    is( $config->force_opac_sso,       0, 'Default force_opac_sso is 0' );
43
    is( $config->autocreate,           0, 'Default autocreate is 0' );
44
};
45
46
subtest 'store always updates singleton' => sub {
47
    plan tests => 3;
48
49
    $schema->resultset('ShibbolethConfig')->delete;
50
51
    my $config1 = Koha::ShibbolethConfig->new(
52
        {
53
            force_opac_sso  => 1,
54
            force_staff_sso => 0,
55
            autocreate      => 1,
56
            sync            => 1,
57
            welcome         => 0
58
        }
59
    )->store;
60
61
    is( $config1->shibboleth_config_id, 1, 'First config has ID 1' );
62
63
    my $config2 = Koha::ShibbolethConfig->new(
64
        {
65
            force_opac_sso  => 0,
66
            force_staff_sso => 1,
67
            autocreate      => 0,
68
            sync            => 0,
69
            welcome         => 1
70
        }
71
    )->store;
72
73
    is( $config2->shibboleth_config_id,         1, 'Second store still has ID 1' );
74
    is( Koha::ShibbolethConfigs->search->count, 1, 'Only one config exists' );
75
};
76
77
subtest 'get_value' => sub {
78
    plan tests => 3;
79
80
    $schema->resultset('ShibbolethConfig')->delete;
81
82
    my $config = Koha::ShibbolethConfigs->new->get_configuration;
83
    $config->force_opac_sso(1)->store;
84
85
    is( $config->get_value('force_opac_sso'),  1,     'get_value returns correct value' );
86
    is( $config->get_value('force_staff_sso'), 0,     'get_value returns correct default' );
87
    is( $config->get_value('nonexistent'),     undef, 'get_value returns undef for nonexistent column' );
88
};
89
90
subtest 'mappings' => sub {
91
    plan tests => 1;
92
93
    $schema->resultset('ShibbolethConfig')->delete;
94
95
    my $config   = Koha::ShibbolethConfigs->new->get_configuration;
96
    my $mappings = $config->mappings;
97
98
    isa_ok( $mappings, 'Koha::ShibbolethFieldMappings', 'mappings returns correct type' );
99
};
100
101
subtest 'get_combined_config' => sub {
102
    plan tests => 4;
103
104
    $schema->resultset('ShibbolethConfig')->delete;
105
    $schema->resultset('ShibbolethFieldMapping')->delete;
106
107
    my $config = Koha::ShibbolethConfigs->new->get_configuration;
108
    $config->force_opac_sso(1)->store;
109
110
    $builder->build_object(
111
        {
112
            class => 'Koha::ShibbolethFieldMappings',
113
            value => {
114
                idp_field     => 'eppn',
115
                koha_field    => 'userid',
116
                is_matchpoint => 1
117
            }
118
        }
119
    );
120
121
    $builder->build_object(
122
        {
123
            class => 'Koha::ShibbolethFieldMappings',
124
            value => {
125
                idp_field     => 'mail',
126
                koha_field    => 'email',
127
                is_matchpoint => 0
128
            }
129
        }
130
    );
131
132
    my $combined = $config->get_combined_config;
133
134
    is( $combined->{force_opac_sso}, 1,        'Combined config includes base settings' );
135
    is( $combined->{matchpoint},     'userid', 'Combined config includes matchpoint' );
136
    ok( exists $combined->{mapping}->{userid}, 'Combined config includes userid mapping' );
137
    ok( exists $combined->{mapping}->{email},  'Combined config includes email mapping' );
138
};
139
140
$schema->storage->txn_rollback;
(-)a/t/db_dependent/Koha/ShibbolethFieldMappings.t (+179 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
# This file is part of Koha
4
#
5
# Koha is free software; you can redistribute it and/or modify it
6
# under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 3 of the License, or
8
# (at your option) any later version.
9
#
10
# Koha is distributed in the hope that it will be useful, but
11
# WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
14
#
15
# You should have received a copy of the GNU General Public License
16
# along with Koha; if not, see <https://www.gnu.org/licenses>.
17
18
use Modern::Perl;
19
20
use Test::NoWarnings;
21
use Test::More tests => 6;
22
use Test::Exception;
23
24
use Koha::ShibbolethFieldMapping;
25
use Koha::ShibbolethFieldMappings;
26
use Koha::Database;
27
28
use t::lib::TestBuilder;
29
30
my $schema = Koha::Database->new->schema;
31
$schema->storage->txn_begin;
32
33
my $builder = t::lib::TestBuilder->new;
34
35
subtest 'basic CRUD operations' => sub {
36
    plan tests => 4;
37
38
    $schema->resultset('ShibbolethFieldMapping')->delete;
39
40
    my $nb_of_mappings = Koha::ShibbolethFieldMappings->search->count;
41
    my $new_mapping_1  = Koha::ShibbolethFieldMapping->new(
42
        {
43
            idp_field     => 'eppn',
44
            koha_field    => 'userid',
45
            is_matchpoint => 1,
46
        }
47
    )->store;
48
49
    like( $new_mapping_1->mapping_id, qr|^\d+$|, 'Adding a new mapping should set the mapping_id' );
50
    is( Koha::ShibbolethFieldMappings->search->count, $nb_of_mappings + 1, 'The mapping should have been added' );
51
52
    my $retrieved_mapping_1 = Koha::ShibbolethFieldMappings->find( $new_mapping_1->mapping_id );
53
    is(
54
        $retrieved_mapping_1->koha_field, $new_mapping_1->koha_field,
55
        'Find a mapping by id should return the correct mapping'
56
    );
57
58
    $retrieved_mapping_1->delete;
59
    is( Koha::ShibbolethFieldMappings->search->count, $nb_of_mappings, 'Delete should have deleted the mapping' );
60
};
61
62
subtest 'store validation' => sub {
63
    plan tests => 2;
64
65
    $schema->resultset('ShibbolethFieldMapping')->delete;
66
67
    throws_ok {
68
        Koha::ShibbolethFieldMapping->new(
69
            {
70
                idp_field => 'eppn',
71
            }
72
        )->store;
73
    }
74
    'Koha::Exceptions::MissingParameter', 'Store without koha_field throws exception';
75
76
    throws_ok {
77
        Koha::ShibbolethFieldMapping->new(
78
            {
79
                koha_field => 'userid',
80
            }
81
        )->store;
82
    }
83
    'Koha::Exceptions::MissingParameter', 'Store without idp_field throws exception';
84
};
85
86
subtest 'ensure_single_matchpoint' => sub {
87
    plan tests => 3;
88
89
    $schema->resultset('ShibbolethFieldMapping')->delete;
90
91
    my $mapping1 = Koha::ShibbolethFieldMapping->new(
92
        {
93
            idp_field     => 'eppn',
94
            koha_field    => 'userid',
95
            is_matchpoint => 1
96
        }
97
    )->store;
98
99
    my $mapping2 = Koha::ShibbolethFieldMapping->new(
100
        {
101
            idp_field     => 'mail',
102
            koha_field    => 'email',
103
            is_matchpoint => 1
104
        }
105
    )->store;
106
107
    $mapping1->discard_changes;
108
    is( $mapping1->is_matchpoint, 0, 'First matchpoint was cleared' );
109
    is( $mapping2->is_matchpoint, 1, 'Second matchpoint remains set' );
110
111
    my $matchpoint_count = Koha::ShibbolethFieldMappings->search( { is_matchpoint => 1 } )->count;
112
    is( $matchpoint_count, 1, 'Only one matchpoint exists' );
113
};
114
115
subtest 'get_matchpoint' => sub {
116
    plan tests => 2;
117
118
    $schema->resultset('ShibbolethFieldMapping')->delete;
119
120
    my $mapping = $builder->build_object(
121
        {
122
            class => 'Koha::ShibbolethFieldMappings',
123
            value => {
124
                idp_field     => 'eppn',
125
                koha_field    => 'userid',
126
                is_matchpoint => 1
127
            }
128
        }
129
    );
130
131
    my $matchpoint = Koha::ShibbolethFieldMappings->new->get_matchpoint;
132
    is( $matchpoint->mapping_id, $mapping->mapping_id, 'get_matchpoint returns correct mapping' );
133
134
    $mapping->is_matchpoint(0)->store;
135
    $matchpoint = Koha::ShibbolethFieldMappings->new->get_matchpoint;
136
    is( $matchpoint, undef, 'get_matchpoint returns undef when no matchpoint exists' );
137
};
138
139
subtest 'get_mapping_config' => sub {
140
    plan tests => 6;
141
142
    $schema->resultset('ShibbolethFieldMapping')->delete;
143
144
    my ( $success, $config ) = Koha::ShibbolethFieldMappings->new->get_mapping_config;
145
    is( $success, 0,     'get_mapping_config returns failure when no matchpoint' );
146
    is( $config,  undef, 'get_mapping_config returns undef config when no matchpoint' );
147
148
    $builder->build_object(
149
        {
150
            class => 'Koha::ShibbolethFieldMappings',
151
            value => {
152
                idp_field       => 'eppn',
153
                koha_field      => 'userid',
154
                is_matchpoint   => 1,
155
                default_content => undef
156
            }
157
        }
158
    );
159
160
    $builder->build_object(
161
        {
162
            class => 'Koha::ShibbolethFieldMappings',
163
            value => {
164
                idp_field       => 'mail',
165
                koha_field      => 'email',
166
                is_matchpoint   => 0,
167
                default_content => undef
168
            }
169
        }
170
    );
171
172
    ( $success, $config ) = Koha::ShibbolethFieldMappings->new->get_mapping_config;
173
    is( $success,                           1,        'get_mapping_config returns success with valid mappings' );
174
    is( $config->{matchpoint},              'userid', 'Matchpoint field is correct' );
175
    is( $config->{mapping}->{userid}->{is}, 'eppn',   'userid mapping is correct' );
176
    is( $config->{mapping}->{email}->{is},  'mail',   'email mapping is correct' );
177
};
178
179
$schema->storage->txn_rollback;
(-)a/t/db_dependent/Shibboleth/Migration.t (+206 lines)
Line 0 Link Here
1
use Modern::Perl;
2
use Test::More tests => 4;
3
use Test::NoWarnings;
4
5
use t::lib::TestBuilder;
6
use File::Temp qw(tempfile);
7
use XML::Simple;
8
9
use C4::Installer qw( TableExists run_atomic_updates );
10
use Koha::Database;
11
use Koha::ShibbolethConfigs;
12
use Koha::ShibbolethFieldMappings;
13
14
my $schema = Koha::Database->new->schema;
15
16
subtest 'Migration from XML config' => sub {
17
    plan tests => 15;
18
19
    $schema->storage->txn_begin;
20
21
    my $dbh = C4::Context->dbh;
22
23
    Koha::ShibbolethConfigs->search()->delete;
24
    Koha::ShibbolethFieldMappings->search()->delete;
25
    $dbh->do(
26
        "DELETE FROM systempreferences WHERE variable IN ('ShibbolethAuthentication', 'staffShibOnly', 'OPACShibOnly')"
27
    );
28
29
    my $xml_content = <<'EOT';
30
<?xml version="1.0" encoding="UTF-8"?>
31
<yazgfs>
32
  <config>
33
    <useshibboleth>1</useshibboleth>
34
    <shibboleth>
35
      <autocreate>1</autocreate>
36
      <sync>1</sync>
37
      <welcome>1</welcome>
38
      <matchpoint>email</matchpoint>
39
      <mapping>
40
        <email is="mail"></email>
41
        <userid is="userid"></userid>
42
        <cardnumber is="id"></cardnumber>
43
        <firstname is="givenname"></firstname>
44
        <surname is="surname"></surname>
45
        <branchcode content="MAIN"></branchcode>
46
        <categorycode content="DEFAULT"></categorycode>
47
        <password is="digitalid"></password>
48
        <borrowernotes content="AUTOMATIC_USER"></borrowernotes>
49
      </mapping>
50
    </shibboleth>
51
  </config>
52
</yazgfs>
53
EOT
54
55
    my ( $fh, $filename ) = tempfile();
56
    print $fh $xml_content;
57
    close $fh;
58
59
    $schema->resultset('Systempreference')->update_or_create(
60
        {
61
            variable    => 'staffShibOnly',
62
            value       => 1,
63
            explanation => 'If ON enables shibboleth only authentication for the staff client',
64
            type        => 'YesNo'
65
        }
66
    );
67
68
    $schema->resultset('Systempreference')->update_or_create(
69
        {
70
            variable    => 'OPACShibOnly',
71
            value       => 1,
72
            explanation => 'If ON enables shibboleth only authentication for the opac',
73
            type        => 'YesNo'
74
        }
75
    );
76
77
    local $ENV{KOHA_CONF} = $filename;
78
79
    run_atomic_updates( ['bug_39224_add_shibboleth_tables.pl'] );
80
81
    ok( $dbh->selectrow_array(q{SHOW TABLES LIKE 'shibboleth_config'}), "shibboleth_config table exists" );
82
    ok(
83
        $dbh->selectrow_array(q{SHOW TABLES LIKE 'shibboleth_field_mappings'}),
84
        "shibboleth_field_mappings table exists"
85
    );
86
87
    my ($syspref_value) =
88
        $dbh->selectrow_array("SELECT value FROM systempreferences WHERE variable = 'ShibbolethAuthentication'");
89
    is( $syspref_value, 1, "ShibbolethAuthentication syspref created with correct value" );
90
91
    my $config = $dbh->selectrow_hashref("SELECT * FROM shibboleth_config");
92
    ok( $config, "Config row created" );
93
    is( $config->{force_opac_sso},  1, "OPACShibOnly migrated correctly" );
94
    is( $config->{force_staff_sso}, 1, "staffShibOnly migrated correctly" );
95
    is( $config->{autocreate},      1, "autocreate setting migrated" );
96
    is( $config->{sync},            1, "sync setting migrated" );
97
    is( $config->{welcome},         1, "welcome setting migrated" );
98
99
    my $old_prefs = $dbh->selectall_arrayref(
100
        "SELECT variable FROM systempreferences WHERE variable IN ('staffShibOnly','OPACShibOnly')");
101
    is( scalar @$old_prefs, 0, "Old sysprefs were removed" );
102
103
    my @mappings = Koha::ShibbolethFieldMappings->search()->as_list;
104
    is( scalar @mappings, 9, "All 9 field mappings migrated" );
105
106
    my $email_mapping = Koha::ShibbolethFieldMappings->find( { koha_field => 'email' } );
107
    is( $email_mapping->idp_field,     'mail', "email mapping IDP field correct" );
108
    is( $email_mapping->is_matchpoint, 1,      "email is matchpoint" );
109
110
    my $branchcode_mapping = Koha::ShibbolethFieldMappings->find( { koha_field => 'branchcode' } );
111
    is( $branchcode_mapping->default_content, 'MAIN', "branchcode default content correct" );
112
    is( $branchcode_mapping->idp_field,       undef,  "branchcode has no IDP field" );
113
114
    $schema->storage->txn_rollback;
115
};
116
117
subtest 'Idempotency - running migration twice' => sub {
118
    plan tests => 5;
119
120
    $schema->storage->txn_begin;
121
122
    my $dbh = C4::Context->dbh;
123
    Koha::ShibbolethConfigs->search()->delete;
124
    Koha::ShibbolethFieldMappings->search()->delete;
125
    $dbh->do("DELETE FROM systempreferences WHERE variable = 'ShibbolethAuthentication'");
126
127
    my $xml_content = <<'EOT';
128
<?xml version="1.0" encoding="UTF-8"?>
129
<yazgfs>
130
  <config>
131
    <useshibboleth>1</useshibboleth>
132
    <shibboleth>
133
      <autocreate>1</autocreate>
134
      <sync>1</sync>
135
      <welcome>1</welcome>
136
      <matchpoint>email</matchpoint>
137
      <mapping>
138
        <email is="mail"></email>
139
        <userid is="userid"></userid>
140
      </mapping>
141
    </shibboleth>
142
  </config>
143
</yazgfs>
144
EOT
145
146
    my ( $fh, $filename ) = tempfile();
147
    print $fh $xml_content;
148
    close $fh;
149
150
    local $ENV{KOHA_CONF} = $filename;
151
152
    run_atomic_updates( ['bug_39224_add_shibboleth_tables.pl'] );
153
154
    my $config_count_before  = Koha::ShibbolethConfigs->count;
155
    my $mapping_count_before = Koha::ShibbolethFieldMappings->count;
156
    my ($syspref_count_before) =
157
        $dbh->selectrow_array("SELECT COUNT(*) FROM systempreferences WHERE variable = 'ShibbolethAuthentication'");
158
159
    run_atomic_updates( ['bug_39224_add_shibboleth_tables.pl'] );
160
161
    my $config_count_after  = Koha::ShibbolethConfigs->count;
162
    my $mapping_count_after = Koha::ShibbolethFieldMappings->count;
163
    my ($syspref_count_after) =
164
        $dbh->selectrow_array("SELECT COUNT(*) FROM systempreferences WHERE variable = 'ShibbolethAuthentication'");
165
166
    is( $config_count_after,  $config_count_before,  "Config row count unchanged after second run" );
167
    is( $mapping_count_after, $mapping_count_before, "Mapping row count unchanged after second run" );
168
    is( $syspref_count_after, $syspref_count_before, "Syspref count unchanged after second run" );
169
170
    my $config = Koha::ShibbolethConfigs->search()->single;
171
    ok( $config, "Config found after second run" );
172
    is( $config->autocreate, 1, "Config values still correct after second run" ) if $config;
173
174
    $schema->storage->txn_rollback;
175
};
176
177
subtest 'Migration without XML config or old sysprefs' => sub {
178
    plan tests => 4;
179
180
    $schema->storage->txn_begin;
181
182
    my $dbh = C4::Context->dbh;
183
    Koha::ShibbolethConfigs->search()->delete;
184
    Koha::ShibbolethFieldMappings->search()->delete;
185
    $dbh->do(
186
        "DELETE FROM systempreferences WHERE variable IN ('ShibbolethAuthentication', 'staffShibOnly', 'OPACShibOnly')"
187
    );
188
189
    local $ENV{KOHA_CONF} = '/nonexistent/path.xml';
190
191
    run_atomic_updates( ['bug_39224_add_shibboleth_tables.pl'] );
192
193
    ok( $dbh->selectrow_array(q{SHOW TABLES LIKE 'shibboleth_config'}), "Tables created without XML" );
194
195
    my ($syspref_value) =
196
        $dbh->selectrow_array("SELECT value FROM systempreferences WHERE variable = 'ShibbolethAuthentication'");
197
    is( $syspref_value, 0, "ShibbolethAuthentication defaults to 0 without XML" );
198
199
    my $config_count = Koha::ShibbolethConfigs->count;
200
    is( $config_count, 0, "No config row created without XML or old sysprefs" );
201
202
    my $mapping_count = Koha::ShibbolethFieldMappings->count;
203
    is( $mapping_count, 0, "No field mappings created without XML" );
204
205
    $schema->storage->txn_rollback;
206
};
(-)a/t/db_dependent/api/v1/shibboleth_config.t (+121 lines)
Line 0 Link Here
1
#!/usr/bin/env perl
2
3
# This file is part of Koha.
4
#
5
# Koha is free software; you can redistribute it and/or modify it
6
# under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 3 of the License, or
8
# (at your option) any later version.
9
#
10
# Koha is distributed in the hope that it will be useful, but
11
# WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
14
#
15
# You should have received a copy of the GNU General Public License
16
# along with Koha; if not, see <https://www.gnu.org/licenses>.
17
18
use Modern::Perl;
19
20
use Test::NoWarnings;
21
use Test::More tests => 3;
22
use Test::Mojo;
23
24
use t::lib::TestBuilder;
25
use t::lib::Mocks;
26
27
use Koha::ShibbolethConfigs;
28
use Koha::Database;
29
30
my $schema  = Koha::Database->new->schema;
31
my $builder = t::lib::TestBuilder->new;
32
33
my $t = Test::Mojo->new('Koha::REST::V1');
34
t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 );
35
36
subtest 'get() tests' => sub {
37
38
    plan tests => 5;
39
40
    $schema->storage->txn_begin;
41
42
    my $librarian = $builder->build_object(
43
        {
44
            class => 'Koha::Patrons',
45
            value => { flags => 2**3 }
46
        }
47
    );
48
    my $password = 'thePassword123';
49
    $librarian->set_password( { password => $password, skip_validation => 1 } );
50
    my $userid = $librarian->userid;
51
52
    my $patron = $builder->build_object(
53
        {
54
            class => 'Koha::Patrons',
55
            value => { flags => 0 }
56
        }
57
    );
58
59
    $patron->set_password( { password => $password, skip_validation => 1 } );
60
    my $unauth_userid = $patron->userid;
61
62
    $schema->resultset('ShibbolethConfig')->delete;
63
64
    my $config = Koha::ShibbolethConfigs->new->get_configuration;
65
66
    $t->get_ok("//$userid:$password@/api/v1/shibboleth/config")->status_is(200)->json_is( $config->to_api );
67
68
    $t->get_ok("//$unauth_userid:$password@/api/v1/shibboleth/config")->status_is(403);
69
70
    $schema->storage->txn_rollback;
71
};
72
73
subtest 'update() tests' => sub {
74
75
    plan tests => 10;
76
77
    $schema->storage->txn_begin;
78
79
    my $librarian = $builder->build_object(
80
        {
81
            class => 'Koha::Patrons',
82
            value => { flags => 2**3 }
83
        }
84
    );
85
    my $password = 'thePassword123';
86
    $librarian->set_password( { password => $password, skip_validation => 1 } );
87
    my $userid = $librarian->userid;
88
89
    my $patron = $builder->build_object(
90
        {
91
            class => 'Koha::Patrons',
92
            value => { flags => 0 }
93
        }
94
    );
95
96
    $patron->set_password( { password => $password, skip_validation => 1 } );
97
    my $unauth_userid = $patron->userid;
98
99
    $schema->resultset('ShibbolethConfig')->delete;
100
101
    my $config = Koha::ShibbolethConfigs->new->get_configuration;
102
103
    my $updated_config = {
104
        force_opac_sso  => 1,
105
        force_staff_sso => 1,
106
        autocreate      => 1,
107
        sync            => 1,
108
        welcome         => 0
109
    };
110
111
    $t->put_ok( "//$unauth_userid:$password@/api/v1/shibboleth/config" => json => $updated_config )->status_is(403);
112
113
    $t->put_ok( "//$userid:$password@/api/v1/shibboleth/config" => json => $updated_config )->status_is(200)
114
        ->json_is( '/force_opac_sso' => 1 )->json_is( '/force_staff_sso' => 1 )->json_is( '/autocreate' => 1 )
115
        ->json_is( '/sync'           => 1 )->json_is( '/welcome'         => 0 );
116
117
    my $updated = Koha::ShibbolethConfigs->find(1);
118
    is( $updated->force_opac_sso, 1, 'force_opac_sso updated in database' );
119
120
    $schema->storage->txn_rollback;
121
};
(-)a/t/db_dependent/api/v1/shibboleth_field_mappings.t (-1 / +356 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/env perl
2
3
# This file is part of Koha.
4
#
5
# Koha is free software; you can redistribute it and/or modify it
6
# under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 3 of the License, or
8
# (at your option) any later version.
9
#
10
# Koha is distributed in the hope that it will be useful, but
11
# WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
14
#
15
# You should have received a copy of the GNU General Public License
16
# along with Koha; if not, see <https://www.gnu.org/licenses>.
17
18
use Modern::Perl;
19
20
use Test::NoWarnings;
21
use Test::More tests => 6;
22
use Test::Mojo;
23
24
use t::lib::TestBuilder;
25
use t::lib::Mocks;
26
27
use Koha::ShibbolethFieldMappings;
28
use Koha::Database;
29
30
my $schema  = Koha::Database->new->schema;
31
my $builder = t::lib::TestBuilder->new;
32
33
my $t = Test::Mojo->new('Koha::REST::V1');
34
t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 );
35
36
subtest 'list() tests' => sub {
37
38
    plan tests => 20;
39
40
    $schema->storage->txn_begin;
41
42
    Koha::ShibbolethFieldMappings->search->delete;
43
44
    my $librarian = $builder->build_object(
45
        {
46
            class => 'Koha::Patrons',
47
            value => { flags => 2**3 }
48
        }
49
    );
50
    my $password = 'thePassword123';
51
    $librarian->set_password( { password => $password, skip_validation => 1 } );
52
    my $userid = $librarian->userid;
53
54
    my $patron = $builder->build_object(
55
        {
56
            class => 'Koha::Patrons',
57
            value => { flags => 0 }
58
        }
59
    );
60
61
    $patron->set_password( { password => $password, skip_validation => 1 } );
62
    my $unauth_userid = $patron->userid;
63
64
    $t->get_ok("//$userid:$password@/api/v1/shibboleth/mappings")->status_is(200)->json_is( [] );
65
66
    my $mapping = $builder->build_object( { class => 'Koha::ShibbolethFieldMappings' } );
67
68
    $t->get_ok("//$userid:$password@/api/v1/shibboleth/mappings")->status_is(200)->json_is( [ $mapping->to_api ] );
69
70
    my $another_mapping = $builder->build_object(
71
        {
72
            class => 'Koha::ShibbolethFieldMappings',
73
            value => { idp_field => 'eppn', koha_field => 'userid' }
74
        }
75
    );
76
77
    $t->get_ok("//$userid:$password@/api/v1/shibboleth/mappings")->status_is(200)->json_is(
78
        [
79
            $mapping->to_api,
80
            $another_mapping->to_api,
81
        ]
82
    );
83
84
    $mapping->delete;
85
    $another_mapping->delete;
86
    $t->get_ok(qq~//$userid:$password@/api/v1/shibboleth/mappings?q=[{"me.koha_field":{"like":"%user%"}}]~)
87
        ->status_is(200)->json_is( [] );
88
89
    my $mapping_to_search = $builder->build_object(
90
        {
91
            class => 'Koha::ShibbolethFieldMappings',
92
            value => {
93
                koha_field => 'userid',
94
            }
95
        }
96
    );
97
98
    $t->get_ok(qq~//$userid:$password@/api/v1/shibboleth/mappings?q=[{"me.koha_field":{"like":"%user%"}}]~)
99
        ->status_is(200)->json_is( [ $mapping_to_search->to_api ] );
100
101
    $t->get_ok("//$userid:$password@/api/v1/shibboleth/mappings?blah=blah")->status_is(400)
102
        ->json_is( [ { path => '/query/blah', message => 'Malformed query string' } ] );
103
104
    $t->get_ok("//$unauth_userid:$password@/api/v1/shibboleth/mappings")->status_is(403);
105
106
    $schema->storage->txn_rollback;
107
};
108
109
subtest 'get() tests' => sub {
110
111
    plan tests => 8;
112
113
    $schema->storage->txn_begin;
114
115
    my $mapping   = $builder->build_object( { class => 'Koha::ShibbolethFieldMappings' } );
116
    my $librarian = $builder->build_object(
117
        {
118
            class => 'Koha::Patrons',
119
            value => { flags => 2**3 }
120
        }
121
    );
122
    my $password = 'thePassword123';
123
    $librarian->set_password( { password => $password, skip_validation => 1 } );
124
    my $userid = $librarian->userid;
125
126
    my $patron = $builder->build_object(
127
        {
128
            class => 'Koha::Patrons',
129
            value => { flags => 0 }
130
        }
131
    );
132
133
    $patron->set_password( { password => $password, skip_validation => 1 } );
134
    my $unauth_userid = $patron->userid;
135
136
    $t->get_ok( "//$userid:$password@/api/v1/shibboleth/mappings/" . $mapping->mapping_id )->status_is(200)
137
        ->json_is( $mapping->to_api );
138
139
    $t->get_ok( "//$unauth_userid:$password@/api/v1/shibboleth/mappings/" . $mapping->mapping_id )->status_is(403);
140
141
    my $mapping_to_delete = $builder->build_object( { class => 'Koha::ShibbolethFieldMappings' } );
142
    my $non_existent_id   = $mapping_to_delete->mapping_id;
143
    $mapping_to_delete->delete;
144
145
    $t->get_ok("//$userid:$password@/api/v1/shibboleth/mappings/$non_existent_id")->status_is(404)
146
        ->json_is( '/error' => 'Mapping not found' );
147
148
    $schema->storage->txn_rollback;
149
};
150
151
subtest 'add() tests' => sub {
152
153
    plan tests => 19;
154
155
    $schema->storage->txn_begin;
156
157
    my $librarian = $builder->build_object(
158
        {
159
            class => 'Koha::Patrons',
160
            value => { flags => 2**3 }
161
        }
162
    );
163
    my $password = 'thePassword123';
164
    $librarian->set_password( { password => $password, skip_validation => 1 } );
165
    my $userid = $librarian->userid;
166
167
    my $patron = $builder->build_object(
168
        {
169
            class => 'Koha::Patrons',
170
            value => { flags => 0 }
171
        }
172
    );
173
174
    $patron->set_password( { password => $password, skip_validation => 1 } );
175
    my $unauth_userid = $patron->userid;
176
177
    my $mapping = {
178
        idp_field     => "mail",
179
        koha_field    => "email",
180
        is_matchpoint => 0,
181
    };
182
183
    $t->post_ok( "//$unauth_userid:$password@/api/v1/shibboleth/mappings" => json => $mapping )->status_is(403);
184
185
    my $mapping_with_invalid_field = {
186
        blah          => "Mapping Blah",
187
        idp_field     => "mail",
188
        koha_field    => "email",
189
        is_matchpoint => 0,
190
    };
191
192
    $t->post_ok( "//$userid:$password@/api/v1/shibboleth/mappings" => json => $mapping_with_invalid_field )
193
        ->status_is(400)->json_is(
194
        "/errors" => [
195
            {
196
                message => "Properties not allowed: blah.",
197
                path    => "/body"
198
            }
199
        ]
200
        );
201
202
    my $mapping_id =
203
        $t->post_ok( "//$userid:$password@/api/v1/shibboleth/mappings" => json => $mapping )
204
        ->status_is( 201, 'REST3.2.1' )->header_like(
205
        Location => qr|^/api/v1/shibboleth/mappings/\d*|,
206
        'REST3.4.1'
207
    )->json_is( '/idp_field' => $mapping->{idp_field} )->json_is( '/koha_field' => $mapping->{koha_field} )
208
        ->tx->res->json->{mapping_id};
209
210
    $mapping->{mapping_id} = undef;
211
    $t->post_ok( "//$userid:$password@/api/v1/shibboleth/mappings" => json => $mapping )->status_is(400)
212
        ->json_has('/errors');
213
214
    $mapping->{mapping_id} = $mapping_id;
215
216
    $t->post_ok( "//$userid:$password@/api/v1/shibboleth/mappings" => json => $mapping )->status_is(400)->json_is(
217
        "/errors" => [
218
            {
219
                message => "Read-only.",
220
                path    => "/body/mapping_id"
221
            }
222
        ]
223
    );
224
225
    my $mapping_without_idp_or_default = {
226
        koha_field    => "phonepro",
227
        is_matchpoint => 0,
228
    };
229
230
    $t->post_ok( "//$userid:$password@/api/v1/shibboleth/mappings" => json => $mapping_without_idp_or_default )
231
        ->status_is(400)->json_is( "/error" => "Either idp_field or default_content must be provided" );
232
233
    $schema->storage->txn_rollback;
234
};
235
236
subtest 'update() tests' => sub {
237
238
    plan tests => 15;
239
240
    $schema->storage->txn_begin;
241
242
    my $librarian = $builder->build_object(
243
        {
244
            class => 'Koha::Patrons',
245
            value => { flags => 2**3 }
246
        }
247
    );
248
    my $password = 'thePassword123';
249
    $librarian->set_password( { password => $password, skip_validation => 1 } );
250
    my $userid = $librarian->userid;
251
252
    my $patron = $builder->build_object(
253
        {
254
            class => 'Koha::Patrons',
255
            value => { flags => 0 }
256
        }
257
    );
258
259
    $patron->set_password( { password => $password, skip_validation => 1 } );
260
    my $unauth_userid = $patron->userid;
261
262
    my $mapping_id = $builder->build_object( { class => 'Koha::ShibbolethFieldMappings' } )->mapping_id;
263
264
    $t->put_ok( "//$unauth_userid:$password@/api/v1/shibboleth/mappings/$mapping_id" => json =>
265
            { idp_field => 'New unauthorized name change' } )->status_is(403);
266
267
    my $mapping_without_idp_or_default = {
268
        koha_field      => 'surname',
269
        idp_field       => undef,
270
        default_content => undef,
271
        is_matchpoint   => 0,
272
    };
273
274
    $t->put_ok(
275
        "//$userid:$password@/api/v1/shibboleth/mappings/$mapping_id" => json => $mapping_without_idp_or_default )
276
        ->status_is(400)->json_is( "/error" => "Either idp_field or default_content must be provided" );
277
278
    my $mapping_with_updated_field = {
279
        idp_field     => "sn",
280
        koha_field    => "surname",
281
        is_matchpoint => 0,
282
    };
283
284
    $t->put_ok( "//$userid:$password@/api/v1/shibboleth/mappings/$mapping_id" => json => $mapping_with_updated_field )
285
        ->status_is(200)->json_is( '/idp_field' => 'sn' );
286
287
    my $mapping_with_invalid_field = {
288
        blah          => "Mapping Blah",
289
        idp_field     => "sn",
290
        koha_field    => "surname",
291
        is_matchpoint => 0,
292
    };
293
294
    $t->put_ok( "//$userid:$password@/api/v1/shibboleth/mappings/$mapping_id" => json => $mapping_with_invalid_field )
295
        ->status_is(400)->json_is(
296
        "/errors" => [
297
            {
298
                message => "Properties not allowed: blah.",
299
                path    => "/body"
300
            }
301
        ]
302
        );
303
304
    my $mapping_to_delete = $builder->build_object( { class => 'Koha::ShibbolethFieldMappings' } );
305
    my $non_existent_id   = $mapping_to_delete->mapping_id;
306
    $mapping_to_delete->delete;
307
308
    $t->put_ok(
309
        "//$userid:$password@/api/v1/shibboleth/mappings/$non_existent_id" => json => $mapping_with_updated_field )
310
        ->status_is(404);
311
312
    $mapping_with_updated_field->{mapping_id} = 2;
313
314
    $t->post_ok( "//$userid:$password@/api/v1/shibboleth/mappings/$mapping_id" => json => $mapping_with_updated_field )
315
        ->status_is(404);
316
317
    $schema->storage->txn_rollback;
318
};
319
320
subtest 'delete() tests' => sub {
321
322
    plan tests => 7;
323
324
    $schema->storage->txn_begin;
325
326
    my $librarian = $builder->build_object(
327
        {
328
            class => 'Koha::Patrons',
329
            value => { flags => 2**3 }
330
        }
331
    );
332
    my $password = 'thePassword123';
333
    $librarian->set_password( { password => $password, skip_validation => 1 } );
334
    my $userid = $librarian->userid;
335
336
    my $patron = $builder->build_object(
337
        {
338
            class => 'Koha::Patrons',
339
            value => { flags => 0 }
340
        }
341
    );
342
343
    $patron->set_password( { password => $password, skip_validation => 1 } );
344
    my $unauth_userid = $patron->userid;
345
346
    my $mapping_id = $builder->build_object( { class => 'Koha::ShibbolethFieldMappings' } )->mapping_id;
347
348
    $t->delete_ok("//$unauth_userid:$password@/api/v1/shibboleth/mappings/$mapping_id")->status_is(403);
349
350
    $t->delete_ok("//$userid:$password@/api/v1/shibboleth/mappings/$mapping_id")->status_is( 204, 'REST3.2.4' )
351
        ->content_is( '', 'REST3.3.4' );
352
353
    $t->delete_ok("//$userid:$password@/api/v1/shibboleth/mappings/$mapping_id")->status_is(404);
354
355
    $schema->storage->txn_rollback;
356
};

Return to bug 39224