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

(-)a/C4/Acquisition.pm (-1 / +1 lines)
Lines 853-859 sub CanUserManageBasket { Link Here
853
        my ($flags) = $sth->fetchrow_array;
853
        my ($flags) = $sth->fetchrow_array;
854
        $sth->finish;
854
        $sth->finish;
855
855
856
        $userflags = C4::Auth::getuserflags($flags, $borrower->{userid}, $dbh);
856
        $userflags = C4::Auth::getuserflags( { userid => $borrower->{userid} });
857
    }
857
    }
858
858
859
    unless ($userflags->{superlibrarian}
859
    unless ($userflags->{superlibrarian}
(-)a/C4/Auth.pm (-82 / +59 lines)
Lines 24-50 use Carp qw( croak ); Link Here
24
use Digest::MD5 qw( md5_base64 );
24
use Digest::MD5 qw( md5_base64 );
25
use CGI::Session;
25
use CGI::Session;
26
26
27
use Encode;
28
use List::MoreUtils qw( any );
29
use Net::CIDR;
30
31
use C4::Auth_with_shibboleth qw( shib_ok get_login_shib login_shib_url logout_shib checkpw_shib );
27
use C4::Context;
32
use C4::Context;
28
use C4::Templates;    # to get the template
29
use C4::Languages;
33
use C4::Languages;
34
use C4::Log qw( logaction );
30
use C4::Search::History;
35
use C4::Search::History;
31
use Koha;
36
use C4::Templates;    # to get the template
32
use Koha::Logger;
33
use Koha::Caches;
34
use Koha::AuthUtils qw( get_script_name hash_password );
37
use Koha::AuthUtils qw( get_script_name hash_password );
38
use Koha::Caches;
39
use Koha::Cash::Registers;
35
use Koha::Checkouts;
40
use Koha::Checkouts;
36
use Koha::DateUtils qw( dt_from_string );
41
use Koha::DateUtils qw( dt_from_string );
37
use Koha::Library::Groups;
38
use Koha::Libraries;
39
use Koha::Cash::Registers;
40
use Koha::Desks;
42
use Koha::Desks;
41
use Koha::Patrons;
43
use Koha::Libraries;
44
use Koha::Library::Groups;
45
use Koha::Logger;
42
use Koha::Patron::Consents;
46
use Koha::Patron::Consents;
43
use List::MoreUtils qw( any );
47
use Koha::Patrons;
44
use Encode;
48
use Koha::Permissions;
45
use C4::Auth_with_shibboleth qw( shib_ok get_login_shib login_shib_url logout_shib checkpw_shib );
49
use Koha;
46
use Net::CIDR;
47
use C4::Log qw( logaction );
48
50
49
# use utf8;
51
# use utf8;
50
52
Lines 1125-1131 sub checkauth { Link Here
1125
1127
1126
                if ( $return == 1 ) {
1128
                if ( $return == 1 ) {
1127
                    my $select = "
1129
                    my $select = "
1128
                    SELECT borrowernumber, firstname, surname, flags, borrowers.branchcode,
1130
                    SELECT borrowernumber, firstname, surname, borrowers.branchcode,
1129
                    branches.branchname    as branchname, email
1131
                    branches.branchname    as branchname, email
1130
                    FROM borrowers
1132
                    FROM borrowers
1131
                    LEFT JOIN branches on borrowers.branchcode=branches.branchcode
1133
                    LEFT JOIN branches on borrowers.branchcode=branches.branchcode
Lines 1141-1147 sub checkauth { Link Here
1141
                        }
1143
                        }
1142
                    }
1144
                    }
1143
                    if ( $sth->rows ) {
1145
                    if ( $sth->rows ) {
1144
                        ( $borrowernumber, $firstname, $surname, $userflags,
1146
                        ( $borrowernumber, $firstname, $surname,
1145
                            $branchcode, $branchname, $emailaddress ) = $sth->fetchrow;
1147
                            $branchcode, $branchname, $emailaddress ) = $sth->fetchrow;
1146
                    }
1148
                    }
1147
1149
Lines 1209-1215 sub checkauth { Link Here
1209
                    $session->param( 'branchname',   $branchname );
1211
                    $session->param( 'branchname',   $branchname );
1210
                    $session->param( 'desk_id',      $desk_id);
1212
                    $session->param( 'desk_id',      $desk_id);
1211
                    $session->param( 'desk_name',     $desk_name);
1213
                    $session->param( 'desk_name',     $desk_name);
1212
                    $session->param( 'flags',        $userflags );
1213
                    $session->param( 'emailaddress', $emailaddress );
1214
                    $session->param( 'emailaddress', $emailaddress );
1214
                    $session->param( 'ip',           $session->remote_addr() );
1215
                    $session->param( 'ip',           $session->remote_addr() );
1215
                    $session->param( 'lasttime',     time() );
1216
                    $session->param( 'lasttime',     time() );
Lines 1955-1989 sub checkpw_internal { Link Here
1955
1956
1956
    my $sth =
1957
    my $sth =
1957
      $dbh->prepare(
1958
      $dbh->prepare(
1958
        "select password,cardnumber,borrowernumber,userid,firstname,surname,borrowers.branchcode,branches.branchname,flags from borrowers join branches on borrowers.branchcode=branches.branchcode where userid=?"
1959
        "select password,cardnumber,borrowernumber,userid,firstname,surname,borrowers.branchcode,branches.branchname from borrowers join branches on borrowers.branchcode=branches.branchcode where userid=?"
1959
      );
1960
      );
1960
    $sth->execute($userid);
1961
    $sth->execute($userid);
1961
    if ( $sth->rows ) {
1962
    if ( $sth->rows ) {
1962
        my ( $stored_hash, $cardnumber, $borrowernumber, $userid, $firstname,
1963
        my ( $stored_hash, $cardnumber, $borrowernumber, $userid, $firstname,
1963
            $surname, $branchcode, $branchname, $flags )
1964
            $surname, $branchcode, $branchname )
1964
          = $sth->fetchrow;
1965
          = $sth->fetchrow;
1965
1966
1966
        if ( checkpw_hash( $password, $stored_hash ) ) {
1967
        if ( checkpw_hash( $password, $stored_hash ) ) {
1967
1968
1968
            C4::Context->set_userenv( "$borrowernumber", $userid, $cardnumber,
1969
            C4::Context->set_userenv( "$borrowernumber", $userid, $cardnumber,
1969
                $firstname, $surname, $branchcode, $branchname, $flags ) unless $no_set_userenv;
1970
                $firstname, $surname, $branchcode, $branchname ) unless $no_set_userenv;
1970
            return 1, $cardnumber, $userid;
1971
            return 1, $cardnumber, $userid;
1971
        }
1972
        }
1972
    }
1973
    }
1973
    $sth =
1974
    $sth =
1974
      $dbh->prepare(
1975
      $dbh->prepare(
1975
        "select password,cardnumber,borrowernumber,userid,firstname,surname,borrowers.branchcode,branches.branchname,flags from borrowers join branches on borrowers.branchcode=branches.branchcode where cardnumber=?"
1976
        "select password,cardnumber,borrowernumber,userid,firstname,surname,borrowers.branchcode,branches.branchname from borrowers join branches on borrowers.branchcode=branches.branchcode where cardnumber=?"
1976
      );
1977
      );
1977
    $sth->execute($userid);
1978
    $sth->execute($userid);
1978
    if ( $sth->rows ) {
1979
    if ( $sth->rows ) {
1979
        my ( $stored_hash, $cardnumber, $borrowernumber, $userid, $firstname,
1980
        my ( $stored_hash, $cardnumber, $borrowernumber, $userid, $firstname,
1980
            $surname, $branchcode, $branchname, $flags )
1981
            $surname, $branchcode, $branchname )
1981
          = $sth->fetchrow;
1982
          = $sth->fetchrow;
1982
1983
1983
        if ( checkpw_hash( $password, $stored_hash ) ) {
1984
        if ( checkpw_hash( $password, $stored_hash ) ) {
1984
1985
1985
            C4::Context->set_userenv( $borrowernumber, $userid, $cardnumber,
1986
            C4::Context->set_userenv( $borrowernumber, $userid, $cardnumber,
1986
                $firstname, $surname, $branchcode, $branchname, $flags ) unless $no_set_userenv;
1987
                $firstname, $surname, $branchcode, $branchname ) unless $no_set_userenv;
1987
            return 1, $cardnumber, $userid;
1988
            return 1, $cardnumber, $userid;
1988
        }
1989
        }
1989
    }
1990
    }
Lines 2007-2053 sub checkpw_hash { Link Here
2007
2008
2008
=head2 getuserflags
2009
=head2 getuserflags
2009
2010
2010
    my $authflags = getuserflags($flags, $userid, [$dbh]);
2011
    my $authflags = getuserflags($userid);
2011
2012
2012
Translates integer flags into permissions strings hash.
2013
Translates integer flags into permissions strings hash.
2013
2014
2014
C<$flags> is the integer userflags value ( borrowers.userflags )
2015
C<$userid> is the members.userid, used for building subpermissions
2015
C<$userid> is the members.userid, used for building subpermissions
2016
C<$authflags> is a hashref of permissions
2017
2016
2018
=cut
2017
=cut
2019
2018
2020
sub getuserflags {
2019
sub getuserflags {
2021
    my $flags  = shift;
2020
    my $params = shift;
2022
    my $userid = shift;
2021
2023
    my $dbh    = @_ ? shift : C4::Context->dbh;
2022
    my $userid               = $params->{userid};
2023
    my $force_subpermissions = $params->{force_subpermissions};
2024
2025
    my $patron = Koha::Patrons->find( { userid => $userid } );
2026
    return unless $patron;
2027
2024
    my $userflags;
2028
    my $userflags;
2025
    {
2029
    my @permissions = Koha::Permissions->search( { parent => undef } );
2026
        # I don't want to do this, but if someone logs in as the database
2030
    foreach my $p (@permissions) {
2027
        # user, it would be preferable not to spam them to death with
2031
        my $patron_has = $p->patron_has( $patron->id );
2028
        # numeric warnings. So, we make $flags numeric.
2029
        no warnings 'numeric';
2030
        $flags += 0;
2031
    }
2032
    my $sth = $dbh->prepare("SELECT bit, flag, defaulton FROM userflags");
2033
    $sth->execute;
2034
2032
2035
    while ( my ( $bit, $flag, $defaulton ) = $sth->fetchrow ) {
2033
        if ( $patron_has && !$force_subpermissions ) {
2036
        if ( ( $flags & ( 2**$bit ) ) || $defaulton ) {
2034
            $userflags->{ $p->code() } = $p->patron_has( $patron->id );
2037
            $userflags->{$flag} = 1;
2038
        }
2035
        }
2039
        else {
2036
        else {
2040
            $userflags->{$flag} = 0;
2037
            my @subpermissions = $p->subpermissions;
2038
            foreach my $sp ( $p->subpermissions ) {
2039
                $userflags->{ $p->code } = $sp->patron_has( $patron->id );
2040
            }
2041
        }
2041
        }
2042
    }
2042
    }
2043
2043
2044
    # get subpermissions and merge with top-level permissions
2045
    my $user_subperms = get_user_subpermissions($userid);
2046
    foreach my $module ( keys %$user_subperms ) {
2047
        next if $userflags->{$module} == 1;    # user already has permission for everything in this module
2048
        $userflags->{$module} = $user_subperms->{$module};
2049
    }
2050
2051
    return $userflags;
2044
    return $userflags;
2052
}
2045
}
2053
2046
Lines 2079-2098 necessary to check borrowers.flags. Link Here
2079
sub get_user_subpermissions {
2072
sub get_user_subpermissions {
2080
    my $userid = shift;
2073
    my $userid = shift;
2081
2074
2082
    my $dbh = C4::Context->dbh;
2075
    return getuserflags( { userid => $userid, force_subpermissions => 1 } );
2083
    my $sth = $dbh->prepare( "SELECT flag, user_permissions.code
2084
                             FROM user_permissions
2085
                             JOIN permissions USING (module_bit, code)
2086
                             JOIN userflags ON (module_bit = bit)
2087
                             JOIN borrowers USING (borrowernumber)
2088
                             WHERE userid = ?" );
2089
    $sth->execute($userid);
2090
2091
    my $user_perms = {};
2092
    while ( my $perm = $sth->fetchrow_hashref ) {
2093
        $user_perms->{ $perm->{'flag'} }->{ $perm->{'code'} } = 1;
2094
    }
2095
    return $user_perms;
2096
}
2076
}
2097
2077
2098
=head2 get_all_subpermissions
2078
=head2 get_all_subpermissions
Lines 2100-2124 sub get_user_subpermissions { Link Here
2100
  my $perm_hashref = get_all_subpermissions();
2080
  my $perm_hashref = get_all_subpermissions();
2101
2081
2102
Returns a hashref of hashrefs defining all specific
2082
Returns a hashref of hashrefs defining all specific
2103
permissions currently defined.  The return value
2083
permissions currently defined.  The return value has
2104
has the same structure as that of C<get_user_subpermissions>,
2084
the same basic structure as that of C<get_user_subpermissions>
2105
except that the innermost hash value is the description
2106
of the subpermission.
2107
2085
2108
=cut
2086
=cut
2109
2087
2110
sub get_all_subpermissions {
2088
sub get_all_subpermissions {
2111
    my $dbh = C4::Context->dbh;
2089
    my $permissions;
2112
    my $sth = $dbh->prepare( "SELECT flag, code
2090
2113
                             FROM permissions
2091
    my @permissions = Koha::Permissions->search({ parent => undef });
2114
                             JOIN userflags ON (module_bit = bit)" );
2092
    foreach my $p ( @permissions ) {
2115
    $sth->execute();
2093
        foreach my $sp ( $p->subpermissions ) {
2116
2094
            $permissions->{ $p->code }->{ $sp->code } = 1;
2117
    my $all_perms = {};
2095
        }
2118
    while ( my $perm = $sth->fetchrow_hashref ) {
2119
        $all_perms->{ $perm->{'flag'} }->{ $perm->{'code'} } = 1;
2120
    }
2096
    }
2121
    return $all_perms;
2097
2098
    return $permissions;
2122
}
2099
}
2123
2100
2124
=head2 haspermission
2101
=head2 haspermission
Lines 2180-2192 sub _dispatch { Link Here
2180
sub haspermission {
2157
sub haspermission {
2181
    my ( $userid, $flagsrequired ) = @_;
2158
    my ( $userid, $flagsrequired ) = @_;
2182
2159
2183
    #Koha::Exceptions::WrongParameter->throw('$flagsrequired should not be undef')
2160
    my $flags = getuserflags( { userid => $userid } );
2184
    #  unless defined($flagsrequired);
2185
2161
2186
    my $sth = C4::Context->dbh->prepare("SELECT flags FROM borrowers WHERE userid=?");
2162
    if ( $userid eq C4::Context->config('user') ) {
2187
    $sth->execute($userid);
2163
2188
    my $row = $sth->fetchrow();
2164
        # Super User Account from /etc/koha.conf
2189
    my $flags = getuserflags( $row, $userid );
2165
        $flags->{'superlibrarian'} = 1;
2166
    }
2190
2167
2191
    return $flags unless defined($flagsrequired);
2168
    return $flags unless defined($flagsrequired);
2192
    return $flags if $flags->{superlibrarian};
2169
    return $flags if $flags->{superlibrarian};
(-)a/C4/Budgets.pm (-2 / +1 lines)
Lines 1037-1044 sub CanUserUseBudget { Link Here
1037
    return 0 unless ($borrower and $budget);
1037
    return 0 unless ($borrower and $budget);
1038
1038
1039
    if (not defined $userflags) {
1039
    if (not defined $userflags) {
1040
        $userflags = C4::Auth::getuserflags($borrower->{flags},
1040
        $userflags = C4::Auth::getuserflags( { userid => $borrower->{userid} } );
1041
            $borrower->{userid});
1042
    }
1041
    }
1043
1042
1044
    unless ($userflags->{superlibrarian}
1043
    unless ($userflags->{superlibrarian}
(-)a/Koha/Patron.pm (-2 / +57 lines)
Lines 43-48 use Koha::Patron::Categories; Link Here
43
use Koha::Patron::Debarments;
43
use Koha::Patron::Debarments;
44
use Koha::Patron::HouseboundProfile;
44
use Koha::Patron::HouseboundProfile;
45
use Koha::Patron::HouseboundRole;
45
use Koha::Patron::HouseboundRole;
46
use Koha::Patron::Permissions;
46
use Koha::Patron::Images;
47
use Koha::Patron::Images;
47
use Koha::Patron::Modifications;
48
use Koha::Patron::Modifications;
48
use Koha::Patron::Relationships;
49
use Koha::Patron::Relationships;
Lines 1670-1676 sub anonymize { Link Here
1670
        split /\s*\|\s*/, C4::Context->preference('BorrowerMandatoryField') };
1671
        split /\s*\|\s*/, C4::Context->preference('BorrowerMandatoryField') };
1671
    $mandatory->{userid} = 1; # needed since sub store does not clear field
1672
    $mandatory->{userid} = 1; # needed since sub store does not clear field
1672
    my @columns = $self->_result->result_source->columns;
1673
    my @columns = $self->_result->result_source->columns;
1673
    @columns = grep { !/borrowernumber|branchcode|categorycode|^date|password|flags|updated_on|lastseen|lang|login_attempts|anonymized/ } @columns;
1674
    @columns = grep { !/borrowernumber|branchcode|categorycode|^date|password|updated_on|lastseen|lang|login_attempts|anonymized/ } @columns;
1674
    push @columns, 'dateofbirth'; # add this date back in
1675
    push @columns, 'dateofbirth'; # add this date back in
1675
    foreach my $col (@columns) {
1676
    foreach my $col (@columns) {
1676
        $self->_anonymize_column($col, $mandatory->{lc $col} );
1677
        $self->_anonymize_column($col, $mandatory->{lc $col} );
Lines 1795-1801 sub to_api_mapping { Link Here
1795
        debarred            => undef,                     # replaced by 'restricted'
1796
        debarred            => undef,                     # replaced by 'restricted'
1796
        debarredcomment     => undef,    # calculated, API consumers will use /restrictions instead
1797
        debarredcomment     => undef,    # calculated, API consumers will use /restrictions instead
1797
        emailpro            => 'secondary_email',
1798
        emailpro            => 'secondary_email',
1798
        flags               => undef,    # permissions manipulation handled in /permissions
1799
        gonenoaddress       => 'incorrect_address',
1799
        gonenoaddress       => 'incorrect_address',
1800
        guarantorid         => 'guarantor_id',
1800
        guarantorid         => 'guarantor_id',
1801
        lastseen            => 'last_seen',
1801
        lastseen            => 'last_seen',
Lines 1910-1915 sub queue_notice { Link Here
1910
1910
1911
=head2 Internal methods
1911
=head2 Internal methods
1912
1912
1913
=head3 has_permission
1914
1915
my $bool = $patron->has_permission( { $top_level_perm => $sub_perm } );
1916
my $bool = $patron->has_permission( $permission_code );
1917
1918
=cut
1919
1920
sub has_permission {
1921
    my ( $self, $code ) = @_;
1922
1923
    if ( ref $code eq 'HASH' ) {
1924
        my ( $pri, $sec ) = %$code;
1925
        $code = $sec eq '1' ? $pri : { '-in' => [ $pri, $sec ] };
1926
    }
1927
1928
    return Koha::Patron::Permissions->search(
1929
        {
1930
            borrowernumber => $self->id,
1931
            code           => $code,
1932
        }
1933
    )->count;
1934
}
1935
1936
=head3 set_permissions
1937
1938
$patron->set_permissions( { permissions => \@permissions } );
1939
1940
Given a list of permissions, set the patron to those and only those permissions
1941
1942
=cut
1943
1944
sub set_permissions {
1945
    my ( $self, $params ) = @_;
1946
1947
    my @permissions = @{ $params->{permissions} };
1948
1949
    $self->_result->result_source->schema->txn_do(
1950
        sub {
1951
            Koha::Patron::Permissions->search( { borrowernumber => $self->id } )
1952
              ->delete();
1953
1954
            Koha::Patron::Permission->new(
1955
                {
1956
                    borrowernumber => $self->id,
1957
                    code           => $_
1958
                }
1959
              )->store()
1960
              for @permissions;
1961
        }
1962
    );
1963
1964
    return $self;
1965
}
1966
1967
1913
=head3 _type
1968
=head3 _type
1914
1969
1915
=cut
1970
=cut
(-)a/Koha/Patron/Permission.pm (+52 lines)
Line 0 Link Here
1
package Koha::Patron::Permission;
2
3
# Copyright ByWater Solutions 2017
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 3 of the License, or (at your option) any later
10
# version.
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
use Modern::Perl;
21
22
use Carp;
23
24
use base qw(Koha::Object);
25
26
=head1 NAME
27
28
Koha::Patron::Permission - Koha User Permission Object class
29
30
This class represents a single permission that a patron has
31
32
=head1 API
33
34
=head2 Class Methods
35
36
=cut
37
38
=head3 type
39
40
=cut
41
42
sub _type {
43
    return 'UserPermission';
44
}
45
46
=head1 AUTHOR
47
48
Kyle M Hall <kyle@bywatersolutions.com>
49
50
=cut
51
52
1;
(-)a/Koha/Patron/Permissions.pm (+56 lines)
Line 0 Link Here
1
package Koha::Patron::Permissions;
2
3
# Copyright ByWater Solutions 2017
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 3 of the License, or (at your option) any later
10
# version.
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
use Modern::Perl;
21
22
use Koha::Patron::Permission;
23
24
use base qw(Koha::Objects);
25
26
=head1 NAME
27
28
Koha::Patron::Permissions - Koha Patron Permissions Object class
29
30
This class represents a set of permissions a patron has
31
32
=head1 API
33
34
=head2 Class Methods
35
36
=cut
37
38
=head3 type
39
40
=cut
41
42
sub _type {
43
    return 'UserPermission';
44
}
45
46
sub object_class {
47
    return 'Koha::Patron::Permission';
48
}
49
50
=head1 AUTHOR
51
52
Kyle M Hall <kyle@bywatersolutions.com>
53
54
=cut
55
56
1;
(-)a/Koha/Permission.pm (+73 lines)
Line 0 Link Here
1
package Koha::Permission;
2
3
# Copyright ByWater Solutions 2017
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 3 of the License, or (at your option) any later
10
# version.
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
use Modern::Perl;
21
22
use Carp;
23
24
use Koha::Patron::Permissions;
25
26
use base qw(Koha::Object);
27
28
=head1 NAME
29
30
Koha::Permission - Koha Permission Object class
31
32
=head1 API
33
34
=head2 Class Methods
35
36
=cut
37
38
=head3  patron_has
39
40
    Accepts a patron id, returns true if patron has this permission, false otherwise
41
=cut
42
43
sub patron_has {
44
    my ( $self, $patron ) = @_;
45
46
    return Koha::Patron::Permissions->find( { borrowernumber => $patron, code => $self->code } ) ? 1 : 0;
47
}
48
49
=head3 subpermissions
50
51
=cut
52
53
sub subpermissions {
54
    my ( $self ) = @_;
55
56
    return Koha::Permissions->search( { parent => $self->code } );
57
}
58
59
=head3 type
60
61
=cut
62
63
sub _type {
64
    return 'Permission';
65
}
66
67
=head1 AUTHOR
68
69
Kyle M Hall <kyle@bywatersolutions.com>
70
71
=cut
72
73
1;
(-)a/Koha/Permissions.pm (+56 lines)
Line 0 Link Here
1
package Koha::Permissions;
2
3
# Copyright ByWater Solutions 2017
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 3 of the License, or (at your option) any later
10
# version.
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
use Modern::Perl;
21
22
use Koha::Permission;
23
24
use base qw(Koha::Objects);
25
26
=head1 NAME
27
28
Koha::Permissions - Koha Permissions Object class
29
30
This object represents a type of permission a user may have.
31
32
=head1 API
33
34
=head2 Class Methods
35
36
=cut
37
38
=head3 type
39
40
=cut
41
42
sub _type {
43
    return 'Permission';
44
}
45
46
sub object_class {
47
    return 'Koha::Permission';
48
}
49
50
=head1 AUTHOR
51
52
Kyle M Hall <kyle@bywatersolutions.com>
53
54
=cut
55
56
1;
(-)a/about.pl (-14 / +8 lines)
Lines 46-51 use Koha::BiblioFrameworks; Link Here
46
use Koha::Email;
46
use Koha::Email;
47
use Koha::Patron::Categories;
47
use Koha::Patron::Categories;
48
use Koha::Patrons;
48
use Koha::Patrons;
49
use Koha::Patron::Permissions;
49
use Koha::Caches;
50
use Koha::Caches;
50
use Koha::Config::SysPrefs;
51
use Koha::Config::SysPrefs;
51
use Koha::Illrequest::Config;
52
use Koha::Illrequest::Config;
Lines 417-437 if ( C4::Context->preference('WebBasedSelfCheck') Link Here
417
      and C4::Context->preference('AutoSelfCheckAllowed')
418
      and C4::Context->preference('AutoSelfCheckAllowed')
418
) {
419
) {
419
    my $userid = C4::Context->preference('AutoSelfCheckID');
420
    my $userid = C4::Context->preference('AutoSelfCheckID');
420
    my $all_permissions = C4::Auth::get_user_subpermissions( $userid );
421
    my $patron = Koha::Patrons->find( { userid => $userid } );
421
    my ( $has_self_checkout_perm, $has_other_permissions );
422
    my $has_self_checkout_perm = $patron->has_permission('self_checkout');
422
    while ( my ( $module, $permissions ) = each %$all_permissions ) {
423
    my $has_other_permissions = Koha::Patron::Permissions->search(
423
        if ( $module eq 'self_check' ) {
424
        {
424
            while ( my ( $permission, $flag ) = each %$permissions ) {
425
            borrowernumber => $patron->id,
425
                if ( $permission eq 'self_checkout_module' ) {
426
            -not           => { code => 'self_checkout' }
426
                    $has_self_checkout_perm = 1;
427
                } else {
428
                    $has_other_permissions = 1;
429
                }
430
            }
431
        } else {
432
            $has_other_permissions = 1;
433
        }
427
        }
434
    }
428
    )->count();
435
    $template->param(
429
    $template->param(
436
        AutoSelfCheckPatronDoesNotHaveSelfCheckPerm => not ( $has_self_checkout_perm ),
430
        AutoSelfCheckPatronDoesNotHaveSelfCheckPerm => not ( $has_self_checkout_perm ),
437
        AutoSelfCheckPatronHasTooManyPerm => $has_other_permissions,
431
        AutoSelfCheckPatronHasTooManyPerm => $has_other_permissions,
(-)a/koha-tmpl/intranet-tmpl/prog/en/includes/members-toolbar.inc (-1 / +1 lines)
Lines 47-53 Link Here
47
                    <li class="disabled"><a data-toggle="tooltip" data-placement="left" title="You are not authorized to renew patrons" id="renewpatron" href="#">Renew patron</a></li>
47
                    <li class="disabled"><a data-toggle="tooltip" data-placement="left" title="You are not authorized to renew patrons" id="renewpatron" href="#">Renew patron</a></li>
48
                [% END %]
48
                [% END %]
49
                [% IF ( CAN_user_permissions ) %]
49
                [% IF ( CAN_user_permissions ) %]
50
                    <li><a id="patronflags" href="/cgi-bin/koha/members/member-flags.pl?member=[% patron.borrowernumber | html %]">Set permissions</a></li>
50
                    <li><a id="patronflags" href="/cgi-bin/koha/members/member-flags.pl?borrowernumber=[% patron.borrowernumber | html %]">Set permissions</a></li>
51
                [% ELSE %]
51
                [% ELSE %]
52
                    <li class="disabled"><a data-toggle="tooltip" data-placement="left" title="You are not authorized to set permissions" id="patronflags" href="#">Set permissions</a></li>
52
                    <li class="disabled"><a data-toggle="tooltip" data-placement="left" title="You are not authorized to set permissions" id="patronflags" href="#">Set permissions</a></li>
53
                [% END %]
53
                [% END %]
(-)a/koha-tmpl/intranet-tmpl/prog/en/includes/permissions.inc (-6 / +1 lines)
Lines 1-4 Link Here
1
[%- BLOCK main_permissions -%]
1
[%- BLOCK permissions -%]
2
    [% SWITCH name %]
2
    [% SWITCH name %]
3
    [%- CASE 'superlibrarian' -%]
3
    [%- CASE 'superlibrarian' -%]
4
        <span class="main_permission superlibrarian_permission">Access to all librarian functions</span>
4
        <span class="main_permission superlibrarian_permission">Access to all librarian functions</span>
Lines 75-85 Link Here
75
    [%- CASE 'problem_reports' -%]
75
    [%- CASE 'problem_reports' -%]
76
        <span class="main_permission problem_reports_permission">OPAC problem reports management</span>
76
        <span class="main_permission problem_reports_permission">OPAC problem reports management</span>
77
        <span class="permissioncode">([% name | html %])</span>
77
        <span class="permissioncode">([% name | html %])</span>
78
    [%- END -%]
79
[%- END -%]
80
81
[%- BLOCK sub_permissions -%]
82
  [% SWITCH name %]
83
    [%- CASE 'circulate_remaining_permissions' -%]
78
    [%- CASE 'circulate_remaining_permissions' -%]
84
        <span class="sub_permission circulate_remaining_permissions_subpermission">
79
        <span class="sub_permission circulate_remaining_permissions_subpermission">
85
            Remaining circulation permissions
80
            Remaining circulation permissions
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/members/member-flags.tt (-76 / +98 lines)
Lines 8-13 Link Here
8
    Set permissions for [% patron.surname | html %], [% patron.firstname | html %] &rsaquo; Patrons &rsaquo; Koha
8
    Set permissions for [% patron.surname | html %], [% patron.firstname | html %] &rsaquo; Patrons &rsaquo; Koha
9
</title>
9
</title>
10
[% INCLUDE 'doc-head-close.inc' %]
10
[% INCLUDE 'doc-head-close.inc' %]
11
<link href="[% interface %]/lib/jquery/plugins/treetable/stylesheets/jquery.treetable.css" rel="stylesheet" type="text/css" />
12
<script type="text/javascript" src="[% interface %]/lib/jquery/plugins/treetable/jquery.treetable.js"></script>
13
<script type="text/javascript">
14
    $(document).ready(function() {
15
        $('#permissions-table').treetable({
16
            expandable: true
17
        });
18
19
        // Expand any parent permissions with children that are set
20
        $('input[name="permission"][checked="checked"]').each(function() {
21
            var id = $(this).data('parent');
22
            if ( id ) {
23
                $('#permissions-table').treetable('expandNode', id );
24
            }
25
        });
26
27
        // Behavior that occurs when a checkbox is changed
28
        $('input[name="permission"]').on('change', function(){
29
            var id = $(this).closest('tr').attr('id');
30
31
            if ( id != 'superlibrarian' ) { // Standard behavior
32
                if ( $(this).attr('checked') ) {
33
                    $('#permissions-table').treetable('expandNode', id );
34
                    $(`input[data-parent=${id}]`).attr('checked', 'checked' );
35
                } else {
36
                    $(`input[data-parent=${id}]`).attr('checked', null );
37
                }
38
            } else { // Superlibrarian behavior
39
                if ( $(this).attr('checked') ) {
40
                    $(`input[name="permission"][value!="superlibrarian"]`).attr('checked', null ).attr('disabled', 'disabled' );
41
                } else {
42
                    $(`input[name="permission"][value!="superlibrarian"]`).attr('disabled', null );
43
                }
44
            }
45
        });
46
    });
47
</script>
11
</head>
48
</head>
12
49
13
<body id="pat_member-flags" class="pat">
50
<body id="pat_member-flags" class="pat">
Lines 35-123 Link Here
35
        <div class="col-sm-10 col-sm-push-2">
72
        <div class="col-sm-10 col-sm-push-2">
36
            <main>
73
            <main>
37
74
38
[% INCLUDE 'members-toolbar.inc' %]
75
<div id="doc3" class="yui-t2">
76
    <div id="bd">
77
        <div id="yui-main">
78
        <div class="yui-b">
79
            [% INCLUDE 'members-toolbar.inc' %]
39
80
40
<form id="flag_form" method="post" action="/cgi-bin/koha/members/member-flags.pl">
81
            <form method="post" action="/cgi-bin/koha/members/member-flags.pl">
41
    <input type="hidden" name="csrf_token" value="[% csrf_token | html %]" />
82
                <input type="hidden" name="csrf_token" value="[% csrf_token %]" />
42
    <input type="hidden" name="member" id="borrowernumber" value="[% patron.borrowernumber | html %]" />
83
                <input type="hidden" name="borrowernumber" id="borrowernumber" value="[% borrowernumber %]" />
43
    <input type="hidden" name="newflags" value="1" />
84
                <input type="hidden" name="set_permissions" value="1" />
44
    <h1>Set permissions for [% patron.surname | html %], [% patron.firstname | html %]</h1>
85
                <h1>Set permissions for [% surname %], [% firstname %]</h1>
45
86
46
    <div id="permissionstree">
87
                <table id="permissions-table">
47
        <div id="permissions_toolbar" class="btn-toolbar">
88
                    <tr data-tt-id="superlibrarian" id="superlibrarian">
48
            <button type="submit" class="btn btn-default"><i class="fa fa-save"></i> Save</button>
89
                        <td>
49
            <a class="btn btn-default" href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% patron.borrowernumber | html %]"><i class="fa fa-remove"></i> Cancel</a>
90
                            [% IF patron.has_permission( p.code ) %]
50
            <a class="toggleall toggleall_on btn btn-link" href="#"><i class="fa fa-plus-square-o"></i> Show all</a>
91
                                <input type="checkbox" name="permission" value="superlibrarian" checked="checked"/>
51
            <a class="toggleall toggleall_off btn btn-link" href="#"><i class="fa fa-minus-square-o"></i> Hide all</a>
92
                            [% ELSE %]
52
            <a id="CheckAllFlags" class="btn btn-link" href="#">
93
                                <input type="checkbox" name="permission" value="superlibrarian"/>
53
                <i class="fa fa-check"></i> Select all
94
                            [% END %]
54
            </a>
95
                        </td>
55
            <a id="UncheckAllFlags" class="btn btn-link" href="#">
96
                        <td>superlibrarian</td>
56
                <i class="fa fa-remove"></i> Clear all
97
                        <td><span class="permissiondesc">[% PROCESS permissions name='superlibrarian' %]</span>
57
            </a>
98
                    </tr>
58
            <div class="btn-group pull-right">
99
                    [% FOREACH p IN permissions %]
59
                Filter: <input type="text" name="permissions_filter" id="permissions_filter" size="20" />
100
                        [% NEXT IF p.code == 'superlibrarian' %]
60
                <a href="#" id="clear_filter" style="display:none"><i class="fa fa-remove"></i></a>
101
                        <tr data-tt-id="[% p.code %]" id="[% p.code %]">
61
            </div>
102
                            <td>
62
        </div>
103
                                [% IF patron.has_permission( p.code ) %]
63
        <div class="permissions">
104
                                    <input type="checkbox" name="permission" value="[% p.code %]" checked="checked"/>
64
            [% FOREACH loo IN loop %]
65
                [% IF ( loo.expand ) %]
66
                    <div id="parent-flag-[% loo.flag | html %]" class="open parent">
67
                [% ELSE %]
68
                    <div id="parent-flag-[% loo.flag | html %]" class="parent">
69
                [% END %]
70
                [% IF ( loo.checked ) %]
71
                    [% IF disable_superlibrarian_privs && loo.bit == 0 %]
72
                        <input type="checkbox" disabled="disabled" data-bit="0" id="flag-0" class="parent flag superlib" name="flag" value="[% loo.flag | html %]" checked="checked" title="The system preference ProtectSuperlibrarianPrivileges is enabled" />
73
                        <input type="hidden" id="flag-0" name="flag" value="[% loo.flag | html %]" >
74
                    [% ELSE %]
75
                          <input type="checkbox" data-bit="[% loo.bit | html %]" id="flag-[% loo.bit | html %]" class="parent flag" name="flag" value="[% loo.flag | html %]" checked="checked" />
76
                    [% END %]
77
                [% ELSE %]
78
                    [% IF disable_superlibrarian_privs && loo.bit == 0 %]
79
                        <input type="checkbox" disabled="disabled" class="flag parent" data-bit="0" id="flag-0" name="flag" value="[% loo.flag | html %]" title="The system preference ProtectSuperlibrarianPrivileges is enabled" />
80
                    [% ELSE %]
81
                        <input type="checkbox" class="flag parent" data-bit="[% loo.bit | html %]" id="flag-[% loo.bit | html %]" name="flag" value="[% loo.flag | html %]" />
82
                    [% END %]
83
                [% END # /IF loo.checked %]
84
                    <label class="permissiondesc" for="flag-[% loo.bit | html %]">
85
                        [% PROCESS main_permissions name=loo.flag %]
86
                    </label>
87
                    [% IF ( loo.flag == "superlibrarian" ) %]<div class="hint superlibrarian-hint">This permission grants access to all areas. If selected, specific sub-permissions cannot be selected.</div>[% END %]
88
                [% IF ( loo.sub_perm_loop ) %]
89
                    <a class="toggle-[% loo.bit | html %] togglechildren_off" href="#" data-bit="[% loo.bit | html %]"><i class="fa fa-minus-square-o"></i> Hide details</a>
90
                    <a class="toggle-[% loo.bit | html %] togglechildren_on" href="#" data-bit="[% loo.bit | html %]"><i class="fa fa-plus-square-o"></i> Show details</a>
91
                    <div class="children" id="flag-[% loo.bit | html %]-children">
92
                        [% FOREACH sub_perm_loo IN loo.sub_perm_loop %]
93
                            <div class="child-flags">
94
                                [% IF ( sub_perm_loo.checked ) %]
95
                                    <input type="checkbox" id="[% sub_perm_loo.id | html %]" class="child flag" name="flag" value="[% sub_perm_loo.perm | html %]" checked="checked" />
96
                                [% ELSE %]
105
                                [% ELSE %]
97
                                    <input type="checkbox" id="[% sub_perm_loo.id | html %]" class="child flag" name="flag" value="[% sub_perm_loo.perm | html %]" />
106
                                    <input type="checkbox" name="permission" value="[% p.code %]"/>
98
                                [% END %]
107
                                [% END %]
99
                                <label class="permissiondesc" for="[% sub_perm_loo.id | html %]">
108
                            </td>
100
                                    [% PROCESS sub_permissions name=sub_perm_loo.code %]
109
                            <td>[% p.code %]</td>
101
                                </label>
110
                            <td><span class="permissiondesc">[% PROCESS permissions name=p.code %]</span>
102
                            </div>
111
                        </tr>
112
113
                        [% FOREACH s IN p.subpermissions() %]
114
                            <tr data-tt-parent-id="[% p.code %]" data-tt-id="[% s.code %]" id="[% s.code %]">
115
                                <td>
116
                                    [% IF patron.has_permission( s.code ) %]
117
                                        <input type="checkbox" name="permission" value="[% s.code %]" checked="checked" data-parent="[% p.code %]"/>
118
                                    [% ELSE %]
119
                                        <input type="checkbox" name="permission" value="[% s.code %]" data-parent="[% p.code %]"/>
120
                                    [% END %]
121
                                </td>
122
                                <td>[% s.code %]</td>
123
                                <td><span class="permissiondesc">[% PROCESS permissions name=s.code %]</span>
124
                            </tr>
103
                        [% END %]
125
                        [% END %]
104
                    </div> <!-- /#flag-[% loo.bit | html %]-children -->
126
                    [% END %]
105
                [% END # /IF loo.sub_perm_loop %]
127
                </table>
106
                </div> <!-- /.parent -->
107
            [% END # /FOREACH loo %]
108
        </div>
109
    </div> <!-- /#permissionstree -->
110
</form>
111
128
112
            </main>
129
                <input type="hidden" name="borrowernumber" value="[% borrowernumber %]" />
113
        </div> <!-- /.col-sm-10.col-sm-push-2 -->
130
131
                <fieldset class="action">
132
                    <input type="submit" value="Save" />
133
                    <a class="cancel" href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrowernumber %]">Cancel</a>
134
                </fieldset>
135
            </form>
136
        </div>
137
    </div>
114
138
115
        <div class="col-sm-2 col-sm-pull-10">
139
    <div class="yui-b">
116
            <aside>
140
    [% INCLUDE 'circ-menu.inc' %]
117
                [% INCLUDE 'circ-menu.inc' %]
141
    </div>
118
            </aside>
142
</div>
119
        </div> <!-- /.col-sm-2.col-sm-pull-10 -->
120
    </div> <!-- /.row -->
121
143
122
[% MACRO jsinclude BLOCK %]
144
[% MACRO jsinclude BLOCK %]
123
    [% INCLUDE 'str/members-menu.inc' %]
145
    [% INCLUDE 'str/members-menu.inc' %]
(-)a/members/member-flags.pl (-149 / +93 lines)
Lines 1-190 Link Here
1
#!/usr/bin/perl
1
#!/usr/bin/perl
2
2
3
# script to edit a member's flags
3
# Copyright 2017 ByWater Solutions;
4
# Written by Steve Tonnesen
4
#
5
# July 26, 2002 (my birthday!)
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
6
19
7
use Modern::Perl;
20
use Modern::Perl;
8
21
9
use CGI qw ( -utf8 );
22
use CGI qw ( -utf8 );
10
use C4::Output qw( output_and_exit_if_error output_and_exit output_html_with_http_headers );
11
use C4::Auth qw( get_template_and_user get_all_subpermissions get_user_subpermissions );
12
use C4::Context;
13
23
24
use C4::Auth;
25
use C4::Context;
26
use C4::Members::Attributes qw(GetBorrowerAttributes);
27
use C4::Members;
28
use C4::Output qw( output_and_exit_if_error output_and_exit output_html_with_http_headers );
29
use C4::Output;
14
use Koha::Patron::Categories;
30
use Koha::Patron::Categories;
31
use Koha::Patron::Images;
15
use Koha::Patrons;
32
use Koha::Patrons;
16
33
use Koha::Permissions;
17
use C4::Output qw( output_and_exit_if_error output_and_exit output_html_with_http_headers );
18
use Koha::Token;
34
use Koha::Token;
19
35
20
my $input = CGI->new;
36
my $input = CGI->new;
21
37
22
my $flagsrequired = { permissions => 1 };
38
my $flagsrequired = { permissions => 1 };
23
my $member=$input->param('member');
39
my $borrowernumber = $input->param('borrowernumber');
24
my $patron = Koha::Patrons->find( $member );
40
25
unless ( $patron ) {
41
my $patron = Koha::Patrons->find($borrowernumber);
26
    print $input->redirect("/cgi-bin/koha/circ/circulation.pl?borrowernumber=$member");
27
    exit;
28
}
29
42
30
my $category_type = $patron->category->category_type;
43
my $category_type = $patron->category->category_type;
31
my $bor = $patron->unblessed;
44
my $bor           = $patron->unblessed;
32
if( $category_type eq 'S' )  { # FIXME Is this really needed?
45
if ( $category_type eq 'S' ) {
33
    $flagsrequired->{'staffaccess'} = 1;
46
    $flagsrequired->{'staffaccess'} = 1;
34
}
47
}
35
my ($template, $loggedinuser, $cookie) = get_template_and_user({
48
my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
49
    {
36
        template_name   => "members/member-flags.tt",
50
        template_name   => "members/member-flags.tt",
37
        query           => $input,
51
        query           => $input,
38
        type            => "intranet",
52
        type            => "intranet",
39
        flagsrequired   => $flagsrequired,
53
        flagsrequired   => $flagsrequired,
40
});
54
    }
55
);
41
56
42
my $logged_in_user = Koha::Patrons->find( $loggedinuser );
57
my $logged_in_user = Koha::Patrons->find( $loggedinuser );
43
output_and_exit_if_error( $input, $cookie, $template, { module => 'members', logged_in_user => $logged_in_user, current_patron => $patron } );
58
output_and_exit_if_error( $input, $cookie, $template, { module => 'members', logged_in_user => $logged_in_user, current_patron => $patron } );
44
59
45
my %member2;
60
if ( $input->param('set_permissions') ) { # update permissions
46
$member2{'borrowernumber'}=$member;
47
48
if ($input->param('newflags')) {
49
61
50
    output_and_exit( $input, $cookie, $template,  'wrong_csrf_token' )
62
    output_and_exit( $input, $cookie, $template,  'wrong_csrf_token' )
51
        unless Koha::Token->new->check_csrf({
63
        unless Koha::Token->new->check_csrf({
52
            session_id => scalar $input->cookie('CGISESSID'),
64
            session_id => scalar $input->cookie('CGISESSID'),
53
            token  => scalar $input->param('csrf_token'),
65
            token      => scalar $input->param('csrf_token'),
54
        });
66
        }
55
67
      );
56
68
57
    my $dbh=C4::Context->dbh();
69
    my @permissions = $input->multi_param('permission');
58
70
59
    my @perms = $input->multi_param('flag');
71
    $patron->set_permissions( { permissions => \@permissions } );
60
    my %all_module_perms = ();
61
    my %sub_perms = ();
62
    foreach my $perm (@perms) {
63
        if ($perm !~ /:/) {
64
            $all_module_perms{$perm} = 1;
65
        } else {
66
            my ($module, $sub_perm) = split /:/, $perm, 2;
67
            push @{ $sub_perms{$module} }, $sub_perm;
68
        }
69
    }
70
72
71
    # construct flags
73
    print $input->redirect(
72
    my $module_flags = 0;
74
        "/cgi-bin/koha/members/moremember.pl?borrowernumber=$borrowernumber");
73
    my $sth=$dbh->prepare("SELECT bit,flag FROM userflags ORDER BY bit");
75
}
74
    $sth->execute();
76
else { # fetch for display
75
    while (my ($bit, $flag) = $sth->fetchrow_array) {
77
    my $permissions = Koha::Permissions->search( { parent => undef } );
76
        if (exists $all_module_perms{$flag}) {
78
    $template->param(
77
            $module_flags += 2**$bit;
79
        patron      => $patron,
78
        }
80
        permissions => $permissions,
79
    }
81
    );
80
    
82
81
    $sth = $dbh->prepare("UPDATE borrowers SET flags=? WHERE borrowernumber=?");
83
    # Patron details boilerplate for patron related templates
82
    my $old_flags = $patron->flags // 0;
84
    if ( $category_type eq 'C' ) {
83
    if( ( $old_flags == 1 || $module_flags == 1 ) &&
85
        my $patron_categories =
84
      $old_flags != $module_flags ) {
86
          Koha::Patron::Categories->search_limited( { category_type => 'A' },
85
        die "Non-superlibrarian is changing superlibrarian privileges" if !C4::Context->IsSuperLibrarian && C4::Context->preference('ProtectSuperlibrarianPrivileges'); # Interface should not allow this, so we can just die here
87
            { order_by => ['categorycode'] } );
86
    }
88
        $template->param( 'CATCODE_MULTI' => 1 )
87
    $sth->execute($module_flags, $member);
89
          if $patron_categories->count > 1;
88
90
        $template->param( 'catcode' => $patron_categories->next )
89
    # deal with subpermissions
91
          if $patron_categories->count == 1;
90
    $sth = $dbh->prepare("DELETE FROM user_permissions WHERE borrowernumber = ?");
91
    $sth->execute($member); 
92
    $sth = $dbh->prepare("INSERT INTO user_permissions (borrowernumber, module_bit, code)
93
                        SELECT ?, bit, ?
94
                        FROM userflags
95
                        WHERE flag = ?");
96
    foreach my $module (keys %sub_perms) {
97
        next if exists $all_module_perms{$module};
98
        foreach my $sub_perm (@{ $sub_perms{$module} }) {
99
            $sth->execute($member, $sub_perm, $module);
100
        }
101
    }
102
    
103
    print $input->redirect("/cgi-bin/koha/members/moremember.pl?borrowernumber=$member");
104
} else {
105
106
    my $accessflags;
107
    my $dbh = C4::Context->dbh();
108
    # FIXME This needs to be improved to avoid doing the same query
109
    my $sth = $dbh->prepare("select bit,flag from userflags");
110
    $sth->execute;
111
    while ( my ( $bit, $flag ) = $sth->fetchrow ) {
112
        if ( $bor->{flags} && $bor->{flags} & 2**$bit ) {
113
            $accessflags->{$flag} = 1;
114
        }
115
    }
92
    }
116
93
117
    my $all_perms  = get_all_subpermissions();
94
    $template->param( adultborrower => 1 ) if ( $category_type =~ /^(A|I)$/ );
118
    my $user_perms = get_user_subpermissions($bor->{'userid'});
95
    $template->param( picture       => 1 ) if $patron->image;
119
    $sth = $dbh->prepare("SELECT bit, flag FROM userflags ORDER BY bit");
120
    $sth->execute;
121
    my @loop;
122
123
    while (my ($bit, $flag) = $sth->fetchrow) {
124
        my $checked='';
125
        if ($accessflags->{$flag}) {
126
            $checked= 1;
127
        }
128
96
129
        my %row = ( bit => $bit,
97
    if ( C4::Context->preference('ExtendedPatronAttributes') ) {
130
            flag => $flag,
98
        my $attributes = GetBorrowerAttributes( $bor->{'borrowernumber'} );
131
            checked => $checked,
99
        $template->param(
100
            ExtendedPatronAttributes => 1,
101
            extendedattributes       => $attributes
132
        );
102
        );
133
134
        my @sub_perm_loop = ();
135
        my $expand_parent = 0;
136
        if ($checked) {
137
            if (exists $all_perms->{$flag}) {
138
                $expand_parent = 1;
139
                foreach my $sub_perm (sort keys %{ $all_perms->{$flag} }) {
140
                    push @sub_perm_loop, {
141
                        id => "${flag}_$sub_perm",
142
                        perm => "$flag:$sub_perm",
143
                        code => $sub_perm,
144
                        checked => 1
145
                    };
146
                }
147
            }
148
        } else {
149
            if (exists $user_perms->{$flag}) {
150
                $expand_parent = 1;
151
                # put selected ones first
152
                foreach my $sub_perm (sort keys %{ $user_perms->{$flag} }) {
153
                    push @sub_perm_loop, {
154
                        id => "${flag}_$sub_perm",
155
                        perm => "$flag:$sub_perm",
156
                        code => $sub_perm,
157
                        checked => 1
158
                    };
159
                }
160
            }
161
            # then ones not selected
162
            if (exists $all_perms->{$flag}) {
163
                foreach my $sub_perm (sort keys %{ $all_perms->{$flag} }) {
164
                    push @sub_perm_loop, {
165
                        id => "${flag}_$sub_perm",
166
                        perm => "$flag:$sub_perm",
167
                        code => $sub_perm,
168
                        checked => 0
169
                    } unless exists $user_perms->{$flag} and exists $user_perms->{$flag}->{$sub_perm};
170
                }
171
            }
172
        }
173
        $row{expand} = $expand_parent;
174
        if ($#sub_perm_loop > -1) {
175
            $row{sub_perm_loop} = \@sub_perm_loop;
176
        }
177
        next if ( ( $row{flag} eq 'cash_management' ) && !C4::Context->preference('UseCashRegisters') );
178
        push @loop, \%row;
179
    }
103
    }
180
104
181
$template->param(
105
    $template->param(
182
    patron         => $patron,
106
        borrowernumber => $bor->{'borrowernumber'},
183
    loop           => \@loop,
107
        cardnumber     => $bor->{'cardnumber'},
184
    csrf_token =>
108
        surname        => $bor->{'surname'},
185
        Koha::Token->new->generate_csrf( { session_id => scalar $input->cookie('CGISESSID'), } ),
109
        firstname      => $bor->{'firstname'},
186
    disable_superlibrarian_privs => C4::Context->preference('ProtectSuperlibrarianPrivileges') ? !C4::Context->IsSuperLibrarian : 0,
110
        othernames     => $bor->{'othernames'},
187
);
111
        categorycode   => $bor->{'categorycode'},
112
        category_type  => $category_type,
113
        categoryname   => $bor->{'description'},
114
        address        => $bor->{address},
115
        address2       => $bor->{'address2'},
116
        streettype     => $bor->{streettype},
117
        city           => $bor->{'city'},
118
        state          => $bor->{'state'},
119
        zipcode        => $bor->{'zipcode'},
120
        country        => $bor->{'country'},
121
        phone          => $bor->{'phone'},
122
        phonepro       => $bor->{'phonepro'},
123
        mobile         => $bor->{'mobile'},
124
        email          => $bor->{'email'},
125
        emailpro       => $bor->{'emailpro'},
126
        branchcode     => $bor->{'branchcode'},
127
        is_child       => ( $category_type eq 'C' ),
128
        RoutingSerials => C4::Context->preference('RoutingSerials'),
129
        csrf_token     => Koha::Token->new->generate_csrf(
130
            { session_id => scalar $input->cookie('CGISESSID'), }
131
        ),
132
    );
188
133
189
    output_html_with_http_headers $input, $cookie, $template->output;
134
    output_html_with_http_headers $input, $cookie, $template->output;
190
135
191
- 

Return to bug 20813