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

(-)a/Koha/Allowlist.pm (+93 lines)
Line 0 Link Here
1
package Koha::Allowlist;
2
3
use Modern::Perl;
4
use Array::Utils qw( array_minus );
5
6
=head1 NAME
7
8
Koha::Allowlist - Allowlist implementation base class
9
10
=head1 API
11
12
=head2 Class Methods
13
14
    my $allow_list Koha::Allowlist->new({ interface => 'staff' });
15
16
=head3 new
17
18
Constructor.
19
20
Interface must be 'staff' or 'opac' - default to 'opac'
21
22
=cut
23
24
sub new {
25
    my ($class, $args) = @_;
26
    $args = {} unless defined $args;
27
    my $self = bless ($args, $class);
28
    $self->{interface} =
29
      ( $args->{interface} && $args->{interface} eq 'staff' )
30
      ? 'staff'
31
      : 'opac';
32
    return $self;
33
}
34
35
=head3 apply
36
37
    my $ui_fields = Koha::Allowlist->new({ interface => 'staff' })->apply({ input => $hashref, additional_deny_list => [qw( list of fields )] });
38
39
40
Apply an allowlist to input data.
41
42
=cut
43
44
sub apply {
45
    my ( $self, $params ) = @_;
46
47
    my $input = $params->{input};
48
    my $additional_deny_list = $params->{additional_deny_list} || [];
49
50
    my $blocked = {};
51
    my $ui_fields = { map { $_ => 1 } $self->get_ui_fields() };
52
    return unless $ui_fields and %$ui_fields;
53
54
    delete $ui_fields->{$_} for @$additional_deny_list;
55
56
    return unless $input  and %$input;
57
58
    my @keys = keys %$input;
59
    foreach my $key (@keys){
60
        unless ( exists $ui_fields->{ $key } ) {
61
            #NOTE: We capture the deleted data so that it can be used for logging purposes
62
            $blocked->{$key} = delete $input->{ $key };
63
        }
64
    }
65
66
    if ( %$blocked ) {
67
        while ( my ($k, $v)=each %$blocked){
68
            # FIXME We should raise an exception from here
69
            my @c = caller;
70
            warn sprintf "Forbidden - Tried to modify '%s' with '%s' from %s", $k, $v, "@c";
71
        }
72
    }
73
74
    return $blocked;
75
}
76
77
=head3 get_ui_fields
78
79
    my $ui_fields = $self->get_ui_fields();
80
    my $ui_fields = Koha::Patron::Allowlist::Public->new->get_ui_fields
81
82
=cut
83
84
sub get_ui_fields {
85
    my ($self)           = @_;
86
    my @all_fields       = $self->_get_all_fields();
87
    my @global_deny_list = $self->_global_deny_list();
88
    my @deny_list        = ( $self->{interface} eq 'staff' ) ? $self->_deny_list_staff() : $self->_deny_list_opac();
89
    my @global_allow_list = array_minus @all_fields, @global_deny_list;
90
    return array_minus @global_allow_list, @deny_list;
91
}
92
93
1;
(-)a/Koha/Patron/Allowlist.pm (-79 / +21 lines)
Lines 1-84 Link Here
1
package Koha::Patron::Allowlist;
1
package Koha::Patron::Allowlist;
2
2
3
use Modern::Perl;
3
use parent 'Koha::Allowlist';
4
use Array::Utils qw( array_minus );
5
6
=head1 NAME
7
8
Koha::Patron::Allowlist - Allowlist implementation for Koha::Patron 
9
10
=head1 API
11
12
=head2 Class Methods
13
14
=head3 new
15
16
=cut
17
18
sub new {
19
    my ($class, $args) = @_;
20
    $args = {} unless defined $args;
21
    my $self = bless ($args, $class);
22
    $self->{ui_fields} = { map { $_ => 1 } $self->get_ui_fields() };
23
    return $self;
24
}
25
26
=head3 apply
27
28
    my $ui_fields = Koha::Patron::Allowlist::Public->new->apply({ input => $hashref, additional_deny_list => [qw( list of fields )] });
