Bugzilla – Attachment 193685 Details for
Bug 39224
Migrate SAML/Shibboleth configuration into Identity Providers
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 39224: Handle patron_attribute:CODE values in auth protocol handlers
a00cb6e.patch (text/plain), 8.70 KB, created by
Martin Renvoize (ashimema)
on 2026-02-24 07:33:48 UTC
(
hide
)
Description:
Bug 39224: Handle patron_attribute:CODE values in auth protocol handlers
Filename:
MIME Type:
Creator:
Martin Renvoize (ashimema)
Created:
2026-02-24 07:33:48 UTC
Size:
8.70 KB
patch
obsolete
>From a00cb6e698cf2947abea60615ba84521ba41e2aa Mon Sep 17 00:00:00 2001 >From: Martin Renvoize <martin.renvoize@openfifth.co.uk> >Date: Mon, 23 Feb 2026 15:54:55 +0000 >Subject: [PATCH] Bug 39224: Handle patron_attribute:CODE values in auth > protocol handlers > >- OAuth _find_patron_by_matchpoint: search via borrower_attributes join > when matchpoint has patron_attribute: prefix >- Auth::Client get_user: strip patron_attribute keys from mapped_data > before patron->set(), apply them via Koha::Patron::Attribute instead >- auth.register: separate patron attributes from borrower fields on > patron creation >- Shibboleth checkpw_shib: search via borrower_attributes for patron > attribute matchpoints >- Shibboleth _autocreate/_sync: route patron_attribute:CODE mapping > values through Koha::Patron::Attribute rather than borrower hash >--- > C4/Auth_with_shibboleth.pm | 54 ++++++++++++++++++++++++++++++------ > Koha/Auth/Client.pm | 22 ++++++++++++++- > Koha/Auth/Client/OAuth.pm | 13 +++++++-- > Koha/REST/Plugin/Auth/IdP.pm | 17 +++++++++++- > 4 files changed, 93 insertions(+), 13 deletions(-) > >diff --git a/C4/Auth_with_shibboleth.pm b/C4/Auth_with_shibboleth.pm >index f6fbcf99089..59e39382c00 100644 >--- a/C4/Auth_with_shibboleth.pm >+++ b/C4/Auth_with_shibboleth.pm >@@ -38,6 +38,8 @@ use List::MoreUtils qw( any ); > > use Koha::Logger; > use Koha::Auth::Identity::Providers; >+use Koha::Patron::Attribute; >+use Koha::Patron::Attributes; > > # Check that shib config is not malformed > >@@ -99,7 +101,16 @@ sub checkpw_shib { > my $config = _get_shib_config(); > > # Does the given shibboleth attribute value ($match) match a valid koha user ? >- my $borrowers = Koha::Patrons->search( { $config->{matchpoint} => $match } ); >+ my $borrowers; >+ if ( $config->{matchpoint} =~ /^patron_attribute:(.+)$/ ) { >+ my $code = $1; >+ $borrowers = Koha::Patrons->search( >+ { 'borrower_attributes.code' => $code, 'borrower_attributes.attribute' => $match }, >+ { join => 'borrower_attributes' } >+ ); >+ } else { >+ $borrowers = Koha::Patrons->search( { $config->{matchpoint} => $match } ); >+ } > if ( $borrowers->count > 1 ) { > > # If we have more than 1 borrower the matchpoint is not unique >@@ -129,17 +140,32 @@ sub checkpw_shib { > sub _autocreate { > my ( $config, $match ) = @_; > >- my %borrower = ( $config->{matchpoint} => $match ); >+ my ( %borrower, %patron_attrs ); >+ >+ if ( $config->{matchpoint} =~ /^patron_attribute:(.+)$/ ) { >+ $patron_attrs{$1} = $match; >+ } else { >+ $borrower{ $config->{matchpoint} } = $match; >+ } > > while ( my ( $key, $entry ) = each %{ $config->{'mapping'} } ) { >- if ( C4::Context->psgi_env ) { >- $borrower{$key} = ( $entry->{'is'} && $ENV{ "HTTP_" . uc( $entry->{'is'} ) } ) || $entry->{'content'} || ''; >+ my $value = >+ C4::Context->psgi_env >+ ? ( $entry->{'is'} && $ENV{ "HTTP_" . uc( $entry->{'is'} ) } ) || $entry->{'content'} || '' >+ : ( $entry->{'is'} && $ENV{ $entry->{'is'} } ) || $entry->{'content'} || ''; >+ if ( $key =~ /^patron_attribute:(.+)$/ ) { >+ $patron_attrs{$1} = $value; > } else { >- $borrower{$key} = ( $entry->{'is'} && $ENV{ $entry->{'is'} } ) || $entry->{'content'} || ''; >+ $borrower{$key} = $value; > } > } > > my $patron = Koha::Patron->new( \%borrower )->store; >+ >+ for my $code ( keys %patron_attrs ) { >+ Koha::Patron::Attribute->new( >+ { borrowernumber => $patron->borrowernumber, code => $code, attribute => $patron_attrs{$code} } )->store; >+ } > $patron->discard_changes; > > C4::Members::Messaging::SetMessagingPreferencesFromDefaults( >@@ -184,17 +210,27 @@ sub _autocreate { > > sub _sync { > my ( $borrowernumber, $config, $match ) = @_; >- my %borrower; >+ my ( %borrower, %patron_attrs ); > $borrower{'borrowernumber'} = $borrowernumber; > while ( my ( $key, $entry ) = each %{ $config->{'mapping'} } ) { >- if ( C4::Context->psgi_env ) { >- $borrower{$key} = ( $entry->{'is'} && $ENV{ "HTTP_" . uc( $entry->{'is'} ) } ) || $entry->{'content'} || ''; >+ my $value = >+ C4::Context->psgi_env >+ ? ( $entry->{'is'} && $ENV{ "HTTP_" . uc( $entry->{'is'} ) } ) || $entry->{'content'} || '' >+ : ( $entry->{'is'} && $ENV{ $entry->{'is'} } ) || $entry->{'content'} || ''; >+ if ( $key =~ /^patron_attribute:(.+)$/ ) { >+ $patron_attrs{$1} = $value; > } else { >- $borrower{$key} = ( $entry->{'is'} && $ENV{ $entry->{'is'} } ) || $entry->{'content'} || ''; >+ $borrower{$key} = $value; > } > } > my $patron = Koha::Patrons->find($borrowernumber); > $patron->set( \%borrower )->store; >+ for my $code ( keys %patron_attrs ) { >+ my $existing = Koha::Patron::Attributes->search( { borrowernumber => $borrowernumber, code => $code } ); >+ $existing->delete; >+ Koha::Patron::Attribute->new( >+ { borrowernumber => $borrowernumber, code => $code, attribute => $patron_attrs{$code} } )->store; >+ } > } > > sub _get_uri { >diff --git a/Koha/Auth/Client.pm b/Koha/Auth/Client.pm >index 3fd4913e694..370e2d9c0b2 100644 >--- a/Koha/Auth/Client.pm >+++ b/Koha/Auth/Client.pm >@@ -23,6 +23,8 @@ use C4::Context; > > use Koha::Exceptions::Auth; > use Koha::Auth::Identity::Providers; >+use Koha::Patron::Attribute; >+use Koha::Patron::Attributes; > > =head1 NAME > >@@ -87,7 +89,25 @@ sub get_user { > $patron = $args->{'patron'}; > $domain = $args->{'domain'}; > >- $patron->set($mapped_data)->store if $patron && $domain->update_on_auth; >+ if ( $patron && $domain->update_on_auth ) { >+ my ( %patron_attrs, %borrower_data ); >+ for my $key ( keys %$mapped_data ) { >+ if ( $key =~ /^patron_attribute:(.+)$/ ) { >+ $patron_attrs{$1} = $mapped_data->{$key}; >+ } else { >+ $borrower_data{$key} = $mapped_data->{$key}; >+ } >+ } >+ $patron->set( \%borrower_data )->store; >+ for my $code ( keys %patron_attrs ) { >+ my $existing = >+ Koha::Patron::Attributes->search( { borrowernumber => $patron->borrowernumber, code => $code } ); >+ $existing->delete; >+ Koha::Patron::Attribute->new( >+ { borrowernumber => $patron->borrowernumber, code => $code, attribute => $patron_attrs{$code} } ) >+ ->store; >+ } >+ } > > $mapped_data->{categorycode} = $domain->default_category_id; > $mapped_data->{branchcode} = $domain->default_library_id; >diff --git a/Koha/Auth/Client/OAuth.pm b/Koha/Auth/Client/OAuth.pm >index df6ff275df1..d50911318ce 100644 >--- a/Koha/Auth/Client/OAuth.pm >+++ b/Koha/Auth/Client/OAuth.pm >@@ -124,9 +124,18 @@ sub _find_patron_by_matchpoint { > > return unless defined $value; > >- my $matchpoint_rs = Koha::Patrons->search( { $matchpoint => $value } ); >+ my $patron_rs; >+ if ( $matchpoint =~ /^patron_attribute:(.+)$/ ) { >+ my $code = $1; >+ $patron_rs = Koha::Patrons->search( >+ { 'borrower_attributes.code' => $code, 'borrower_attributes.attribute' => $value }, >+ { join => 'borrower_attributes' } >+ ); >+ } else { >+ $patron_rs = Koha::Patrons->search( { $matchpoint => $value } ); >+ } > >- return $matchpoint_rs->count ? $matchpoint_rs->next : undef; >+ return $patron_rs->count ? $patron_rs->next : undef; > } > > 1; >diff --git a/Koha/REST/Plugin/Auth/IdP.pm b/Koha/REST/Plugin/Auth/IdP.pm >index dd035fe78fa..2f60bf6e36d 100644 >--- a/Koha/REST/Plugin/Auth/IdP.pm >+++ b/Koha/REST/Plugin/Auth/IdP.pm >@@ -23,6 +23,7 @@ use Mojo::Base 'Mojolicious::Plugin'; > > use Koha::Exceptions; > use Koha::Exceptions::Auth; >+use Koha::Patron::Attribute; > use Koha::Patrons; > > use C4::Auth qw(create_basic_session); >@@ -89,7 +90,21 @@ if other values or none are passed. > Koha::Exceptions::Auth::Unauthorized->throw( code => 401 ); > } > >- return Koha::Patron->new($data)->store; >+ my ( %patron_attrs, %borrower_data ); >+ for my $key ( keys %$data ) { >+ if ( $key =~ /^patron_attribute:(.+)$/ ) { >+ $patron_attrs{$1} = $data->{$key}; >+ } else { >+ $borrower_data{$key} = $data->{$key}; >+ } >+ } >+ my $patron = Koha::Patron->new( \%borrower_data )->store; >+ for my $code ( keys %patron_attrs ) { >+ Koha::Patron::Attribute->new( >+ { borrowernumber => $patron->borrowernumber, code => $code, attribute => $patron_attrs{$code} } ) >+ ->store; >+ } >+ return $patron; > } > ); > >-- >2.53.0 >
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
|
193618
|
193619
|
193620
|
193621
|
193622
|
193623
|
193624
|
193625
|
193626
|
193627
|
193681
|
193682
|
193683
|
193684
| 193685 |
193686
|
193687
|
193688
|
193689
|
193690
|
193691
|
193692