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

(-)a/C4/Auth.pm (-29 / +48 lines)
Lines 23-28 use Digest::MD5 qw(md5_base64); Link Here
23
use JSON qw/encode_json/;
23
use JSON qw/encode_json/;
24
use URI::Escape;
24
use URI::Escape;
25
use CGI::Session;
25
use CGI::Session;
26
use Scalar::Util qw(blessed);
27
use Try::Tiny;
26
28
27
require Exporter;
29
require Exporter;
28
use C4::Context;
30
use C4::Context;
Lines 226-232 sub get_template_and_user { Link Here
226
        # We are going to use the $flags returned by checkauth
228
        # We are going to use the $flags returned by checkauth
227
        # to create the template's parameters that will indicate
229
        # to create the template's parameters that will indicate
228
        # which menus the user can access.
230
        # which menus the user can access.
229
        if ( $flags && $flags->{superlibrarian} == 1 ) {
231
        if ( $flags && $flags->{superlibrarian} ) {
230
            $template->param( CAN_user_circulate        => 1 );
232
            $template->param( CAN_user_circulate        => 1 );
231
            $template->param( CAN_user_catalogue        => 1 );
233
            $template->param( CAN_user_catalogue        => 1 );
232
            $template->param( CAN_user_parameters       => 1 );
234
            $template->param( CAN_user_parameters       => 1 );
Lines 254-264 sub get_template_and_user { Link Here
254
256
255
        if ($flags) {
257
        if ($flags) {
256
            foreach my $module ( keys %$all_perms ) {
258
            foreach my $module ( keys %$all_perms ) {
257
                if ( defined($flags->{$module}) && $flags->{$module} == 1 ) {
259
                if ( ref( $flags->{$module} ) ) {
258
                    foreach my $subperm ( keys %{ $all_perms->{$module} } ) {
259
                        $template->param( "CAN_user_${module}_${subperm}" => 1 );
260
                    }
261
                } elsif ( ref( $flags->{$module} ) ) {
262
                    foreach my $subperm ( keys %{ $flags->{$module} } ) {
260
                    foreach my $subperm ( keys %{ $flags->{$module} } ) {
263
                        $template->param( "CAN_user_${module}_${subperm}" => 1 );
261
                        $template->param( "CAN_user_${module}_${subperm}" => 1 );
264
                    }
262
                    }
Lines 990-996 sub checkauth { Link Here
990
988
991
                if ( $return == 1 ) {
989
                if ( $return == 1 ) {
992
                    my $select = "
990
                    my $select = "
993
                    SELECT borrowernumber, firstname, surname, flags, borrowers.branchcode,
991
                    SELECT borrowernumber, firstname, surname, borrowers.branchcode,
994
                    branches.branchname    as branchname,
992
                    branches.branchname    as branchname,
995
                    branches.branchprinter as branchprinter,
993
                    branches.branchprinter as branchprinter,
996
                    email
994
                    email
Lines 1013-1019 sub checkauth { Link Here
1013
                        }
1011
                        }
1014
                    }
1012
                    }
1015
                    if ( $sth->rows ) {
1013
                    if ( $sth->rows ) {
1016
                        ( $borrowernumber, $firstname, $surname, $userflags,
1014
                        ( $borrowernumber, $firstname, $surname,
1017
                            $branchcode, $branchname, $branchprinter, $emailaddress ) = $sth->fetchrow;
1015
                            $branchcode, $branchname, $branchprinter, $emailaddress ) = $sth->fetchrow;
1018
                        $debug and print STDERR "AUTH_3 results: " .
1016
                        $debug and print STDERR "AUTH_3 results: " .
1019
                          "$cardnumber,$borrowernumber,$userid,$firstname,$surname,$userflags,$branchcode,$emailaddress\n";
1017
                          "$cardnumber,$borrowernumber,$userid,$firstname,$surname,$userflags,$branchcode,$emailaddress\n";
Lines 1739-1745 sub checkpw_internal { Link Here
1739
1737
1740
    my $sth =
1738
    my $sth =
1741
      $dbh->prepare(
1739
      $dbh->prepare(
1742
        "select password,cardnumber,borrowernumber,userid,firstname,surname,borrowers.branchcode,branches.branchname,flags from borrowers join branches on borrowers.branchcode=branches.branchcode where userid=?"
1740
        "select password,cardnumber,borrowernumber,userid,firstname,surname,borrowers.branchcode,branches.branchname from borrowers join branches on borrowers.branchcode=branches.branchcode where userid=?"
1743
      );
1741
      );
1744
    $sth->execute($userid);
1742
    $sth->execute($userid);
1745
    if ( $sth->rows ) {
1743
    if ( $sth->rows ) {
Lines 1756-1773 sub checkpw_internal { Link Here
1756
    }
1754
    }
1757
    $sth =
1755
    $sth =
1758
      $dbh->prepare(
1756
      $dbh->prepare(
1759
        "select password,cardnumber,borrowernumber,userid,firstname,surname,borrowers.branchcode,branches.branchname,flags from borrowers join branches on borrowers.branchcode=branches.branchcode where cardnumber=?"
1757
        "select password,cardnumber,borrowernumber,userid,firstname,surname,borrowers.branchcode,branches.branchname from borrowers join branches on borrowers.branchcode=branches.branchcode where cardnumber=?"
1760
      );
1758
      );
1761
    $sth->execute($userid);
1759
    $sth->execute($userid);
1762
    if ( $sth->rows ) {
1760
    if ( $sth->rows ) {
1763
        my ( $stored_hash, $cardnumber, $borrowernumber, $userid, $firstname,
1761
        my ( $stored_hash, $cardnumber, $borrowernumber, $userid, $firstname,
1764
            $surname, $branchcode, $branchname, $flags )
1762
            $surname, $branchcode, $branchname )
1765
          = $sth->fetchrow;
1763
          = $sth->fetchrow;
1766
1764
1767
        if ( checkpw_hash( $password, $stored_hash ) ) {
1765
        if ( checkpw_hash( $password, $stored_hash ) ) {
1768
1766
1769
            C4::Context->set_userenv( $borrowernumber, $userid, $cardnumber,
1767
            C4::Context->set_userenv( $borrowernumber, $userid, $cardnumber,
1770
                $firstname, $surname, $branchcode, $branchname, $flags );
1768
                $firstname, $surname, $branchcode, $branchname );
1771
            return 1, $cardnumber, $userid;
1769
            return 1, $cardnumber, $userid;
1772
        }
1770
        }
1773
    }
1771
    }
Lines 1799-1804 sub checkpw_hash { Link Here
1799
}
1797
}
1800
1798
1801
=head2 getuserflags
1799
=head2 getuserflags
1800
@DEPRECATED, USE THE Koha::Auth::PermissionManager
1802
1801
1803
    my $authflags = getuserflags($flags, $userid, [$dbh]);
1802
    my $authflags = getuserflags($flags, $userid, [$dbh]);
1804
1803
Lines 1811-1816 C<$authflags> is a hashref of permissions Link Here
1811
=cut
1810
=cut
1812
1811
1813
sub getuserflags {
1812
sub getuserflags {
1813
    #@DEPRECATED, USE THE Koha::Auth::PermissionManager
1814
    my $flags  = shift;
1814
    my $flags  = shift;
1815
    my $userid = shift;
1815
    my $userid = shift;
1816
    my $dbh    = @_ ? shift : C4::Context->dbh;
1816
    my $dbh    = @_ ? shift : C4::Context->dbh;
Lines 1822-1827 sub getuserflags { Link Here
1822
        no warnings 'numeric';
1822
        no warnings 'numeric';
1823
        $flags += 0;
1823
        $flags += 0;
1824
    }
1824
    }
1825
    return get_user_subpermissions($userid);
1826
1827
    #@DEPRECATED, USE THE Koha::Auth::PermissionManager
1825
    my $sth = $dbh->prepare("SELECT bit, flag, defaulton FROM userflags");
1828
    my $sth = $dbh->prepare("SELECT bit, flag, defaulton FROM userflags");
1826
    $sth->execute;
1829
    $sth->execute;
1827
1830
Lines 1845-1851 sub getuserflags { Link Here
1845
}
1848
}
1846
1849
1847
=head2 get_user_subpermissions
1850
=head2 get_user_subpermissions
1848
1851
@DEPRECATED, USE THE Koha::Auth::PermissionManager
1849
  $user_perm_hashref = get_user_subpermissions($userid);
1852
  $user_perm_hashref = get_user_subpermissions($userid);
1850
1853
1851
Given the userid (note, not the borrowernumber) of a staff user,
1854
Given the userid (note, not the borrowernumber) of a staff user,
Lines 1870-1894 necessary to check borrowers.flags. Link Here
1870
=cut
1873
=cut
1871
1874
1872
sub get_user_subpermissions {
1875
sub get_user_subpermissions {
1876
    #@DEPRECATED, USE THE Koha::Auth::PermissionManager
1873
    my $userid = shift;
1877
    my $userid = shift;
1874
1878
1875
    my $dbh = C4::Context->dbh;
1879
    use Koha::Auth::PermissionManager;
1876
    my $sth = $dbh->prepare( "SELECT flag, user_permissions.code
1880
    my $permissionManager = Koha::Auth::PermissionManager->new();
1877
                             FROM user_permissions
1881
    my $borrowerPermissions = $permissionManager->getBorrowerPermissions($userid); #Prefetch all related tables.
1878
                             JOIN permissions USING (module_bit, code)
1879
                             JOIN userflags ON (module_bit = bit)
1880
                             JOIN borrowers USING (borrowernumber)
1881
                             WHERE userid = ?" );
1882
    $sth->execute($userid);
1883
1884
    my $user_perms = {};
1882
    my $user_perms = {};
1885
    while ( my $perm = $sth->fetchrow_hashref ) {
1883
    foreach my $perm ( @$borrowerPermissions ) {
1886
        $user_perms->{ $perm->{'flag'} }->{ $perm->{'code'} } = 1;
1884
        $user_perms->{ $perm->getPermissionModule->module }->{ $perm->getPermission->code } = 1;
1887
    }
1885
    }
1886
1888
    return $user_perms;
1887
    return $user_perms;
1889
}
1888
}
1890
1889
1891
=head2 get_all_subpermissions
1890
=head2 get_all_subpermissions
1891
@DEPRECATED, USE THE Koha::Auth::PermissionManager
1892
1892
1893
  my $perm_hashref = get_all_subpermissions();
1893
  my $perm_hashref = get_all_subpermissions();
1894
1894
Lines 1901-1906 of the subpermission. Link Here
1901
=cut
1901
=cut
1902
1902
1903
sub get_all_subpermissions {
1903
sub get_all_subpermissions {
1904
    #@DEPRECATED, USE THE Koha::Auth::PermissionManager
1905
    use Koha::Auth::PermissionManager;
1906
    my $permissionManager = Koha::Auth::PermissionManager->new();
1907
    my $all_permissions = $permissionManager->listKohaPermissionsAsHASH();
1908
    foreach my $module ( keys %$all_permissions ) {
1909
        my $permissionModule = $all_permissions->{$module};
1910
        foreach my $code (keys %{$permissionModule->{permissions}}) {
1911
            my $permission = $permissionModule->{permissions}->{$code};
1912
            $all_permissions->{$module}->{$code} = $permission->{'description'};
1913
        }
1914
    }
1915
    return $all_permissions;
1916
1917
    #@DEPRECATED, USE THE Koha::Auth::PermissionManager
1904
    my $dbh = C4::Context->dbh;
1918
    my $dbh = C4::Context->dbh;
1905
    my $sth = $dbh->prepare( "SELECT flag, code, description
1919
    my $sth = $dbh->prepare( "SELECT flag, code, description
1906
                             FROM permissions
1920
                             FROM permissions
Lines 1915-1920 sub get_all_subpermissions { Link Here
1915
}
1929
}
1916
1930
1917
=head2 haspermission
1931
=head2 haspermission
1932
@DEPRECATED, USE THE Koha::Auth::PermissionManager
1918
1933
1919
  $flags = ($userid, $flagsrequired);
1934
  $flags = ($userid, $flagsrequired);
1920
1935
Lines 1926-1936 Returns member's flags or 0 if a permission is not met. Link Here
1926
=cut
1941
=cut
1927
1942
1928
sub haspermission {
1943
sub haspermission {
1944
    #@DEPRECATED, USE THE Koha::Auth::PermissionManager
1929
    my ( $userid, $flagsrequired ) = @_;
1945
    my ( $userid, $flagsrequired ) = @_;
1930
    my $sth = C4::Context->dbh->prepare("SELECT flags FROM borrowers WHERE userid=?");
1946
1931
    $sth->execute($userid);
1947
    my $flags = getuserflags( undef, $userid );
1932
    my $row = $sth->fetchrow();
1948
    #Sanitate 1 to * because we no longer have 1's from the koha.borrowers.flags.
1933
    my $flags = getuserflags( $row, $userid );
1949
    foreach my $module (%$flagsrequired) {
1950
        $flagsrequired->{$module} = '*' if $flagsrequired->{$module} && $flagsrequired->{$module} eq '1';
1951
    }
1952
1934
    if ( $userid eq C4::Context->config('user') ) {
1953
    if ( $userid eq C4::Context->config('user') ) {
1935
1954
1936
        # Super User Account from /etc/koha.conf
1955
        # Super User Account from /etc/koha.conf
Lines 1947-1953 sub haspermission { Link Here
1947
    foreach my $module ( keys %$flagsrequired ) {
1966
    foreach my $module ( keys %$flagsrequired ) {
1948
        my $subperm = $flagsrequired->{$module};
1967
        my $subperm = $flagsrequired->{$module};
1949
        if ( $subperm eq '*' ) {
1968
        if ( $subperm eq '*' ) {
1950
            return 0 unless ( $flags->{$module} == 1 or ref( $flags->{$module} ) );
1969
            return 0 unless ( ref( $flags->{$module} ) );
1951
        } else {
1970
        } else {
1952
            return 0 unless (
1971
            return 0 unless (
1953
                ( defined $flags->{$module} and
1972
                ( defined $flags->{$module} and
(-)a/C4/Members.pm (-10 / +1 lines)
Lines 230-246 sub GetMemberDetails { Link Here
230
    $borrower->{'amountoutstanding'} = $amount;
230
    $borrower->{'amountoutstanding'} = $amount;
231
    # FIXME - patronflags calls GetMemberAccountRecords... just have patronflags return $amount
231
    # FIXME - patronflags calls GetMemberAccountRecords... just have patronflags return $amount
232
    my $flags = patronflags( $borrower);
232
    my $flags = patronflags( $borrower);
233
    my $accessflagshash;
234
233
235
    $sth = $dbh->prepare("select bit,flag from userflags");
234
    $borrower->{'flags'}     = $flags; #Is this the flags-column? @DEPRECATED!
236
    $sth->execute;
237
    while ( my ( $bit, $flag ) = $sth->fetchrow ) {
238
        if ( $borrower->{'flags'} && $borrower->{'flags'} & 2**$bit ) {
239
            $accessflagshash->{$flag} = 1;
240
        }
241
    }
242
    $borrower->{'flags'}     = $flags;
243
    $borrower->{'authflags'} = $accessflagshash;
244
235
245
    # For the purposes of making templates easier, we'll define a
236
    # For the purposes of making templates easier, we'll define a
246
    # 'showname' which is the alternate form the user's first name if 
237
    # 'showname' which is the alternate form the user's first name if 
(-)a/Koha/Auth/BorrowerPermission.pm (+221 lines)
Line 0 Link Here
1
package Koha::Auth::BorrowerPermission;
2
3
# Copyright 2015 Vaara-kirjastot
4
#
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>.
19
20
use Modern::Perl;
21
use Scalar::Util qw(blessed);
22
23
use Koha::Auth::BorrowerPermissions;
24
use Koha::Auth::PermissionModules;
25
use Koha::Auth::Permissions;
26
use Koha::Borrowers;
27
28
use Koha::Exception::BadParameter;
29
30
use base qw(Koha::Object);
31
32
sub type {
33
    return 'BorrowerPermission';
34
}
35
sub object_class {
36
    return 'Koha::Auth::BorrowerPermission';
37
}
38
39
=head NAME
40
41
Koha::Auth::BorrowerPermission
42
43
=head SYNOPSIS
44
45
Object representation of a Permission given to a Borrower.
46
47
=head new
48
49
    my $borrowerPermission = Koha::Auth::BorrowerPermission->new({
50
                                borrowernumber => 12,
51
                                permission_module_id => 2,
52
                                permission => $Koha::Auth::Permission,
53
    });
54
    my $borrowerPermission = Koha::Auth::BorrowerPermission->new({
55
                                borrower => $Koha::Borrower,
56
                                permissionModule => $Koha::Auth::PermissionModule,
57
                                permission_id => 22,
58
    });
59
60
Remember to ->store() the returned object to persist it in the DB.
61
@PARAM1 HASHRef of constructor parameters:
62
            MANDATORY keys:
63
                borrower or borrowernumber
64
                permissionModule or permission_module_id
65
                permission or permission_id
66
            Values can be either Koha::Object derivatives or their respective DB primary keys
67
@RETURNS Koha::Auth::BorrowerPermission
68
=cut
69
70
sub new {
71
    my ($class, $params) = @_;
72
73
    _validateParams($params);
74
75
    #Check for duplicates, and update existing permission if available.
76
    my $self = Koha::Auth::BorrowerPermissions->find({borrowernumber => $params->{borrower}->borrowernumber,
77
                                                      permission_module_id => $params->{permissionModule}->permission_module_id,
78
                                                      permission_id => $params->{permission}->permission_id,
79
                                                    });
80
    $self = $class->SUPER::new() unless $self;
81
    $self->{params} = $params;
82
    $self->set({borrowernumber => $self->getBorrower()->borrowernumber,
83
                permission_id => $self->getPermission()->permission_id,
84
                permission_module_id => $self->getPermissionModule()->permission_module_id
85
                });
86
    return $self;
87
}
88
89
=head getBorrower
90
91
    my $borrower = $borrowerPermission->getBorrower();
92
93
@RETURNS Koha::Borrower
94
=cut
95
96
sub getBorrower {
97
    my ($self) = @_;
98
99
    unless ($self->{params}->{borrower}) {
100
        my $dbix_borrower = $self->_result()->borrower;
101
        my $borrower = Koha::Borrower->_new_from_dbic($dbix_borrower);
102
        $self->{params}->{borrower} = $borrower;
103
    }
104
    return $self->{params}->{borrower};
105
}
106
107
=head setBorrower
108
109
    my $borrowerPermission = $borrowerPermission->setBorrower( $borrower );
110
111
Set the Borrower.
112
When setting the DB is automatically updated as well.
113
@PARAM1 Koha::Borrower, set the given Borrower to this BorrowerPermission.
114
@RETURNS Koha::Auth::BorrowerPermission,
115
=cut
116
117
sub setBorrower {
118
    my ($self, $borrower) = @_;
119
120
    unless (blessed($borrower) && $borrower->isa('Koha::Borrower')) {
121
        Koha::Exception::BadParameter->throw(error => __PACKAGE__."->setPermissionModule():> Given parameter '\\$borrower' is not a Koha::Borrower-object!");
122
    }
123
    $self->{params}->{borrower} = $borrower;
124
    $self->set({borrowernumber => $borrower->borrowernumber()});
125
    $self->store();
126
}
127
128
=head getPermissionModule
129
130
    my $permissionModule = $borrowerPermission->getPermissionModule();
131
132
@RETURNS Koha::Auth::PermissionModule
133
=cut
134
135
sub getPermissionModule {
136
    my ($self) = @_;
137
138
    unless ($self->{params}->{permissionModule}) {
139
        my $dbix_object = $self->_result()->permission_module;
140
        my $object = Koha::Auth::PermissionModule->_new_from_dbic($dbix_object);
141
        $self->{params}->{permissionModule} = $object;
142
    }
143
    return $self->{params}->{permissionModule};
144
}
145
146
=head setPermissionModule
147
148
    my $borrowerPermission = $borrowerPermission->setPermissionModule( $permissionModule );
149
150
Set the PermissionModule.
151
When setting the DB is automatically updated as well.
152
@PARAM1 Koha::Auth::PermissionModule, set the given PermissionModule as
153
                                      the PermissionModule of this BorrowePermission.
154
@RETURNS Koha::Auth::BorrowerPermission,
155
=cut
156
157
sub setPermissionModule {
158
    my ($self, $permissionModule) = @_;
159
160
    unless (blessed($permissionModule) && $permissionModule->isa('Koha::Auth::PermissionModule')) {
161
        Koha::Exception::BadParameter->throw(error => __PACKAGE__."->setPermissionModule():> Given parameter '\$permissionModule' is not a Koha::Auth::PermissionModule-object!");
162
    }
163
    $self->{params}->{permissionModule} = $permissionModule;
164
    $self->set({permission_module_id => $permissionModule->permission_module_id()});
165
    $self->store();
166
}
167
168
=head getPermission
169
170
    my $permission = $borrowerPermission->getPermission();
171
172
@RETURNS Koha::Auth::Permission
173
=cut
174
175
sub getPermission {
176
    my ($self) = @_;
177
178
    unless ($self->{params}->{permission}) {
179
        my $dbix_object = $self->_result()->permission;
180
        my $object = Koha::Auth::Permission->_new_from_dbic($dbix_object);
181
        $self->{params}->{permission} = $object;
182
    }
183
    return $self->{params}->{permission};
184
}
185
186
=head setPermission
187
188
    my $borrowerPermission = $borrowerPermission->setPermission( $permission );
189
190
Set the Permission.
191
When setting the DB is automatically updated as well.
192
@PARAM1 Koha::Auth::Permission, set the given Permission to this BorrowerPermission.
193
@RETURNS Koha::Auth::BorrowerPermission,
194
=cut
195
196
sub setPermission {
197
    my ($self, $permission) = @_;
198
199
    unless (blessed($permission) && $permission->isa('Koha::Auth::Permission')) {
200
        Koha::Exception::BadParameter->throw(error => __PACKAGE__."->setPermission():> Given parameter '\$permission' is not a Koha::Auth::Permission-object!");
201
    }
202
    $self->{params}->{permission} = $permission;
203
    $self->set({permission_id => $permission->permission_id()});
204
    $self->store();
205
}
206
207
=head _validateParams
208
209
Validates the given constructor parameters and fetches the Koha::Objects when needed.
210
211
=cut
212
213
sub _validateParams {
214
    my ($params) = @_;
215
216
    $params->{permissionModule} = Koha::Auth::PermissionModules->cast( $params->{permission_module_id} || $params->{permissionModule} );
217
    $params->{permission} = Koha::Auth::Permissions->cast( $params->{permission_id} || $params->{permission} );
218
    $params->{borrower} = Koha::Borrowers->cast(  $params->{borrowernumber} || $params->{borrower}  );
219
}
220
221
1;
(-)a/Koha/Auth/BorrowerPermissions.pm (+38 lines)
Line 0 Link Here
1
package Koha::Auth::BorrowerPermissions;
2
3
# Copyright 2015 Vaara-kirjastot
4
#
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>.
19
20
use Modern::Perl;
21
use Scalar::Util qw(blessed);
22
23
use Koha::Auth::BorrowerPermission;
24
25
use base qw(Koha::Objects);
26
27
sub type {
28
    return 'BorrowerPermission';
29
}
30
sub object_class {
31
    return 'Koha::Auth::BorrowerPermission';
32
}
33
34
sub _get_castable_unique_columns {
35
    return ['borrower_permission_id'];
36
}
37
38
1;
(-)a/Koha/Auth/Permission.pm (+60 lines)
Line 0 Link Here
1
package Koha::Auth::Permission;
2
3
# Copyright 2015 Vaara-kirjastot
4
#
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>.
19
20
use Modern::Perl;
21
22
use Koha::Auth::Permissions;
23
24
use Koha::Exception::BadParameter;
25
26
use base qw(Koha::Object);
27
28
sub type {
29
    return 'Permission';
30
}
31
sub object_class {
32
    return 'Koha::Auth::Permission';
33
}
34
35
sub new {
36
    my ($class, $params) = @_;
37
38
    _validateParams($params);
39
40
    my $self = Koha::Auth::Permissions->find({code => $params->{code}, module => $params->{module}});
41
    $self = $class->SUPER::new() unless $self;
42
    $self->set($params);
43
    return $self;
44
}
45
46
sub _validateParams {
47
    my ($params) = @_;
48
49
    unless ($params->{description} && length $params->{description} > 0) {
50
        Koha::Exception::BadParameter->throw(error => "Koha::Auth::Permission->new():> Parameter 'description' isn't defined or is empty.");
51
    }
52
    unless ($params->{module} && length $params->{module} > 0) {
53
        Koha::Exception::BadParameter->throw(error => "Koha::Auth::Permission->new():> Parameter 'module' isn't defined or is empty.");
54
    }
55
    unless ($params->{code} && length $params->{code} > 0) {
56
        Koha::Exception::BadParameter->throw(error => "Koha::Auth::Permission->new():> Parameter 'code' isn't defined or is empty.");
57
    }
58
}
59
60
1;
(-)a/Koha/Auth/PermissionManager.pm (+529 lines)
Line 0 Link Here
1
package Koha::Auth::PermissionManager;
2
3
# Copyright 2015 Vaara-kirjastot
4
#
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>.
19
20
use Modern::Perl;
21
use Scalar::Util qw(blessed);
22
use Try::Tiny;
23
24
use Koha::Database;
25
use Koha::Auth::Permission;
26
use Koha::Auth::PermissionModule;
27
use Koha::Auth::BorrowerPermission;
28
use Koha::Auth::BorrowerPermissions;
29
30
use Koha::Exception::BadParameter;
31
use Koha::Exception::NoPermission;
32
use Koha::Exception::UnknownProgramState;
33
34
=head NAME Koha::Auth::PermissionManager
35
36
=head SYNOPSIS
37
38
PermissionManager is a gateway to all Koha's permission operations. You shouldn't
39
need to touch individual Koha::Auth::Permission* -objects.
40
41
=head USAGE
42
43
See t::db_dependent::Koha::Auth::PermissionManager.t
44
45
=head new
46
47
    my $permissionManager = Koha::Auth::PermissionManager->new();
48
49
Instantiates a new PemissionManager.
50
51
In the future this Manager can easily be improved with Koha::Cache.
52
53
=cut
54
55
sub new {
56
    my ($class, $self) = @_;
57
    $self = {} unless $self;
58
    bless($self, $class);
59
    return $self;
60
}
61
62
=head addPermission
63
64
    $permissionManager->addPermission({ code => "end_remaining_hostilities",
65
                                        description => "All your base are belong to us",
66
    });
67
68
INSERTs or UPDATEs a Koha::Auth::Permission to the Koha DB.
69
Very handy when introducing new features that need new permissions.
70
71
@PARAM1 Koha::Auth::Permission
72
        or
73
        HASHRef of all the koha.permissions-table columns set.
74
@THROWS Koha::Exception::BadParameter
75
=cut
76
77
sub addPermission {
78
    my ($self, $permission) = @_;
79
    if (blessed($permission) && not($permission->isa('Koha::Auth::Permission'))) {
80
        Koha::Exception::BadParameter->throw(error => __PACKAGE__."::addPermission():> Given permission is not a Koha::Auth::Permission-object.");
81
    }
82
    elsif (ref($permission) eq 'HASH') {
83
        $permission = Koha::Auth::Permission->new($permission);
84
    }
85
    unless (blessed($permission)) {
86
        Koha::Exception::BadParameter->throw(error => __PACKAGE__."::addPermission():> Given permission '$permission' is not of a recognized format.");
87
    }
88
89
    $permission->store();
90
}
91
92
=head getPermission
93
94
    my $permission = $permissionManager->getPermission('edit_items'); #koha.permissions.code
95
    my $permission = $permissionManager->getPermission(12);           #koha.permissions.permission_id
96
    my $permission = $permissionManager->getPermission($dbix_Permission); #Koha::Schema::Result::Permission
97
98
@RETURNS Koha::Auth::Permission-object
99
@THROWS Koha::Exception::BadParameter
100
=cut
101
102
sub getPermission {
103
    my ($self, $permissionId) = @_;
104
105
    try {
106
        return Koha::Auth::Permissions->cast($permissionId);
107
    } catch {
108
        if (blessed($_) && $_->isa('Koha::Exception::UnknownObject')) {
109
            #We catch this type of exception, and simply return nothing, since there was no such Permission
110
        }
111
        else {
112
            die $_;
113
        }
114
    };
115
}
116
117
=head delPermission
118
119
    $permissionManager->delPermission('edit_items'); #koha.permissions.code
120
    $permissionManager->delPermission(12);           #koha.permissions.permission_id
121
    $permissionManager->delPermission($dbix_Permission); #Koha::Schema::Result::Permission
122
    $permissionManager->delPermission($permission); #Koha::Auth::Permission
123
124
@THROWS Koha::Exception::UnknownObject if no given object in DB to delete.
125
=cut
126
127
sub delPermission {
128
    my ($self, $permissionId) = @_;
129
130
    my $permission = Koha::Auth::Permissions->cast($permissionId);
131
    $permission->delete();
132
}
133
134
=head addPermissionModule
135
136
    $permissionManager->addPermissionModule({   module => "scotland",
137
                                                description => "William Wallace is my hero!",
138
    });
139
140
INSERTs or UPDATEs a Koha::Auth::PermissionModule to the Koha DB.
141
Very handy when introducing new features that need new permissions.
142
143
@PARAM1 Koha::Auth::PermissionModule
144
        or
145
        HASHRef of all the koha.permission_modules-table columns set.
146
@THROWS Koha::Exception::BadParameter
147
=cut
148
149
sub addPermissionModule {
150
    my ($self, $permissionModule) = @_;
151
    if (blessed($permissionModule) && not($permissionModule->isa('Koha::Auth::PermissionModule'))) {
152
        Koha::Exception::BadParameter->throw(error => __PACKAGE__."::addPermission():> Given permissionModule is not a Koha::Auth::PermissionModule-object.");
153
    }
154
    elsif (ref($permissionModule) eq 'HASH') {
155
        $permissionModule = Koha::Auth::PermissionModule->new($permissionModule);
156
    }
157
    unless (blessed($permissionModule)) {
158
        Koha::Exception::BadParameter->throw(error => __PACKAGE__."::addPermission():> Given permissionModule '$permissionModule' is not of a recognized format.");
159
    }
160
161
    $permissionModule->store();
162
}
163
164
=head getPermissionModule
165
166
    my $permission = $permissionManager->getPermissionModule('cataloguing'); #koha.permission_modules.module
167
    my $permission = $permissionManager->getPermission(12);           #koha.permission_modules.permission_module_id
168
    my $permission = $permissionManager->getPermission($dbix_Permission); #Koha::Schema::Result::PermissionModule
169
170
@RETURNS Koha::Auth::PermissionModule-object
171
@THROWS Koha::Exception::BadParameter
172
=cut
173
174
sub getPermissionModule {
175
    my ($self, $permissionModuleId) = @_;
176
177
    try {
178
        return Koha::Auth::PermissionModules->cast($permissionModuleId);
179
    } catch {
180
        if (blessed($_) && $_->isa('Koha::Exception::UnknownObject')) {
181
            #We catch this type of exception, and simply return nothing, since there was no such PermissionModule
182
        }
183
        else {
184
            die $_;
185
        }
186
    };
187
}
188
189
=head delPermissionModule
190
191
    $permissionManager->delPermissionModule('cataloguing'); #koha.permission_modules.module
192
    $permissionManager->delPermissionModule(12);           #koha.permission_modules.permission_module_id
193
    $permissionManager->delPermissionModule($dbix_Permission); #Koha::Schema::Result::PermissionModule
194
    $permissionManager->delPermissionModule($permissionModule); #Koha::Auth::PermissionModule
195
196
@THROWS Koha::Exception::UnknownObject if no given object in DB to delete.
197
@THROWS Koha::Exception::BadParameter
198
=cut
199
200
sub delPermissionModule {
201
    my ($self, $permissionModuleId) = @_;
202
203
    my $permissionModule = Koha::Auth::PermissionModules->cast($permissionModuleId);
204
    $permissionModule->delete();
205
}
206
207
=head getKohaPermissions
208
209
    my $kohaPermissions = $permissionManager->getKohaPermissions();
210
211
Gets all the PermissionModules and their related Permissions in one huge DB query.
212
@RETURNS ARRAYRef of Koha::Auth::PermissionModule-objects with related objects prefetched.
213
=cut
214
215
sub getKohaPermissions {
216
    my ($self) = @_;
217
218
    my $schema = Koha::Database->new()->schema();
219
    my @permissionModules = $schema->resultset('PermissionModule')->search(
220
                                                            {},
221
                                                            {   join => ['permissions'],
222
                                                                prefetch => ['permissions'],
223
                                                                order_by => ['me.module', 'permissions.code'],
224
                                                            }
225
                                                        );
226
    #Cast DBIx to Koha::Object.
227
    for (my $i=0 ; $i<scalar(@permissionModules) ; $i++) {
228
        $permissionModules[$i] = Koha::Auth::PermissionModules->cast( $permissionModules[$i] );
229
    }
230
    return \@permissionModules;
231
}
232
233
=head listKohaPermissionsAsHASH
234
235
@RETURNS HASHRef, a HASH-representation of all the permissions and permission modules
236
in Koha. Eg:
237
                 {
238
                    acquisitions => {
239
                        description => "Yada yada",
240
                        module => 'acquisitions',
241
                        permission_module_id => 21,
242
                        permissions => {
243
                            budget_add_del => {
244
                                description => "More yada yada",
245
                                code => 'budget_add_del',
246
                                permission_id => 12,
247
                            }
248
                            budget_manage => {
249
                                description => "Yaawn yadayawn",
250
                                ...
251
                            }
252
                            ...
253
                        }
254
                    },
255
                    borrowers => {
256
                        ...
257
                    },
258
                    ...
259
                 }
260
=cut
261
262
sub listKohaPermissionsAsHASH {
263
    my ($self) = @_;
264
    my $permissionModules = $self->getKohaPermissions();
265
    my $hash = {};
266
267
    foreach my $permissionModule (sort {$a->module cmp $b->module} @$permissionModules) {
268
        my $module = $permissionModule->module;
269
270
        $hash->{$module} = $permissionModule->_result->{'_column_data'};
271
        $hash->{$module}->{permissions} = {};
272
273
        my $permissions = $permissionModule->getPermissions;
274
        foreach my $permission (sort {$a->code cmp $b->code} @$permissions) {
275
            my $code = $permission->code;
276
277
            $hash->{$module}->{permissions}->{$code} = $permission->_result->{'_column_data'};
278
        }
279
    }
280
    return $hash;
281
}
282
283
=head getBorrowerPermissions
284
285
    my $borrowerPermissions = $permissionManager->getBorrowerPermissions($borrower);     #Koha::Borrower
286
    my $borrowerPermissions = $permissionManager->getBorrowerPermissions($dbix_borrower);#Koha::Schema::Resultset::Borrower
287
    my $borrowerPermissions = $permissionManager->getBorrowerPermissions(1012);          #koha.borrowers.borrowernumber
288
    my $borrowerPermissions = $permissionManager->getBorrowerPermissions('167A0012311'); #koha.borrowers.cardnumber
289
    my $borrowerPermissions = $permissionManager->getBorrowerPermissions('bill69');      #koha.borrowers.userid
290
291
@RETURNS ARRAYRef of Koha::Auth::BorrowerPermission-objects
292
@THROWS Koha::Exception::UnknownObject, if the given $borrower cannot be casted to Koha::Borrower
293
@THROWS Koha::Exception::BadParameter
294
=cut
295
296
sub getBorrowerPermissions {
297
    my ($self, $borrower) = @_;
298
    $borrower = Koha::Borrowers->cast($borrower);
299
300
    if ($borrower->isSuperuser()) {
301
        return [Koha::Auth::BorrowerPermission->new({borrower => $borrower, permission => 'superlibrarian', permissionModule => 'superlibrarian'})];
302
    }
303
304
    my $schema = Koha::Database->new()->schema();
305
306
    my @borrowerPermissions = $schema->resultset('BorrowerPermission')->search({borrowernumber => $borrower->borrowernumber},
307
                                                                               {join => ['permission','permission_module'],
308
                                                                                prefetch => ['permission','permission_module'],
309
                                                                                order_by => ['permission_module.module', 'permission.code']});
310
    for (my $i=0 ; $i<scalar(@borrowerPermissions) ; $i++) {
311
        $borrowerPermissions[$i] = Koha::Auth::BorrowerPermissions->cast($borrowerPermissions[$i]);
312
    }
313
    return \@borrowerPermissions;
314
}
315
316
=head grantPermissions
317
318
    $permissionManager->grantPermissions($borrower, {borrowers => 'view_borrowers',
319
                                                     reserveforothers => ['place_holds'],
320
                                                     tools => ['edit_news', 'edit_notices'],
321
                                                     acquisition => {
322
                                                       budger_add_del => 1,
323
                                                       budget_modify => 1,
324
                                                     },
325
                                                    }
326
                                        );
327
328
Adds a group of permissions to one user.
329
@THROWS Koha::Exception::UnknownObject, if the given $borrower cannot be casted to Koha::Borrower
330
@THROWS Koha::Exception::BadParameter
331
=cut
332
333
sub grantPermissions {
334
    my ($self, $borrower, $permissionsGroup) = @_;
335
336
    while (my ($module, $permissions) = each(%$permissionsGroup)) {
337
        if (ref($permissions) eq 'ARRAY') {
338
            foreach my $permission (@$permissions) {
339
                $self->grantPermission($borrower, $module, $permission);
340
            }
341
        }
342
        elsif (ref($permissions) eq 'HASH') {
343
            foreach my $permission (keys(%$permissions)) {
344
                $self->grantPermission($borrower, $module, $permission);
345
            }
346
        }
347
        else {
348
            $self->grantPermission($borrower, $module, $permissions);
349
        }
350
    }
351
}
352
353
=head grantPermission
354
355
    my $borrowerPermission = $permissionManager->grantPermission($borrower, $permissionModule, $permission);
356
357
@PARAM1 Koha::Borrower or
358
        Scalar koha.borrowers.borrowernumber or
359
        Scalar koha.borrowers.cardnumber or
360
        Scalar koha.borrowers.userid or
361
@PARAM2 Koha::Auth::PermissionModule-object
362
        Scalar koha.permission_modules.module or
363
        Scalar koha.permission_modules.permission_module_id
364
@PARAM3 Koha::Auth::Permission-object or
365
        Scalar koha.permissions.code or
366
        Scalar koha.permissions.permission_id
367
@RETURNS Koha::Auth::BorrowerPermissions
368
@THROWS Koha::Exception::UnknownObject, if the given parameters cannot be casted to Koha::Object-subclasses
369
@THROWS Koha::Exception::BadParameter
370
=cut
371
372
sub grantPermission {
373
    my ($self, $borrower, $permissionModule, $permission) = @_;
374
375
    my $borrowerPermission = Koha::Auth::BorrowerPermission->new({borrower => $borrower, permissionModule => $permissionModule, permission => $permission});
376
    $borrowerPermission->store();
377
    return $borrowerPermission;
378
}
379
380
=head
381
382
    $permissionManager->revokePermission($borrower, $permissionModule, $permission);
383
384
Revokes a Permission from a Borrower
385
same parameters as grantPermission()
386
387
@THROWS Koha::Exception::UnknownObject, if the given parameters cannot be casted to Koha::Object-subclasses
388
@THROWS Koha::Exception::BadParameter
389
=cut
390
391
sub revokePermission {
392
    my ($self, $borrower, $permissionModule, $permission) = @_;
393
394
    my $borrowerPermission = Koha::Auth::BorrowerPermission->new({borrower => $borrower, permissionModule => $permissionModule, permission => $permission});
395
    $borrowerPermission->delete();
396
    return $borrowerPermission;
397
}
398
399
=head revokeAllPermissions
400
401
    $permissionManager->revokeAllPermissions($borrower);
402
403
@THROWS Koha::Exception::UnknownObject, if the given $borrower cannot be casted to Koha::Borrower
404
@THROWS Koha::Exception::BadParameter
405
=cut
406
407
sub revokeAllPermissions {
408
    my ($self, $borrower) = @_;
409
    $borrower = Koha::Borrowers->cast($borrower);
410
411
    my $schema = Koha::Database->new()->schema();
412
    $schema->resultset('BorrowerPermission')->search({borrowernumber => $borrower->borrowernumber})->delete_all();
413
}
414
415
=head hasPermissions
416
417
See if the given Borrower has all of the given permissions
418
@PARAM1 Koha::Borrower, or any of the koha.borrowers-table's unique identifiers.
419
@PARAM2 HASHRef of needed permissions,
420
    {
421
        borrowers => 'view_borrowers',
422
        reserveforothers => ['place_holds'],
423
        tools => ['edit_news', 'edit_notices'],
424
        acquisition => {
425
            budger_add_del => 1,
426
            budget_modify => 1,
427
        },
428
        coursereserves => '*', #Means any Permission under this PermissionModule
429
   }
430
@RETURNS see hasPermission()
431
@THROWS Koha::Exception::NoPermission, from hasPermission() if permission is missing.
432
=cut
433
434
sub hasPermissions {
435
    my ($self, $borrower, $requiredPermissions) = @_;
436
437
    foreach my $module (keys(%$requiredPermissions)) {
438
        my $permissions = $requiredPermissions->{$module};
439
        if (ref($permissions) eq 'ARRAY') {
440
            foreach my $permission (@$permissions) {
441
                $self->hasPermission($borrower, $module, $permission);
442
            }
443
        }
444
        elsif (ref($permissions) eq 'HASH') {
445
            foreach my $permission (keys(%$permissions)) {
446
                $self->hasPermission($borrower, $module, $permission);
447
            }
448
        }
449
        else {
450
            $self->hasPermission($borrower, $module, $permissions);
451
        }
452
    }
453
    return 1;
454
}
455
456
=head hasPermission
457
458
See if the given Borrower has the given permission
459
@PARAM1 Koha::Borrower, or any of the koha.borrowers-table's unique identifiers.
460
@PARAM2 Koha::Auth::PermissionModule or koha.permission_modules.module or koha.permission_modules.permission_module_id
461
@PARAM3 Koha::Auth::Permission or koha.permissions.code or koha.permissions.permission_id or
462
                               '*' if we just need any permission for the given PermissionModule.
463
@RETURNS Integer, 1 if permission check succeeded.
464
                  2 if user is a superlibrarian.
465
                  Catch Exceptions if permission check fails.
466
@THROWS Koha::Exception::NoPermission, if Borrower is missing the permission.
467
                                       Exception tells which permission is missing.
468
@THROWS Koha::Exception::UnknownObject, if the given parameters cannot be casted to Koha::Object-subclasses
469
@THROWS Koha::Exception::BadParameter
470
=cut
471
472
sub hasPermission {
473
    my ($self, $borrower, $permissionModule, $permission) = @_;
474
475
    $borrower = Koha::Borrowers->cast($borrower);
476
    $permissionModule = Koha::Auth::PermissionModules->cast($permissionModule);
477
    $permission = Koha::Auth::Permissions->cast($permission) unless $permission eq '*';
478
479
    my $error;
480
    if ($permission eq '*') {
481
        my $borrowerPermission = Koha::Auth::BorrowerPermissions->search({borrowernumber => $borrower->borrowernumber,
482
                                                 permission_module_id => $permissionModule->permission_module_id,
483
                                                })->next();
484
        return 1 if ($borrowerPermission);
485
        $error = "Borrower '".$borrower->borrowernumber."' lacks any permission under permission module '".$permissionModule->module."'.";
486
    }
487
    else {
488
        my $borrowerPermission = Koha::Auth::BorrowerPermissions->search({borrowernumber => $borrower->borrowernumber,
489
                                                 permission_module_id => $permissionModule->permission_module_id,
490
                                                 permission_id => $permission->permission_id,
491
                                                })->next();
492
        return 1 if ($borrowerPermission);
493
        $error = "Borrower '".$borrower->borrowernumber."' lacks permission module '".$permissionModule->module."' and permission '".$permission->code."'.";
494
    }
495
496
    return 2 if not($permissionModule->module eq 'superlibrarian') && $self->_isSuperuser($borrower);
497
    return 2 if not($permissionModule->module eq 'superlibrarian') && $self->_isSuperlibrarian($borrower);
498
    Koha::Exception::NoPermission->throw(error => $error);
499
}
500
501
sub _isSuperuser {
502
    my ($self, $borrower) = @_;
503
    $borrower = Koha::Borrowers->cast($borrower);
504
505
    if ( $borrower->userid && $borrower->userid eq C4::Context->config('user') ) {
506
        return 1;
507
    }
508
    elsif ( $borrower->userid && $borrower->userid eq 'demo' && C4::Context->config('demo') ) {
509
        return 1;
510
    }
511
    return 0;
512
}
513
514
sub _isSuperlibrarian {
515
    my ($self, $borrower) = @_;
516
517
    try {
518
        return $self->hasPermission($borrower, 'superlibrarian', 'superlibrarian');
519
    } catch {
520
        if (blessed($_) && $_->isa('Koha::Exception::NoPermission')) {
521
            return 0;
522
        }
523
        else {
524
            die $_;
525
        }
526
    };
527
}
528
529
1;
(-)a/Koha/Auth/PermissionModule.pm (+78 lines)
Line 0 Link Here
1
package Koha::Auth::PermissionModule;
2
3
# Copyright 2015 Vaara-kirjastot
4
#
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>.
19
20
use Modern::Perl;
21
22
use Koha::Auth::PermissionModules;
23
24
use Koha::Exception::BadParameter;
25
26
use base qw(Koha::Object);
27
28
sub type {
29
    return 'PermissionModule';
30
}
31
sub object_class {
32
    return 'Koha::Auth::PermissionModule';
33
}
34
35
sub new {
36
    my ($class, $params) = @_;
37
38
    _validateParams($params);
39
40
    my $self = Koha::Auth::PermissionModules->find({module => $params->{module}});
41
    $self = $class->SUPER::new() unless $self;
42
    $self->set($params);
43
    return $self;
44
}
45
46
sub _validateParams {
47
    my ($params) = @_;
48
49
    unless ($params->{description} && length $params->{description} > 0) {
50
        Koha::Exception::BadParameter->throw(error => "Koha::Auth::Permission->new():> Parameter 'description' isn't defined or is empty.");
51
    }
52
    unless ($params->{module} && length $params->{module} > 0) {
53
        Koha::Exception::BadParameter->throw(error => "Koha::Auth::Permission->new():> Parameter 'module' isn't defined or is empty.");
54
    }
55
}
56
57
=head getPermissions
58
59
    my $permissions = $permissionModule->getPermissions();
60
61
@RETURNS List of Koha::Auth::Permission-objects
62
=cut
63
64
sub getPermissions {
65
    my ($self) = @_;
66
67
    unless ($self->{params}->{permissions}) {
68
        $self->{params}->{permissions} = [];
69
        my @dbix_objects = $self->_result()->permissions;
70
        foreach my $dbix_object (@dbix_objects) {
71
            my $object = Koha::Auth::Permission->_new_from_dbic($dbix_object);
72
            push @{$self->{params}->{permissions}}, $object;
73
        }
74
    }
75
    return $self->{params}->{permissions};
76
}
77
78
1;
(-)a/Koha/Auth/PermissionModules.pm (+38 lines)
Line 0 Link Here
1
package Koha::Auth::PermissionModules;
2
3
# Copyright 2015 Vaara-kirjastot
4
#
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>.
19
20
use Modern::Perl;
21
use Scalar::Util qw(blessed);
22
23
use Koha::Auth::PermissionModule;
24
25
use base qw(Koha::Objects);
26
27
sub type {
28
    return 'PermissionModule';
29
}
30
sub object_class {
31
    return 'Koha::Auth::PermissionModule';
32
}
33
34
sub _get_castable_unique_columns {
35
    return ['permission_module_id', 'module'];
36
}
37
38
1;
(-)a/Koha/Auth/Permissions.pm (+42 lines)
Line 0 Link Here
1
package Koha::Auth::Permissions;
2
3
# Copyright 2015 Vaara-kirjastot
4
#
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>.
19
20
use Modern::Perl;
21
use Scalar::Util qw(blessed);
22
23
use Koha::Auth::Permission;
24
25
use Koha::Exception::BadParameter;
26
use Koha::Exception::UnknownObject;
27
28
use base qw(Koha::Objects);
29
30
sub type {
31
    return 'Permission';
32
}
33
34
sub object_class {
35
    return 'Koha::Auth::Permission';
36
}
37
38
sub _get_castable_unique_columns {
39
    return ['permission_id', 'code'];
40
}
41
42
1;
(-)a/Koha/AuthUtils.pm (-1 lines)
Lines 166-172 sub _createTemporarySuperuser { Link Here
166
                       firstname  => $superuserName,
166
                       firstname  => $superuserName,
167
                       surname    => $superuserName,
167
                       surname    => $superuserName,
168
                       branchcode => 'NO_LIBRARY_SET',
168
                       branchcode => 'NO_LIBRARY_SET',
169
                       flags      => 1,
170
                       email      => C4::Context->preference('KohaAdminEmailAddress')
169
                       email      => C4::Context->preference('KohaAdminEmailAddress')
171
                    });
170
                    });
172
    return $borrower;
171
    return $borrower;
(-)a/Koha/Schema/Result/Borrower.pm (-24 / +47 lines)
Lines 309-319 __PACKAGE__->table("borrowers"); Link Here
309
  is_nullable: 1
309
  is_nullable: 1
310
  size: 60
310
  size: 60
311
311
312
=head2 flags
313
314
  data_type: 'integer'
315
  is_nullable: 1
316
317
=head2 userid
312
=head2 userid
318
313
319
  data_type: 'varchar'
314
  data_type: 'varchar'
Lines 542-549 __PACKAGE__->add_columns( Link Here
542
  { data_type => "varchar", is_nullable => 1, size => 1 },
537
  { data_type => "varchar", is_nullable => 1, size => 1 },
543
  "password",
538
  "password",
544
  { data_type => "varchar", is_nullable => 1, size => 60 },
539
  { data_type => "varchar", is_nullable => 1, size => 60 },
545
  "flags",
546
  { data_type => "integer", is_nullable => 1 },
547
  "userid",
540
  "userid",
548
  { data_type => "varchar", is_nullable => 1, size => 75 },
541
  { data_type => "varchar", is_nullable => 1, size => 75 },
549
  "opacnote",
542
  "opacnote",
Lines 648-653 __PACKAGE__->has_many( Link Here
648
  { cascade_copy => 0, cascade_delete => 0 },
641
  { cascade_copy => 0, cascade_delete => 0 },
649
);
642
);
650
643
644
=head2 api_keys
645
646
Type: has_many
647
648
Related object: L<Koha::Schema::Result::ApiKey>
649
650
=cut
651
652
__PACKAGE__->has_many(
653
  "api_keys",
654
  "Koha::Schema::Result::ApiKey",
655
  { "foreign.borrowernumber" => "self.borrowernumber" },
656
  { cascade_copy => 0, cascade_delete => 0 },
657
);
658
659
=head2 api_timestamp
660
661
Type: might_have
662
663
Related object: L<Koha::Schema::Result::ApiTimestamp>
664
665
=cut
666
667
__PACKAGE__->might_have(
668
  "api_timestamp",
669
  "Koha::Schema::Result::ApiTimestamp",
670
  { "foreign.borrowernumber" => "self.borrowernumber" },
671
  { cascade_copy => 0, cascade_delete => 0 },
672
);
673
651
=head2 aqbasketusers
674
=head2 aqbasketusers
652
675
653
Type: has_many
676
Type: has_many
Lines 753-758 __PACKAGE__->has_many( Link Here
753
  { cascade_copy => 0, cascade_delete => 0 },
776
  { cascade_copy => 0, cascade_delete => 0 },
754
);
777
);
755
778
779
=head2 borrower_permissions
780
781
Type: has_many
782
783
Related object: L<Koha::Schema::Result::BorrowerPermission>
784
785
=cut
786
787
__PACKAGE__->has_many(
788
  "borrower_permissions",
789
  "Koha::Schema::Result::BorrowerPermission",
790
  { "foreign.borrowernumber" => "self.borrowernumber" },
791
  { cascade_copy => 0, cascade_delete => 0 },
792
);
793
756
=head2 borrower_syncs
794
=head2 borrower_syncs
757
795
758
Type: has_many
796
Type: has_many
Lines 1053-1073 __PACKAGE__->has_many( Link Here
1053
  { cascade_copy => 0, cascade_delete => 0 },
1091
  { cascade_copy => 0, cascade_delete => 0 },
1054
);
1092
);
1055
1093
1056
=head2 user_permissions
1057
1058
Type: has_many
1059
1060
Related object: L<Koha::Schema::Result::UserPermission>
1061
1062
=cut
1063
1064
__PACKAGE__->has_many(
1065
  "user_permissions",
1066
  "Koha::Schema::Result::UserPermission",
1067
  { "foreign.borrowernumber" => "self.borrowernumber" },
1068
  { cascade_copy => 0, cascade_delete => 0 },
1069
);
1070
1071
=head2 virtualshelfcontents
1094
=head2 virtualshelfcontents
1072
1095
1073
Type: has_many
1096
Type: has_many
Lines 1154-1161 Composing rels: L</aqorder_users> -> ordernumber Link Here
1154
__PACKAGE__->many_to_many("ordernumbers", "aqorder_users", "ordernumber");
1177
__PACKAGE__->many_to_many("ordernumbers", "aqorder_users", "ordernumber");
1155
1178
1156
1179
1157
# Created by DBIx::Class::Schema::Loader v0.07039 @ 2015-04-27 16:08:40
1180
# Created by DBIx::Class::Schema::Loader v0.07039 @ 2015-07-11 12:59:56
1158
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:Z50zYBD3Hqlv5/EnoLnyZw
1181
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:ZRxBjZb0KKxabonVI/2vjg
1159
1182
1160
1183
1161
# You can replace this text with custom content, and it will be preserved on regeneration
1184
# You can replace this text with custom content, and it will be preserved on regeneration
(-)a/Koha/Schema/Result/Permission.pm (-34 / +45 lines)
Lines 23-39 __PACKAGE__->table("permissions"); Link Here
23
23
24
=head1 ACCESSORS
24
=head1 ACCESSORS
25
25
26
=head2 module_bit
26
=head2 permission_id
27
27
28
  data_type: 'integer'
28
  data_type: 'integer'
29
  default_value: 0
29
  is_auto_increment: 1
30
  is_nullable: 0
31
32
=head2 module
33
34
  data_type: 'varchar'
30
  is_foreign_key: 1
35
  is_foreign_key: 1
31
  is_nullable: 0
36
  is_nullable: 0
37
  size: 32
32
38
33
=head2 code
39
=head2 code
34
40
35
  data_type: 'varchar'
41
  data_type: 'varchar'
36
  default_value: (empty string)
37
  is_nullable: 0
42
  is_nullable: 0
38
  size: 64
43
  size: 64
39
44
Lines 46-60 __PACKAGE__->table("permissions"); Link Here
46
=cut
51
=cut
47
52
48
__PACKAGE__->add_columns(
53
__PACKAGE__->add_columns(
49
  "module_bit",
54
  "permission_id",
50
  {
55
  { data_type => "integer", is_auto_increment => 1, is_nullable => 0 },
51
    data_type      => "integer",
56
  "module",
52
    default_value  => 0,
57
  { data_type => "varchar", is_foreign_key => 1, is_nullable => 0, size => 32 },
53
    is_foreign_key => 1,
54
    is_nullable    => 0,
55
  },
56
  "code",
58
  "code",
57
  { data_type => "varchar", default_value => "", is_nullable => 0, size => 64 },
59
  { data_type => "varchar", is_nullable => 0, size => 64 },
58
  "description",
60
  "description",
59
  { data_type => "varchar", is_nullable => 1, size => 255 },
61
  { data_type => "varchar", is_nullable => 1, size => 255 },
60
);
62
);
Lines 63-69 __PACKAGE__->add_columns( Link Here
63
65
64
=over 4
66
=over 4
65
67
66
=item * L</module_bit>
68
=item * L</permission_id>
69
70
=back
71
72
=cut
73
74
__PACKAGE__->set_primary_key("permission_id");
75
76
=head1 UNIQUE CONSTRAINTS
77
78
=head2 C<code>
79
80
=over 4
67
81
68
=item * L</code>
82
=item * L</code>
69
83
Lines 71-116 __PACKAGE__->add_columns( Link Here
71
85
72
=cut
86
=cut
73
87
74
__PACKAGE__->set_primary_key("module_bit", "code");
88
__PACKAGE__->add_unique_constraint("code", ["code"]);
75
89
76
=head1 RELATIONS
90
=head1 RELATIONS
77
91
78
=head2 module_bit
92
=head2 borrower_permissions
79
93
80
Type: belongs_to
94
Type: has_many
81
95
82
Related object: L<Koha::Schema::Result::Userflag>
96
Related object: L<Koha::Schema::Result::BorrowerPermission>
83
97
84
=cut
98
=cut
85
99
86
__PACKAGE__->belongs_to(
100
__PACKAGE__->has_many(
87
  "module_bit",
101
  "borrower_permissions",
88
  "Koha::Schema::Result::Userflag",
102
  "Koha::Schema::Result::BorrowerPermission",
89
  { bit => "module_bit" },
103
  { "foreign.permission_id" => "self.permission_id" },
90
  { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
104
  { cascade_copy => 0, cascade_delete => 0 },
91
);
105
);
92
106
93
=head2 user_permissions
107
=head2 module
94
108
95
Type: has_many
109
Type: belongs_to
96
110
97
Related object: L<Koha::Schema::Result::UserPermission>
111
Related object: L<Koha::Schema::Result::PermissionModule>
98
112
99
=cut
113
=cut
100
114
101
__PACKAGE__->has_many(
115
__PACKAGE__->belongs_to(
102
  "user_permissions",
116
  "module",
103
  "Koha::Schema::Result::UserPermission",
117
  "Koha::Schema::Result::PermissionModule",
104
  {
118
  { module => "module" },
105
    "foreign.code"       => "self.code",
119
  { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
106
    "foreign.module_bit" => "self.module_bit",
107
  },
108
  { cascade_copy => 0, cascade_delete => 0 },
109
);
120
);
110
121
111
122
112
# Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-10-14 20:56:21
123
# Created by DBIx::Class::Schema::Loader v0.07039 @ 2015-07-28 17:08:28
113
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:Ut3lzlxoPPoIIwmhJViV1Q
124
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:ugaurNx48ISDyRgoAlBk2A
114
125
115
126
116
# You can replace this text with custom content, and it will be preserved on regeneration
127
# You can replace this text with custom content, and it will be preserved on regeneration
(-)a/installer/data/mysql/en/mandatory/userflags.sql (-20 / +20 lines)
Lines 1-21 Link Here
1
INSERT INTO userflags (bit, flag, flagdesc, defaulton) VALUES
1
INSERT INTO permission_modules (module, description) VALUES
2
(0,'superlibrarian','Access to all librarian functions',0),
2
('superlibrarian','Access to all librarian functions'),
3
(1,'circulate','Check out and check in items',0),
3
('circulate','Check out and check in items'),
4
(2,'catalogue','<b>Required for staff login.</b> Staff access, allows viewing of catalogue in staff client.',0),
4
('catalogue','<b>Required for staff login.</b> Staff access, allows viewing of catalogue in staff client.'),
5
(3,'parameters','Manage Koha system settings (Administration panel)',0),
5
('parameters','Manage Koha system settings (Administration panel)'),
6
(4,'borrowers','Add or modify patrons',0),
6
('borrowers','Add or modify patrons'),
7
(5,'permissions','Set user permissions',0),
7
('permissions','Set user permissions'),
8
(6,'reserveforothers','Place and modify holds for patrons',0),
8
('reserveforothers','Place and modify holds for patrons'),
9
(9,'editcatalogue','Edit catalog (Modify bibliographic/holdings data)',0),
9
('editcatalogue','Edit catalog (Modify bibliographic/holdings data)'),
10
(10,'updatecharges','Manage patrons fines and fees',0),
10
('updatecharges','Manage patrons fines and fees'),
11
(11,'acquisition','Acquisition and/or suggestion management',0),
11
('acquisition','Acquisition and/or suggestion management'),
12
(12,'management','Set library management parameters (deprecated)',0),
12
('management','Set library management parameters (deprecated)'),
13
(13,'tools','Use all tools (expand for granular tools permissions)',0),
13
('tools','Use all tools (expand for granular tools permissions)'),
14
(14,'editauthorities','Edit authorities',0),
14
('editauthorities','Edit authorities'),
15
(15,'serials','Manage serial subscriptions',0),
15
('serials','Manage serial subscriptions'),
16
(16,'reports','Allow access to the reports module',0),
16
('reports','Allow access to the reports module'),
17
(17,'staffaccess','Allow staff members to modify permissions for other staff members',0),
17
('staffaccess','Allow staff members to modify permissions for other staff members'),
18
(18,'coursereserves','Course reserves',0),
18
('coursereserves','Course reserves'),
19
(19, 'plugins', 'Koha plugins', '0'),
19
('plugins', 'Koha plugins'),
20
(20, 'lists', 'Lists', 0)
20
('lists', 'Lists')
21
;
21
;
(-)a/installer/data/mysql/en/mandatory/userpermissions.sql (-76 / +83 lines)
Lines 1-77 Link Here
1
INSERT INTO permissions (module_bit, code, description) VALUES
1
INSERT INTO permissions (module, code, description) VALUES
2
   ( 1, 'circulate_remaining_permissions', 'Remaining circulation permissions'),
2
   ( 'superlibrarian',  'superlibrarian', 'Access to all librarian functions'),
3
   ( 1, 'override_renewals', 'Override blocked renewals'),
3
   ( 'circulate',       'circulate_remaining_permissions', 'Remaining circulation permissions'),
4
   ( 1, 'overdues_report', 'Execute overdue items report'),
4
   ( 'circulate',       'override_renewals', 'Override blocked renewals'),
5
   ( 1, 'force_checkout', 'Force checkout if a limitation exists'),
5
   ( 'circulate',       'overdues_report', 'Execute overdue items report'),
6
   ( 1, 'manage_restrictions', 'Manage restrictions for accounts'),
6
   ( 'circulate',       'force_checkout', 'Force checkout if a limitation exists'),
7
   ( 3, 'parameters_remaining_permissions', 'Remaining system parameters permissions'),
7
   ( 'circulate',       'manage_restrictions', 'Manage restrictions for accounts'),
8
   ( 3, 'manage_circ_rules', 'manage circulation rules'),
8
   ( 'catalogue',       'staff_login', 'Allow staff login.'),
9
   ( 6, 'place_holds', 'Place holds for patrons'),
9
   ( 'parameters',      'parameters_remaining_permissions', 'Remaining system parameters permissions'),
10
   ( 6, 'modify_holds_priority', 'Modify holds priority'),
10
   ( 'parameters',      'manage_circ_rules', 'manage circulation rules'),
11
   ( 9, 'edit_catalogue', 'Edit catalog (Modify bibliographic/holdings data)'),
11
   ( 'borrowers',       'view_borrowers', 'Show borrower details and search for borrowers.'),
12
   ( 9, 'fast_cataloging', 'Fast cataloging'),
12
   ( 'permissions',     'set_permissions', 'Set user permissions'),
13
   ( 9, 'edit_items', 'Edit items'),
13
   ( 'reserveforothers','place_holds', 'Place holds for patrons'),
14
   ( 9, 'edit_items_restricted', 'Limit item modification to subfields defined in the SubfieldsToAllowForRestrictedEditing preference (please note that edit_item is still required)'),
14
   ( 'reserveforothers','modify_holds_priority', 'Modify holds priority'),
15
   ( 9, 'delete_all_items', 'Delete all items at once'),
15
   ( 'editcatalogue',   'edit_catalogue', 'Edit catalog (Modify bibliographic/holdings data)'),
16
   (10, 'writeoff', 'Write off fines and fees'),
16
   ( 'editcatalogue',   'fast_cataloging', 'Fast cataloging'),
17
   (10, 'remaining_permissions', 'Remaining permissions for managing fines and fees'),
17
   ( 'editcatalogue',   'edit_items', 'Edit items'),
18
   (11, 'vendors_manage', 'Manage vendors'),
18
   ( 'editcatalogue',   'edit_items_restricted', 'Limit item modification to subfields defined in the SubfieldsToAllowForRestrictedEditing preference (please note that edit_item is still required)'),
19
   (11, 'contracts_manage', 'Manage contracts'),
19
   ( 'editcatalogue',   'delete_all_items', 'Delete all items at once'),
20
   (11, 'period_manage', 'Manage periods'),
20
   ( 'updatecharges',   'writeoff', 'Write off fines and fees'),
21
   (11, 'budget_manage', 'Manage budgets'),
21
   ( 'updatecharges',   'remaining_permissions', 'Remaining permissions for managing fines and fees'),
22
   (11, 'budget_modify', 'Modify budget (can''t create lines, but can modify existing ones)'),
22
   ( 'acquisition',     'vendors_manage', 'Manage vendors'),
23
   (11, 'planning_manage', 'Manage budget plannings'),
23
   ( 'acquisition',     'contracts_manage', 'Manage contracts'),
24
   (11, 'order_manage', 'Manage orders & basket'),
24
   ( 'acquisition',     'period_manage', 'Manage periods'),
25
   (11, 'order_manage_all', 'Manage all orders and baskets, regardless of restrictions on them'),
25
   ( 'acquisition',     'budget_manage', 'Manage budgets'),
26
   (11, 'group_manage', 'Manage orders & basketgroups'),
26
   ( 'acquisition',     'budget_modify', 'Modify budget (can''t create lines, but can modify existing ones)'),
27
   (11, 'order_receive', 'Manage orders & basket'),
27
   ( 'acquisition',     'planning_manage', 'Manage budget plannings'),
28
   (11, 'budget_add_del', 'Add and delete budgets (but can''t modify budgets)'),
28
   ( 'acquisition',     'order_manage', 'Manage orders & basket'),
29
   (11, 'budget_manage_all', 'Manage all budgets'),
29
   ( 'acquisition',     'order_manage_all', 'Manage all orders and baskets, regardless of restrictions on them'),
30
   (13, 'edit_news', 'Write news for the OPAC and staff interfaces'),
30
   ( 'acquisition',     'group_manage', 'Manage orders & basketgroups'),
31
   (13, 'label_creator', 'Create printable labels and barcodes from catalog and patron data'),
31
   ( 'acquisition',     'order_receive', 'Manage orders & basket'),
32
   (13, 'edit_calendar', 'Define days when the library is closed'),
32
   ( 'acquisition',     'budget_add_del', 'Add and delete budgets (but can''t modify budgets)'),
33
   (13, 'moderate_comments', 'Moderate patron comments'),
33
   ( 'acquisition',     'budget_manage_all', 'Manage all budgets'),
34
   (13, 'edit_notices', 'Define notices'),
34
   ( 'management',      'management', 'Set library management parameters (deprecated)'),
35
   (13, 'edit_notice_status_triggers', 'Set notice/status triggers for overdue items'),
35
   ( 'tools',           'edit_news', 'Write news for the OPAC and staff interfaces'),
36
   (13, 'edit_quotes', 'Edit quotes for quote-of-the-day feature'),
36
   ( 'tools',           'label_creator', 'Create printable labels and barcodes from catalog and patron data'),
37
   (13, 'view_system_logs', 'Browse the system logs'),
37
   ( 'tools',           'edit_calendar', 'Define days when the library is closed'),
38
   (13, 'inventory', 'Perform inventory (stocktaking) of your catalog'),
38
   ( 'tools',           'moderate_comments', 'Moderate patron comments'),
39
   (13, 'stage_marc_import', 'Stage MARC records into the reservoir'),
39
   ( 'tools',           'edit_notices', 'Define notices'),
40
   (13, 'manage_staged_marc', 'Managed staged MARC records, including completing and reversing imports'),
40
   ( 'tools',           'edit_notice_status_triggers', 'Set notice/status triggers for overdue items'),
41
   (13, 'export_catalog', 'Export bibliographic and holdings data'),
41
   ( 'tools',           'edit_quotes', 'Edit quotes for quote-of-the-day feature'),
42
   (13, 'import_patrons', 'Import patron data'),
42
   ( 'tools',           'view_system_logs', 'Browse the system logs'),
43
   (13, 'edit_patrons', 'Perform batch modification of patrons'),
43
   ( 'tools',           'inventory', 'Perform inventory (stocktaking) of your catalog'),
44
   (13, 'delete_anonymize_patrons', 'Delete old borrowers and anonymize circulation history (deletes borrower reading history)'),
44
   ( 'tools',           'stage_marc_import', 'Stage MARC records into the reservoir'),
45
   (13, 'batch_upload_patron_images', 'Upload patron images in a batch or one at a time'),
45
   ( 'tools',           'manage_staged_marc', 'Managed staged MARC records, including completing and reversing imports'),
46
   (13, 'schedule_tasks', 'Schedule tasks to run'),
46
   ( 'tools',           'export_catalog', 'Export bibliographic and holdings data'),
47
   (13, 'items_batchmod', 'Perform batch modification of items'),
47
   ( 'tools',           'import_patrons', 'Import patron data'),
48
   (13, 'items_batchmod_restricted', 'Limit batch item modification to subfields defined in the SubfieldsToAllowForRestrictedBatchmod preference (please note that items_batchmod is still required)'),
48
   ( 'tools',           'edit_patrons', 'Perform batch modification of patrons'),
49
   (13, 'items_batchdel', 'Perform batch deletion of items'),
49
   ( 'tools',           'delete_anonymize_patrons', 'Delete old borrowers and anonymize circulation history (deletes borrower reading history)'),
50
   (13, 'manage_csv_profiles', 'Manage CSV export profiles'),
50
   ( 'tools',           'batch_upload_patron_images', 'Upload patron images in a batch or one at a time'),
51
   (13, 'moderate_tags', 'Moderate patron tags'),
51
   ( 'tools',           'schedule_tasks', 'Schedule tasks to run'),
52
   (13, 'rotating_collections', 'Manage rotating collections'),
52
   ( 'tools',           'items_batchmod', 'Perform batch modification of items'),
53
   (13, 'upload_local_cover_images', 'Upload local cover images'),
53
   ( 'tools',           'items_batchmod_restricted', 'Limit batch item modification to subfields defined in the SubfieldsToAllowForRestrictedBatchmod preference (please note that items_batchmod is still required)'),
54
   (13, 'manage_patron_lists', 'Add, edit and delete patron lists and their contents'),
54
   ( 'tools',           'items_batchdel', 'Perform batch deletion of items'),
55
   (13, 'records_batchmod', 'Perform batch modification of records (biblios or authorities)'),
55
   ( 'tools',           'manage_csv_profiles', 'Manage CSV export profiles'),
56
   (13, 'marc_modification_templates', 'Manage marc modification templates'),
56
   ( 'tools',           'moderate_tags', 'Moderate patron tags'),
57
   (13, 'records_batchdel', 'Perform batch deletion of records (bibliographic or authority)'),
57
   ( 'tools',           'rotating_collections', 'Manage rotating collections'),
58
   (15, 'check_expiration', 'Check the expiration of a serial'),
58
   ( 'tools',           'upload_local_cover_images', 'Upload local cover images'),
59
   (15, 'claim_serials', 'Claim missing serials'),
59
   ( 'tools',           'manage_patron_lists', 'Add, edit and delete patron lists and their contents'),
60
   (15, 'create_subscription', 'Create a new subscription'),
60
   ( 'tools',           'records_batchmod', 'Perform batch modification of records (biblios or authorities)'),
61
   (15, 'delete_subscription', 'Delete an existing subscription'),
61
   ( 'tools',           'marc_modification_templates', 'Manage marc modification templates'),
62
   (15, 'edit_subscription', 'Edit an existing subscription'),
62
   ( 'tools',           'records_batchdel', 'Perform batch deletion of records (bibliographic or authority)'),
63
   (15, 'receive_serials', 'Serials receiving'),
63
   ( 'editauthorities', 'edit_authorities', 'Edit authorities'),
64
   (15, 'renew_subscription', 'Renew a subscription'),
64
   ( 'serials',         'check_expiration', 'Check the expiration of a serial'),
65
   (15, 'routing', 'Routing'),
65
   ( 'serials',         'claim_serials', 'Claim missing serials'),
66
   (15, 'superserials', 'Manage subscriptions from any branch (only applies when IndependentBranches is used)'),
66
   ( 'serials',         'create_subscription', 'Create a new subscription'),
67
   (16, 'execute_reports', 'Execute SQL reports'),
67
   ( 'serials',         'delete_subscription', 'Delete an existing subscription'),
68
   (16, 'create_reports', 'Create SQL reports'),
68
   ( 'serials',         'edit_subscription', 'Edit an existing subscription'),
69
   (18, 'manage_courses', 'Add, edit and delete courses'),
69
   ( 'serials',         'receive_serials', 'Serials receiving'),
70
   (18, 'add_reserves', 'Add course reserves'),
70
   ( 'serials',         'renew_subscription', 'Renew a subscription'),
71
   (18, 'delete_reserves', 'Remove course reserves'),
71
   ( 'serials',         'routing', 'Routing'),
72
   (19, 'manage', 'Manage plugins ( install / uninstall )'),
72
   ( 'serials',         'superserials', 'Manage subscriptions from any branch (only applies when IndependentBranches is used)'),
73
   (19, 'tool', 'Use tool plugins'),
73
   ( 'reports',         'execute_reports', 'Execute SQL reports'),
74
   (19, 'report', 'Use report plugins'),
74
   ( 'reports',         'create_reports', 'Create SQL reports'),
75
   (19, 'configure', 'Configure plugins'),
75
   ( 'staffaccess',     'staff_access_permissions', 'Allow staff members to modify permissions for other staff members'),
76
   (20, 'delete_public_lists', 'Delete public lists')
76
   ( 'coursereserves',  'manage_courses', 'Add, edit and delete courses'),
77
   ( 'coursereserves',  'add_reserves', 'Add course reserves'),
78
   ( 'coursereserves',  'delete_reserves', 'Remove course reserves'),
79
   ( 'plugins',         'manage', 'Manage plugins ( install / uninstall )'),
80
   ( 'plugins',         'tool', 'Use tool plugins'),
81
   ( 'plugins',         'report', 'Use report plugins'),
82
   ( 'plugins',         'configure', 'Configure plugins'),
83
   ( 'lists',           'delete_public_lists', 'Delete public lists')
77
;
84
;
(-)a/installer/data/mysql/kohastructure.sql (-45 / +49 lines)
Lines 249-255 CREATE TABLE `borrowers` ( -- this table includes information about your patrons Link Here
249
  `ethnotes` varchar(255) default NULL, -- unused in Koha
249
  `ethnotes` varchar(255) default NULL, -- unused in Koha
250
  `sex` varchar(1) default NULL, -- patron/borrower's gender
250
  `sex` varchar(1) default NULL, -- patron/borrower's gender
251
  `password` varchar(60) default NULL, -- patron/borrower's encrypted password
251
  `password` varchar(60) default NULL, -- patron/borrower's encrypted password
252
  `flags` int(11) default NULL, -- will include a number associated with the staff member's permissions
253
  `userid` varchar(75) default NULL, -- patron/borrower's opac and/or staff client log in
252
  `userid` varchar(75) default NULL, -- patron/borrower's opac and/or staff client log in
254
  `opacnote` mediumtext, -- a note on the patron/borrower's account that is visible in the OPAC and staff client
253
  `opacnote` mediumtext, -- a note on the patron/borrower's account that is visible in the OPAC and staff client
255
  `contactnote` varchar(255) default NULL, -- a note related to the patron/borrower's alternate address
254
  `contactnote` varchar(255) default NULL, -- a note related to the patron/borrower's alternate address
Lines 879-885 CREATE TABLE `deletedborrowers` ( -- stores data related to the patrons/borrower Link Here
879
  `ethnotes` varchar(255) default NULL, -- unused in Koha
878
  `ethnotes` varchar(255) default NULL, -- unused in Koha
880
  `sex` varchar(1) default NULL, -- patron/borrower's gender
879
  `sex` varchar(1) default NULL, -- patron/borrower's gender
881
  `password` varchar(30) default NULL, -- patron/borrower's encrypted password
880
  `password` varchar(30) default NULL, -- patron/borrower's encrypted password
882
  `flags` int(11) default NULL, -- will include a number associated with the staff member's permissions
883
  `userid` varchar(30) default NULL, -- patron/borrower's opac and/or staff client log in
881
  `userid` varchar(30) default NULL, -- patron/borrower's opac and/or staff client log in
884
  `opacnote` mediumtext, -- a note on the patron/borrower's account that is visible in the OPAC and staff client
882
  `opacnote` mediumtext, -- a note on the patron/borrower's account that is visible in the OPAC and staff client
885
  `contactnote` varchar(255) default NULL, -- a note related to the patron/borrower's alternate address
883
  `contactnote` varchar(255) default NULL, -- a note related to the patron/borrower's alternate address
Lines 2291-2309 CREATE TABLE `tags_index` ( -- a weighted list of all tags and where they are us Link Here
2291
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
2289
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
2292
2290
2293
--
2291
--
2294
-- Table structure for table `userflags`
2295
--
2296
2297
DROP TABLE IF EXISTS `userflags`;
2298
CREATE TABLE `userflags` (
2299
  `bit` int(11) NOT NULL default 0,
2300
  `flag` varchar(30) default NULL,
2301
  `flagdesc` varchar(255) default NULL,
2302
  `defaulton` int(11) default NULL,
2303
  PRIMARY KEY  (`bit`)
2304
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
2305
2306
--
2307
-- Table structure for table `virtualshelves`
2292
-- Table structure for table `virtualshelves`
2308
--
2293
--
2309
2294
Lines 2484-2503 CREATE TABLE language_script_mapping ( Link Here
2484
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
2469
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
2485
2470
2486
--
2471
--
2487
-- Table structure for table `permissions`
2488
--
2489
2490
DROP TABLE IF EXISTS `permissions`;
2491
CREATE TABLE `permissions` (
2492
  `module_bit` int(11) NOT NULL DEFAULT 0,
2493
  `code` varchar(64) DEFAULT NULL,
2494
  `description` varchar(255) DEFAULT NULL,
2495
  PRIMARY KEY  (`module_bit`, `code`),
2496
  CONSTRAINT `permissions_ibfk_1` FOREIGN KEY (`module_bit`) REFERENCES `userflags` (`bit`)
2497
    ON DELETE CASCADE ON UPDATE CASCADE
2498
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
2499
2500
--
2501
-- Table structure for table `serialitems`
2472
-- Table structure for table `serialitems`
2502
--
2473
--
2503
2474
Lines 2512-2532 CREATE TABLE `serialitems` ( Link Here
2512
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
2483
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
2513
2484
2514
--
2485
--
2515
-- Table structure for table `user_permissions`
2516
--
2517
2518
DROP TABLE IF EXISTS `user_permissions`;
2519
CREATE TABLE `user_permissions` (
2520
  `borrowernumber` int(11) NOT NULL DEFAULT 0,
2521
  `module_bit` int(11) NOT NULL DEFAULT 0,
2522
  `code` varchar(64) DEFAULT NULL,
2523
  CONSTRAINT `user_permissions_ibfk_1` FOREIGN KEY (`borrowernumber`) REFERENCES `borrowers` (`borrowernumber`)
2524
    ON DELETE CASCADE ON UPDATE CASCADE,
2525
  CONSTRAINT `user_permissions_ibfk_2` FOREIGN KEY (`module_bit`, `code`) REFERENCES `permissions` (`module_bit`, `code`)
2526
    ON DELETE CASCADE ON UPDATE CASCADE
2527
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
2528
2529
--
2530
-- Table structure for table `tmp_holdsqueue`
2486
-- Table structure for table `tmp_holdsqueue`
2531
--
2487
--
2532
2488
Lines 3338-3344 CREATE TABLE IF NOT EXISTS `borrower_modifications` ( Link Here
3338
  `ethnotes` varchar(255) DEFAULT NULL,
3294
  `ethnotes` varchar(255) DEFAULT NULL,
3339
  `sex` varchar(1) DEFAULT NULL,
3295
  `sex` varchar(1) DEFAULT NULL,
3340
  `password` varchar(30) DEFAULT NULL,
3296
  `password` varchar(30) DEFAULT NULL,
3341
  `flags` int(11) DEFAULT NULL,
3342
  `userid` varchar(75) DEFAULT NULL,
3297
  `userid` varchar(75) DEFAULT NULL,
3343
  `opacnote` mediumtext,
3298
  `opacnote` mediumtext,
3344
  `contactnote` varchar(255) DEFAULT NULL,
3299
  `contactnote` varchar(255) DEFAULT NULL,
Lines 3378-3383 CREATE TABLE uploaded_files ( Link Here
3378
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
3333
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
3379
3334
3380
--
3335
--
3336
-- Table structure for table permissions
3337
--
3338
3339
DROP TABLE IF EXISTS permissions;
3340
CREATE TABLE permissions (
3341
  permission_id int(11) NOT NULL auto_increment,
3342
  module varchar(32) NOT NULL,
3343
  code varchar(64) NOT NULL,
3344
  description varchar(255) DEFAULT NULL,
3345
  PRIMARY KEY  (permission_id),
3346
  UNIQUE KEY (code),
3347
  CONSTRAINT permissions_to_modules_ibfk1 FOREIGN KEY (module) REFERENCES permission_modules (module)
3348
    ON DELETE CASCADE ON UPDATE CASCADE
3349
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
3350
3351
--
3352
-- Table structure for table permission_modules
3353
--
3354
3355
DROP TABLE IF EXISTS permission_modules;
3356
CREATE TABLE permission_modules (
3357
  permission_module_id int(11) NOT NULL auto_increment,
3358
  module varchar(32) NOT NULL,
3359
  description varchar(255) DEFAULT NULL,
3360
  PRIMARY KEY  (permission_module_id),
3361
  UNIQUE KEY (module)
3362
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
3363
3364
--
3365
-- Table structure for table borrower_permissions
3366
--
3367
3368
DROP TABLE IF EXISTS borrower_permissions;
3369
CREATE TABLE borrower_permissions (
3370
  borrower_permission_id int(11) NOT NULL auto_increment,
3371
  borrowernumber int(11) NOT NULL,
3372
  permission_module_id int(11) NOT NULL,
3373
  permission_id int(11) NOT NULL,
3374
  PRIMARY KEY  (borrower_permission_id),
3375
  UNIQUE KEY (borrowernumber, permission_module_id, permission_id),
3376
  CONSTRAINT borrower_permissions_ibfk_1 FOREIGN KEY (borrowernumber) REFERENCES borrowers (borrowernumber)
3377
    ON DELETE CASCADE ON UPDATE CASCADE,
3378
  CONSTRAINT borrower_permissions_ibfk_2 FOREIGN KEY (permission_id) REFERENCES permissions (permission_id)
3379
    ON DELETE CASCADE ON UPDATE CASCADE,
3380
  CONSTRAINT borrower_permissions_ibfk_3 FOREIGN KEY (permission_module_id) REFERENCES permission_modules (permission_module_id)
3381
    ON DELETE CASCADE ON UPDATE CASCADE
3382
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
3383
3384
--
3381
-- Table structure for table linktracker
3385
-- Table structure for table linktracker
3382
-- This stores clicks to external links
3386
-- This stores clicks to external links
3383
--
3387
--
(-)a/installer/data/mysql/updatedatabase.pl (+113 lines)
Lines 7822-7827 if ( CheckVersion($DBversion) ) { Link Here
7822
    SetVersion($DBversion);
7822
    SetVersion($DBversion);
7823
}
7823
}
7824
7824
7825
$DBversion = "3.21.00.XXX";
7826
if ( CheckVersion($DBversion) ) {
7827
    my $upgradeDone;
7828
    my $permissionModule = $dbh->selectrow_hashref("SELECT * FROM permission_modules LIMIT 1");
7829
    if ($permissionModule) {
7830
        print "Upgrade to $DBversion ALREADY DONE?!? (Bug 14540 - Move member-flags.pl to PermissionsManager to better manage permissions for testing.)\n";
7831
        $upgradeDone = 1;
7832
    }
7833
    unless ($upgradeDone) {
7834
        ##CREATE new TABLEs
7835
        ##CREATing instead of ALTERing existing tables because this way the changes are more easy to understand.
7836
        $dbh->do("CREATE TABLE permission_modules (
7837
                    permission_module_id int(11) NOT NULL auto_increment,
7838
                    module varchar(32) NOT NULL,
7839
                    description varchar(255) DEFAULT NULL,
7840
                    PRIMARY KEY  (permission_module_id),
7841
                    UNIQUE KEY (module)
7842
                  ) ENGINE=InnoDB DEFAULT CHARSET=utf8;");
7843
        $dbh->do("INSERT INTO permission_modules (permission_module_id, module, description) SELECT bit, flag, flagdesc FROM userflags WHERE bit != 0;"); #superlibrarian causes primary key conflict
7844
        $dbh->do("INSERT INTO permission_modules (permission_module_id, module, description) SELECT 21, flag, flagdesc FROM userflags WHERE bit = 0;");   #So add him by himself.
7845
7846
        $dbh->do("ALTER TABLE permissions RENAME TO permissions_old");
7847
        $dbh->do("CREATE TABLE permissions (
7848
                    permission_id int(11) NOT NULL auto_increment,
7849
                    module varchar(32) NOT NULL,
7850
                    code varchar(64) NOT NULL,
7851
                    description varchar(255) DEFAULT NULL,
7852
                    PRIMARY KEY  (permission_id),
7853
                    UNIQUE KEY (code),
7854
                    CONSTRAINT permissions_to_modules_ibfk1 FOREIGN KEY (module) REFERENCES permission_modules (module)
7855
                      ON DELETE CASCADE ON UPDATE CASCADE
7856
                  ) ENGINE=InnoDB DEFAULT CHARSET=utf8;");
7857
        $dbh->do("INSERT INTO permissions (module, code, description)
7858
                    SELECT userflags.flag, code, description FROM permissions_old
7859
                      LEFT JOIN userflags ON permissions_old.module_bit = userflags.bit;");
7860
7861
        $dbh->do("CREATE TABLE borrower_permissions (
7862
                    borrower_permission_id int(11) NOT NULL auto_increment,
7863
                    borrowernumber int(11) NOT NULL,
7864
                    permission_module_id int(11) NOT NULL,
7865
                    permission_id int(11) NOT NULL,
7866
                    PRIMARY KEY  (borrower_permission_id),
7867
                    UNIQUE KEY (borrowernumber, permission_module_id, permission_id),
7868
                    CONSTRAINT borrower_permissions_ibfk_1 FOREIGN KEY (borrowernumber) REFERENCES borrowers (borrowernumber)
7869
                      ON DELETE CASCADE ON UPDATE CASCADE,
7870
                    CONSTRAINT borrower_permissions_ibfk_2 FOREIGN KEY (permission_id) REFERENCES permissions (permission_id)
7871
                      ON DELETE CASCADE ON UPDATE CASCADE,
7872
                    CONSTRAINT borrower_permissions_ibfk_3 FOREIGN KEY (permission_module_id) REFERENCES permission_modules (permission_module_id)
7873
                      ON DELETE CASCADE ON UPDATE CASCADE
7874
                  ) ENGINE=InnoDB DEFAULT CHARSET=utf8;");
7875
        $dbh->do("INSERT INTO borrower_permissions (borrowernumber, permission_module_id, permission_id)
7876
                    SELECT user_permissions.borrowernumber, user_permissions.module_bit, permissions.permission_id
7877
                    FROM user_permissions
7878
                    LEFT JOIN permissions ON user_permissions.code = permissions.code
7879
                    LEFT JOIN borrowers ON borrowers.borrowernumber = user_permissions.borrowernumber
7880
                    WHERE borrowers.borrowernumber IS NOT NULL;"); #It is possible to have user_permissions dangling around not pointing to anything, so make sure we dont try to move nonexisting borrower permissions.
7881
7882
        ##Add subpermissions to the stand-alone modules (modules with no subpermissions)
7883
        $dbh->do("INSERT INTO permissions (module, code, description) VALUES ('superlibrarian', 'superlibrarian', 'Access to all librarian functions.');");
7884
        $dbh->do("INSERT INTO permissions (module, code, description) VALUES ('catalogue', 'staff_login', 'Allow staff login.');");
7885
        $dbh->do("INSERT INTO permissions (module, code, description) VALUES ('borrowers', 'view_borrowers', 'Show borrower details and search for borrowers.');");
7886
        $dbh->do("INSERT INTO permissions (module, code, description) VALUES ('permissions', 'set_permissions', 'Set user permissions.');");
7887
        $dbh->do("INSERT INTO permissions (module, code, description) VALUES ('management', 'management', 'Set library management parameters (deprecated).');");
7888
        $dbh->do("INSERT INTO permissions (module, code, description) VALUES ('editauthorities', 'edit_authorities', 'Edit authorities.');");
7889
        $dbh->do("INSERT INTO permissions (module, code, description) VALUES ('staffaccess', 'staff_access_permissions', 'Allow staff members to modify permissions for other staff members.');");
7890
7891
        ##Create borrower_permissions to replace singular userflags from borrowers.flags.
7892
        use Koha::Borrowers;
7893
        my $sth = $dbh->prepare("
7894
                INSERT INTO borrower_permissions (borrowernumber, permission_module_id, permission_id)
7895
                VALUES (?,
7896
                        (SELECT permission_module_id FROM permission_modules WHERE module = ?),
7897
                        (SELECT permission_id FROM permissions WHERE code = ?)
7898
                       );
7899
                ");
7900
        my @borrowers = Koha::Borrowers->search({});
7901
        foreach my $b (@borrowers) {
7902
            next unless $b->flags;
7903
            if ( ( $b->flags & ( 2**0 ) ) ) {
7904
                $sth->execute($b->borrowernumber, 'superlibrarian', 'superlibrarian');
7905
            }
7906
            if ( ( $b->flags & ( 2**2 ) ) ) {
7907
                $sth->execute($b->borrowernumber, 'catalogue', 'staff_login');
7908
            }
7909
            if ( ( $b->flags & ( 2**4 ) ) ) {
7910
                $sth->execute($b->borrowernumber, 'borrowers', 'view_borrowers');
7911
            }
7912
            if ( ( $b->flags & ( 2**5 ) ) ) {
7913
                $sth->execute($b->borrowernumber, 'permissions', 'set_permissions');
7914
            }
7915
            if ( ( $b->flags & ( 2**12 ) ) ) {
7916
                $sth->execute($b->borrowernumber, 'management', 'management');
7917
            }
7918
            if ( ( $b->flags & ( 2**14 ) ) ) {
7919
                $sth->execute($b->borrowernumber, 'editauthorities', 'edit_authorities');
7920
            }
7921
            if ( ( $b->flags & ( 2**17 ) ) ) {
7922
                $sth->execute($b->borrowernumber, 'staffaccess', 'staff_access_permissions');
7923
            }
7924
        }
7925
7926
        ##Cleanup redundant tables.
7927
        $dbh->do("DELETE FROM userflags"); #Cascades to other tables.
7928
        $dbh->do("DROP TABLE user_permissions");
7929
        $dbh->do("DROP TABLE permissions_old");
7930
        $dbh->do("DROP TABLE userflags");
7931
        $dbh->do("ALTER TABLE borrowers DROP COLUMN flags");
7932
7933
        print "Upgrade to $DBversion done (Bug 14540 - Move member-flags.pl to PermissionsManager to better manage permissions for testing.)\n";
7934
        SetVersion($DBversion);
7935
    }
7936
}
7937
7825
$DBversion = "3.15.00.002";
7938
$DBversion = "3.15.00.002";
7826
if(CheckVersion($DBversion)) {
7939
if(CheckVersion($DBversion)) {
7827
    $dbh->do("ALTER TABLE deleteditems MODIFY materials text;");
7940
    $dbh->do("ALTER TABLE deleteditems MODIFY materials text;");
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/members/member-flags.tt (-7 / +7 lines)
Lines 9-31 Link Here
9
        $("#permissionstree").treeview({animated: "fast", collapsed: true});
9
        $("#permissionstree").treeview({animated: "fast", collapsed: true});
10
10
11
        // Enforce Superlibrarian Privilege Mutual Exclusivity
11
        // Enforce Superlibrarian Privilege Mutual Exclusivity
12
        if($('input[id="flag-0"]:checked').length){
12
        if($('input[id="flag-superlibrarian"]:checked').length){
13
            if ($('input[name="flag"]:checked').length > 1){
13
            if ($('input[name="flag"]:checked').length > 1){
14
                alert('Inconsistency Detected!\n\nThe superlibrarian privilege is mutually exclusive of other privileges, as it includes them all.\n\nThis patron\'s privileges will now be reset to include only superlibrarian.');
14
                alert('Inconsistency Detected!\n\nThe superlibrarian privilege is mutually exclusive of other privileges, as it includes them all.\n\nThis patron\'s privileges will now be reset to include only superlibrarian.');
15
            }
15
            }
16
16
17
            $('input[name="flag"]').each(function() {
17
            $('input[name="flag"]').each(function() {
18
                if($(this).attr('id') != "flag-0"){
18
                if($(this).attr('id') != "flag-superlibrarian"){
19
                    $(this).attr('disabled', 'disabled');
19
                    $(this).attr('disabled', 'disabled');
20
                    $(this).removeAttr('checked', 'checked');
20
                    $(this).removeAttr('checked', 'checked');
21
                }
21
                }
22
            });
22
            });
23
        }
23
        }
24
24
25
        $('input#flag-0').click(function() {
25
        $('input#flag-superlibrarian').click(function() {
26
            if($('input[id="flag-0"]:checked').length){
26
            if($('input[id="flag-superlibrarian"]:checked').length){
27
                $('input[name="flag"]').each(function() {
27
                $('input[name="flag"]').each(function() {
28
                    if($(this).attr('id') != "flag-0"){
28
                    if($(this).attr('id') != "flag-superlibrarian"){
29
                        $(this).attr('disabled', 'disabled');
29
                        $(this).attr('disabled', 'disabled');
30
                        $(this).removeAttr('checked', 'checked');
30
                        $(this).removeAttr('checked', 'checked');
31
                    }
31
                    }
Lines 121-129 Link Here
121
        <!-- <li class="folder-close">One level down<ul> -->
121
        <!-- <li class="folder-close">One level down<ul> -->
122
    [% FOREACH loo IN loop %]
122
    [% FOREACH loo IN loop %]
123
        [% IF ( loo.expand ) %]
123
        [% IF ( loo.expand ) %]
124
        <li class="open">
124
        <li class="[% loo.flag %] open">
125
        [% ELSE %]
125
        [% ELSE %]
126
        <li>
126
        <li class="[% loo.flag %]">
127
        [% END %]
127
        [% END %]
128
			[% IF ( loo.checked ) %]
128
			[% IF ( loo.checked ) %]
129
			   <input type="checkbox" id="flag-[% loo.bit %]" name="flag" value="[% loo.flag %]" checked="checked" onclick="toggleChildren(this)" />
129
			   <input type="checkbox" id="flag-[% loo.bit %]" name="flag" value="[% loo.flag %]" checked="checked" onclick="toggleChildren(this)" />
(-)a/members/member-flags.pl (-101 / +97 lines)
Lines 14-20 use C4::Context; Link Here
14
use C4::Members;
14
use C4::Members;
15
use C4::Branch;
15
use C4::Branch;
16
use C4::Members::Attributes qw(GetBorrowerAttributes);
16
use C4::Members::Attributes qw(GetBorrowerAttributes);
17
#use C4::Acquisitions;
17
use Koha::Auth::PermissionManager;
18
19
use Koha::Exception::BadParameter;
18
20
19
use C4::Output;
21
use C4::Output;
20
22
Lines 35-155 my ($template, $loggedinuser, $cookie) = get_template_and_user({ Link Here
35
        debug           => 1,
37
        debug           => 1,
36
});
38
});
37
39
38
40
my $permissionManager = Koha::Auth::PermissionManager->new();
39
my %member2;
41
my %member2;
40
$member2{'borrowernumber'}=$member;
42
$member2{'borrowernumber'}=$member;
41
43
42
if ($input->param('newflags')) {
44
if ($input->param('newflags')) {
43
    my $dbh=C4::Context->dbh();
45
    my $dbh=C4::Context->dbh();
44
46
47
	#Cast CGI-params into a permissions HASH.
45
    my @perms = $input->param('flag');
48
    my @perms = $input->param('flag');
46
    my %all_module_perms = ();
47
    my %sub_perms = ();
49
    my %sub_perms = ();
48
    foreach my $perm (@perms) {
50
    foreach my $perm (@perms) {
49
        if ($perm !~ /:/) {
51
		if ($perm eq 'superlibrarian') {
50
            $all_module_perms{$perm} = 1;
52
			$sub_perms{superlibrarian}->{superlibrarian} = 1;
53
		}
54
        elsif ($perm !~ /:/) {
55
            #DEPRECATED, GUI still sends the module flags here even though they have been removed from the DB.
51
        } else {
56
        } else {
52
            my ($module, $sub_perm) = split /:/, $perm, 2;
57
            my ($module, $sub_perm) = split /:/, $perm, 2;
53
            push @{ $sub_perms{$module} }, $sub_perm;
58
            $sub_perms{$module}->{$sub_perm} = 1;
54
        }
59
        }
55
    }
60
    }
56
61
57
    # construct flags
62
	$permissionManager->revokeAllPermissions($member);
58
    my $module_flags = 0;
63
	$permissionManager->grantPermissions($member, \%sub_perms);
59
    my $sth=$dbh->prepare("SELECT bit,flag FROM userflags ORDER BY bit");
64
60
    $sth->execute();
61
    while (my ($bit, $flag) = $sth->fetchrow_array) {
62
        if (exists $all_module_perms{$flag}) {
63
            $module_flags += 2**$bit;
64
        }
65
    }
66
    
67
    $sth = $dbh->prepare("UPDATE borrowers SET flags=? WHERE borrowernumber=?");
68
    $sth->execute($module_flags, $member);
69
    
70
    # deal with subpermissions
71
    $sth = $dbh->prepare("DELETE FROM user_permissions WHERE borrowernumber = ?");
72
    $sth->execute($member); 
73
    $sth = $dbh->prepare("INSERT INTO user_permissions (borrowernumber, module_bit, code)
74
                        SELECT ?, bit, ?
75
                        FROM userflags
76
                        WHERE flag = ?");
77
    foreach my $module (keys %sub_perms) {
78
        next if exists $all_module_perms{$module};
79
        foreach my $sub_perm (@{ $sub_perms{$module} }) {
80
            $sth->execute($member, $sub_perm, $module);
81
        }
82
    }
83
    
84
    print $input->redirect("/cgi-bin/koha/members/moremember.pl?borrowernumber=$member");
65
    print $input->redirect("/cgi-bin/koha/members/moremember.pl?borrowernumber=$member");
85
} else {
66
} else {
86
#     my ($bor,$flags,$accessflags)=GetMemberDetails($member,'');
67
    my $all_perms  = $permissionManager->listKohaPermissionsAsHASH();
87
    my $flags = $bor->{'flags'};
68
    my $user_perms = $permissionManager->getBorrowerPermissions($member);
88
    my $accessflags = $bor->{'authflags'};
69
89
    my $dbh=C4::Context->dbh();
70
	$all_perms = markBorrowerGrantedPermissions($all_perms, $user_perms);
90
    my $all_perms  = get_all_subpermissions();
71
91
    my $user_perms = get_user_subpermissions($bor->{'userid'});
92
    my $sth=$dbh->prepare("SELECT bit,flag,flagdesc FROM userflags ORDER BY bit");
93
    $sth->execute;
94
    my @loop;
72
    my @loop;
95
    while (my ($bit, $flag, $flagdesc) = $sth->fetchrow) {
73
	#Make sure the superlibrarian module is always on top.
96
	    my $checked='';
74
	push @loop, preparePermissionModuleForDisplay($all_perms, 'superlibrarian');
97
	    if ($accessflags->{$flag}) {
75
    foreach my $module (sort(keys(%$all_perms))) {
98
	        $checked= 1;
76
		push @loop, preparePermissionModuleForDisplay($all_perms, $module) unless $module eq 'superlibrarian';
99
	    }
100
101
	    my %row = ( bit => $bit,
102
		    flag => $flag,
103
		    checked => $checked,
104
		    flagdesc => $flagdesc );
105
106
        my @sub_perm_loop = ();
107
        my $expand_parent = 0;
108
        if ($checked) {
109
            if (exists $all_perms->{$flag}) {
110
                $expand_parent = 1;
111
                foreach my $sub_perm (sort keys %{ $all_perms->{$flag} }) {
112
                    push @sub_perm_loop, {
113
                        id => "${flag}_$sub_perm",
114
                        perm => "$flag:$sub_perm",
115
                        code => $sub_perm,
116
                        description => $all_perms->{$flag}->{$sub_perm},
117
                        checked => 1
118
                    };
119
                }
120
            }
121
        } else {
122
            if (exists $user_perms->{$flag}) {
123
                $expand_parent = 1;
124
                # put selected ones first
125
                foreach my $sub_perm (sort keys %{ $user_perms->{$flag} }) {
126
                    push @sub_perm_loop, {
127
                        id => "${flag}_$sub_perm",
128
                        perm => "$flag:$sub_perm",
129
                        code => $sub_perm,
130
                        description => $all_perms->{$flag}->{$sub_perm},
131
                        checked => 1
132
                    };
133
                }
134
            }
135
            # then ones not selected
136
            if (exists $all_perms->{$flag}) {
137
                foreach my $sub_perm (sort keys %{ $all_perms->{$flag} }) {
138
                    push @sub_perm_loop, {
139
                        id => "${flag}_$sub_perm",
140
                        perm => "$flag:$sub_perm",
141
                        code => $sub_perm,
142
                        description => $all_perms->{$flag}->{$sub_perm},
143
                        checked => 0
144
                    } unless exists $user_perms->{$flag} and exists $user_perms->{$flag}->{$sub_perm};
145
                }
146
            }
147
        }
148
        $row{expand} = $expand_parent;
149
        if ($#sub_perm_loop > -1) {
150
            $row{sub_perm_loop} = \@sub_perm_loop;
151
        }
152
	    push @loop, \%row;
153
    }
77
    }
154
78
155
    if ( $bor->{'category_type'} eq 'C') {
79
    if ( $bor->{'category_type'} eq 'C') {
Lines 172-179 if (C4::Context->preference('ExtendedPatronAttributes')) { Link Here
172
}
96
}
173
97
174
# Computes full borrower address
98
# Computes full borrower address
175
my $roadtype = C4::Koha::GetAuthorisedValueByCode( 'ROADTYPE', $bor->{streettype} );
99
my $roadtype = C4::Koha::GetAuthorisedValueByCode( 'ROADTYPE', $bor->{streettype} ) || '';
176
my $address = $bor->{'streetnumber'} . " $roadtype " . $bor->{'address'};
100
my $address = ($bor->{'streetnumber'} || '') . " $roadtype " . ($bor->{'address'} || '');
177
101
178
$template->param(
102
$template->param(
179
		borrowernumber => $bor->{'borrowernumber'},
103
		borrowernumber => $bor->{'borrowernumber'},
Lines 206-208 $template->param( Link Here
206
    output_html_with_http_headers $input, $cookie, $template->output;
130
    output_html_with_http_headers $input, $cookie, $template->output;
207
131
208
}
132
}
133
134
=head markBorrowerGrantedPermissions
135
136
Adds a 'checked'-value for all subpermissions in the all-Koha-Permissions-list
137
that the current borrower has been granted.
138
@PARAM1 HASHRef of all Koha permissions and modules.
139
@PARAM1 ARRAYRef of all the granted Koha::Auth::BorrowerPermission-objects.
140
@RETURNS @PARAM1, slightly checked.
141
=cut
142
143
sub markBorrowerGrantedPermissions {
144
	my ($all_perms, $user_perms) = @_;
145
146
	foreach my $borrowerPermission (@$user_perms) {
147
		my $module = $borrowerPermission->getPermissionModule->module;
148
		my $code   = $borrowerPermission->getPermission->code;
149
		$all_perms->{$module}->{permissions}->{$code}->{checked} = 1;
150
	}
151
	return $all_perms;
152
}
153
154
=head checkIfAllModulePermissionsGranted
155
156
@RETURNS Boolean, 1 if all permissions granted.
157
=cut
158
159
sub checkIfAllModulePermissionsGranted {
160
	my ($moduleHash) = @_;
161
	foreach my $code (keys(%{$moduleHash->{permissions}})) {
162
		unless ($moduleHash->{permissions}->{$code}->{checked}) {
163
			return 0;
164
		}
165
	}
166
	return 1;
167
}
168
169
sub preparePermissionModuleForDisplay {
170
	my ($all_perms, $module) = @_;
171
172
	my $moduleHash = $all_perms->{$module};
173
	my $checked = checkIfAllModulePermissionsGranted($moduleHash);
174
175
	my %row = (
176
		bit => $module,
177
		flag => $module,
178
		checked => $checked,
179
		flagdesc => $moduleHash->{description} );
180
181
	my @sub_perm_loop = ();
182
	my $expand_parent = 0;
183
184
	if ($module ne 'superlibrarian') {
185
		foreach my $sub_perm (sort keys %{ $all_perms->{$module}->{permissions} }) {
186
			my $sub_perm_checked = $all_perms->{$module}->{permissions}->{$sub_perm}->{checked};
187
			$expand_parent = 1 if $sub_perm_checked;
188
189
			push @sub_perm_loop, {
190
				id => "${module}_$sub_perm",
191
				perm => "$module:$sub_perm",
192
				code => $sub_perm,
193
				description => $all_perms->{$module}->{permissions}->{$sub_perm}->{description},
194
				checked => $sub_perm_checked || 0,
195
			};
196
		}
197
198
		$row{expand} = $expand_parent;
199
		if ($#sub_perm_loop > -1) {
200
			$row{sub_perm_loop} = \@sub_perm_loop;
201
		}
202
	}
203
	return \%row;
204
}
(-)a/misc/devel/interactiveWebDriverShell.pl (-2 / +7 lines)
Lines 115-127 my $supportedPageObjects = { Link Here
115
    "members/moremember.pl" =>
115
    "members/moremember.pl" =>
116
    {   package     => "t::lib::Page::Members::Moremember",
116
    {   package     => "t::lib::Page::Members::Moremember",
117
        urlEndpoint => "members/moremember.pl",
117
        urlEndpoint => "members/moremember.pl",
118
        status      => "not implemented",
118
        status      => "OK",
119
        params      => ["borrowernumber"],
119
        params      => ["borrowernumber"],
120
    },
120
    },
121
    "members/member-flags.pl" =>
121
    "members/member-flags.pl" =>
122
    {   package     => "t::lib::Page::Members::MemberFlags",
122
    {   package     => "t::lib::Page::Members::MemberFlags",
123
        urlEndpoint => "members/member-flags.pl",
123
        urlEndpoint => "members/member-flags.pl",
124
        status      => "not implemented",
124
        status      => "OK",
125
        params      => ["borrowernumber"],
125
        params      => ["borrowernumber"],
126
    },
126
    },
127
    "catalogue/detail.pl" =>
127
    "catalogue/detail.pl" =>
Lines 138-143 my $supportedPageObjects = { Link Here
138
        urlEndpoint => "opac/opac-main.pl",
138
        urlEndpoint => "opac/opac-main.pl",
139
        status      => "OK",
139
        status      => "OK",
140
    },
140
    },
141
    "opac/opac-search.pl" =>
142
    {   package     => "t::lib::Page::Opac::OpacSearch",
143
        urlEndpoint => "opac/opac-search.pl",
144
        status      => "OK",
145
    },
141
};
146
};
142
################################################################################
147
################################################################################
143
  ########## END OF PAGE CONFIGURATIONS ##########
148
  ########## END OF PAGE CONFIGURATIONS ##########
(-)a/opac/opac-user.pl (-1 / +1 lines)
Lines 349-355 foreach my $res (@reserves) { Link Here
349
$template->param( WAITING => \@waiting );
349
$template->param( WAITING => \@waiting );
350
350
351
# current alert subscriptions
351
# current alert subscriptions
352
my $alerts = getalert($borrowernumber);
352
my $alerts = getalert($borrowernumber) if $borrowernumber;
353
foreach ( @$alerts ) {
353
foreach ( @$alerts ) {
354
    $_->{ $_->{type} } = 1;
354
    $_->{ $_->{type} } = 1;
355
    $_->{relatedto} = findrelatedto( $_->{type}, $_->{externalid} );
355
    $_->{relatedto} = findrelatedto( $_->{type}, $_->{externalid} );
(-)a/t/db_dependent/Koha/Auth.t (-6 / +51 lines)
Lines 22-28 use Modern::Perl; Link Here
22
use Test::More;
22
use Test::More;
23
use Try::Tiny; #Even Selenium::Remote::Driver uses Try::Tiny :)
23
use Try::Tiny; #Even Selenium::Remote::Driver uses Try::Tiny :)
24
24
25
use Koha::Auth::PermissionManager;
26
25
use t::lib::Page::Mainpage;
27
use t::lib::Page::Mainpage;
28
use t::lib::Page::Opac::OpacMain;
26
29
27
use t::lib::TestObjects::BorrowerFactory;
30
use t::lib::TestObjects::BorrowerFactory;
28
31
Lines 36-52 my $borrowers = $borrowerFactory->createTestGroup([ Link Here
36
             surname    => 'Kivi',
39
             surname    => 'Kivi',
37
             cardnumber => '1A01',
40
             cardnumber => '1A01',
38
             branchcode => 'CPL',
41
             branchcode => 'CPL',
39
             flags      => '1', #superlibrarian, not exactly a very good way of doing permission testing?
40
             userid     => 'mini_admin',
42
             userid     => 'mini_admin',
41
             password   => $password,
43
             password   => $password,
42
            },
44
            },
45
            {firstname  => 'Admin',
46
             surname    => 'Administrative',
47
             cardnumber => 'maxi_admin',
48
             branchcode => 'FPL',
49
             userid     => 'maxi_admin',
50
             password   => $password,
51
            },
43
        ], undef, $testContext);
52
        ], undef, $testContext);
44
53
54
my $permissionManager = Koha::Auth::PermissionManager->new();
55
$permissionManager->grantPermission($borrowers->{'1A01'}, 'catalogue', 'staff_login');
56
$permissionManager->grantPermission($borrowers->{'maxi_admin'}, 'superlibrarian', 'superlibrarian');
57
45
##Test context set, starting testing:
58
##Test context set, starting testing:
46
eval { #run in a eval-block so we don't die without tearing down the test context
59
eval { #run in a eval-block so we don't die without tearing down the test context
47
60
48
    testPasswordLogin();
61
    my $mainpage = t::lib::Page::Mainpage->new();
62
    testPasswordLoginLogout($mainpage);
63
    testSuperuserPasswordLoginLogout($mainpage);
64
    testSuperlibrarianPasswordLoginLogout($mainpage);
65
    $mainpage->quit();
49
66
67
    my $opacmain = t::lib::Page::Opac::OpacMain->new();
68
    testOpacPasswordLoginLogout($opacmain);
69
    testSuperuserPasswordLoginLogout($opacmain);
70
    testOpacSuperlibrarianPasswordLoginLogout($opacmain);
71
    $opacmain->quit();
50
};
72
};
51
if ($@) { #Catch all leaking errors and gracefully terminate.
73
if ($@) { #Catch all leaking errors and gracefully terminate.
52
    warn $@;
74
    warn $@;
Lines 66-72 sub tearDown { Link Here
66
    ###  STARTING TEST IMPLEMENTATIONS         ###
88
    ###  STARTING TEST IMPLEMENTATIONS         ###
67
######################################################
89
######################################################
68
90
69
sub testPasswordLogin {
91
sub testPasswordLoginLogout {
70
    my $mainpage = t::lib::Page::Mainpage->new();
92
    my ($mainpage) = @_;
71
    $mainpage->isPasswordLoginAvailable()->doPasswordLogin($borrowers->{'1A01'}->userid(), $password)->quit();
93
    $mainpage->isPasswordLoginAvailable()->doPasswordLogin($borrowers->{'1A01'}->userid(), $password)
72
}
94
             ->isLoggedInBranchCode($borrowers->{'1A01'}->branchcode())
95
             ->doPasswordLogout();
96
}
97
sub testOpacPasswordLoginLogout {
98
    my ($mainpage) = @_;
99
    $mainpage->isPasswordLoginAvailable()->doPasswordLogin($borrowers->{'1A01'}->userid(), $password)
100
             ->doPasswordLogout();
101
}
102
sub testSuperuserPasswordLoginLogout {
103
    my ($mainpage) = @_;
104
    $mainpage->isPasswordLoginAvailable()->doPasswordLogin(C4::Context->config('user'), C4::Context->config('pass'))
105
             ->doPasswordLogout();
106
}
107
sub testSuperlibrarianPasswordLoginLogout {
108
    my ($mainpage) = @_;
109
    $mainpage->isPasswordLoginAvailable()->doPasswordLogin($borrowers->{'maxi_admin'}->userid(), $password)
110
             ->isLoggedInBranchCode($borrowers->{'maxi_admin'}->branchcode())
111
             ->doPasswordLogout();
112
}
113
sub testOpacSuperlibrarianPasswordLoginLogout {
114
    my ($mainpage) = @_;
115
    $mainpage->isPasswordLoginAvailable()->doPasswordLogin($borrowers->{'maxi_admin'}->userid(), $password)
116
             ->doPasswordLogout();
117
}
(-)a/t/db_dependent/Koha/Auth/BorrowerPermission.t (+102 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
# Copyright 2015 Vaara-kirjastot
4
#
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>.
19
20
use Modern::Perl;
21
use Test::More;
22
23
use Koha::Auth::BorrowerPermission;
24
use Koha::Auth::BorrowerPermissions;
25
26
use t::lib::TestObjects::ObjectFactory;
27
use t::lib::TestObjects::BorrowerFactory;
28
29
##Setting up the test context
30
my $testContext = {};
31
32
my $borrowerFactory = t::lib::TestObjects::BorrowerFactory->new();
33
my $borrowers = $borrowerFactory->createTestGroup([
34
            {firstname  => 'Olli-Antti',
35
             surname    => 'Kivi',
36
             cardnumber => '1A01',
37
             branchcode => 'CPL',
38
            },
39
            {firstname  => 'Alli-Ontti',
40
             surname    => 'Ivik',
41
             cardnumber => '1A02',
42
             branchcode => 'CPL',
43
            },
44
        ], undef, $testContext);
45
46
##Test context set, starting testing:
47
eval { #run in a eval-block so we don't die without tearing down the test context
48
    ##Basic id-based creation.
49
    my $borrowerPermissionById = Koha::Auth::BorrowerPermission->new({borrowernumber => $borrowers->{'1A01'}->borrowernumber, permission_module_id => 1, permission_id => 1});
50
    $borrowerPermissionById->store();
51
    my @borrowerPermissionById = Koha::Auth::BorrowerPermissions->search({borrowernumber => $borrowers->{'1A01'}->borrowernumber});
52
    is(scalar(@borrowerPermissionById), 1, "BorrowerPermissions, id-based creation:> Borrower has only one permission");
53
    is($borrowerPermissionById[0]->permission_module_id, 1, "BorrowerPermissions, id-based creation:> Same permission_module_id");
54
    is($borrowerPermissionById[0]->permission_id, 1, "BorrowerPermissions, id-based creation:> Same permission_id");
55
56
    ##Basic name-based creation.
57
    my $borrowerPermissionByName = Koha::Auth::BorrowerPermission->new({borrowernumber => $borrowers->{'1A02'}->borrowernumber, permissionModule => 'circulate', permission => 'manage_restrictions'});
58
    $borrowerPermissionByName->store();
59
    my @borrowerPermissionByName = Koha::Auth::BorrowerPermissions->search({borrowernumber => $borrowers->{'1A02'}->borrowernumber});
60
    is(scalar(@borrowerPermissionByName), 1, "BorrowerPermissions, name-based creation:> Borrower has only one permission");
61
    is($borrowerPermissionByName[0]->getPermissionModule->module, 'circulate', "BorrowerPermissions, name-based creation:> Same permission_module");
62
    is($borrowerPermissionByName[0]->getPermission->code, 'manage_restrictions', "BorrowerPermissions, name-based creation:> Same permission");
63
64
    ##Testing setter/getter for Borrower
65
    my $borrower1A01 = $borrowerPermissionById->getBorrower();
66
    is($borrower1A01->cardnumber, "1A01", "BorrowerPermissions, setter/getter:> getBorrower() 1A01");
67
    my $borrower1A02 = $borrowerPermissionByName->getBorrower();
68
    is($borrower1A02->cardnumber, "1A02", "BorrowerPermissions, setter/getter:> getBorrower() 1A02");
69
70
    $borrowerPermissionById->setBorrower($borrower1A02);
71
    is($borrowerPermissionById->getBorrower()->cardnumber, "1A02", "BorrowerPermissions, setter/getter:> setBorrower() 1A02");
72
    $borrowerPermissionByName->setBorrower($borrower1A01);
73
    is($borrowerPermissionByName->getBorrower()->cardnumber, "1A01", "BorrowerPermissions, setter/getter:> setBorrower() 1A01");
74
75
    ##Testing getter for PermissionModule
76
    my $permissionModule1 = $borrowerPermissionById->getPermissionModule();
77
    is($permissionModule1->permission_module_id, 1, "BorrowerPermissions, setter/getter:> getPermissionModule() 1");
78
    my $permissionModuleCirculate = $borrowerPermissionByName->getPermissionModule();
79
    is($permissionModuleCirculate->module, "circulate", "BorrowerPermissions, setter/getter:> getPermissionModule() circulate");
80
81
    #Not testing setters because changing the module might not make any sense.
82
    #Then we would need to make sure we dont end up with bad permissionModule->permission combinations.
83
84
    ##Testing getter for Permission
85
    my $permission1 = $borrowerPermissionById->getPermission();
86
    is($permission1->permission_id, 1, "BorrowerPermissions, setter/getter:> getPermission() 1");
87
    my $permissionManage_restrictions = $borrowerPermissionByName->getPermission();
88
    is($permissionManage_restrictions->code, "manage_restrictions", "BorrowerPermissions, setter/getter:> getPermission() manage_restrictions");
89
};
90
if ($@) { #Catch all leaking errors and gracefully terminate.
91
    warn $@;
92
    tearDown();
93
    exit 1;
94
}
95
96
##All tests done, tear down test context
97
$borrowerFactory->tearDownTestContext($testContext);
98
done_testing;
99
100
sub tearDown {
101
    t::lib::TestObjects::ObjectFactory->tearDownTestContext($testContext);
102
}
(-)a/t/db_dependent/Koha/Auth/PermissionManager.t (+221 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
# Copyright 2015 Vaara-kirjastot
4
#
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>.
19
20
use Modern::Perl;
21
use Test::More;
22
use Try::Tiny;
23
use Scalar::Util qw(blessed);
24
25
use Koha::Auth::PermissionManager;
26
27
use t::lib::TestObjects::ObjectFactory;
28
use t::lib::TestObjects::BorrowerFactory;
29
30
31
##Setting up the test context
32
my $testContext = {};
33
34
my $borrowerFactory = t::lib::TestObjects::BorrowerFactory->new();
35
my $borrowers = $borrowerFactory->createTestGroup([
36
            {firstname  => 'Olli-Antti',
37
             surname    => 'Kivi',
38
             cardnumber => '1A01',
39
             branchcode => 'CPL',
40
            },
41
            {firstname  => 'Alli-Ontti',
42
             surname    => 'Ivik',
43
             cardnumber => '1A02',
44
             branchcode => 'CPL',
45
            },
46
        ], undef, $testContext);
47
48
##Test context set, starting testing:
49
eval { #run in a eval-block so we don't die without tearing down the test context
50
    my $permissionManager = Koha::Auth::PermissionManager->new();
51
    my ($permissionModule, $permission, $failureCaughtFlag, $permissionsList);
52
53
    ##Test getBorrowerPermissions
54
    $permissionManager->grantPermission($borrowers->{'1A01'}, 'circulate', 'force_checkout');
55
    $permissionManager->grantPermission($borrowers->{'1A01'}, 'circulate', 'manage_restrictions');
56
    $permissionsList = $permissionManager->getBorrowerPermissions($borrowers->{'1A01'});
57
    is($permissionsList->[0]->getPermission->code, 'force_checkout', "PermissionManager, getBorrowerPermissions:> Check 1.");
58
    is($permissionsList->[1]->getPermission->code, 'manage_restrictions', "PermissionManager, getBorrowerPermissions:> Check 2.");
59
    $permissionManager->revokePermission($borrowers->{'1A01'}, 'circulate', 'force_checkout');
60
    $permissionManager->revokePermission($borrowers->{'1A01'}, 'circulate', 'manage_restrictions');
61
62
    ##Test grantPermissions && revokeAllPermissions
63
    $permissionManager->grantPermissions($borrowers->{'1A01'},
64
                                         {  borrowers => 'view_borrowers',
65
                                            reserveforothers => ['place_holds'],
66
                                            tools => ['edit_news', 'edit_notices'],
67
                                            acquisition => {
68
                                              budget_add_del => 1,
69
                                              budget_modify => 1,
70
                                            },
71
                                        });
72
    $permissionManager->hasPermission($borrowers->{'1A01'}, 'borrowers', 'view_borrowers');
73
    $permissionManager->hasPermission($borrowers->{'1A01'}, 'tools', 'edit_notices');
74
    $permissionManager->hasPermission($borrowers->{'1A01'}, 'acquisition', 'budget_modify');
75
    $permissionsList = $permissionManager->getBorrowerPermissions($borrowers->{'1A01'});
76
    is(scalar(@$permissionsList), 6, "PermissionManager, grantPermissions:> Permissions as HASH, ARRAY and Scalar.");
77
78
    $permissionManager->revokeAllPermissions($borrowers->{'1A01'});
79
    $permissionsList = $permissionManager->getBorrowerPermissions($borrowers->{'1A01'});
80
    is(scalar(@$permissionsList), 0, "PermissionManager, revokeAllPermissions:> No permissions left.");
81
82
    ##Test listKohaPermissionsAsHASH
83
    my $listedPermissions = $permissionManager->listKohaPermissionsAsHASH();
84
    ok(ref($listedPermissions->{circulate}->{permissions}->{force_checkout}) eq 'HASH', "PermissionManager, listKohaPermissionsAsHASH:> Check 1.");
85
    ok(ref($listedPermissions->{editcatalogue}->{permissions}->{edit_catalogue}) eq 'HASH', "PermissionManager, listKohaPermissionsAsHASH:> Check 2.");
86
    ok(defined($listedPermissions->{reports}->{permissions}->{create_reports}->{description}), "PermissionManager, listKohaPermissionsAsHASH:> Check 3.");
87
    ok(defined($listedPermissions->{permissions}->{description}), "PermissionManager, listKohaPermissionsAsHASH:> Check 4.");
88
89
90
91
    ###   TESTING WITH unique keys, instead of the recommended Koha::Objects. ###
92
    #Arguably this makes for more clear tests cases :)
93
    ##Add/get PermissionModule
94
    $permissionModule = $permissionManager->addPermissionModule({module => 'test', description => 'Just testing this module.'});
95
    is($permissionModule->module, "test", "PermissionManager from names, add/getPermissionModule:> Module added.");
96
    $permissionModule = $permissionManager->getPermissionModule('test');
97
    is($permissionModule->module, "test", "PermissionManager from names, add/getPermissionModule:> Module got.");
98
99
    ##Add/get Permission
100
    $permission = $permissionManager->addPermission({module => 'test', code => 'testperm', description => 'Just testing this permission.'});
101
    is($permission->code, "testperm", "PermissionManager from names, add/getPermission:> Permission added.");
102
    $permission = $permissionManager->getPermission('testperm');
103
    is($permission->code, "testperm", "PermissionManager from names, add/getPermission:> Permission got.");
104
105
    ##Grant permission
106
    $permissionManager->grantPermission($borrowers->{'1A01'}, 'test', 'testperm');
107
    ok($permissionManager->hasPermission($borrowers->{'1A01'}, 'test', 'testperm'), "PermissionManager from names, grant/hasPermission:> Borrower granted permission.");
108
109
    ##hasPermission with wildcard
110
    ok($permissionManager->hasPermission($borrowers->{'1A01'}, 'test', '*'), "PermissionManager from names, hasPermission:> Wildcard permission.");
111
112
    ##hasPermissions with wildcard
113
    ok($permissionManager->hasPermissions($borrowers->{'1A01'}, {test => ['*']}), "PermissionManager from names, hasPermission:> Wildcard permissions from array.");
114
115
    ##Revoke permission
116
    $permissionManager->revokePermission($borrowers->{'1A01'}, 'test', 'testperm');
117
    $failureCaughtFlag = 0;
118
    try {
119
        $permissionManager->hasPermission($borrowers->{'1A01'}, 'test', 'testperm');
120
    } catch {
121
        if (blessed($_) && $_->isa('Koha::Exception::NoPermission')) {
122
            $failureCaughtFlag = 1;
123
        }
124
        else {
125
            die $_; #Somekind of another problem arised and rethrow it.
126
        }
127
    };
128
    ok($failureCaughtFlag, "PermissionManager from names, revoke/hasPermission:> Borrower revoked permission.");
129
130
    ##Delete permissions and modules we just made. When we delete the module first, the permissions is ON CASCADE DELETEd
131
    $permissionManager->delPermissionModule('test');
132
    $permissionModule = $permissionManager->getPermissionModule('test');
133
    ok(not(defined($permissionModule)), "PermissionManager from names, delPermissionModule:> Module deleted.");
134
135
    $failureCaughtFlag = 0;
136
    try {
137
        #This subpermission is now deleted due to cascading delete of the parent permissionModule
138
        #We catch the exception gracefully and report test success
139
        $permissionManager->delPermission('testperm');
140
    } catch {
141
        if (blessed($_) && $_->isa('Koha::Exception::UnknownObject')) {
142
            $failureCaughtFlag = 1;
143
        }
144
        else {
145
            die $_; #Somekind of another problem arised and rethrow it.
146
        }
147
    };
148
    ok($failureCaughtFlag, "PermissionManager from names, delPermission:> Permission already deleted, exception caught.");
149
    $permission = $permissionManager->getPermission('testperm');
150
    ok(not(defined($permission)), "PermissionManager from names, delPermission:> Permission deleted.");
151
152
153
154
    ###  TESTING WITH Koha::Object parameters instead.  ###
155
    ##Add/get PermissionModule
156
    $permissionModule = $permissionManager->addPermissionModule({module => 'test', description => 'Just testing this module.'});
157
    is($permissionModule->module, "test", "PermissionManager from objects, add/getPermissionModule:> Module added.");
158
    $permissionModule = $permissionManager->getPermissionModule($permissionModule);
159
    is($permissionModule->module, "test", "PermissionManager from objects, add/getPermissionModule:> Module got.");
160
161
    ##Add/get Permission
162
    $permission = $permissionManager->addPermission({module => 'test', code => 'testperm', description => 'Just testing this permission.'});
163
    is($permission->code, "testperm", "PermissionManager from objects, add/getPermission:> Permission added.");
164
    $permission = $permissionManager->getPermission($permission);
165
    is($permission->code, "testperm", "PermissionManager from objects, add/getPermission:> Permission got.");
166
167
    ##Grant permission
168
    $permissionManager->grantPermission($borrowers->{'1A01'}, $permissionModule, $permission);
169
    ok($permissionManager->hasPermission($borrowers->{'1A01'}, $permissionModule, $permission), "PermissionManager from objects, grant/hasPermission:> Borrower granted permission.");
170
171
    ##hasPermission with wildcard
172
    ok($permissionManager->hasPermission($borrowers->{'1A01'}, $permissionModule, '*'), "PermissionManager from objects, hasPermission:> Wildcard permission.");
173
174
    ##hasPermissions with wildcard, we quite cannot use a blessed Object as a HASH key
175
    #ok($permissionManager->hasPermissions($borrowers->{'1A01'}, {$permissionModule->module() => ['*']}), "PermissionManager from objects, hasPermission:> Wildcard permissions from array.");
176
177
    ##Revoke permission
178
    $permissionManager->revokePermission($borrowers->{'1A01'}, $permissionModule, $permission);
179
    $failureCaughtFlag = 0;
180
    try {
181
        $permissionManager->hasPermission($borrowers->{'1A01'}, $permissionModule, $permission);
182
    } catch {
183
        if (blessed($_) && $_->isa('Koha::Exception::NoPermission')) {
184
            $failureCaughtFlag = 1;
185
        }
186
        else {
187
            die $_; #Somekind of another problem arised and rethrow it.
188
        }
189
    };
190
    ok($failureCaughtFlag, "PermissionManager from objects, revoke/hasPermission:> Borrower revoked permission.");
191
192
    ##Delete permissions and modules we just made
193
    $permissionManager->delPermission($permission);
194
    $permission = $permissionManager->getPermission('testperm');
195
    ok(not(defined($permission)), "PermissionManager from objects, delPermission:> Permission deleted.");
196
197
    $permissionManager->delPermissionModule($permissionModule);
198
    $permissionModule = $permissionManager->getPermissionModule('test');
199
    ok(not(defined($permissionModule)), "PermissionManager from objects, delPermissionModule:> Module deleted.");
200
201
202
203
    ##Testing superlibrarian permission
204
    $permissionManager->revokeAllPermissions($borrowers->{'1A01'});
205
    $permissionManager->grantPermission($borrowers->{'1A01'}, 'superlibrarian', 'superlibrarian');
206
    ok($permissionManager->hasPermission($borrowers->{'1A01'}, 'staffaccess', 'staff_access_permissions'), "PermissionManager, superuser permission:> Superuser has all permissions 1.");
207
    ok($permissionManager->hasPermission($borrowers->{'1A01'}, 'tools', 'batch_upload_patron_images'), "PermissionManager, superuser permission:> Superuser has all permissions 2.");
208
};
209
if ($@) { #Catch all leaking errors and gracefully terminate.
210
    warn $@;
211
    tearDown();
212
    exit 1;
213
}
214
215
##All tests done, tear down test context
216
tearDown();
217
done_testing;
218
219
sub tearDown {
220
    t::lib::TestObjects::ObjectFactory->tearDownTestContext($testContext);
221
}
(-)a/t/db_dependent/Members/member-flags.t (+100 lines)
Line 0 Link Here
1
#!/usr/bin/env perl
2
3
# Copyright 2015 Open Source Freedom Fighters
4
#
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>.
19
20
use Modern::Perl;
21
22
use Test::More;
23
use Try::Tiny; #Even Selenium::Remote::Driver uses Try::Tiny :)
24
use Scalar::Util qw(blessed);
25
26
use t::lib::Page::Members::MemberFlags;
27
use t::lib::TestObjects::BorrowerFactory;
28
use Koha::Auth::PermissionManager;
29
30
31
##Setting up the test context
32
my $testContext = {};
33
34
my $password = '1234';
35
my $borrowerFactory = t::lib::TestObjects::BorrowerFactory->new();
36
my $borrowers = $borrowerFactory->createTestGroup([
37
            {firstname  => 'Olli-Antti',
38
             surname    => 'Kivi',
39
             cardnumber => '1A01',
40
             branchcode => 'CPL',
41
             userid     => 'mini_admin',
42
             password   => $password,
43
            },
44
        ], undef, $testContext);
45
46
##Test context set, starting testing:
47
eval { #run in a eval-block so we don't die without tearing down the test context
48
49
    testGrantRevokePermissions();
50
51
};
52
if ($@) { #Catch all leaking errors and gracefully terminate.
53
    warn $@;
54
    tearDown();
55
    exit 1;
56
}
57
58
##All tests done, tear down test context
59
tearDown();
60
done_testing;
61
62
sub tearDown {
63
    t::lib::TestObjects::ObjectFactory->tearDownTestContext($testContext);
64
}
65
66
sub testGrantRevokePermissions {
67
    my $permissionManager = Koha::Auth::PermissionManager->new();
68
    $permissionManager->grantPermissions($borrowers->{'1A01'}, {permissions => 'set_permissions',
69
                                                                catalogue => 'staff_login',
70
                                                                staffaccess => 'staff_access_permissions',
71
                                                                circulate => 'override_renewals',
72
                                                                borrowers => 'view_borrowers',
73
                                                              });
74
75
    my $memberflags = t::lib::Page::Members::MemberFlags->new({borrowernumber => $borrowers->{'1A01'}->borrowernumber});
76
77
    $memberflags->isPasswordLoginAvailable()->doPasswordLogin($borrowers->{'1A01'}->userid, $password)
78
                ->togglePermission('editcatalogue', 'delete_all_items') #Add this
79
                ->togglePermission('editcatalogue', 'edit_items') #Add this
80
                ->togglePermission('circulate', 'override_renewals') #Remove this permission
81
                ->submitPermissionTree();
82
83
    ok($permissionManager->hasPermissions($borrowers->{'1A01'},{editcatalogue => ['delete_all_items', 'edit_items']}),
84
    "member-flags.pl:> Granting new permissions succeeded.");
85
86
    my $failureCaughtFlag = 0;
87
    try {
88
        $permissionManager->hasPermission($borrowers->{'1A01'}, 'circulate', 'override_renewals');
89
    } catch {
90
        if (blessed($_) && $_->isa('Koha::Exception::NoPermission')) {
91
            $failureCaughtFlag = 1;
92
        }
93
        else {
94
            die $_; #Somekind of another problem arised and rethrow it.
95
        }
96
    };
97
    ok($failureCaughtFlag, "member-flags.pl:> Revoking permissions succeeded.");
98
99
    $permissionManager->revokeAllPermissions($borrowers->{'1A01'});
100
}
(-)a/t/db_dependent/Opac/opac-search.t (-1 / +79 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/env perl
2
3
# Copyright 2015 Open Source Freedom Fighters
4
#
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>.
19
20
use Modern::Perl;
21
22
use Test::More;
23
24
use t::lib::Page::Opac::OpacSearch;
25
use t::lib::TestObjects::BorrowerFactory;
26
27
28
##Setting up the test context
29
my $testContext = {};
30
31
my $password = '1234';
32
my $borrowerFactory = t::lib::TestObjects::BorrowerFactory->new();
33
my $borrowers = $borrowerFactory->createTestGroup([
34
            {firstname  => 'Olli-Antti',
35
             surname    => 'Kivi',
36
             cardnumber => '1A01',
37
             branchcode => 'CPL',
38
             userid     => 'mini_admin',
39
             password   => $password,
40
            },
41
        ], undef, $testContext);
42
43
##Test context set, starting testing:
44
eval { #run in a eval-block so we don't die without tearing down the test context
45
46
    my $opacsearch = t::lib::Page::Opac::OpacSearch->new();
47
    testAnonymousSearchHistory($opacsearch);
48
49
};
50
if ($@) { #Catch all leaking errors and gracefully terminate.
51
    warn $@;
52
    tearDown();
53
    exit 1;
54
}
55
56
##All tests done, tear down test context
57
tearDown();
58
done_testing;
59
60
sub tearDown {
61
    t::lib::TestObjects::ObjectFactory->tearDownTestContext($testContext);
62
}
63
64
sub testAnonymousSearchHistory {
65
    my $opacsearch = shift;
66
67
    $opacsearch->doSetSearchFieldTerm(1, 'Author', 'nengard')->doSearchSubmit()->navigateAdvancedSearch()
68
               ->doSetSearchFieldTerm(1, 'Author', 'joubu')->doSearchSubmit()->navigateAdvancedSearch()
69
               ->doSetSearchFieldTerm(1, 'Author', 'khall')->doSearchSubmit()->navigateHome()
70
               ->doPasswordLogin($borrowers->{'1A01'}->userid, $password)->navigateAdvancedSearch()
71
               ->doSetSearchFieldTerm(1, 'Author', 'magnuse')->doSearchSubmit()->navigateAdvancedSearch()
72
               ->doSetSearchFieldTerm(1, 'Author', 'cait')->doSearchSubmit()->navigateSearchHistory()
73
               ->testDoSearchHistoriesExist(['nengard',
74
                                             'joubu',
75
                                             'khall',
76
                                             'magnuse',
77
                                             'cait'])
78
               ->quit();
79
}

Return to bug 14540