From 24d5a1f9367637f5c653eddf84778201f0c19a82 Mon Sep 17 00:00:00 2001
From: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Date: Wed, 1 Sep 2021 15:16:12 +0200
Subject: [PATCH] Bug 28935: Enforce *UnwantedField sysprefs
Content-Type: text/plain; charset=utf-8

I didn't recreate the problem on selfmod but it existed for selfreg.

Create 2 attributes, 2 visible at the OPAC but only 1 editable.
Self reg and modify the input hidden value.

Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl>
---
 Koha/Patron/Allowlist.pm               |  8 ++++--
 opac/opac-memberentry.pl               |  6 ++--
 t/db_dependent/Koha/Patron/Allowlist.t | 40 +++++++++++++++++++++++++-
 3 files changed, 49 insertions(+), 5 deletions(-)

diff --git a/Koha/Patron/Allowlist.pm b/Koha/Patron/Allowlist.pm
index 0e696b1ba4..7dafd025c6 100644
--- a/Koha/Patron/Allowlist.pm
+++ b/Koha/Patron/Allowlist.pm
@@ -25,7 +25,7 @@ sub new {
 
 =head3 apply
 
-    my $ui_fields = Koha::Patron::Allowlist::Public->new->apply({ input => $hashref });
+    my $ui_fields = Koha::Patron::Allowlist::Public->new->apply({ input => $hashref, additional_deny_list => [qw( list of fields )] });
 
 Apply an allowlist to input data.
 
@@ -34,11 +34,15 @@ Apply an allowlist to input data.
 sub apply {
     my ( $self, $params ) = @_;
 
+    my $input = $params->{input};
+    my $additional_deny_list = $params->{additional_deny_list} || [];
+
     my $blocked = {};
     my $ui_fields = $self->{ui_fields};
     return unless $ui_fields and %$ui_fields;
 
-    my $input = $params->{input};
+    delete $ui_fields->{$_} for @$additional_deny_list;
+
     return unless $input  and %$input;
 
     my @keys = keys %$input;
diff --git a/opac/opac-memberentry.pl b/opac/opac-memberentry.pl
index 0d6f9c0013..c1f35fe63f 100755
--- a/opac/opac-memberentry.pl
+++ b/opac/opac-memberentry.pl
@@ -135,7 +135,8 @@ if ( $action eq 'create' ) {
     my $consent_dt = delete $borrower{gdpr_proc_consent};
     delete $borrower{'password2'};
 
-    $ui_allowlist->apply({ input => \%borrower });
+    my @unwanted_fields = split( /\|/, C4::Context->preference('PatronSelfRegistrationBorrowerUnwantedField') || q|| );
+    $ui_allowlist->apply({ input => \%borrower, additional_deny_list => \@unwanted_fields });
 
     my $cardnumber_error_code;
     if ( !grep { $_ eq 'cardnumber' } @empty_mandatory_fields ) {
@@ -274,7 +275,8 @@ elsif ( $action eq 'update' ) {
     # Send back the data to the template
     %borrower = ( %$borrower, %borrower );
 
-    $ui_allowlist->apply({ input => \%borrower });
+    my @unwanted_fields = split( /\|/, C4::Context->preference('PatronSelfModificationBorrowerUnwantedField') || q|| );
+    $ui_allowlist->apply({ input => \%borrower, additional_deny_list => \@unwanted_fields });
 
     if (@empty_mandatory_fields || @$invalidformfields) {
         $template->param(
diff --git a/t/db_dependent/Koha/Patron/Allowlist.t b/t/db_dependent/Koha/Patron/Allowlist.t
index b8f21096ac..5327f54e41 100644
--- a/t/db_dependent/Koha/Patron/Allowlist.t
+++ b/t/db_dependent/Koha/Patron/Allowlist.t
@@ -17,7 +17,7 @@
 
 use Modern::Perl;
 
-use Test::More tests => 5;
+use Test::More tests => 6;
 
 use Test::MockModule;
 use Test::Exception;
@@ -64,3 +64,41 @@ subtest 'Public Allowlist' => sub {
     is( $input->{surname},  'test surname', 'surname preserved' );
     is( $input->{flags}, undef, 'flags filtered' );
 };
+
+subtest 'additional_deny_list' => sub {
+    plan tests => 10;
+
+    my $input = { firstname => 'test firstname', surname => 'test surname' };
+    my $allowlist = Koha::Patron::Allowlist::Public->new();
+
+    $allowlist->apply({
+        input => $input,
+        additional_deny_list => [],
+    });
+
+    is( $input->{firstname}, 'test firstname', 'firstname preserved' );
+    is( $input->{surname},   'test surname',   'surname filtered' );
+    is( $input->{flags},     undef,            'flags filtered' );
+
+    $allowlist->apply({
+        input => $input,
+        additional_deny_list => ['not_here'],
+    });
+
+    is( $input->{firstname}, 'test firstname', 'firstname preserved' );
+    is( $input->{surname},   'test surname',   'surname filtered' );
+    is( $input->{flags},     undef,            'flags filtered' );
+
+    warning_like {
+        $allowlist->apply({
+            input => $input,
+            additional_deny_list => ['surname'],
+        });
+    }
+    qr{Forbidden - Tried to modify 'surname' with 'test surname' from};
+
+    is( $input->{firstname}, 'test firstname', 'firstname preserved' );
+    is( $input->{surname},   undef,            'surname filtered' );
+    is( $input->{flags},     undef,            'flags filtered' );
+
+};
-- 
2.20.1