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

(-)a/Koha/Patron/Allowlist.pm (-14 / +146 lines)
Lines 1-6 Link Here
1
package Koha::Patron::Allowlist;
1
package Koha::Patron::Allowlist;
2
2
3
use Modern::Perl;
3
use Modern::Perl;
4
use Array::Utils qw( array_minus );
4
5
5
=head1 NAME
6
=head1 NAME
6
7
Lines 18-54 sub new { Link Here
18
    my ($class, $args) = @_;
19
    my ($class, $args) = @_;
19
    $args = {} unless defined $args;
20
    $args = {} unless defined $args;
20
    my $self = bless ($args, $class);
21
    my $self = bless ($args, $class);
21
    $self->{ui_fields} = $self->_get_ui_fields() unless $self->{ui_fields};
22
    $self->{ui_fields} = { map { $_ => 1 } $self->get_ui_fields() };
22
    return $self;
23
    return $self;
23
}
24
}
24
25
25
=head3 apply
26
=head3 apply
26
27
27
Apply an allowlist to input data
28
    my $ui_fields = Koha::Patron::Allowlist::Public->new->apply({ input => $hashref });
29
30
Apply an allowlist to input data.
28
31
29
=cut
32
=cut
30
33
31
sub apply {
34
sub apply {
32
    my ( $self, $params ) = @_;
35
    my ( $self, $params ) = @_;
36
33
    my $blocked = {};
37
    my $blocked = {};
34
    my $ui_fields = $self->{ui_fields};
38
    my $ui_fields = $self->{ui_fields};
35
    if ($ui_fields && ref $ui_fields eq 'HASH'){
39
    return unless $ui_fields and %$ui_fields;
36
        my $input = $params->{input};
40
37
        if ( $input && ref $input eq 'HASH' ){
41
    my $input = $params->{input};
38
            my @keys = keys %$input;
42
    return unless $input  and %$input;
39
            foreach my $key (@keys){
43
40
                if ( ! $ui_fields->{ $key } ){
44
    my @keys = keys %$input;
41
                    #NOTE: We capture the deleted data so that it can be used for logging purposes
45
    foreach my $key (@keys){
42
                    $blocked->{$key} = delete $input->{ $key };
46
        unless ( exists $ui_fields->{ $key } ) {
43
                }
47
            #NOTE: We capture the deleted data so that it can be used for logging purposes
44
            }
48
            $blocked->{$key} = delete $input->{ $key };
45
        }
49
        }
46
    }
50
    }
51
52
    if ( %$blocked ) {
53
        while ( my ($k, $v)=each %$blocked){
54
            # FIXME We should raise an exception from here
55
            my @c = caller;
56
            warn sprintf "Forbidden - Tried to modify '%s' with '%s' from %s", $k, $v, "@c";
57
        }
58
    }
59
47
    return $blocked;
60
    return $blocked;
48
}
61
}
49
62
50
sub _get_ui_fields {
63
=head3 get_ui_fields
51
    return undef;
64
65
    my $ui_fields = $self->get_ui_fields();
66
    my $ui_fields = Koha::Patron::Allowlist::Public->new->get_ui_fields
67
68
=cut
69
70
sub get_ui_fields {
71
    my ($self)           = @_;
72
    my @all_fields       = $self->_get_all_fields();
73
    my @global_deny_list = $self->_global_deny_list();
74
    my @deny_list        = $self->_deny_list();
75
    my @global_allow_list = array_minus @all_fields, @global_deny_list;
76
    return array_minus @global_allow_list, @deny_list;
77
}
78
79
# This must not be replaced by Koha::Patrons->columns
80
# We want developper to not forget to adjust it manually and add new attribute to the deny list if needed
81
sub _get_all_fields {
82
    return qw(
83
      borrowernumber
84
      cardnumber
85
      surname
86
      firstname
87
      title
88
      othernames
89
      initials
90
      streetnumber
91
      streettype
92
      address
93
      address2
94
      city
95
      state
96
      zipcode
97
      country
98
      email
99
      phone
100
      mobile
101
      fax
102
      emailpro
103
      phonepro
104
      B_streetnumber
105
      B_streettype
106
      B_address
107
      B_address2
108
      B_city
109
      B_state
110
      B_zipcode
111
      B_country
112
      B_email
113
      B_phone
114
      dateofbirth
115
      branchcode
116
      categorycode
117
      dateenrolled
118
      dateexpiry
119
      date_renewed
120
      gonenoaddress
121
      lost
122
      debarred
123
      debarredcomment
124
      contactname
125
      contactfirstname
126
      contacttitle
127
      borrowernotes
128
      relationship
129
      sex
130
      password
131
      flags
132
      userid
133
      opacnote
134
      contactnote
135
      sort1
136
      sort2
137
      altcontactfirstname
138
      altcontactsurname
139
      altcontactaddress1
140
      altcontactaddress2
141
      altcontactaddress3
142
      altcontactstate
143
      altcontactzipcode
144
      altcontactcountry
145
      altcontactphone
146
      smsalertnumber
147
      sms_provider_id
148
      privacy
149
      privacy_guarantor_fines
150
      privacy_guarantor_checkouts
151
      checkprevcheckout
152
      updated_on
153
      lastseen
154
      lang
155
      login_attempts
156
      overdrive_auth_token
157
      anonymized
158
      autorenew_checkouts
159
      primary_contact_method
160
    );
161
}
162
163
sub _global_deny_list {
164
    return qw(
165
      borrowernumber
166
      date_renewed
167
      gonenoaddress
168
      lost
169
      debarred
170
      debarredcomment
171
      relationship
172
      flags
173
      privacy
174
      privacy_guarantor_fines
175
      privacy_guarantor_checkouts
176
      checkprevcheckout
177
      updated_on
178
      lastseen
179
      lang
180
      login_attempts
181
      overdrive_auth_token
182
      anonymized
183
    );
52
}
184
}
53
185
54
1;
186
1;
(-)a/Koha/Patron/Allowlist/Public.pm (-58 / +11 lines)
Lines 2-65 package Koha::Patron::Allowlist::Public; Link Here
2
2
3
use parent 'Koha::Patron::Allowlist';
3
use parent 'Koha::Patron::Allowlist';
4
4
5
sub _get_ui_fields {
5
sub _deny_list {
6
    my $ui_fields = {
6
    return qw(
7
        'cardnumber' => 1,
7
      dateenrolled
8
        'surname' => 1,
8
      dateexpiry
9
        'firstname' => 1,
9
      borrowernotes
10
        'title' => 1,
10
      opacnote
11
        'othernames' => 1,
11
      sort1
12
        'initials' => 1,
12
      sort2
13
        'streetnumber' => 1,
13
      sms_provider_id
14
        'streettype' => 1,
14
      autorenew_checkouts
15
        'address' => 1,
15
    );
16
        'address2' => 1,
17
        'city' => 1,
18
        'state' => 1,
19
        'zipcode' => 1,
20
        'country' => 1,
21
        'email' => 1,
22
        'phone' => 1,
23
        'mobile' => 1,
24
        'fax' => 1,
25
        'emailpro' => 1,
26
        'phonepro' => 1,
27
        'B_streetnumber' => 1,
28
        'B_streettype' => 1,
29
        'B_address' => 1,
30
        'B_address2' => 1,
31
        'B_city' => 1,
32
        'B_state' => 1,
33
        'B_zipcode' => 1,
34
        'B_country' => 1,
35
        'B_email' => 1,
36
        'B_phone' => 1,
37
        'dateofbirth' => 1,
38
        'dateenrolled' => undef,
39
        'dateexpiry' => undef,
40
        'branchcode' => 1,
41
        'categorycode' => 1,
42
        'contactname' => 1,
43
        'contactfirstname' => 1,
44
        'borrowernotes' => undef,
45
        'sex' => 1,
46
        'password' => 1,
47
        'userid' => 1,
48
        'opacnote' => undef,
49
        'contactnote' => 1,
50
        'altcontactfirstname' => 1,
51
        'altcontactsurname' => 1,
52
        'altcontactaddress1' => 1,
53
        'altcontactaddress2' => 1,
54
        'altcontactaddress3' => 1,
55
        'altcontactstate' => 1,
56
        'altcontactzipcode' => 1,
57
        'altcontactcountry' => 1,
58
        'altcontactphone' => 1,
59
        'smsalertnumber' => 1,
60
        'primary_contact_method' => 1,
61
    };
62
    return $ui_fields;
63
}
16
}
64
17
65
1;
18
1;
(-)a/Koha/Patron/Allowlist/Staff.pm (-63 / +2 lines)
Lines 2-70 package Koha::Patron::Allowlist::Staff; Link Here
2
2
3
use parent 'Koha::Patron::Allowlist';
3
use parent 'Koha::Patron::Allowlist';
4
4
5
sub _get_ui_fields {
5
sub _deny_list {
6
    my $ui_fields = {
6
    return ();
7
        'cardnumber' => 1,
8
        'surname' => 1,
9
        'firstname' => 1,
10
        'title' => 1,
11
        'othernames' => 1,
12
        'initials' => 1,
13
        'streetnumber' => 1,
14
        'streettype' => 1,
15
        'address' => 1,
16
        'address2' => 1,
17
        'city' => 1,
18
        'state' => 1,
19
        'zipcode' => 1,
20
        'country' => 1,
21
        'email' => 1,
22
        'phone' => 1,
23
        'mobile' => 1,
24
        'fax' => 1,
25
        'emailpro' => 1,
26
        'phonepro' => 1,
27
        'B_streetnumber' => 1,
28
        'B_streettype' => 1,
29
        'B_address' => 1,
30
        'B_address2' => 1,
31
        'B_city' => 1,
32
        'B_state' => 1,
33
        'B_zipcode' => 1,
34
        'B_country' => 1,
35
        'B_email' => 1,
36
        'B_phone' => 1,
37
        'dateofbirth' => 1,
38
        'dateenrolled' => 1,
39
        'dateexpiry' => 1,
40
        'branchcode' => 1,
41
        'categorycode' => 1,
42
        'contactname' => 1,
43
        'contactfirstname' => 1,
44
        'borrowernotes' => 1,
45
        'sex' => 1,
46
        'password' => 1,
47
        'userid' => 1,
48
        'opacnote' => 1,
49
        'contactnote' => 1,
50
        'altcontactfirstname' => 1,
51
        'altcontactsurname' => 1,
52
        'altcontactaddress1' => 1,
53
        'altcontactaddress2' => 1,
54
        'altcontactaddress3' => 1,
55
        'altcontactstate' => 1,
56
        'altcontactzipcode' => 1,
57
        'altcontactcountry' => 1,
58
        'altcontactphone' => 1,
59
        'smsalertnumber' => 1,
60
        'primary_contact_method' => 1,
61
        'autorenew_checkouts' => 1,
62
        'sort1' => 1,
63
        'sort2' => 1,
64
        'gonenoaddress' => 1,
65
        'lost' => 1,
66
    };
67
    return $ui_fields;
68
}
7
}
69
8
70
1;
9
1;
(-)a/t/Koha/Patron/Allowlist.t (-10 / +27 lines)
Lines 17-48 Link Here
17
17
18
use Modern::Perl;
18
use Modern::Perl;
19
19
20
use Test::More tests => 4;
20
use Test::More tests => 5;
21
21
22
use Test::MockModule;
22
use Test::MockModule;
23
use Test::Exception;
23
use Test::Exception;
24
use Test::Warn;
25
26
use Koha::Patrons;
27
use Koha::Patron::Allowlist;
24
28
25
use t::lib::Mocks;
29
use t::lib::Mocks;
26
30
27
use_ok('Koha::Patron::Allowlist::Staff');
31
use_ok('Koha::Patron::Allowlist::Staff');
28
use_ok('Koha::Patron::Allowlist::Public');
32
use_ok('Koha::Patron::Allowlist::Public');
29
33
34
subtest '_get_all_fields' => sub {
35
    my @columns = Koha::Patrons->columns;
36
    is_deeply(
37
        \@columns,
38
        [ Koha::Patron::Allowlist->_get_all_fields ],
39
        'All DB columns must be listed in _get_all_fields'
40
    );
41
};
42
30
subtest 'Staff Allowlist' => sub {
43
subtest 'Staff Allowlist' => sub {
31
    plan tests => 3;
44
    plan tests => 4;
32
    my $input = { firstname => 'test firstname', surname => 'test surname', flags => '1' };
45
    my $input = { firstname => 'test firstname', surname => 'test surname', flags => '1' };
33
    my $allowlist = Koha::Patron::Allowlist::Staff->new();
46
    my $allowlist = Koha::Patron::Allowlist::Staff->new();
34
    $allowlist->apply({ input => $input, });
47
    warning_like {
35
    ok( $input->{firstname} eq 'test firstname', 'firstname preserved' );
48
        $allowlist->apply({ input => $input, });
36
    ok( $input->{surname} eq 'test surname', 'surname preserved' );
49
    } qr{Forbidden - Tried to modify 'flags' with '1' from};
50
    is( $input->{firstname}, 'test firstname', 'firstname preserved' );
51
    is( $input->{surname}, 'test surname', 'surname preserved' );
37
    is( $input->{flags}, undef, 'flags filtered' );
52
    is( $input->{flags}, undef, 'flags filtered' );
38
};
53
};
39
54
40
subtest 'Public Allowlist' => sub {
55
subtest 'Public Allowlist' => sub {
41
    plan tests => 3;
56
    plan tests => 4;
42
    my $input = { firstname => 'test firstname', surname => 'test surname', flags => '1' };
57
    my $input = { firstname => 'test firstname', surname => 'test surname', flags => '1' };
43
    my $allowlist = Koha::Patron::Allowlist::Public->new();
58
    my $allowlist = Koha::Patron::Allowlist::Public->new();
44
    $allowlist->apply({ input => $input, });
59
    warning_like {
45
    ok( $input->{firstname} eq 'test firstname', 'firstname preserved' );
60
        $allowlist->apply({ input => $input, });
46
    ok( $input->{surname} eq 'test surname', 'surname preserved' );
61
    } qr{Forbidden - Tried to modify 'flags' with '1' from};
62
63
    is( $input->{firstname}, 'test firstname', 'firstname preserved' );
64
    is( $input->{surname},  'test surname', 'surname preserved' );
47
    is( $input->{flags}, undef, 'flags filtered' );
65
    is( $input->{flags}, undef, 'flags filtered' );
48
};
66
};
49
- 

Return to bug 28935