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

(-)a/installer/data/mysql/atomicupdate/bug_39224.pl (+398 lines)
Line 0 Link Here
1
use Modern::Perl;
2
use Koha::Installer::Output qw(say_warning say_success say_info);
3
use JSON;
4
5
return {
6
    bug_number  => "39224",
7
    description =>
8
        "Unified identity providers: normalized mappings, hostname-based selection, SAML2/Shibboleth migration",
9
    up => sub {
10
        my ($args) = @_;
11
        my ( $dbh, $out ) = @$args{qw(dbh out)};
12
13
        # ── 1. Update identity_providers.protocol enum ─────────────────────────────
14
        # Remove CAS and LDAP (unsupported via this interface), add SAML2.
15
16
        if ( column_exists( 'identity_providers', 'protocol' ) ) {
17
            my ($current_type) = $dbh->selectrow_array(
18
                "SELECT COLUMN_TYPE FROM INFORMATION_SCHEMA.COLUMNS
19
                 WHERE TABLE_SCHEMA = DATABASE()
20
                 AND TABLE_NAME = 'identity_providers'
21
                 AND COLUMN_NAME = 'protocol'"
22
            );
23
24
            unless ( $current_type && $current_type eq "enum('OAuth','OIDC','SAML2')" ) {
25
26
                # Warn about and remove any providers using protocols no longer in the enum.
27
                for my $protocol (qw(CAS LDAP)) {
28
                    my ($count) = $dbh->selectrow_array(
29
                        "SELECT COUNT(*) FROM identity_providers WHERE protocol = ?",
30
                        undef, $protocol
31
                    );
32
                    if ($count) {
33
                        say_warning(
34
                            $out,
35
                            "Removing $count identity provider(s) with protocol '$protocol'"
36
                                . " (no longer supported via this interface)"
37
                        );
38
                        $dbh->do(
39
                            "DELETE FROM identity_providers WHERE protocol = ?",
40
                            undef, $protocol
41
                        );
42
                    }
43
                }
44
45
                $dbh->do(
46
                    q{
47
                    ALTER TABLE identity_providers
48
                        MODIFY COLUMN `protocol`
49
                        enum('OAuth','OIDC','SAML2')
50
                        COLLATE utf8mb4_unicode_ci NOT NULL
51
                        COMMENT 'Protocol provider speaks'
52
                }
53
                );
54
                say_success(
55
                    $out,
56
                    "Updated identity_providers.protocol enum to ('OAuth','OIDC','SAML2')"
57
                );
58
            }
59
        }
60
61
        # ── 2. Add enabled column to identity_providers ────────────────────────────
62
63
        unless ( column_exists( 'identity_providers', 'enabled' ) ) {
64
            $dbh->do(
65
                q{
66
                ALTER TABLE identity_providers
67
                    ADD COLUMN `enabled` tinyint(1) NOT NULL DEFAULT 1
68
                    COMMENT 'Whether this provider is active'
69
                    AFTER `config`
70
            }
71
            );
72
            say_success( $out, "Added column 'identity_providers.enabled'" );
73
        }
74
75
        # ── 3. Create identity_provider_mappings table ─────────────────────────────
76
77
        unless ( TableExists('identity_provider_mappings') ) {
78
            $dbh->do(
79
                q{
80
                CREATE TABLE `identity_provider_mappings` (
81
                    `mapping_id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'primary key',
82
                    `identity_provider_id` int(11) NOT NULL COMMENT 'Reference to identity provider',
83
                    `provider_field` varchar(255) DEFAULT NULL COMMENT 'Attribute name from the identity provider',
84
                    `koha_field` varchar(255) NOT NULL COMMENT 'Corresponding field in Koha borrowers table',
85
                    `default_content` varchar(255) DEFAULT NULL COMMENT 'Default value if provider does not supply this field',
86
                    `is_matchpoint` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'Use this field to match existing patrons',
87
                    PRIMARY KEY (`mapping_id`),
88
                    UNIQUE KEY `provider_koha_field` (`identity_provider_id`, `koha_field`),
89
                    KEY `provider_field_idx` (`provider_field`),
90
                    CONSTRAINT `idp_mapping_ibfk_1` FOREIGN KEY (`identity_provider_id`)
91
                        REFERENCES `identity_providers` (`identity_provider_id`) ON DELETE CASCADE
92
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
93
            }
94
            );
95
            say_success( $out, "Added new table 'identity_provider_mappings'" );
96
        }
97
98
        # ── 4. Migrate OAuth/OIDC JSON mappings to normalized rows ─────────────────
99
        # The old identity_providers table stored mappings as a JSON blob.
100
101
        if ( column_exists( 'identity_providers', 'mapping' ) ) {
102
            my $providers = $dbh->selectall_arrayref(
103
                "SELECT identity_provider_id, mapping, matchpoint FROM identity_providers
104
                 WHERE mapping IS NOT NULL AND mapping != '' AND mapping != '{}'",
105
                { Slice => {} }
106
            );
107
108
            my $migrated = 0;
109
            for my $provider (@$providers) {
110
                my $mapping_json = $provider->{mapping};
111
                my $matchpoint   = $provider->{matchpoint};
112
                my $provider_id  = $provider->{identity_provider_id};
113
114
                my $mapping;
115
                eval { $mapping = decode_json($mapping_json) };
116
                next unless $mapping && ref $mapping eq 'HASH';
117
118
                for my $koha_field ( keys %$mapping ) {
119
                    my $provider_field = $mapping->{$koha_field};
120
                    my $is_matchpoint  = ( defined $matchpoint && $matchpoint eq $koha_field ) ? 1 : 0;
121
122
                    $dbh->do(
123
                        q{
124
                        INSERT IGNORE INTO identity_provider_mappings
125
                        (identity_provider_id, provider_field, koha_field, is_matchpoint)
126
                        VALUES (?, ?, ?, ?)
127
                    }, undef,
128
                        $provider_id, $provider_field, $koha_field, $is_matchpoint
129
                    );
130
                    $migrated++;
131
                }
132
            }
133
134
            say_success(
135
                $out,
136
                "Migrated $migrated OAuth/OIDC field mapping(s) to identity_provider_mappings"
137
            );
138
139
            $dbh->do("ALTER TABLE identity_providers DROP COLUMN `mapping`");
140
            say_success( $out, "Dropped column 'identity_providers.mapping'" );
141
142
            $dbh->do("ALTER TABLE identity_providers DROP COLUMN `matchpoint`");
143
            say_success( $out, "Dropped column 'identity_providers.matchpoint'" );
144
        }
145
146
        # ── 5. Add send_welcome_email to identity_provider_domains ────────────────
147
148
        unless ( column_exists( 'identity_provider_domains', 'send_welcome_email' ) ) {
149
            $dbh->do(
150
                q{
151
                ALTER TABLE identity_provider_domains
152
                    ADD COLUMN `send_welcome_email` tinyint(1) NOT NULL DEFAULT 0
153
                    COMMENT 'Send welcome email to patron on first login'
154
                    AFTER `auto_register_staff`
155
            }
156
            );
157
            say_success( $out, "Added column 'identity_provider_domains.send_welcome_email'" );
158
        }
159
160
        # ── 6. Create canonical hostnames table ────────────────────────────────────
161
162
        unless ( TableExists('hostnames') ) {
163
            $dbh->do(
164
                q{
165
                CREATE TABLE `hostnames` (
166
                    `hostname_id` int(11) NOT NULL AUTO_INCREMENT
167
                        COMMENT 'Unique identifier for this hostname',
168
                    `hostname` varchar(255) NOT NULL
169
                        COMMENT 'Server hostname string',
170
                    PRIMARY KEY (`hostname_id`),
171
                    UNIQUE KEY `hostname` (`hostname`)
172
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
173
                COMMENT='Canonical hostname registry for identity provider selection'
174
            }
175
            );
176
            say_success( $out, "Added new table 'hostnames'" );
177
178
            # Seed reserved rows: hostname_id=1 for OPACBaseURL, hostname_id=2 for staffClientBaseURL.
179
            for my $info ( [ 'OPACBaseURL', 1 ], [ 'staffClientBaseURL', 2 ] ) {
180
                my ( $pref_name, $id ) = @$info;
181
                my ($url) = $dbh->selectrow_array(
182
                    "SELECT value FROM systempreferences WHERE LOWER(variable) = LOWER(?)",
183
                    undef, $pref_name
184
                );
185
                my ($hostname) = ( $url // '' ) =~ m{^https?://([^/:?#]+)} or next;
186
                $dbh->do(
187
                    "INSERT IGNORE INTO hostnames (hostname_id, hostname) VALUES (?, ?)",
188
                    undef, $id, $hostname
189
                );
190
                say_success( $out, "Seeded hostname_id=$id from $pref_name ($hostname)" );
191
            }
192
        }
193
194
        # ── 7. Create/upgrade identity_provider_hostnames bridge table ─────────────
195
196
        unless ( TableExists('identity_provider_hostnames') ) {
197
            $dbh->do(
198
                q{
199
                CREATE TABLE `identity_provider_hostnames` (
200
                    `identity_provider_hostname_id` int(11) NOT NULL AUTO_INCREMENT
201
                        COMMENT 'unique key, used to identify the hostname entry',
202
                    `hostname_id` int(11) NOT NULL
203
                        COMMENT 'FK to hostnames table',
204
                    `identity_provider_id` int(11) NOT NULL
205
                        COMMENT 'Identity provider associated with this hostname',
206
                    `is_enabled` tinyint(1) NOT NULL DEFAULT 1
207
                        COMMENT 'Whether this hostname is active for this provider',
208
                    `force_sso` tinyint(1) NOT NULL DEFAULT 0
209
                        COMMENT 'Force SSO redirect for users on this hostname',
210
                    PRIMARY KEY (`identity_provider_hostname_id`),
211
                    UNIQUE KEY `hostname_id_provider` (`hostname_id`, `identity_provider_id`),
212
                    KEY `idp_hostname_provider_idx` (`identity_provider_id`),
213
                    CONSTRAINT `fk_iph_hostname` FOREIGN KEY (`hostname_id`)
214
                        REFERENCES `hostnames` (`hostname_id`)
215
                        ON DELETE CASCADE ON UPDATE RESTRICT,
216
                    CONSTRAINT `idp_hostname_ibfk_1` FOREIGN KEY (`identity_provider_id`)
217
                        REFERENCES `identity_providers` (`identity_provider_id`)
218
                        ON DELETE CASCADE ON UPDATE RESTRICT
219
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
220
                COMMENT='Maps server hostnames to identity providers (many-to-many).'
221
            }
222
            );
223
            say_success( $out, "Added new table 'identity_provider_hostnames'" );
224
        }
225
226
        # ── 8. Migrate Shibboleth config from kha-conf.xml to identity_providers ──────────────────────
227
        # Reads useshibboleth from koha-conf.xml and migrates it to a DB syspref.
228
        # Also migrates the <shibboleth> mapping config to a SAML2 identity provider.
229
230
        {
231
            require C4::Context;
232
            my $use_shib = C4::Context->config('useshibboleth') // 0;
233
234
            if ($use_shib) {
235
                my $shib_cfg = C4::Context->config('shibboleth');
236
                unless ($shib_cfg) {
237
                    say_warning(
238
                        $out,
239
                        "useshibboleth=1 in koha-conf.xml but no <shibboleth> section found; "
240
                            . "please configure the SAML2 identity provider manually"
241
                    );
242
                } else {
243
244
                    # Check if a SAML2 provider already exists (idempotent)
245
                    my ($saml2_id) = $dbh->selectrow_array(
246
                        "SELECT identity_provider_id FROM identity_providers
247
                         WHERE protocol = 'SAML2' LIMIT 1"
248
                    );
249
250
                    unless ($saml2_id) {
251
                        my $config = encode_json(
252
                            {
253
                                autocreate => $shib_cfg->{autocreate} ? 1 : 0,
254
                                sync       => $shib_cfg->{sync}       ? 1 : 0,
255
                                welcome    => $shib_cfg->{welcome}    ? 1 : 0,
256
                            }
257
                        );
258
259
                        $dbh->do(
260
                            q{
261
                            INSERT INTO identity_providers
262
                            (code, description, protocol, config, enabled)
263
                            VALUES ('shibboleth', 'Shibboleth (migrated from koha-conf.xml)', 'SAML2', ?, 1)
264
                        }, undef, $config
265
                        );
266
                        $saml2_id = $dbh->last_insert_id( undef, undef, 'identity_providers', undef );
267
                        say_success(
268
                            $out,
269
                            "Migrated Shibboleth config to identity_providers (id=$saml2_id)"
270
                        );
271
272
                        # Create a default wildcard domain entry for the Shibboleth provider
273
                        $dbh->do(
274
                            q{
275
                            INSERT IGNORE INTO identity_provider_domains
276
                            (identity_provider_id, domain, allow_opac, allow_staff,
277
                             auto_register_opac, auto_register_staff, update_on_auth, send_welcome_email)
278
                            VALUES (?, NULL, 1, 1, ?, 0, ?, ?)
279
                        }, undef,
280
                            $saml2_id,
281
                            $shib_cfg->{autocreate} ? 1 : 0,
282
                            $shib_cfg->{sync}       ? 1 : 0,
283
                            $shib_cfg->{welcome}    ? 1 : 0,
284
                        );
285
                        say_success(
286
                            $out,
287
                            "Created default domain entry for Shibboleth provider"
288
                        );
289
                    }
290
291
                    # Migrate field mappings from the <shibboleth><mapping> section
292
                    if ( $saml2_id && $shib_cfg->{mapping} && ref $shib_cfg->{mapping} eq 'HASH' ) {
293
                        my $matchpoint = $shib_cfg->{matchpoint};
294
                        my $mapped     = 0;
295
296
                        for my $koha_field ( keys %{ $shib_cfg->{mapping} } ) {
297
                            my $entry = $shib_cfg->{mapping}{$koha_field};
298
299
                            # Entry may be a hashref with {is => 'attr'} or just a string
300
                            my $provider_field = ref $entry eq 'HASH' ? $entry->{is}                       : $entry;
301
                            my $is_matchpoint  = ( defined $matchpoint && $matchpoint eq $koha_field ) ? 1 : 0;
302
303
                            $dbh->do(
304
                                q{
305
                                INSERT IGNORE INTO identity_provider_mappings
306
                                (identity_provider_id, provider_field, koha_field, is_matchpoint)
307
                                VALUES (?, ?, ?, ?)
308
                            }, undef,
309
                                $saml2_id, $provider_field, $koha_field, $is_matchpoint
310
                            );
311
                            $mapped++;
312
                        }
313
314
                        say_success(
315
                            $out,
316
                            "Migrated $mapped Shibboleth field mapping(s) to identity_provider_mappings"
317
                        );
318
                    }
319
                }
320
            }
321
        }
322
323
        # ── 9. Migrate OPACShibOnly / staffShibOnly to hostname-based force_sso ───
324
        # For each shibOnly syspref that is ON, create a force_sso=1 entry in the
325
        # identity_provider_hostnames table using the corresponding base URL syspref
326
        # to determine the hostname.
327
328
        my %shib_only_map = (
329
            OPACShibOnly  => 'OPACBaseURL',
330
            staffShibOnly => 'staffClientBaseURL',
331
        );
332
333
        for my $pref_name ( sort keys %shib_only_map ) {
334
            my ($shib_only) = $dbh->selectrow_array(
335
                "SELECT value FROM systempreferences WHERE variable = ?",
336
                undef, $pref_name
337
            );
338
            next unless $shib_only;
339
340
            my ($saml2_id) = $dbh->selectrow_array(
341
                "SELECT identity_provider_id FROM identity_providers
342
                 WHERE protocol = 'SAML2' LIMIT 1"
343
            );
344
            unless ($saml2_id) {
345
                say_warning(
346
                    $out,
347
                    "'$pref_name' is enabled but no SAML2 provider found; "
348
                        . "please configure force_sso manually after adding a SAML2 provider"
349
                );
350
                next;
351
            }
352
353
            my $url_pref = $shib_only_map{$pref_name};
354
            my ($url) = $dbh->selectrow_array(
355
                "SELECT value FROM systempreferences WHERE variable = ?",
356
                undef, $url_pref
357
            );
358
            unless ( $url && $url =~ m{^https?://([^/:]+)} ) {
359
                say_warning(
360
                    $out,
361
                    "'$pref_name' is enabled but '$url_pref' is not set or not a valid URL; "
362
                        . "please configure force_sso manually"
363
                );
364
                next;
365
            }
366
            my $hostname = $1;
367
368
            $dbh->do(
369
                "INSERT IGNORE INTO hostnames (hostname) VALUES (?)",
370
                undef, $hostname
371
            );
372
            my ($hostname_id) = $dbh->selectrow_array(
373
                "SELECT hostname_id FROM hostnames WHERE hostname = ?",
374
                undef, $hostname
375
            );
376
377
            $dbh->do(
378
                q{
379
                INSERT IGNORE INTO identity_provider_hostnames
380
                (hostname_id, identity_provider_id, is_enabled, force_sso)
381
                VALUES (?, ?, 1, 1)
382
            }, undef, $hostname_id, $saml2_id
383
            );
384
            say_success(
385
                $out,
386
                "Enabled force_sso for hostname '$hostname' (migrated from $pref_name)"
387
            );
388
        }
389
390
        $dbh->do("DELETE FROM systempreferences WHERE variable IN ('OPACShibOnly', 'staffShibOnly')");
391
        say_success(
392
            $out,
393
            "Removed system preferences 'OPACShibOnly' and 'staffShibOnly'"
394
        );
395
396
        return 1;
397
    },
398
};
(-)a/installer/data/mysql/kohastructure.sql (-3 / +60 lines)
Lines 3642-3647 CREATE TABLE `housebound_visit` ( Link Here
3642
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
3642
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
3643
/*!40101 SET character_set_client = @saved_cs_client */;
3643
/*!40101 SET character_set_client = @saved_cs_client */;
3644
3644
3645
--
3646
-- Table structure for table `hostnames`
3647
--
3648
3649
DROP TABLE IF EXISTS `hostnames`;
3650
/*!40101 SET @saved_cs_client     = @@character_set_client */;
3651
/*!40101 SET character_set_client = utf8mb4 */;
3652
CREATE TABLE `hostnames` (
3653
  `hostname_id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'Unique identifier for this hostname',
3654
  `hostname` varchar(255) NOT NULL COMMENT 'Server hostname string',
3655
  PRIMARY KEY (`hostname_id`),
3656
  UNIQUE KEY `hostname` (`hostname`)
3657
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Canonical hostname registry for identity provider selection';
3658
/*!40101 SET character_set_client = @saved_cs_client */;
3659
3645
--
3660
--
3646
-- Table structure for table `identity_provider_domains`
3661
-- Table structure for table `identity_provider_domains`
3647
--
3662
--
Lines 3660-3665 CREATE TABLE `identity_provider_domains` ( Link Here
3660
  `allow_staff` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'Allow provider from staff interface',
3675
  `allow_staff` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'Allow provider from staff interface',
3661
  `auto_register_opac` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'Allow user auto register (OPAC)',
3676
  `auto_register_opac` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'Allow user auto register (OPAC)',
3662
  `auto_register_staff` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'Allow user auto register (Staff interface)',
3677
  `auto_register_staff` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'Allow user auto register (Staff interface)',
3678
  `send_welcome_email` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'Send welcome email to patron on first login',
3663
  PRIMARY KEY (`identity_provider_domain_id`),
3679
  PRIMARY KEY (`identity_provider_domain_id`),
3664
  UNIQUE KEY `identity_provider_id` (`identity_provider_id`,`domain`),
3680
  UNIQUE KEY `identity_provider_id` (`identity_provider_id`,`domain`),
3665
  KEY `domain` (`domain`),
3681
  KEY `domain` (`domain`),
Lines 3673-3678 CREATE TABLE `identity_provider_domains` ( Link Here
3673
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
3689
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
3674
/*!40101 SET character_set_client = @saved_cs_client */;
3690
/*!40101 SET character_set_client = @saved_cs_client */;
3675
3691
3692
--
3693
-- Table structure for table `identity_provider_hostnames`
3694
--
3695
3696
DROP TABLE IF EXISTS `identity_provider_hostnames`;
3697
/*!40101 SET @saved_cs_client     = @@character_set_client */;
3698
/*!40101 SET character_set_client = utf8mb4 */;
3699
CREATE TABLE `identity_provider_hostnames` (
3700
  `identity_provider_hostname_id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'unique key, used to identify the hostname entry',
3701
  `hostname_id` int(11) NOT NULL COMMENT 'FK to hostnames table',
3702
  `identity_provider_id` int(11) NOT NULL COMMENT 'Identity provider associated with this hostname',
3703
  `is_enabled` tinyint(1) NOT NULL DEFAULT 1 COMMENT 'Whether this hostname is active for this provider',
3704
  `force_sso` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'Force SSO redirect for users on this hostname',
3705
  PRIMARY KEY (`identity_provider_hostname_id`),
3706
  UNIQUE KEY `hostname_id_provider` (`hostname_id`,`identity_provider_id`),
3707
  KEY `idp_hostname_provider_idx` (`identity_provider_id`),
3708
  CONSTRAINT `fk_iph_hostname` FOREIGN KEY (`hostname_id`) REFERENCES `hostnames` (`hostname_id`) ON DELETE CASCADE ON UPDATE RESTRICT,
3709
  CONSTRAINT `idp_hostname_ibfk_1` FOREIGN KEY (`identity_provider_id`) REFERENCES `identity_providers` (`identity_provider_id`) ON DELETE CASCADE ON UPDATE RESTRICT
3710
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Maps server hostnames to identity providers (many-to-many). A hostname may be linked to multiple providers.';
3711
/*!40101 SET character_set_client = @saved_cs_client */;
3712
3713
--
3714
-- Table structure for table `identity_provider_mappings`
3715
--
3716
3717
DROP TABLE IF EXISTS `identity_provider_mappings`;
3718
/*!40101 SET @saved_cs_client     = @@character_set_client */;
3719
/*!40101 SET character_set_client = utf8mb4 */;
3720
CREATE TABLE `identity_provider_mappings` (
3721
  `mapping_id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'primary key',
3722
  `identity_provider_id` int(11) NOT NULL COMMENT 'Reference to identity provider',
3723
  `provider_field` varchar(255) DEFAULT NULL COMMENT 'Attribute name from the identity provider',
3724
  `koha_field` varchar(255) NOT NULL COMMENT 'Corresponding field in Koha borrowers table',
3725
  `default_content` varchar(255) DEFAULT NULL COMMENT 'Default value if provider does not supply this field',
3726
  `is_matchpoint` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'Use this field to match existing patrons',
3727
  PRIMARY KEY (`mapping_id`),
3728
  UNIQUE KEY `provider_koha_field` (`identity_provider_id`,`koha_field`),
3729
  KEY `provider_field_idx` (`provider_field`),
3730
  CONSTRAINT `idp_mapping_ibfk_1` FOREIGN KEY (`identity_provider_id`) REFERENCES `identity_providers` (`identity_provider_id`) ON DELETE CASCADE
3731
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
3732
/*!40101 SET character_set_client = @saved_cs_client */;
3733
3676
--
3734
--
3677
-- Table structure for table `identity_providers`
3735
-- Table structure for table `identity_providers`
3678
--
3736
--
Lines 3684-3693 CREATE TABLE `identity_providers` ( Link Here
3684
  `identity_provider_id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'unique key, used to identify the provider',
3742
  `identity_provider_id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'unique key, used to identify the provider',
3685
  `code` varchar(20) NOT NULL COMMENT 'Provider code',
3743
  `code` varchar(20) NOT NULL COMMENT 'Provider code',
3686
  `description` varchar(255) NOT NULL COMMENT 'Description for the provider',
3744
  `description` varchar(255) NOT NULL COMMENT 'Description for the provider',
3687
  `protocol` enum('OAuth','OIDC','LDAP','CAS') NOT NULL COMMENT 'Protocol provider speaks',
3745
  `protocol` enum('OAuth','OIDC','SAML2') NOT NULL COMMENT 'Protocol provider speaks',
3688
  `config` longtext NOT NULL COMMENT 'Configuration of the provider in JSON format',
3746
  `config` longtext NOT NULL COMMENT 'Configuration of the provider in JSON format',
3689
  `mapping` longtext NOT NULL COMMENT 'Configuration to map provider data to Koha user',
3747
  `enabled` tinyint(1) NOT NULL DEFAULT 1 COMMENT 'Whether this provider is active',
3690
  `matchpoint` enum('email','userid','cardnumber') NOT NULL COMMENT 'The patron attribute to be used as matchpoint',
3691
  `icon_url` varchar(255) DEFAULT NULL COMMENT 'Provider icon URL',
3748
  `icon_url` varchar(255) DEFAULT NULL COMMENT 'Provider icon URL',
3692
  PRIMARY KEY (`identity_provider_id`),
3749
  PRIMARY KEY (`identity_provider_id`),
3693
  UNIQUE KEY `code` (`code`),
3750
  UNIQUE KEY `code` (`code`),
(-)a/installer/data/mysql/mandatory/sysprefs.sql (-3 lines)
Lines 573-579 INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` Link Here
573
('opacSerialDefaultTab','subscriptions','holdings|serialcollection|subscriptions|titlenotes','Define the default tab for serials in OPAC.','Choice'),
573
('opacSerialDefaultTab','subscriptions','holdings|serialcollection|subscriptions|titlenotes','Define the default tab for serials in OPAC.','Choice'),
574
('OPACSerialIssueDisplayCount','3',NULL,'Number of serial issues to display per subscription in the OPAC','Integer'),
574
('OPACSerialIssueDisplayCount','3',NULL,'Number of serial issues to display per subscription in the OPAC','Integer'),
575
('OPACShelfBrowser','1',NULL,'Enable/disable Shelf Browser on item details page. WARNING: this feature is very resource consuming on collections with large numbers of items.','YesNo'),
575
('OPACShelfBrowser','1',NULL,'Enable/disable Shelf Browser on item details page. WARNING: this feature is very resource consuming on collections with large numbers of items.','YesNo'),
576
('OPACShibOnly','0',NULL,'If ON enables shibboleth only authentication for the opac','YesNo'),
577
('OPACShowCheckoutName','0',NULL,'Displays in the OPAC the name of patron who has checked out the material. WARNING: Most sites should leave this off. It is intended for corporate or special sites which need to track who has the item.','YesNo'),
576
('OPACShowCheckoutName','0',NULL,'Displays in the OPAC the name of patron who has checked out the material. WARNING: Most sites should leave this off. It is intended for corporate or special sites which need to track who has the item.','YesNo'),
578
('OPACShowHoldQueueDetails','none','none|priority|holds|holds_priority','Show holds details in OPAC','Choice'),
577
('OPACShowHoldQueueDetails','none','none|priority|holds|holds_priority','Show holds details in OPAC','Choice'),
579
('OPACShowLibraries', '1', NULL, 'If enabled, a "Libraries" link appears in the OPAC pointing to a page with library information', 'YesNo'),
578
('OPACShowLibraries', '1', NULL, 'If enabled, a "Libraries" link appears in the OPAC pointing to a page with library information', 'YesNo'),
Lines 782-788 INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` Link Here
782
('StaffLoginRestrictLibraryByIP','0',NULL,'If ON, IP authentication is enabled, blocking access to the staff interface from unauthorized IP addresses based on branch','YesNo'),
781
('StaffLoginRestrictLibraryByIP','0',NULL,'If ON, IP authentication is enabled, blocking access to the staff interface from unauthorized IP addresses based on branch','YesNo'),
783
('StaffSearchResultsDisplayBranch','holdingbranch','holdingbranch|homebranch','Controls the display of the home or holding branch for staff search results','Choice'),
782
('StaffSearchResultsDisplayBranch','holdingbranch','holdingbranch|homebranch','Controls the display of the home or holding branch for staff search results','Choice'),
784
('StaffSerialIssueDisplayCount','3',NULL,'Number of serial issues to display per subscription in the staff interface','Integer'),
783
('StaffSerialIssueDisplayCount','3',NULL,'Number of serial issues to display per subscription in the staff interface','Integer'),
785
('staffShibOnly','0',NULL,'If ON enables shibboleth only authentication for the staff client','YesNo'),
786
('StaticHoldsQueueWeight','0',NULL,'Specify a list of library location codes separated by commas -- the list of codes will be traversed and weighted with first values given higher weight for holds fulfillment -- alternatively, if RandomizeHoldsQueueWeight is set, the list will be randomly selective','Integer'),
784
('StaticHoldsQueueWeight','0',NULL,'Specify a list of library location codes separated by commas -- the list of codes will be traversed and weighted with first values given higher weight for holds fulfillment -- alternatively, if RandomizeHoldsQueueWeight is set, the list will be randomly selective','Integer'),
787
('StatisticsFields','location|itype|ccode', NULL, 'Define Fields (from the items table) used for statistics members','Free'),
785
('StatisticsFields','location|itype|ccode', NULL, 'Define Fields (from the items table) used for statistics members','Free'),
788
('StockRotation','0',NULL,'If ON, enables the stock rotation module','YesNo'),
786
('StockRotation','0',NULL,'If ON, enables the stock rotation module','YesNo'),
789
- 

Return to bug 39224