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

(-)a/C4/Acquisition.pm (-1 / +1 lines)
Lines 848-854 sub CanUserManageBasket { Link Here
848
        my ($flags) = $sth->fetchrow_array;
848
        my ($flags) = $sth->fetchrow_array;
849
        $sth->finish;
849
        $sth->finish;
850
850
851
        $userflags = C4::Auth::getuserflags($flags, $borrower->{userid}, $dbh);
851
        $userflags = C4::Auth::getuserflags( { userid => $borrower->{userid} });
852
    }
852
    }
853
853
854
    unless ($userflags->{superlibrarian}
854
    unless ($userflags->{superlibrarian}
(-)a/C4/Auth.pm (-69 / +42 lines)
Lines 36-41 use Koha::AuthUtils qw(get_script_name hash_password); Link Here
36
use Koha::Library::Groups;
36
use Koha::Library::Groups;
37
use Koha::Libraries;
37
use Koha::Libraries;
38
use Koha::Patrons;
38
use Koha::Patrons;
39
use Koha::Permissions;
39
use POSIX qw/strftime/;
40
use POSIX qw/strftime/;
40
use List::MoreUtils qw/ any /;
41
use List::MoreUtils qw/ any /;
41
use Encode qw( encode is_utf8);
42
use Encode qw( encode is_utf8);
Lines 57-63 BEGIN { Link Here
57
    @EXPORT_OK = qw(&check_api_auth &get_session &check_cookie_auth &checkpw &checkpw_internal &checkpw_hash
58
    @EXPORT_OK = qw(&check_api_auth &get_session &check_cookie_auth &checkpw &checkpw_internal &checkpw_hash
58
      &get_all_subpermissions &get_user_subpermissions
59
      &get_all_subpermissions &get_user_subpermissions
59
    );
60
    );
60
    %EXPORT_TAGS = ( EditPermissions => [qw(get_all_subpermissions get_user_subpermissions)] );
61
    $ldap      = C4::Context->config('useldapserver') || 0;
61
    $ldap      = C4::Context->config('useldapserver') || 0;
62
    $cas       = C4::Context->preference('casAuthentication');
62
    $cas       = C4::Context->preference('casAuthentication');
63
    $shib      = C4::Context->config('useshibboleth') || 0;
63
    $shib      = C4::Context->config('useshibboleth') || 0;
Lines 1065-1071 sub checkauth { Link Here
1065
1065
1066
                if ( $return == 1 ) {
1066
                if ( $return == 1 ) {
1067
                    my $select = "
1067
                    my $select = "
1068
                    SELECT borrowernumber, firstname, surname, flags, borrowers.branchcode,
1068
                    SELECT borrowernumber, firstname, surname, borrowers.branchcode,
1069
                    branches.branchname    as branchname,
1069
                    branches.branchname    as branchname,
1070
                    branches.branchprinter as branchprinter,
1070
                    branches.branchprinter as branchprinter,
1071
                    email
1071
                    email
Lines 1088-1097 sub checkauth { Link Here
1088
                        }
1088
                        }
1089
                    }
1089
                    }
1090
                    if ( $sth->rows ) {
1090
                    if ( $sth->rows ) {
1091
                        ( $borrowernumber, $firstname, $surname, $userflags,
1091
                        ( $borrowernumber, $firstname, $surname,
1092
                            $branchcode, $branchname, $branchprinter, $emailaddress ) = $sth->fetchrow;
1092
                            $branchcode, $branchname, $branchprinter, $emailaddress ) = $sth->fetchrow;
1093
                        $debug and print STDERR "AUTH_3 results: " .
1093
                        $debug and print STDERR "AUTH_3 results: " .
1094
                          "$cardnumber,$borrowernumber,$userid,$firstname,$surname,$userflags,$branchcode,$emailaddress\n";
1094
                          "$cardnumber,$borrowernumber,$userid,$firstname,$surname,$branchcode,$emailaddress\n";
1095
                    } else {
1095
                    } else {
1096
                        print STDERR "AUTH_3: no results for userid='$userid', cardnumber='$cardnumber'.\n";
1096
                        print STDERR "AUTH_3: no results for userid='$userid', cardnumber='$cardnumber'.\n";
1097
                    }
1097
                    }
Lines 1143-1149 sub checkauth { Link Here
1143
                    $session->param( 'surname',      $surname );
1143
                    $session->param( 'surname',      $surname );
1144
                    $session->param( 'branch',       $branchcode );
1144
                    $session->param( 'branch',       $branchcode );
1145
                    $session->param( 'branchname',   $branchname );
1145
                    $session->param( 'branchname',   $branchname );
1146
                    $session->param( 'flags',        $userflags );
1147
                    $session->param( 'emailaddress', $emailaddress );
1146
                    $session->param( 'emailaddress', $emailaddress );
1148
                    $session->param( 'ip',           $session->remote_addr() );
1147
                    $session->param( 'ip',           $session->remote_addr() );
1149
                    $session->param( 'lasttime',     time() );
1148
                    $session->param( 'lasttime',     time() );
Lines 1848-1882 sub checkpw_internal { Link Here
1848
1847
1849
    my $sth =
1848
    my $sth =
1850
      $dbh->prepare(
1849
      $dbh->prepare(
1851
        "select password,cardnumber,borrowernumber,userid,firstname,surname,borrowers.branchcode,branches.branchname,flags from borrowers join branches on borrowers.branchcode=branches.branchcode where userid=?"
1850
        "select password,cardnumber,borrowernumber,userid,firstname,surname,borrowers.branchcode,branches.branchname from borrowers join branches on borrowers.branchcode=branches.branchcode where userid=?"
1852
      );
1851
      );
1853
    $sth->execute($userid);
1852
    $sth->execute($userid);
1854
    if ( $sth->rows ) {
1853
    if ( $sth->rows ) {
1855
        my ( $stored_hash, $cardnumber, $borrowernumber, $userid, $firstname,
1854
        my ( $stored_hash, $cardnumber, $borrowernumber, $userid, $firstname,
1856
            $surname, $branchcode, $branchname, $flags )
1855
            $surname, $branchcode, $branchname )
1857
          = $sth->fetchrow;
1856
          = $sth->fetchrow;
1858
1857
1859
        if ( checkpw_hash( $password, $stored_hash ) ) {
1858
        if ( checkpw_hash( $password, $stored_hash ) ) {
1860
1859
1861
            C4::Context->set_userenv( "$borrowernumber", $userid, $cardnumber,
1860
            C4::Context->set_userenv( "$borrowernumber", $userid, $cardnumber,
1862
                $firstname, $surname, $branchcode, $branchname, $flags ) unless $no_set_userenv;
1861
                $firstname, $surname, $branchcode, $branchname ) unless $no_set_userenv;
1863
            return 1, $cardnumber, $userid;
1862
            return 1, $cardnumber, $userid;
1864
        }
1863
        }
1865
    }
1864
    }
1866
    $sth =
1865
    $sth =
1867
      $dbh->prepare(
1866
      $dbh->prepare(
1868
        "select password,cardnumber,borrowernumber,userid,firstname,surname,borrowers.branchcode,branches.branchname,flags from borrowers join branches on borrowers.branchcode=branches.branchcode where cardnumber=?"
1867
        "select password,cardnumber,borrowernumber,userid,firstname,surname,borrowers.branchcode,branches.branchname from borrowers join branches on borrowers.branchcode=branches.branchcode where cardnumber=?"
1869
      );
1868
      );
1870
    $sth->execute($userid);
1869
    $sth->execute($userid);
1871
    if ( $sth->rows ) {
1870
    if ( $sth->rows ) {
1872
        my ( $stored_hash, $cardnumber, $borrowernumber, $userid, $firstname,
1871
        my ( $stored_hash, $cardnumber, $borrowernumber, $userid, $firstname,
1873
            $surname, $branchcode, $branchname, $flags )
1872
            $surname, $branchcode, $branchname )
1874
          = $sth->fetchrow;
1873
          = $sth->fetchrow;
1875
1874
1876
        if ( checkpw_hash( $password, $stored_hash ) ) {
1875
        if ( checkpw_hash( $password, $stored_hash ) ) {
1877
1876
1878
            C4::Context->set_userenv( $borrowernumber, $userid, $cardnumber,
1877
            C4::Context->set_userenv( $borrowernumber, $userid, $cardnumber,
1879
                $firstname, $surname, $branchcode, $branchname, $flags ) unless $no_set_userenv;
1878
                $firstname, $surname, $branchcode, $branchname ) unless $no_set_userenv;
1880
            return 1, $cardnumber, $userid;
1879
            return 1, $cardnumber, $userid;
1881
        }
1880
        }
1882
    }
1881
    }
Lines 1900-1946 sub checkpw_hash { Link Here
1900
1899
1901
=head2 getuserflags
1900
=head2 getuserflags
1902
1901
1903
    my $authflags = getuserflags($flags, $userid, [$dbh]);
1902
    my $authflags = getuserflags($userid);
1904
1903
1905
Translates integer flags into permissions strings hash.
1904
Translates integer flags into permissions strings hash.
1906
1905
1907
C<$flags> is the integer userflags value ( borrowers.userflags )
1908
C<$userid> is the members.userid, used for building subpermissions
1906
C<$userid> is the members.userid, used for building subpermissions
1909
C<$authflags> is a hashref of permissions
1910
1907
1911
=cut
1908
=cut
1912
1909
1913
sub getuserflags {
1910
sub getuserflags {
1914
    my $flags  = shift;
1911
    my $params = shift;
1915
    my $userid = shift;
1912
1916
    my $dbh    = @_ ? shift : C4::Context->dbh;
1913
    my $userid               = $params->{userid};
1914
    my $force_subpermissions = $params->{force_subpermissions};
1915
1916
    my $patron = Koha::Patrons->find( { userid => $userid } );
1917
    return unless $patron;
1918
1917
    my $userflags;
1919
    my $userflags;
1918
    {
1920
    my @permissions = Koha::Permissions->search( { parent => undef } );
1919
        # I don't want to do this, but if someone logs in as the database
1921
    foreach my $p (@permissions) {
1920
        # user, it would be preferable not to spam them to death with
1922
        my $patron_has = $p->patron_has( $patron->id );
1921
        # numeric warnings. So, we make $flags numeric.
1922
        no warnings 'numeric';
1923
        $flags += 0;
1924
    }
1925
    my $sth = $dbh->prepare("SELECT bit, flag, defaulton FROM userflags");
1926
    $sth->execute;
1927
1923
1928
    while ( my ( $bit, $flag, $defaulton ) = $sth->fetchrow ) {
1924
        if ( $patron_has && !$force_subpermissions ) {
1929
        if ( ( $flags & ( 2**$bit ) ) || $defaulton ) {
1925
            $userflags->{ $p->code() } = $p->patron_has( $patron->id );
1930
            $userflags->{$flag} = 1;
1931
        }
1926
        }
1932
        else {
1927
        else {
1933
            $userflags->{$flag} = 0;
1928
            my @subpermissions = $p->subpermissions;
1929
            foreach my $sp ( $p->subpermissions ) {
1930
                $userflags->{ $p->code } = $sp->patron_has( $patron->id );
1931
            }
1934
        }
1932
        }
1935
    }
1933
    }
1936
1934
1937
    # get subpermissions and merge with top-level permissions
1938
    my $user_subperms = get_user_subpermissions($userid);
1939
    foreach my $module ( keys %$user_subperms ) {
1940
        next if $userflags->{$module} == 1;    # user already has permission for everything in this module
1941
        $userflags->{$module} = $user_subperms->{$module};
1942
    }
1943
1944
    return $userflags;
1935
    return $userflags;
1945
}
1936
}
1946
1937
Lines 1972-1991 necessary to check borrowers.flags. Link Here
1972
sub get_user_subpermissions {
1963
sub get_user_subpermissions {
1973
    my $userid = shift;
1964
    my $userid = shift;
1974
1965
1975
    my $dbh = C4::Context->dbh;
1966
    return getuserflags( { userid => $userid, force_subpermissions => 1 } );
1976
    my $sth = $dbh->prepare( "SELECT flag, user_permissions.code
1977
                             FROM user_permissions
1978
                             JOIN permissions USING (module_bit, code)
1979
                             JOIN userflags ON (module_bit = bit)
1980
                             JOIN borrowers USING (borrowernumber)
1981
                             WHERE userid = ?" );
1982
    $sth->execute($userid);
1983
1984
    my $user_perms = {};
1985
    while ( my $perm = $sth->fetchrow_hashref ) {
1986
        $user_perms->{ $perm->{'flag'} }->{ $perm->{'code'} } = 1;
1987
    }
1988
    return $user_perms;
1989
}
1967
}
1990
1968
1991
=head2 get_all_subpermissions
1969
=head2 get_all_subpermissions
Lines 1993-2017 sub get_user_subpermissions { Link Here
1993
  my $perm_hashref = get_all_subpermissions();
1971
  my $perm_hashref = get_all_subpermissions();
1994
1972
1995
Returns a hashref of hashrefs defining all specific
1973
Returns a hashref of hashrefs defining all specific
1996
permissions currently defined.  The return value
1974
permissions currently defined.  The return value has
1997
has the same structure as that of C<get_user_subpermissions>,
1975
the same basic structure as that of C<get_user_subpermissions>
1998
except that the innermost hash value is the description
1999
of the subpermission.
2000
1976
2001
=cut
1977
=cut
2002
1978
2003
sub get_all_subpermissions {
1979
sub get_all_subpermissions {
2004
    my $dbh = C4::Context->dbh;
1980
    my $permissions;
2005
    my $sth = $dbh->prepare( "SELECT flag, code
1981
2006
                             FROM permissions
1982
    my @permissions = Koha::Permissions->search({ parent => undef });
2007
                             JOIN userflags ON (module_bit = bit)" );
1983
    foreach my $p ( @permissions ) {
2008
    $sth->execute();
1984
        foreach my $sp ( $p->subpermissions ) {
2009
1985
            $permissions->{ $p->code }->{ $sp->code } = 1;
2010
    my $all_perms = {};
1986
        }
2011
    while ( my $perm = $sth->fetchrow_hashref ) {
2012
        $all_perms->{ $perm->{'flag'} }->{ $perm->{'code'} } = 1;
2013
    }
1987
    }
2014
    return $all_perms;
1988
1989
    return $permissions;
2015
}
1990
}
2016
1991
2017
=head2 haspermission
1992
=head2 haspermission
Lines 2027-2036 Returns member's flags or 0 if a permission is not met. Link Here
2027
2002
2028
sub haspermission {
2003
sub haspermission {
2029
    my ( $userid, $flagsrequired ) = @_;
2004
    my ( $userid, $flagsrequired ) = @_;
2030
    my $sth = C4::Context->dbh->prepare("SELECT flags FROM borrowers WHERE userid=?");
2005
2031
    $sth->execute($userid);
2006
    my $flags = getuserflags( { userid => $userid } );
2032
    my $row = $sth->fetchrow();
2033
    my $flags = getuserflags( $row, $userid );
2034
    if ( $userid eq C4::Context->config('user') ) {
2007
    if ( $userid eq C4::Context->config('user') ) {
2035
2008
2036
        # Super User Account from /etc/koha.conf
2009
        # Super User Account from /etc/koha.conf
(-)a/C4/Budgets.pm (-2 / +1 lines)
Lines 971-978 sub CanUserUseBudget { Link Here
971
    return 0 unless ($borrower and $budget);
971
    return 0 unless ($borrower and $budget);
972
972
973
    if (not defined $userflags) {
973
    if (not defined $userflags) {
974
        $userflags = C4::Auth::getuserflags($borrower->{flags},
974
        $userflags = C4::Auth::getuserflags( { userid => $borrower->{userid} } );
975
            $borrower->{userid});
976
    }
975
    }
977
976
978
    unless ($userflags->{superlibrarian}
977
    unless ($userflags->{superlibrarian}
(-)a/Koha/Patron.pm (+50 lines)
Lines 34-39 use Koha::Old::Checkouts; Link Here
34
use Koha::Patron::Categories;
34
use Koha::Patron::Categories;
35
use Koha::Patron::HouseboundProfile;
35
use Koha::Patron::HouseboundProfile;
36
use Koha::Patron::HouseboundRole;
36
use Koha::Patron::HouseboundRole;
37
use Koha::Patron::Permissions;
37
use Koha::Patron::Images;
38
use Koha::Patron::Images;
38
use Koha::Patrons;
39
use Koha::Patrons;
39
use Koha::Virtualshelves;
40
use Koha::Virtualshelves;
Lines 1034-1039 sub generate_userid { Link Here
1034
1035
1035
=head2 Internal methods
1036
=head2 Internal methods
1036
1037
1038
=head3 has_permission
1039
1040
my $bool = $patron->has_permission( $permission_code );
1041
1042
=cut
1043
1044
sub has_permission {
1045
    my ( $self, $code ) = @_;
1046
1047
    return Koha::Patron::Permissions->find(
1048
        {
1049
            borrowernumber => $self->id,
1050
            code           => $code,
1051
        }
1052
    ) ? 1 : 0;
1053
}
1054
1055
=head3 set_permissions
1056
1057
$patron->set_permissions( { permissions => \@permissions } );
1058
1059
Given a list of permissions, set the patron to those and only those permissions
1060
1061
=cut
1062
1063
sub set_permissions {
1064
    my ( $self, $params ) = @_;
1065
1066
    my @permissions = @{ $params->{permissions} };
1067
1068
    $self->_result->result_source->schema->txn_do(
1069
        sub {
1070
            Koha::Patron::Permissions->search( { borrowernumber => $self->id } )
1071
              ->delete();
1072
1073
            Koha::Patron::Permission->new(
1074
                {
1075
                    borrowernumber => $self->id,
1076
                    code           => $_
1077
                }
1078
              )->store()
1079
              for @permissions;
1080
        }
1081
    );
1082
1083
    return $self;
1084
}
1085
1086
1037
=head3 _type
1087
=head3 _type
1038
1088
1039
=cut
1089
=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 43-48 use Koha::DateUtils qw(dt_from_string output_pref); Link Here
43
use Koha::Acquisition::Currencies;
43
use Koha::Acquisition::Currencies;
44
use Koha::Patron::Categories;
44
use Koha::Patron::Categories;
45
use Koha::Patrons;
45
use Koha::Patrons;
46
use Koha::Patron::Permissions;
46
use Koha::Caches;
47
use Koha::Caches;
47
use Koha::Config::SysPrefs;
48
use Koha::Config::SysPrefs;
48
use Koha::Illrequest::Config;
49
use Koha::Illrequest::Config;
Lines 414-434 if ( C4::Context->preference('WebBasedSelfCheck') Link Here
414
      and C4::Context->preference('AutoSelfCheckAllowed')
415
      and C4::Context->preference('AutoSelfCheckAllowed')
415
) {
416
) {
416
    my $userid = C4::Context->preference('AutoSelfCheckID');
417
    my $userid = C4::Context->preference('AutoSelfCheckID');
417
    my $all_permissions = C4::Auth::get_user_subpermissions( $userid );
418
    my $patron = Koha::Patrons->find( { userid => $userid } );
418
    my ( $has_self_checkout_perm, $has_other_permissions );
419
    my $has_self_checkout_perm = $patron->has_permission('self_checkout');
419
    while ( my ( $module, $permissions ) = each %$all_permissions ) {
420
    my $has_other_permissions = Koha::Patron::Permissions->search(
420
        if ( $module eq 'self_check' ) {
421
        {
421
            while ( my ( $permission, $flag ) = each %$permissions ) {
422
            borrowernumber => $patron->id,
422
                if ( $permission eq 'self_checkout_module' ) {
423
            -not           => { code => 'self_checkout' }
423
                    $has_self_checkout_perm = 1;
424
                } else {
425
                    $has_other_permissions = 1;
426
                }
427
            }
428
        } else {
429
            $has_other_permissions = 1;
430
        }
424
        }
431
    }
425
    )->count();
432
    $template->param(
426
    $template->param(
433
        AutoSelfCheckPatronDoesNotHaveSelfCheckPerm => not ( $has_self_checkout_perm ),
427
        AutoSelfCheckPatronDoesNotHaveSelfCheckPerm => not ( $has_self_checkout_perm ),
434
        AutoSelfCheckPatronHasTooManyPerm => $has_other_permissions,
428
        AutoSelfCheckPatronHasTooManyPerm => $has_other_permissions,
(-)a/koha-tmpl/intranet-tmpl/prog/en/includes/members-toolbar.inc (-1 / +1 lines)
Lines 51-57 Link Here
51
                    <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>
51
                    <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>
52
                [% END %]
52
                [% END %]
53
                [% IF ( CAN_user_permissions ) %]
53
                [% IF ( CAN_user_permissions ) %]
54
                    <li><a id="patronflags" href="/cgi-bin/koha/members/member-flags.pl?member=[% patron.borrowernumber %]">Set permissions</a></li>
54
                    <li><a id="patronflags" href="/cgi-bin/koha/members/member-flags.pl?borrowernumber=[% patron.borrowernumber %]">Set permissions</a></li>
55
                [% ELSE %]
55
                [% ELSE %]
56
                    <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>
56
                    <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>
57
                [% END %]
57
                [% 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' -%]<span>Access to all librarian functions</span>
3
    [%- CASE 'superlibrarian' -%]<span>Access to all librarian functions</span>
4
    [%- CASE 'circulate' -%]<span>Check out and check in items</span>
4
    [%- CASE 'circulate' -%]<span>Check out and check in items</span>
Lines 22-32 Link Here
22
    [%- CASE 'clubs' -%]<span>Patron clubs</span>
22
    [%- CASE 'clubs' -%]<span>Patron clubs</span>
23
    [%- CASE 'ill' -%]<span>Create and modify Interlibrary loan requests</span>
23
    [%- CASE 'ill' -%]<span>Create and modify Interlibrary loan requests</span>
24
    [%- CASE 'self_check' -%]<span>Self check modules</span>
24
    [%- CASE 'self_check' -%]<span>Self check modules</span>
25
    [%- END -%]
26
[%- END -%]
27
28
[%- BLOCK sub_permissions -%]
29
  [% SWITCH name %]
30
    [%- CASE 'circulate_remaining_permissions' -%]<span>Remaining circulation permissions</span>
25
    [%- CASE 'circulate_remaining_permissions' -%]<span>Remaining circulation permissions</span>
31
    [%- CASE 'force_checkout' -%]<span>Force checkout if a limitation exists</span>
26
    [%- CASE 'force_checkout' -%]<span>Force checkout if a limitation exists</span>
32
    [%- CASE 'manage_restrictions' -%]<span>Manage restrictions for accounts</span>
27
    [%- CASE 'manage_restrictions' -%]<span>Manage restrictions for accounts</span>
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/members/member-flags.tt (-66 / +101 lines)
Lines 6-11 Link Here
6
<title>Koha &rsaquo; Patrons &rsaquo; Set permissions for [% patron.surname %], [% patron.firstname %]</title>
6
<title>Koha &rsaquo; Patrons &rsaquo; Set permissions for [% patron.surname %], [% patron.firstname %]</title>
7
[% Asset.css("css/treeview/jquery.treeview.css") %]
7
[% Asset.css("css/treeview/jquery.treeview.css") %]
8
[% INCLUDE 'doc-head-close.inc' %]
8
[% INCLUDE 'doc-head-close.inc' %]
9
<link href="[% interface %]/lib/jquery/plugins/treetable/stylesheets/jquery.treetable.css" rel="stylesheet" type="text/css" />
10
<script type="text/javascript" src="[% interface %]/lib/jquery/plugins/treetable/jquery.treetable.js"></script>
11
<script type="text/javascript">
12
    $(document).ready(function() {
13
        $('#permissions-table').treetable({
14
            expandable: true
15
        });
16
17
        // Expand any parent permissions with children that are set
18
        $('input[name="permission"][checked="checked"]').each(function() {
19
            var id = $(this).data('parent');
20
            if ( id ) {
21
                $('#permissions-table').treetable('expandNode', id );
22
            }
23
        });
24
25
        // Behavior that occurs when a checkbox is changed
26
        $('input[name="permission"]').on('change', function(){
27
            var id = $(this).closest('tr').attr('id');
28
29
            if ( id != 'superlibrarian' ) { // Standard behavior
30
                if ( $(this).attr('checked') ) {
31
                    $('#permissions-table').treetable('expandNode', id );
32
                    $(`input[data-parent=${id}]`).attr('checked', 'checked' );
33
                } else {
34
                    $(`input[data-parent=${id}]`).attr('checked', null );
35
                }
36
            } else { // Superlibrarian behavior
37
                if ( $(this).attr('checked') ) {
38
                    $(`input[name="permission"][value!="superlibrarian"]`).attr('checked', null ).attr('disabled', 'disabled' );
39
                } else {
40
                    $(`input[name="permission"][value!="superlibrarian"]`).attr('disabled', null );
41
                }
42
            }
43
        });
44
    });
45
</script>
9
</head>
46
</head>
10
47
11
<body id="pat_member-flags" class="pat">
48
<body id="pat_member-flags" class="pat">
Lines 15-88 Link Here
15
<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> &rsaquo; <a href="/cgi-bin/koha/members/members-home.pl">Patrons</a>  &rsaquo; Set permissions for [% patron.surname %], [% patron.firstname %]</div>
52
<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> &rsaquo; <a href="/cgi-bin/koha/members/members-home.pl">Patrons</a>  &rsaquo; Set permissions for [% patron.surname %], [% patron.firstname %]</div>
16
53
17
<div id="doc3" class="yui-t2">
54
<div id="doc3" class="yui-t2">
18
   
55
    <div id="bd">
19
   <div id="bd">
56
        <div id="yui-main">
20
	<div id="yui-main">
57
        <div class="yui-b">
21
	<div class="yui-b">
58
            [% INCLUDE 'members-toolbar.inc' %]
22
[% INCLUDE 'members-toolbar.inc' %]
59
23
60
            <form method="post" action="/cgi-bin/koha/members/member-flags.pl">
24
<form method="post" action="/cgi-bin/koha/members/member-flags.pl">
61
                <input type="hidden" name="csrf_token" value="[% csrf_token %]" />
25
    <input type="hidden" name="csrf_token" value="[% csrf_token %]" />
62
                <input type="hidden" name="borrowernumber" id="borrowernumber" value="[% borrowernumber %]" />
26
    <input type="hidden" name="member" id="borrowernumber" value="[% patron.borrowernumber %]" />
63
                <input type="hidden" name="set_permissions" value="1" />
27
    <input type="hidden" name="newflags" value="1" />
64
                <h1>Set permissions for [% surname %], [% firstname %]</h1>
28
    <h1>Set permissions for [% patron.surname %], [% patron.firstname %]</h1>
65
29
    <!-- <ul id="permissionstree"><li class="root">All privileges<ul> -->
66
                <table id="permissions-table">
30
    <ul id="permissionstree" class="treeview-grey">
67
                    <tr data-tt-id="superlibrarian" id="superlibrarian">
31
        <!-- <li class="folder-close">One level down<ul> -->
68
                        <td>
32
    [% FOREACH loo IN loop %]
69
                            [% IF patron.has_permission( p.code ) %]
33
        [% IF ( loo.expand ) %]
70
                                <input type="checkbox" name="permission" value="superlibrarian" checked="checked"/>
34
        <li class="open">
71
                            [% ELSE %]
35
        [% ELSE %]
72
                                <input type="checkbox" name="permission" value="superlibrarian"/>
36
        <li>
73
                            [% END %]
37
        [% END %]
74
                        </td>
38
			[% IF ( loo.checked ) %]
75
                        <td>superlibrarian</td>
39
          [% IF disable_superlibrarian_privs && loo.bit == 0 %]
76
                        <td><span class="permissiondesc">[% PROCESS permissions name='superlibrarian' %]</span>
40
              <input type="checkbox" disabled="disabled" class="flag parent superlib" id="flag-[% loo.bit %]_disabled" name="flag" value="[% loo.flag %]" checked="checked" title="The system preference ProtectSuperlibrarianPrivileges is enabled" />
77
                    </tr>
41
              <input type="hidden" id="flag-[% loo.bit %]" name="flag" value="[% loo.flag %]" >
78
                    [% FOREACH p IN permissions %]
42
          [% ELSE %]
79
                        [% NEXT IF p.code == 'superlibrarian' %]
43
              <input type="checkbox" class="flag parent" id="flag-[% loo.bit %]" name="flag" value="[% loo.flag %]" checked="checked" />
80
                        <tr data-tt-id="[% p.code %]" id="[% p.code %]">
44
          [% END %]
81
                            <td>
45
			[% ELSE %]
82
                                [% IF patron.has_permission( p.code ) %]
46
          [% IF disable_superlibrarian_privs && loo.bit == 0 %]
83
                                    <input type="checkbox" name="permission" value="[% p.code %]" checked="checked"/>
47
              <input type="checkbox" disabled="disabled" class="flag parent" id="flag-[% loo.bit %]_disabled" name="flag" value="[% loo.flag %]" title="The system preference ProtectSuperlibrarianPrivileges is enabled" />
84
                                [% ELSE %]
48
          [% ELSE %]
85
                                    <input type="checkbox" name="permission" value="[% p.code %]"/>
49
              <input type="checkbox" class="flag parent" id="flag-[% loo.bit %]" name="flag" value="[% loo.flag %]" />
86
                                [% END %]
50
          [% END %]
87
                            </td>
51
			[% END %]
88
                            <td>[% p.code %]</td>
52
                <label class="permissioncode" for="flag-[% loo.bit %]">[% loo.flag %]</label>
89
                            <td><span class="permissiondesc">[% PROCESS permissions name=p.code %]</span>
53
                <span class="permissiondesc">[% PROCESS main_permissions name=loo.flag %]</span>
90
                        </tr>
54
            [% IF ( loo.sub_perm_loop ) %]
91
55
                <ul id="flag-[% loo.bit %]-children">
92
                        [% FOREACH s IN p.subpermissions() %]
56
                    [% FOREACH sub_perm_loo IN loo.sub_perm_loop %]
93
                            <tr data-tt-parent-id="[% p.code %]" data-tt-id="[% s.code %]" id="[% s.code %]">
57
                        <li>
94
                                <td>
58
			            [% IF ( sub_perm_loo.checked ) %]
95
                                    [% IF patron.has_permission( s.code ) %]
59
                            <input type="checkbox" class="flag child" id="[% sub_perm_loo.id %]" name="flag" value="[% sub_perm_loo.perm %]" checked="checked" />
96
                                        <input type="checkbox" name="permission" value="[% s.code %]" checked="checked" data-parent="[% p.code %]"/>
60
			            [% ELSE %]
97
                                    [% ELSE %]
61
                            <input type="checkbox" class="flag child" id="[% sub_perm_loo.id %]" name="flag" value="[% sub_perm_loo.perm %]" />
98
                                        <input type="checkbox" name="permission" value="[% s.code %]" data-parent="[% p.code %]"/>
62
			            [% END %]
99
                                    [% END %]
63
                    <label class="permissioncode" for="[% sub_perm_loo.id %]">[% sub_perm_loo.code %]</label>
100
                                </td>
64
                             <span class="permissiondesc">[% PROCESS sub_permissions name=sub_perm_loo.code %]</span>
101
                                <td>[% s.code %]</td>
65
                        </li>
102
                                <td><span class="permissiondesc">[% PROCESS permissions name=s.code %]</span>
103
                            </tr>
104
                        [% END %]
66
                    [% END %]
105
                    [% END %]
67
                </ul>
106
                </table>
68
                </li>
69
            [% ELSE %]
70
                </li>
71
			[% END %]
72
    [% END %]
73
        <!-- </ul></li> -->
74
    <!-- </ul></li></ul> -->
75
    </ul>
76
77
<fieldset class="action"><input type="submit" value="Save" /> <a class="cancel" href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% patron.borrowernumber %]">Cancel</a></fieldset>
78
79
</form>
80
</div>
81
</div>
82
107
83
<div class="yui-b">
108
                <input type="hidden" name="borrowernumber" value="[% borrowernumber %]" />
84
[% INCLUDE 'circ-menu.inc' %]
109
85
</div>
110
                <fieldset class="action">
111
                    <input type="submit" value="Save" />
112
                    <a class="cancel" href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% borrowernumber %]">Cancel</a>
113
                </fieldset>
114
            </form>
115
        </div>
116
    </div>
117
118
    <div class="yui-b">
119
    [% INCLUDE 'circ-menu.inc' %]
120
    </div>
86
</div>
121
</div>
87
122
88
[% MACRO jsinclude BLOCK %]
123
[% MACRO jsinclude BLOCK %]
(-)a/members/member-flags.pl (-159 / +88 lines)
Lines 1-208 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;
23
use C4::Output;
11
use C4::Auth qw(:DEFAULT :EditPermissions);
24
use C4::Auth;
12
use C4::Context;
25
use C4::Context;
13
use C4::Members;
26
use C4::Members;
14
use C4::Members::Attributes qw(GetBorrowerAttributes);
27
use C4::Members::Attributes qw(GetBorrowerAttributes);
15
#use C4::Acquisitions;
16
28
17
use Koha::Patron::Categories;
18
use Koha::Patrons;
29
use Koha::Patrons;
30
use Koha::Patron::Images;
31
use Koha::Patron::Categories;
19
32
20
use C4::Output;
21
use Koha::Token;
33
use Koha::Token;
34
use Koha::Permissions;
22
35
23
my $input = new CGI;
36
my $input = new CGI;
24
37
25
my $flagsrequired = { permissions => 1 };
38
my $flagsrequired = { permissions => 1 };
26
my $member=$input->param('member');
39
my $borrowernumber = $input->param('borrowernumber');
27
my $patron = Koha::Patrons->find( $member );
40
28
unless ( $patron ) {
41
my $patron = Koha::Patrons->find($borrowernumber);
29
    print $input->redirect("/cgi-bin/koha/circ/circulation.pl?borrowernumber=$member");
30
    exit;
31
}
32
42
33
my $category_type = $patron->category->category_type;
43
my $category_type = $patron->category->category_type;
34
my $bor = $patron->unblessed;
44
my $bor           = $patron->unblessed;
35
if( $category_type eq 'S' )  { # FIXME Is this really needed?
45
if ( $category_type eq 'S' ) {
36
    $flagsrequired->{'staffaccess'} = 1;
46
    $flagsrequired->{'staffaccess'} = 1;
37
}
47
}
38
my ($template, $loggedinuser, $cookie) = get_template_and_user({
48
my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
49
    {
39
        template_name   => "members/member-flags.tt",
50
        template_name   => "members/member-flags.tt",
40
        query           => $input,
51
        query           => $input,
41
        type            => "intranet",
52
        type            => "intranet",
42
        authnotrequired => 0,
53
        authnotrequired => 0,
43
        flagsrequired   => $flagsrequired,
54
        flagsrequired   => $flagsrequired,
44
        debug           => 1,
55
        debug           => 1,
45
});
56
    }
57
);
46
58
47
my $logged_in_user = Koha::Patrons->find( $loggedinuser ) or die "Not logged in";
59
my $logged_in_user = Koha::Patrons->find( $loggedinuser ) or die "Not logged in";
48
output_and_exit_if_error( $input, $cookie, $template, { module => 'members', logged_in_user => $logged_in_user, current_patron => $patron } );
60
output_and_exit_if_error( $input, $cookie, $template, { module => 'members', logged_in_user => $logged_in_user, current_patron => $patron } );
49
61
50
my %member2;
62
if ( $input->param('set_permissions') ) { # update permissions
51
$member2{'borrowernumber'}=$member;
52
53
if ($input->param('newflags')) {
54
63
55
    die "Wrong CSRF token"
64
    die "Wrong CSRF token"
56
        unless Koha::Token->new->check_csrf({
65
      unless Koha::Token->new->check_csrf(
66
        {
57
            session_id => scalar $input->cookie('CGISESSID'),
67
            session_id => scalar $input->cookie('CGISESSID'),
58
            token  => scalar $input->param('csrf_token'),
68
            token      => scalar $input->param('csrf_token'),
59
        });
69
        }
70
      );
60
71
72
    my @permissions = $input->multi_param('permission');
61
73
62
    my $dbh=C4::Context->dbh();
74
    $patron->set_permissions( { permissions => \@permissions } );
63
75
64
    my @perms = $input->multi_param('flag');
76
    print $input->redirect(
65
    my %all_module_perms = ();
77
        "/cgi-bin/koha/members/moremember.pl?borrowernumber=$borrowernumber");
66
    my %sub_perms = ();
78
}
67
    foreach my $perm (@perms) {
79
else { # fetch for display
68
        if ($perm !~ /:/) {
80
    my $permissions = Koha::Permissions->search( { parent => undef } );
69
            $all_module_perms{$perm} = 1;
81
    $template->param(
70
        } else {
82
        patron      => $patron,
71
            my ($module, $sub_perm) = split /:/, $perm, 2;
83
        permissions => $permissions,
72
            push @{ $sub_perms{$module} }, $sub_perm;
84
    );
73
        }
74
    }
75
85
76
    # construct flags
86
    # Patron details boilerplate for patron related templates
77
    my $module_flags = 0;
87
    if ( $category_type eq 'C' ) {
78
    my $sth=$dbh->prepare("SELECT bit,flag FROM userflags ORDER BY bit");
88
        my $patron_categories =
79
    $sth->execute();
89
          Koha::Patron::Categories->search_limited( { category_type => 'A' },
80
    while (my ($bit, $flag) = $sth->fetchrow_array) {
90
            { order_by => ['categorycode'] } );
81
        if (exists $all_module_perms{$flag}) {
91
        $template->param( 'CATCODE_MULTI' => 1 )
82
            $module_flags += 2**$bit;
92
          if $patron_categories->count > 1;
83
        }
93
        $template->param( 'catcode' => $patron_categories->next )
94
          if $patron_categories->count == 1;
84
    }
95
    }
85
    
86
    $sth = $dbh->prepare("UPDATE borrowers SET flags=? WHERE borrowernumber=?");
87
    my $old_flags = $patron->flags // 0;
88
    if( ( $old_flags == 1 || $module_flags == 1 ) &&
89
      $old_flags != $module_flags ) {
90
        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
91
    }
92
    $sth->execute($module_flags, $member);
93
94
    # deal with subpermissions
95
    $sth = $dbh->prepare("DELETE FROM user_permissions WHERE borrowernumber = ?");
96
    $sth->execute($member); 
97
    $sth = $dbh->prepare("INSERT INTO user_permissions (borrowernumber, module_bit, code)
98
                        SELECT ?, bit, ?
99
                        FROM userflags
100
                        WHERE flag = ?");
101
    foreach my $module (keys %sub_perms) {
102
        next if exists $all_module_perms{$module};
103
        foreach my $sub_perm (@{ $sub_perms{$module} }) {
104
            $sth->execute($member, $sub_perm, $module);
105
        }
106
    }
107
    
108
    print $input->redirect("/cgi-bin/koha/members/moremember.pl?borrowernumber=$member");
109
} else {
110
111
    my $accessflags;
112
    my $dbh = C4::Context->dbh();
113
    # FIXME This needs to be improved to avoid doing the same query
114
    my $sth = $dbh->prepare("select bit,flag from userflags");
115
    $sth->execute;
116
    while ( my ( $bit, $flag ) = $sth->fetchrow ) {
117
        if ( $bor->{flags} && $bor->{flags} & 2**$bit ) {
118
            $accessflags->{$flag} = 1;
119
        }
120
    }
121
122
    my $all_perms  = get_all_subpermissions();
123
    my $user_perms = get_user_subpermissions($bor->{'userid'});
124
    $sth = $dbh->prepare("SELECT bit, flag FROM userflags ORDER BY bit");
125
    $sth->execute;
126
    my @loop;
127
96
128
    while (my ($bit, $flag) = $sth->fetchrow) {
97
    $template->param( adultborrower => 1 ) if ( $category_type =~ /^(A|I)$/ );
129
        my $checked='';
98
    $template->param( picture       => 1 ) if $patron->image;
130
        if ($accessflags->{$flag}) {
131
            $checked= 1;
132
        }
133
99
134
        my %row = ( bit => $bit,
100
    if ( C4::Context->preference('ExtendedPatronAttributes') ) {
135
            flag => $flag,
101
        my $attributes = GetBorrowerAttributes( $bor->{'borrowernumber'} );
136
            checked => $checked,
102
        $template->param(
103
            ExtendedPatronAttributes => 1,
104
            extendedattributes       => $attributes
137
        );
105
        );
138
139
        my @sub_perm_loop = ();
140
        my $expand_parent = 0;
141
        if ($checked) {
142
            if (exists $all_perms->{$flag}) {
143
                $expand_parent = 1;
144
                foreach my $sub_perm (sort keys %{ $all_perms->{$flag} }) {
145
                    push @sub_perm_loop, {
146
                        id => "${flag}_$sub_perm",
147
                        perm => "$flag:$sub_perm",
148
                        code => $sub_perm,
149
                        checked => 1
150
                    };
151
                }
152
            }
153
        } else {
154
            if (exists $user_perms->{$flag}) {
155
                $expand_parent = 1;
156
                # put selected ones first
157
                foreach my $sub_perm (sort keys %{ $user_perms->{$flag} }) {
158
                    push @sub_perm_loop, {
159
                        id => "${flag}_$sub_perm",
160
                        perm => "$flag:$sub_perm",
161
                        code => $sub_perm,
162
                        checked => 1
163
                    };
164
                }
165
            }
166
            # then ones not selected
167
            if (exists $all_perms->{$flag}) {
168
                foreach my $sub_perm (sort keys %{ $all_perms->{$flag} }) {
169
                    push @sub_perm_loop, {
170
                        id => "${flag}_$sub_perm",
171
                        perm => "$flag:$sub_perm",
172
                        code => $sub_perm,
173
                        checked => 0
174
                    } unless exists $user_perms->{$flag} and exists $user_perms->{$flag}->{$sub_perm};
175
                }
176
            }
177
        }
178
        $row{expand} = $expand_parent;
179
        if ($#sub_perm_loop > -1) {
180
            $row{sub_perm_loop} = \@sub_perm_loop;
181
        }
182
        push @loop, \%row;
183
    }
184
185
    if ( $patron->is_child ) {
186
        my $patron_categories = Koha::Patron::Categories->search_limited({ category_type => 'A' }, {order_by => ['categorycode']});
187
        $template->param( 'CATCODE_MULTI' => 1) if $patron_categories->count > 1;
188
        $template->param( 'catcode' => $patron_categories->next->categorycode )  if $patron_categories->count == 1;
189
    }
106
    }
190
107
191
if (C4::Context->preference('ExtendedPatronAttributes')) {
192
    my $attributes = GetBorrowerAttributes($bor->{'borrowernumber'});
193
    $template->param(
108
    $template->param(
194
        ExtendedPatronAttributes => 1,
109
        borrowernumber => $bor->{'borrowernumber'},
195
        extendedattributes => $attributes
110
        cardnumber     => $bor->{'cardnumber'},
111
        surname        => $bor->{'surname'},
112
        firstname      => $bor->{'firstname'},
113
        othernames     => $bor->{'othernames'},
114
        categorycode   => $bor->{'categorycode'},
115
        category_type  => $category_type,
116
        categoryname   => $bor->{'description'},
117
        address        => $bor->{address},
118
        address2       => $bor->{'address2'},
119
        streettype     => $bor->{streettype},
120
        city           => $bor->{'city'},
121
        state          => $bor->{'state'},
122
        zipcode        => $bor->{'zipcode'},
123
        country        => $bor->{'country'},
124
        phone          => $bor->{'phone'},
125
        phonepro       => $bor->{'phonepro'},
126
        mobile         => $bor->{'mobile'},
127
        email          => $bor->{'email'},
128
        emailpro       => $bor->{'emailpro'},
129
        branchcode     => $bor->{'branchcode'},
130
        is_child       => ( $category_type eq 'C' ),
131
        RoutingSerials => C4::Context->preference('RoutingSerials'),
132
        csrf_token     => Koha::Token->new->generate_csrf(
133
            { session_id => scalar $input->cookie('CGISESSID'), }
134
        ),
196
    );
135
    );
197
}
198
199
$template->param(
200
    patron         => $patron,
201
    loop           => \@loop,
202
    csrf_token =>
203
        Koha::Token->new->generate_csrf( { session_id => scalar $input->cookie('CGISESSID'), } ),
204
    disable_superlibrarian_privs => C4::Context->preference('ProtectSuperlibrarianPrivileges') ? !C4::Context->IsSuperLibrarian : 0,
205
);
206
136
207
    output_html_with_http_headers $input, $cookie, $template->output;
137
    output_html_with_http_headers $input, $cookie, $template->output;
208
138
209
- 

Return to bug 20813