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

(-)a/Koha/AllowList.pm (-45 / +41 lines)
Lines 27-45 Koha::AllowList - Allow list implementation base class Link Here
27
27
28
=head3 new
28
=head3 new
29
29
30
    my $allow_list = Koha::AllowList->new;
30
    my $allow_list = Koha::AllowList->new({ defaults => $list });
31
31
32
    Constructor.
32
    Constructor.
33
33
34
=cut
34
=cut
35
35
36
our $defaults = [];
37
38
sub new {
36
sub new {
39
    my ($class, $args) = @_;
37
    my ( $class, $args ) = @_; # args hash with keys: defaults
40
    $args //= {};
38
    $args = {} if !$args or ref($args) ne 'HASH';
41
    my $self = bless( $args, $class );
39
    my $defaults = ref($args->{defaults}) eq 'ARRAY' ? $args->{defaults} : [];
40
41
    my $self = bless( {}, $class );
42
    $self->{_defaults} = $defaults;
42
    $self->{_entries} = {};
43
    $self->{_entries} = {};
44
    $self->add( @$defaults );
43
    return $self;
45
    return $self;
44
}
46
}
45
47
Lines 51-57 sub new { Link Here
51
53
52
sub add {
54
sub add {
53
    my ( $self, @args ) = @_;
55
    my ( $self, @args ) = @_;
54
    # TODO Could be extended by passing things like column3 => { staff => 1 }
55
    foreach my $arg ( @args ) {
56
    foreach my $arg ( @args ) {
56
        $self->{_entries}->{$arg} = 1;
57
        $self->{_entries}->{$arg} = 1;
57
    }
58
    }
Lines 72-87 sub remove { Link Here
72
73
73
=head3 apply
74
=head3 apply
74
75
75
    my $blocked = $allowlist->apply({
76
    my $result = $allowlist->apply({
76
        input => $hashref | $arrayref, verbose => 1, dry_run => 0,
77
        input => $hashref | $arrayref, dump => $dump,
77
    });
78
    });
78
79
79
    Apply an allowlist to input data. Note that we modify the passed
80
    Apply an allowlist to input data. Returns result as hash- or arrayref.
80
    reference unless the dry_run flag is true.
81
    If you pass a dump hashref, blocked entries will be written. When you
81
    The verbose flag controls the warn statement.
82
    pass an arrayref, the dump looks like: { blocked1 => 1, .. }
82
83
    Returns a hash of blocked entries. Might be useful for logging purposes.
84
    When you pass an arrayref, the return looks like: { blocked1 => 1, blocked2 => 1, .. }
85
83
86
=cut
84
=cut
87
85
Lines 89-154 sub apply { Link Here
89
    my ( $self, $params ) = @_;
87
    my ( $self, $params ) = @_;
90
    my $input = $params->{input} or return;
88
    my $input = $params->{input} or return;
91
    return if ref($input) ne 'HASH' && ref($input) ne 'ARRAY';
89
    return if ref($input) ne 'HASH' && ref($input) ne 'ARRAY';
92
    my $dry = $params->{dry_run};
93
90
94
    my $blocked = {};
91
    my $dump = {};
92
    my $result;
95
    if( ref($input) eq 'ARRAY' ) {
93
    if( ref($input) eq 'ARRAY' ) {
96
        my ( @ok, @nok );
94
        $result = [];
97
        map { $self->{_entries}->{$_} ? push @ok, $_ : push @nok, $_;  } @$input;
95
        map { $self->{_entries}->{$_} ? ( push @$result, $_ ) : ( $dump->{$_} = 1 );  } @$input;
98
        @$input = @ok if !$dry;
99
        $blocked = { map { ( $_ => 1 ) } @nok };
100
    } else { # Handle hashref
96
    } else { # Handle hashref
101
        foreach my $key ( keys %$input ) {
97
        $result = {};
102
            unless ( $self->{_entries}->{$key} ) {
98
        map { $self->{_entries}->{$_} ? ( $result->{$_} = $input->{$_} ) : ( $dump->{$_} = $input->{$_} );  } keys %$input;
103
                if( ref($input) eq 'HASH' ) {
104
                    $blocked->{$key} = $dry ? $input->{$key} : delete $input->{$key};
105
                }
106
            }
107
        }
108
    }
99
    }
109
    warn 'Koha::AllowList: apply blocked one or more keys' if keys %$blocked && $params->{verbose};
100
    map { $params->{dump}->{$_} = $dump->{$_}; } keys %$dump if ref($params->{dump}) eq 'HASH';
110
    return $blocked;
101
    return $result;
111
}
102
}
112
103
113
=head3 check
104
=head3 check
114
105
115
    my $blocked = $allowlist->check({ input => $a, verbose => 0 });
106
    my $bool = $allowlist->check({ input => $a, dump => $dump });
116
107
117
    This is just a shortcut for ->apply({ dry_run => 1 })
108
    This is just a shortcut for running ->apply and checking if nothing was blocked.
109
    Optional dump variable serves the same purpose.
110
    Returns a boolean (1 or empty string). True means that all input is allowed,
111
    but only if there was input.
118
112
119
=cut
113
=cut
120
114
121
sub check {
115
sub check {
122
    my ( $self, $params ) = @_;
116
    my ( $self, $params ) = @_;
123
    return $self->apply({ %$params, dry_run => 1 });
117
    my $dump = {};
118
    my $rv = $self->apply({ %$params, dump => $dump });
119
    map { $params->{dump}->{$_} = $dump->{$_}; } keys %$dump if ref($params->{dump}) eq 'HASH';
120
    return $rv ? keys %$dump == 0 : q{};
124
}
121
}
125
122
126
=head3 load
123
=head3 reset
127
124
128
    my $fields = $self->load;
125
    $allowlist->reset;
129
126
130
    Loads default allow list entries.
127
    Restore default entries.
131
132
    This routine should be overridden when subclassing.
133
128
134
=cut
129
=cut
135
130
136
sub load {
131
sub reset {
137
    my ( $self ) = @_;
132
    my ( $self ) = @_;
138
    $self->add( @$defaults );
133
    $self->{_entries} = {};
134
    $self->add( @{$self->{_defaults}} );
139
}
135
}
140
136
141
=head3 unload
137
=head3 keys
142
138
143
    $allowlist->unload;
139
    @keys = $allowlist->keys;
144
140
145
    Clear all entries.
141
    Return the allow list entries.
146
142
147
=cut
143
=cut
148
144
149
sub unload {
145
sub keys {
150
    my ( $self ) = @_;
146
    my ( $self ) = @_;
151
    $self->{_entries} = {};
147
    return sort keys %{$self->{_entries}};
152
}
148
}
153
149
154
1;
150
1;
(-)a/t/Koha/AllowList.t (-30 / +40 lines)
Lines 16-64 Link Here
16
# along with Koha; if not, see <http://www.gnu.org/licenses>.
16
# along with Koha; if not, see <http://www.gnu.org/licenses>.
17
17
18
use Modern::Perl;
18
use Modern::Perl;
19
use Data::Dumper qw( Dumper );
19
use Test::More tests => 1;
20
use Test::More tests => 1;
20
21
21
use Koha::AllowList;
22
use Koha::AllowList;
22
23
23
subtest 'AllowList' => sub {
24
subtest 'AllowList' => sub {
24
    plan tests => 13;
25
    plan tests => 17;
25
26
26
    my $allowlist = Koha::AllowList->new;
27
    my $defaults = [ 'col1' ];
27
    $allowlist->load;
28
    my $allowlist = Koha::AllowList->new({ defaults => $defaults });
28
    is( $allowlist->apply, undef, 'No input returns undef' );
29
    is( $allowlist->apply, undef, 'No input returns undef' );
29
    is( %{$allowlist->apply({ input => {} })}, 0, 'Empty hash returns nothing blocked' );
30
    is( %{$allowlist->apply({ input => {} })}, 0, 'Empty hash returns empty hash' );
30
31
31
    # Test return from apply on hashrefs
32
    # Test apply on hashrefs
32
    my @input = ( col1 => 1, col2 => 2, col3 => 3, col4 => 4 );
33
    my $input = { col1 => 1, col2 => 2, col3 => 3, col4 => 4 };
33
    my $blocked = $allowlist->apply({ input => { @input } });
34
    $allowlist->remove('col1'); # results in empty allow list
35
    my $blocked = {};
36
    $allowlist->apply({ input => $input, dump => $blocked });
34
    is( keys %$blocked, 4, 'Empty list blocks all' );
37
    is( keys %$blocked, 4, 'Empty list blocks all' );
35
    $allowlist->add( 'col1' );
38
    $allowlist->reset; # Back to col1
36
    $blocked = $allowlist->apply({ input => { @input } });
39
    $blocked = {};
40
    $allowlist->apply({ input => $input, dump => $blocked });
37
    is( keys %$blocked, 3, 'One field allowed' );
41
    is( keys %$blocked, 3, 'One field allowed' );
38
    is( $blocked->{col1}, undef, 'And that is col1' );
42
    is( $blocked->{col1}, undef, 'And that is col1' );
39
    $allowlist->remove( 'col1' );
40
    $blocked = $allowlist->apply({ input => { @input } });
41
    is( keys %$blocked, 4, 'Back to 4 after removing col1' );
42
    $allowlist->add( 'col2' );
43
    $allowlist->add( 'col2' );
43
    $allowlist->unload;
44
    $blocked = {};
44
    $blocked = $allowlist->apply({ input => { @input } });
45
    my $result = $allowlist->apply({ input => $input, dump => $blocked  });
45
    is( keys %$blocked, 4, 'Same after unloading' );
46
    is( keys %$blocked, 2, 'Two fields blocked' );
47
    is( keys %$result, 2, 'Two fields allowed' );
48
    is( $result->{col2}, 2, 'Check a result' );
49
    $allowlist->reset; # Undo col2
50
    $blocked = {};
51
    $allowlist->apply({ input => $input, dump => $blocked  });
52
    is( keys %$blocked, 3, 'Back to three blocked' );
46
53
47
    # Test dry run
54
    # Test check method
48
    my $input2 = { col1 => 1, col2 => 2, col3 => 3, col4 => 4 };
55
    $blocked = {};
56
    $input = { col1 => 1, col2 => 2, col3 => 3, col4 => 4 };
49
    $allowlist->add( 'col1', 'col3' );
57
    $allowlist->add( 'col1', 'col3' );
50
    $blocked = $allowlist->check({ input => $input2 });
58
    is( $allowlist->check({ input => $input, dump => $blocked }), q{}, 'Check returns false' );
51
    is( keys %$blocked, 2, 'Expected two entries' );
59
    is( keys %$blocked, 2, 'Dumped 2 entries' );
52
    is( keys %$input2, 4, 'Expected no change in input2' );
60
    $allowlist->add( 'col2', 'col4' );
53
    $blocked = $allowlist->apply({ input => $input2 });
61
    is( $allowlist->check({ input => $input }), 1, 'Check returns true' );
54
    is( keys %$input2, 2, 'Apply removed entries now' );
55
62
56
    # Test array
63
    # Test on arrays
57
    @input = ( 'col1', 'col2', 'col3', 'col4', 'col5' );
64
    $allowlist->remove( 'col2', 'col3' );
58
    $blocked = $allowlist->check({ input => [ @input ] });
65
    $input = [ 'col1', 'col2', 'col3', 'col4', 'col5' ];
66
    $blocked = {};
67
    $result = $allowlist->apply({ input => $input, dump => $blocked });
68
    is( @$result, 2, 'Expected 2 allowed entries' );
69
    is( ( grep { $_ eq 'col1' } @$result ), 1, 'col1 allowed' );
59
    is( keys %$blocked, 3, 'Expected three blocked entries' );
70
    is( keys %$blocked, 3, 'Expected three blocked entries' );
60
    $input2 = [ @input ];
71
    is( $blocked->{col2}, 1, 'col2 blocked' );
61
    $blocked = $allowlist->apply({ input => $input2 });
72
62
    is( keys %$blocked, 3, 'Expected three blocked entries again' );
73
    # Test keys method
63
    is( @$input2, 2, 'Expect two entries now in input2' );
74
    is( join(',', $allowlist->keys), 'col1,col4', 'List current entries' );
64
};
75
};
65
- 

Return to bug 28999