29
30
Apply an allowlist to input data.
31
32
=cut
33
34
sub apply {
35
    my ( $self, $params ) = @_;
36
37
    my $input = $params->{input};
38
    my $additional_deny_list = $params->{additional_deny_list} || [];
39
40
    my $blocked = {};
41
    my $ui_fields = $self->{ui_fields};
42
    return unless $ui_fields and %$ui_fields;
43
44
    delete $ui_fields->{$_} for @$additional_deny_list;
45
46
    return unless $input  and %$input;
47
48
    my @keys = keys %$input;
49
    foreach my $key (@keys){
50
        unless ( exists $ui_fields->{ $key } ) {
51
            #NOTE: We capture the deleted data so that it can be used for logging purposes
52
            $blocked->{$key} = delete $input->{ $key };
53
        }
54
    }
55
56
    if ( %$blocked ) {
57
        while ( my ($k, $v)=each %$blocked){
58
            # FIXME We should raise an exception from here
59
            my @c = caller;
60
            warn sprintf "Forbidden - Tried to modify '%s' with '%s' from %s", $k, $v, "@c";
61
        }
62
    }
63
64
    return $blocked;
65
}
66
67
=head3 get_ui_fields
68
69
    my $ui_fields = $self->get_ui_fields();
70
    my $ui_fields = Koha::Patron::Allowlist::Public->new->get_ui_fields
71
72
=cut
73
74
sub get_ui_fields {
75
    my ($self)           = @_;
76
    my @all_fields       = $self->_get_all_fields();
77
    my @global_deny_list = $self->_global_deny_list();
78
    my @deny_list        = $self->_deny_list();
79
    my @global_allow_list = array_minus @all_fields, @global_deny_list;
80
    return array_minus @global_allow_list, @deny_list;
81
}
82
4
83
# This must not be replaced by Koha::Patrons->columns
5
# This must not be replaced by Koha::Patrons->columns
84
# We want developper to not forget to adjust it manually and add new attribute to the deny list if needed
6
# We want developper to not forget to adjust it manually and add new attribute to the deny list if needed
Lines 184-187 sub _global_deny_list { Link Here
184
    );
106
    );
185
}
107
}
186
108
109
sub _deny_list_opac {
110
    return qw(
111
      dateenrolled
112
      dateexpiry
113
      gonenoaddress
114
      lost
115
      borrowernotes
116
      relationship
117
      opacnote
118
      sort1
119
      sort2
120
      sms_provider_id
121
      autorenew_checkouts
122
    );
123
}
124
125
sub _deny_list_staff {
126
    return qw();
127
}
128
187
1;
129
1;
(-)a/Koha/Patron/Allowlist/Public.pm (-21 lines)
Lines 1-21 Link Here
1
package Koha::Patron::Allowlist::Public;
2
3
use parent 'Koha::Patron::Allowlist';
4
5
sub _deny_list {
6
    return qw(
7
      dateenrolled
8
      dateexpiry
9
      gonenoaddress
10
      lost
11
      borrowernotes
12
      relationship
13
      opacnote
14
      sort1
15
      sort2
16
      sms_provider_id
17
      autorenew_checkouts
18
    );
19
}
20
21
1;
(-)a/Koha/Patron/Allowlist/Staff.pm (-9 lines)
Lines 1-9 Link Here
1
package Koha::Patron::Allowlist::Staff;
2
3
use parent 'Koha::Patron::Allowlist';
4
5
sub _deny_list {
6
    return ();
7
}
8
9
1;
(-)a/members/memberentry.pl (-1 / +1 lines)
Lines 48-54 use Email::Valid; Link Here
48
use Koha::SMS::Providers;
48
use Koha::SMS::Providers;
49
use Koha::Patron::Allowlist::Staff;
49
use Koha::Patron::Allowlist::Staff;
50
50
51
my $ui_allowlist = Koha::Patron::Allowlist::Staff->new();
51
my $ui_allowlist = Koha::Patron::Allowlist->new({ interface => 'staff' });
52
52
53
53
54
my $input = CGI->new;
54
my $input = CGI->new;
(-)a/opac/opac-memberentry.pl (-2 / +2 lines)
Lines 46-54 use Koha::Patron::Categories; Link Here
46
use Koha::Token;
46
use Koha::Token;
47
use Koha::AuthorisedValues;
47
use Koha::AuthorisedValues;
48
48
49
use Koha::Patron::Allowlist::Public;
49
use Koha::Patron::Allowlist;
50
50
51
my $ui_allowlist = Koha::Patron::Allowlist::Public->new();
51
my $ui_allowlist = Koha::Patron::Allowlist->new();
52
52
53
my $cgi = CGI->new;
53
my $cgi = CGI->new;
54
my $dbh = C4::Context->dbh;
54
my $dbh = C4::Context->dbh;
(-)a/t/db_dependent/Koha/Patron/Allowlist.t (-8 / +4 lines)
Lines 17-23 Link Here
17
17
18
use Modern::Perl;
18
use Modern::Perl;
19
19
20
use Test::More tests => 6;
20
use Test::More tests => 4;
21
21
22
use Test::MockModule;
22
use Test::MockModule;
23
use Test::Exception;
23
use Test::Exception;
Lines 28-36 use Koha::Patron::Allowlist; Link Here
28
28
29
use t::lib::Mocks;
29
use t::lib::Mocks;
30
30
31
use_ok('Koha::Patron::Allowlist::Staff');
32
use_ok('Koha::Patron::Allowlist::Public');
33
34
subtest '_get_all_fields' => sub {
31
subtest '_get_all_fields' => sub {
35
    my @columns = Koha::Patrons->columns;
32
    my @columns = Koha::Patrons->columns;
36
    is_deeply(
33
    is_deeply(
Lines 43-49 subtest '_get_all_fields' => sub { Link Here
43
subtest 'Staff Allowlist' => sub {
40
subtest 'Staff Allowlist' => sub {
44
    plan tests => 4;
41
    plan tests => 4;
45
    my $input = { firstname => 'test firstname', surname => 'test surname', flags => '1' };
42
    my $input = { firstname => 'test firstname', surname => 'test surname', flags => '1' };
46
    my $allowlist = Koha::Patron::Allowlist::Staff->new();
43
    my $allowlist = Koha::Patron::Allowlist->new({ interface => 'staff' });
47
    warning_like {
44
    warning_like {
48
        $allowlist->apply({ input => $input, });
45
        $allowlist->apply({ input => $input, });
49
    } qr{Forbidden - Tried to modify 'flags' with '1' from};
46
    } qr{Forbidden - Tried to modify 'flags' with '1' from};
Lines 55-61 subtest 'Staff Allowlist' => sub { Link Here
55
subtest 'Public Allowlist' => sub {
52
subtest 'Public Allowlist' => sub {
56
    plan tests => 4;
53
    plan tests => 4;
57
    my $input = { firstname => 'test firstname', surname => 'test surname', flags => '1' };
54
    my $input = { firstname => 'test firstname', surname => 'test surname', flags => '1' };
58
    my $allowlist = Koha::Patron::Allowlist::Public->new();
55
    my $allowlist = Koha::Patron::Allowlist->new();
59
    warning_like {
56
    warning_like {
60
        $allowlist->apply({ input => $input, });
57
        $allowlist->apply({ input => $input, });
61
    } qr{Forbidden - Tried to modify 'flags' with '1' from};
58
    } qr{Forbidden - Tried to modify 'flags' with '1' from};
Lines 69-75 subtest 'additional_deny_list' => sub { Link Here
69
    plan tests => 10;
66
    plan tests => 10;
70
67
71
    my $input = { firstname => 'test firstname', surname => 'test surname' };
68
    my $input = { firstname => 'test firstname', surname => 'test surname' };
72
    my $allowlist = Koha::Patron::Allowlist::Public->new();
69
    my $allowlist = Koha::Patron::Allowlist->new();
73
70
74
    $allowlist->apply({
71
    $allowlist->apply({
75
        input => $input,
72
        input => $input,
76
- 

Return to bug 28935