Bugzilla – Attachment 41402 Details for
Bug 14540
Move member-flags.pl to PermissionsManager to better manage permissions for testing.
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 14540 - Move member-flags.pl to PermissionsManager to better manage permissions for testing.
Bug-14540---Move-member-flagspl-to-PermissionsMana.patch (text/plain), 127.19 KB, created by
Olli-Antti Kivilahti
on 2015-08-06 10:25:54 UTC
(
hide
)
Description:
Bug 14540 - Move member-flags.pl to PermissionsManager to better manage permissions for testing.
Filename:
MIME Type:
Creator:
Olli-Antti Kivilahti
Created:
2015-08-06 10:25:54 UTC
Size:
127.19 KB
patch
obsolete
>From 986183b44bf27b39d909cfa8874a48ee541c77e5 Mon Sep 17 00:00:00 2001 >From: Olli-Antti Kivilahti <olli-antti.kivilahti@jns.fi> >Date: Mon, 13 Jul 2015 09:15:12 +0000 >Subject: [PATCH] Bug 14540 - Move member-flags.pl to PermissionsManager to > better manage permissions for testing. >MIME-Version: 1.0 >Content-Type: text/plain; charset=UTF-8 >Content-Transfer-Encoding: 8bit > >Currently there is no nice way to grant/revoke permissions for Borrowers in Koha. >This is a big problem when doing integration testing and when working with >permissions using the future REST API. > >Currently we have one web-script, member-flags.pl, which deals with all >permission-related things. Basically it always DELETEs all your permissions and >then adds them again with some modifications. There is no internal API for >creating permissions and this makes automated testing significantly harder. >To create permissions for a test borrower, we must decrypt the arcane way of >creating koha.borrowers.flags and add user_permissions with brittle SQL-queries. >This makes for very messy test scripts, and quite frankly this is hardly ever done >in Koha. >Also the koha.borrowers.flags-column is pretty horrible. It is 19-bit binary >array where each bit tells of the borrower has all permissions for the respective >permission module. This is very difficult to calculate and the mechanism is hard >to understand. This feature is also unnecessary, since we are always interested in >having the specific permissions. We don't need to know if one Borrower has all the >permissions for one module. Also what happens if more subpermissions are added to >the module? Existing all-permission-holders lose their all-permissions-status? > >Instead we could have a nice internal API to work with permissions. > >My patch introduces a new database structure for permissions >(not necessarily better), Koha::Object implementation of the DB structure, >and most importantly, a Koha::Auth::PermissionManager which is a gateway to all >permissions-related actions. > >This feature is well tested with unit tests and PageObject integration tests. >See the tests for usage examples. >Especially the t/db_dependent/Members/member-flags.t >I hope you like it :) > >SELENIUM TESTS: >Now that the new permission manager enables setting permissions easily in test >environments. This patch introduces more complex PageObject regressions tests. >-Logged in branch regression test for Intra. >-OPAC password login/logout >-OPAC anonymous search history preservation. > >VOCABULARY: > >Module (permission_modules) > => a module which consists of specific Permissions. > Typically covers one Module in Koha. >Permission (permission) > => a specific Permission of a Module. Granting a > Borrower the permission to do something. >Borrower permission (borrower_permissions) > => A specific Permission a specific Borrower has, eg. the permission to > edit bibliographic records. > >TEST PLAN: > >-2. Note the permissions a bunch of borrowers has. >-1. run updatedatabase.pl >0. Observe that those borrowers still have the same permissions. For modules > which didn't have any subpermissions, a generic subpermission is added and > the borrowers should have it if they had the existing module permission. > >Basic login: > >1. Go to Koha staff client >2. Make a password login. >3. Browse to any other staff client pages to confirm that the session is active > and login persists on other pages. > >Modify permissions: > >1. Go to member-flags.pl (Home ⺠Patrons ⺠Set permissions) >2. Change your permissions. Save. >3. Go back to member-flags.pl >4. Observe that you see the same permissions you just set. > >Modify superlibrarian permission: > >1. Go to member-flags.pl (Home ⺠Patrons ⺠Set permissions) >2. Give the superlibrarian-permission. Observe all other permissions vanishing. > Save. >3. Go back to member-flags.pl >4. Observe that you see only the superlibrarian-permission active. >5. Observe that the superlibrarian permission is the only top-level permission > which doesn't have any subpermissions. >--- > C4/Auth.pm | 77 +-- > C4/Members.pm | 11 +- > Koha/Auth/BorrowerPermission.pm | 221 +++++++++ > Koha/Auth/BorrowerPermissions.pm | 38 ++ > Koha/Auth/Permission.pm | 60 +++ > Koha/Auth/PermissionManager.pm | 529 +++++++++++++++++++++ > Koha/Auth/PermissionModule.pm | 78 +++ > Koha/Auth/PermissionModules.pm | 38 ++ > Koha/Auth/Permissions.pm | 42 ++ > Koha/AuthUtils.pm | 1 - > Koha/Schema/Result/Borrower.pm | 71 ++- > Koha/Schema/Result/Permission.pm | 79 +-- > installer/data/mysql/en/mandatory/userflags.sql | 40 +- > .../data/mysql/en/mandatory/userpermissions.sql | 159 ++++--- > installer/data/mysql/kohastructure.sql | 94 ++-- > installer/data/mysql/updatedatabase.pl | 113 +++++ > .../prog/en/modules/members/member-flags.tt | 14 +- > members/member-flags.pl | 198 ++++---- > misc/devel/interactiveWebDriverShell.pl | 9 +- > opac/opac-user.pl | 2 +- > t/db_dependent/Koha/Auth.t | 57 ++- > t/db_dependent/Koha/Auth/BorrowerPermission.t | 102 ++++ > t/db_dependent/Koha/Auth/PermissionManager.t | 221 +++++++++ > t/db_dependent/Members/member-flags.t | 100 ++++ > t/db_dependent/Opac/opac-search.t | 79 +++ > 25 files changed, 2077 insertions(+), 356 deletions(-) > create mode 100644 Koha/Auth/BorrowerPermission.pm > create mode 100644 Koha/Auth/BorrowerPermissions.pm > create mode 100644 Koha/Auth/Permission.pm > create mode 100644 Koha/Auth/PermissionManager.pm > create mode 100644 Koha/Auth/PermissionModule.pm > create mode 100644 Koha/Auth/PermissionModules.pm > create mode 100644 Koha/Auth/Permissions.pm > create mode 100644 t/db_dependent/Koha/Auth/BorrowerPermission.t > create mode 100644 t/db_dependent/Koha/Auth/PermissionManager.t > create mode 100644 t/db_dependent/Members/member-flags.t > create mode 100644 t/db_dependent/Opac/opac-search.t > >diff --git a/C4/Auth.pm b/C4/Auth.pm >index 34c3f91..1e6d464 100644 >--- a/C4/Auth.pm >+++ b/C4/Auth.pm >@@ -23,6 +23,8 @@ use Digest::MD5 qw(md5_base64); > use JSON qw/encode_json/; > use URI::Escape; > use CGI::Session; >+use Scalar::Util qw(blessed); >+use Try::Tiny; > > require Exporter; > use C4::Context; >@@ -226,7 +228,7 @@ sub get_template_and_user { > # We are going to use the $flags returned by checkauth > # to create the template's parameters that will indicate > # which menus the user can access. >- if ( $flags && $flags->{superlibrarian} == 1 ) { >+ if ( $flags && $flags->{superlibrarian} ) { > $template->param( CAN_user_circulate => 1 ); > $template->param( CAN_user_catalogue => 1 ); > $template->param( CAN_user_parameters => 1 ); >@@ -254,11 +256,7 @@ sub get_template_and_user { > > if ($flags) { > foreach my $module ( keys %$all_perms ) { >- if ( defined($flags->{$module}) && $flags->{$module} == 1 ) { >- foreach my $subperm ( keys %{ $all_perms->{$module} } ) { >- $template->param( "CAN_user_${module}_${subperm}" => 1 ); >- } >- } elsif ( ref( $flags->{$module} ) ) { >+ if ( ref( $flags->{$module} ) ) { > foreach my $subperm ( keys %{ $flags->{$module} } ) { > $template->param( "CAN_user_${module}_${subperm}" => 1 ); > } >@@ -992,7 +990,7 @@ sub checkauth { > > if ( $return == 1 ) { > my $select = " >- SELECT borrowernumber, firstname, surname, flags, borrowers.branchcode, >+ SELECT borrowernumber, firstname, surname, borrowers.branchcode, > branches.branchname as branchname, > branches.branchprinter as branchprinter, > email >@@ -1015,7 +1013,7 @@ sub checkauth { > } > } > if ( $sth->rows ) { >- ( $borrowernumber, $firstname, $surname, $userflags, >+ ( $borrowernumber, $firstname, $surname, > $branchcode, $branchname, $branchprinter, $emailaddress ) = $sth->fetchrow; > $debug and print STDERR "AUTH_3 results: " . > "$cardnumber,$borrowernumber,$userid,$firstname,$surname,$userflags,$branchcode,$emailaddress\n"; >@@ -1741,7 +1739,7 @@ sub checkpw_internal { > > my $sth = > $dbh->prepare( >- "select password,cardnumber,borrowernumber,userid,firstname,surname,borrowers.branchcode,branches.branchname,flags from borrowers join branches on borrowers.branchcode=branches.branchcode where userid=?" >+ "select password,cardnumber,borrowernumber,userid,firstname,surname,borrowers.branchcode,branches.branchname from borrowers join branches on borrowers.branchcode=branches.branchcode where userid=?" > ); > $sth->execute($userid); > if ( $sth->rows ) { >@@ -1758,18 +1756,18 @@ sub checkpw_internal { > } > $sth = > $dbh->prepare( >- "select password,cardnumber,borrowernumber,userid,firstname,surname,borrowers.branchcode,branches.branchname,flags from borrowers join branches on borrowers.branchcode=branches.branchcode where cardnumber=?" >+ "select password,cardnumber,borrowernumber,userid,firstname,surname,borrowers.branchcode,branches.branchname from borrowers join branches on borrowers.branchcode=branches.branchcode where cardnumber=?" > ); > $sth->execute($userid); > if ( $sth->rows ) { > my ( $stored_hash, $cardnumber, $borrowernumber, $userid, $firstname, >- $surname, $branchcode, $branchname, $flags ) >+ $surname, $branchcode, $branchname ) > = $sth->fetchrow; > > if ( checkpw_hash( $password, $stored_hash ) ) { > > C4::Context->set_userenv( $borrowernumber, $userid, $cardnumber, >- $firstname, $surname, $branchcode, $branchname, $flags ); >+ $firstname, $surname, $branchcode, $branchname ); > return 1, $cardnumber, $userid; > } > } >@@ -1801,6 +1799,7 @@ sub checkpw_hash { > } > > =head2 getuserflags >+@DEPRECATED, USE THE Koha::Auth::PermissionManager > > my $authflags = getuserflags($flags, $userid, [$dbh]); > >@@ -1813,6 +1812,7 @@ C<$authflags> is a hashref of permissions > =cut > > sub getuserflags { >+ #@DEPRECATED, USE THE Koha::Auth::PermissionManager > my $flags = shift; > my $userid = shift; > my $dbh = @_ ? shift : C4::Context->dbh; >@@ -1824,6 +1824,9 @@ sub getuserflags { > no warnings 'numeric'; > $flags += 0; > } >+ return get_user_subpermissions($userid); >+ >+ #@DEPRECATED, USE THE Koha::Auth::PermissionManager > my $sth = $dbh->prepare("SELECT bit, flag, defaulton FROM userflags"); > $sth->execute; > >@@ -1847,7 +1850,7 @@ sub getuserflags { > } > > =head2 get_user_subpermissions >- >+@DEPRECATED, USE THE Koha::Auth::PermissionManager > $user_perm_hashref = get_user_subpermissions($userid); > > Given the userid (note, not the borrowernumber) of a staff user, >@@ -1872,25 +1875,22 @@ necessary to check borrowers.flags. > =cut > > sub get_user_subpermissions { >+ #@DEPRECATED, USE THE Koha::Auth::PermissionManager > my $userid = shift; > >- my $dbh = C4::Context->dbh; >- my $sth = $dbh->prepare( "SELECT flag, user_permissions.code >- FROM user_permissions >- JOIN permissions USING (module_bit, code) >- JOIN userflags ON (module_bit = bit) >- JOIN borrowers USING (borrowernumber) >- WHERE userid = ?" ); >- $sth->execute($userid); >- >+ use Koha::Auth::PermissionManager; >+ my $permissionManager = Koha::Auth::PermissionManager->new(); >+ my $borrowerPermissions = $permissionManager->getBorrowerPermissions($userid); #Prefetch all related tables. > my $user_perms = {}; >- while ( my $perm = $sth->fetchrow_hashref ) { >- $user_perms->{ $perm->{'flag'} }->{ $perm->{'code'} } = 1; >+ foreach my $perm ( @$borrowerPermissions ) { >+ $user_perms->{ $perm->getPermissionModule->module }->{ $perm->getPermission->code } = 1; > } >+ > return $user_perms; > } > > =head2 get_all_subpermissions >+@DEPRECATED, USE THE Koha::Auth::PermissionManager > > my $perm_hashref = get_all_subpermissions(); > >@@ -1903,6 +1903,20 @@ of the subpermission. > =cut > > sub get_all_subpermissions { >+ #@DEPRECATED, USE THE Koha::Auth::PermissionManager >+ use Koha::Auth::PermissionManager; >+ my $permissionManager = Koha::Auth::PermissionManager->new(); >+ my $all_permissions = $permissionManager->listKohaPermissionsAsHASH(); >+ foreach my $module ( keys %$all_permissions ) { >+ my $permissionModule = $all_permissions->{$module}; >+ foreach my $code (keys %{$permissionModule->{permissions}}) { >+ my $permission = $permissionModule->{permissions}->{$code}; >+ $all_permissions->{$module}->{$code} = $permission->{'description'}; >+ } >+ } >+ return $all_permissions; >+ >+ #@DEPRECATED, USE THE Koha::Auth::PermissionManager > my $dbh = C4::Context->dbh; > my $sth = $dbh->prepare( "SELECT flag, code, description > FROM permissions >@@ -1917,6 +1931,7 @@ sub get_all_subpermissions { > } > > =head2 haspermission >+@DEPRECATED, USE THE Koha::Auth::PermissionManager > > $flags = ($userid, $flagsrequired); > >@@ -1928,11 +1943,15 @@ Returns member's flags or 0 if a permission is not met. > =cut > > sub haspermission { >+ #@DEPRECATED, USE THE Koha::Auth::PermissionManager > my ( $userid, $flagsrequired ) = @_; >- my $sth = C4::Context->dbh->prepare("SELECT flags FROM borrowers WHERE userid=?"); >- $sth->execute($userid); >- my $row = $sth->fetchrow(); >- my $flags = getuserflags( $row, $userid ); >+ >+ my $flags = getuserflags( undef, $userid ); >+ #Sanitate 1 to * because we no longer have 1's from the koha.borrowers.flags. >+ foreach my $module (%$flagsrequired) { >+ $flagsrequired->{$module} = '*' if $flagsrequired->{$module} && $flagsrequired->{$module} eq '1'; >+ } >+ > if ( $userid eq C4::Context->config('user') ) { > > # Super User Account from /etc/koha.conf >@@ -1949,7 +1968,7 @@ sub haspermission { > foreach my $module ( keys %$flagsrequired ) { > my $subperm = $flagsrequired->{$module}; > if ( $subperm eq '*' ) { >- return 0 unless ( $flags->{$module} == 1 or ref( $flags->{$module} ) ); >+ return 0 unless ( ref( $flags->{$module} ) ); > } else { > return 0 unless ( > ( defined $flags->{$module} and >diff --git a/C4/Members.pm b/C4/Members.pm >index 1a172db..e84095a 100644 >--- a/C4/Members.pm >+++ b/C4/Members.pm >@@ -230,17 +230,8 @@ sub GetMemberDetails { > $borrower->{'amountoutstanding'} = $amount; > # FIXME - patronflags calls GetMemberAccountRecords... just have patronflags return $amount > my $flags = patronflags( $borrower); >- my $accessflagshash; > >- $sth = $dbh->prepare("select bit,flag from userflags"); >- $sth->execute; >- while ( my ( $bit, $flag ) = $sth->fetchrow ) { >- if ( $borrower->{'flags'} && $borrower->{'flags'} & 2**$bit ) { >- $accessflagshash->{$flag} = 1; >- } >- } >- $borrower->{'flags'} = $flags; >- $borrower->{'authflags'} = $accessflagshash; >+ $borrower->{'flags'} = $flags; #Is this the flags-column? @DEPRECATED! > > # For the purposes of making templates easier, we'll define a > # 'showname' which is the alternate form the user's first name if >diff --git a/Koha/Auth/BorrowerPermission.pm b/Koha/Auth/BorrowerPermission.pm >new file mode 100644 >index 0000000..945abaa >--- /dev/null >+++ b/Koha/Auth/BorrowerPermission.pm >@@ -0,0 +1,221 @@ >+package Koha::Auth::BorrowerPermission; >+ >+# Copyright 2015 Vaara-kirjastot >+# >+# This file is part of Koha. >+# >+# Koha is free software; you can redistribute it and/or modify it >+# under the terms of the GNU General Public License as published by >+# the Free Software Foundation; either version 3 of the License, or >+# (at your option) any later version. >+# >+# Koha is distributed in the hope that it will be useful, but >+# WITHOUT ANY WARRANTY; without even the implied warranty of >+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+# GNU General Public License for more details. >+# >+# You should have received a copy of the GNU General Public License >+# along with Koha; if not, see <http://www.gnu.org/licenses>. >+ >+use Modern::Perl; >+use Scalar::Util qw(blessed); >+ >+use Koha::Auth::BorrowerPermissions; >+use Koha::Auth::PermissionModules; >+use Koha::Auth::Permissions; >+use Koha::Borrowers; >+ >+use Koha::Exception::BadParameter; >+ >+use base qw(Koha::Object); >+ >+sub type { >+ return 'BorrowerPermission'; >+} >+sub object_class { >+ return 'Koha::Auth::BorrowerPermission'; >+} >+ >+=head NAME >+ >+Koha::Auth::BorrowerPermission >+ >+=head SYNOPSIS >+ >+Object representation of a Permission given to a Borrower. >+ >+=head new >+ >+ my $borrowerPermission = Koha::Auth::BorrowerPermission->new({ >+ borrowernumber => 12, >+ permission_module_id => 2, >+ permission => $Koha::Auth::Permission, >+ }); >+ my $borrowerPermission = Koha::Auth::BorrowerPermission->new({ >+ borrower => $Koha::Borrower, >+ permissionModule => $Koha::Auth::PermissionModule, >+ permission_id => 22, >+ }); >+ >+Remember to ->store() the returned object to persist it in the DB. >+@PARAM1 HASHRef of constructor parameters: >+ MANDATORY keys: >+ borrower or borrowernumber >+ permissionModule or permission_module_id >+ permission or permission_id >+ Values can be either Koha::Object derivatives or their respective DB primary keys >+@RETURNS Koha::Auth::BorrowerPermission >+=cut >+ >+sub new { >+ my ($class, $params) = @_; >+ >+ _validateParams($params); >+ >+ #Check for duplicates, and update existing permission if available. >+ my $self = Koha::Auth::BorrowerPermissions->find({borrowernumber => $params->{borrower}->borrowernumber, >+ permission_module_id => $params->{permissionModule}->permission_module_id, >+ permission_id => $params->{permission}->permission_id, >+ }); >+ $self = $class->SUPER::new() unless $self; >+ $self->{params} = $params; >+ $self->set({borrowernumber => $self->getBorrower()->borrowernumber, >+ permission_id => $self->getPermission()->permission_id, >+ permission_module_id => $self->getPermissionModule()->permission_module_id >+ }); >+ return $self; >+} >+ >+=head getBorrower >+ >+ my $borrower = $borrowerPermission->getBorrower(); >+ >+@RETURNS Koha::Borrower >+=cut >+ >+sub getBorrower { >+ my ($self) = @_; >+ >+ unless ($self->{params}->{borrower}) { >+ my $dbix_borrower = $self->_result()->borrower; >+ my $borrower = Koha::Borrower->_new_from_dbic($dbix_borrower); >+ $self->{params}->{borrower} = $borrower; >+ } >+ return $self->{params}->{borrower}; >+} >+ >+=head setBorrower >+ >+ my $borrowerPermission = $borrowerPermission->setBorrower( $borrower ); >+ >+Set the Borrower. >+When setting the DB is automatically updated as well. >+@PARAM1 Koha::Borrower, set the given Borrower to this BorrowerPermission. >+@RETURNS Koha::Auth::BorrowerPermission, >+=cut >+ >+sub setBorrower { >+ my ($self, $borrower) = @_; >+ >+ unless (blessed($borrower) && $borrower->isa('Koha::Borrower')) { >+ Koha::Exception::BadParameter->throw(error => __PACKAGE__."->setPermissionModule():> Given parameter '\\$borrower' is not a Koha::Borrower-object!"); >+ } >+ $self->{params}->{borrower} = $borrower; >+ $self->set({borrowernumber => $borrower->borrowernumber()}); >+ $self->store(); >+} >+ >+=head getPermissionModule >+ >+ my $permissionModule = $borrowerPermission->getPermissionModule(); >+ >+@RETURNS Koha::Auth::PermissionModule >+=cut >+ >+sub getPermissionModule { >+ my ($self) = @_; >+ >+ unless ($self->{params}->{permissionModule}) { >+ my $dbix_object = $self->_result()->permission_module; >+ my $object = Koha::Auth::PermissionModule->_new_from_dbic($dbix_object); >+ $self->{params}->{permissionModule} = $object; >+ } >+ return $self->{params}->{permissionModule}; >+} >+ >+=head setPermissionModule >+ >+ my $borrowerPermission = $borrowerPermission->setPermissionModule( $permissionModule ); >+ >+Set the PermissionModule. >+When setting the DB is automatically updated as well. >+@PARAM1 Koha::Auth::PermissionModule, set the given PermissionModule as >+ the PermissionModule of this BorrowePermission. >+@RETURNS Koha::Auth::BorrowerPermission, >+=cut >+ >+sub setPermissionModule { >+ my ($self, $permissionModule) = @_; >+ >+ unless (blessed($permissionModule) && $permissionModule->isa('Koha::Auth::PermissionModule')) { >+ Koha::Exception::BadParameter->throw(error => __PACKAGE__."->setPermissionModule():> Given parameter '\$permissionModule' is not a Koha::Auth::PermissionModule-object!"); >+ } >+ $self->{params}->{permissionModule} = $permissionModule; >+ $self->set({permission_module_id => $permissionModule->permission_module_id()}); >+ $self->store(); >+} >+ >+=head getPermission >+ >+ my $permission = $borrowerPermission->getPermission(); >+ >+@RETURNS Koha::Auth::Permission >+=cut >+ >+sub getPermission { >+ my ($self) = @_; >+ >+ unless ($self->{params}->{permission}) { >+ my $dbix_object = $self->_result()->permission; >+ my $object = Koha::Auth::Permission->_new_from_dbic($dbix_object); >+ $self->{params}->{permission} = $object; >+ } >+ return $self->{params}->{permission}; >+} >+ >+=head setPermission >+ >+ my $borrowerPermission = $borrowerPermission->setPermission( $permission ); >+ >+Set the Permission. >+When setting the DB is automatically updated as well. >+@PARAM1 Koha::Auth::Permission, set the given Permission to this BorrowerPermission. >+@RETURNS Koha::Auth::BorrowerPermission, >+=cut >+ >+sub setPermission { >+ my ($self, $permission) = @_; >+ >+ unless (blessed($permission) && $permission->isa('Koha::Auth::Permission')) { >+ Koha::Exception::BadParameter->throw(error => __PACKAGE__."->setPermission():> Given parameter '\$permission' is not a Koha::Auth::Permission-object!"); >+ } >+ $self->{params}->{permission} = $permission; >+ $self->set({permission_id => $permission->permission_id()}); >+ $self->store(); >+} >+ >+=head _validateParams >+ >+Validates the given constructor parameters and fetches the Koha::Objects when needed. >+ >+=cut >+ >+sub _validateParams { >+ my ($params) = @_; >+ >+ $params->{permissionModule} = Koha::Auth::PermissionModules->cast( $params->{permission_module_id} || $params->{permissionModule} ); >+ $params->{permission} = Koha::Auth::Permissions->cast( $params->{permission_id} || $params->{permission} ); >+ $params->{borrower} = Koha::Borrowers->cast( $params->{borrowernumber} || $params->{borrower} ); >+} >+ >+1; >\ No newline at end of file >diff --git a/Koha/Auth/BorrowerPermissions.pm b/Koha/Auth/BorrowerPermissions.pm >new file mode 100644 >index 0000000..706fb23 >--- /dev/null >+++ b/Koha/Auth/BorrowerPermissions.pm >@@ -0,0 +1,38 @@ >+package Koha::Auth::BorrowerPermissions; >+ >+# Copyright 2015 Vaara-kirjastot >+# >+# This file is part of Koha. >+# >+# Koha is free software; you can redistribute it and/or modify it >+# under the terms of the GNU General Public License as published by >+# the Free Software Foundation; either version 3 of the License, or >+# (at your option) any later version. >+# >+# Koha is distributed in the hope that it will be useful, but >+# WITHOUT ANY WARRANTY; without even the implied warranty of >+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+# GNU General Public License for more details. >+# >+# You should have received a copy of the GNU General Public License >+# along with Koha; if not, see <http://www.gnu.org/licenses>. >+ >+use Modern::Perl; >+use Scalar::Util qw(blessed); >+ >+use Koha::Auth::BorrowerPermission; >+ >+use base qw(Koha::Objects); >+ >+sub type { >+ return 'BorrowerPermission'; >+} >+sub object_class { >+ return 'Koha::Auth::BorrowerPermission'; >+} >+ >+sub _get_castable_unique_columns { >+ return ['borrower_permission_id']; >+} >+ >+1; >diff --git a/Koha/Auth/Permission.pm b/Koha/Auth/Permission.pm >new file mode 100644 >index 0000000..32771ee >--- /dev/null >+++ b/Koha/Auth/Permission.pm >@@ -0,0 +1,60 @@ >+package Koha::Auth::Permission; >+ >+# Copyright 2015 Vaara-kirjastot >+# >+# This file is part of Koha. >+# >+# Koha is free software; you can redistribute it and/or modify it >+# under the terms of the GNU General Public License as published by >+# the Free Software Foundation; either version 3 of the License, or >+# (at your option) any later version. >+# >+# Koha is distributed in the hope that it will be useful, but >+# WITHOUT ANY WARRANTY; without even the implied warranty of >+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+# GNU General Public License for more details. >+# >+# You should have received a copy of the GNU General Public License >+# along with Koha; if not, see <http://www.gnu.org/licenses>. >+ >+use Modern::Perl; >+ >+use Koha::Auth::Permissions; >+ >+use Koha::Exception::BadParameter; >+ >+use base qw(Koha::Object); >+ >+sub type { >+ return 'Permission'; >+} >+sub object_class { >+ return 'Koha::Auth::Permission'; >+} >+ >+sub new { >+ my ($class, $params) = @_; >+ >+ _validateParams($params); >+ >+ my $self = Koha::Auth::Permissions->find({code => $params->{code}, module => $params->{module}}); >+ $self = $class->SUPER::new() unless $self; >+ $self->set($params); >+ return $self; >+} >+ >+sub _validateParams { >+ my ($params) = @_; >+ >+ unless ($params->{description} && length $params->{description} > 0) { >+ Koha::Exception::BadParameter->throw(error => "Koha::Auth::Permission->new():> Parameter 'description' isn't defined or is empty."); >+ } >+ unless ($params->{module} && length $params->{module} > 0) { >+ Koha::Exception::BadParameter->throw(error => "Koha::Auth::Permission->new():> Parameter 'module' isn't defined or is empty."); >+ } >+ unless ($params->{code} && length $params->{code} > 0) { >+ Koha::Exception::BadParameter->throw(error => "Koha::Auth::Permission->new():> Parameter 'code' isn't defined or is empty."); >+ } >+} >+ >+1; >\ No newline at end of file >diff --git a/Koha/Auth/PermissionManager.pm b/Koha/Auth/PermissionManager.pm >new file mode 100644 >index 0000000..7cb72ae >--- /dev/null >+++ b/Koha/Auth/PermissionManager.pm >@@ -0,0 +1,529 @@ >+package Koha::Auth::PermissionManager; >+ >+# Copyright 2015 Vaara-kirjastot >+# >+# This file is part of Koha. >+# >+# Koha is free software; you can redistribute it and/or modify it >+# under the terms of the GNU General Public License as published by >+# the Free Software Foundation; either version 3 of the License, or >+# (at your option) any later version. >+# >+# Koha is distributed in the hope that it will be useful, but >+# WITHOUT ANY WARRANTY; without even the implied warranty of >+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+# GNU General Public License for more details. >+# >+# You should have received a copy of the GNU General Public License >+# along with Koha; if not, see <http://www.gnu.org/licenses>. >+ >+use Modern::Perl; >+use Scalar::Util qw(blessed); >+use Try::Tiny; >+ >+use Koha::Database; >+use Koha::Auth::Permission; >+use Koha::Auth::PermissionModule; >+use Koha::Auth::BorrowerPermission; >+use Koha::Auth::BorrowerPermissions; >+ >+use Koha::Exception::BadParameter; >+use Koha::Exception::NoPermission; >+use Koha::Exception::UnknownProgramState; >+ >+=head NAME Koha::Auth::PermissionManager >+ >+=head SYNOPSIS >+ >+PermissionManager is a gateway to all Koha's permission operations. You shouldn't >+need to touch individual Koha::Auth::Permission* -objects. >+ >+=head USAGE >+ >+See t::db_dependent::Koha::Auth::PermissionManager.t >+ >+=head new >+ >+ my $permissionManager = Koha::Auth::PermissionManager->new(); >+ >+Instantiates a new PemissionManager. >+ >+In the future this Manager can easily be improved with Koha::Cache. >+ >+=cut >+ >+sub new { >+ my ($class, $self) = @_; >+ $self = {} unless $self; >+ bless($self, $class); >+ return $self; >+} >+ >+=head addPermission >+ >+ $permissionManager->addPermission({ code => "end_remaining_hostilities", >+ description => "All your base are belong to us", >+ }); >+ >+INSERTs or UPDATEs a Koha::Auth::Permission to the Koha DB. >+Very handy when introducing new features that need new permissions. >+ >+@PARAM1 Koha::Auth::Permission >+ or >+ HASHRef of all the koha.permissions-table columns set. >+@THROWS Koha::Exception::BadParameter >+=cut >+ >+sub addPermission { >+ my ($self, $permission) = @_; >+ if (blessed($permission) && not($permission->isa('Koha::Auth::Permission'))) { >+ Koha::Exception::BadParameter->throw(error => __PACKAGE__."::addPermission():> Given permission is not a Koha::Auth::Permission-object."); >+ } >+ elsif (ref($permission) eq 'HASH') { >+ $permission = Koha::Auth::Permission->new($permission); >+ } >+ unless (blessed($permission)) { >+ Koha::Exception::BadParameter->throw(error => __PACKAGE__."::addPermission():> Given permission '$permission' is not of a recognized format."); >+ } >+ >+ $permission->store(); >+} >+ >+=head getPermission >+ >+ my $permission = $permissionManager->getPermission('edit_items'); #koha.permissions.code >+ my $permission = $permissionManager->getPermission(12); #koha.permissions.permission_id >+ my $permission = $permissionManager->getPermission($dbix_Permission); #Koha::Schema::Result::Permission >+ >+@RETURNS Koha::Auth::Permission-object >+@THROWS Koha::Exception::BadParameter >+=cut >+ >+sub getPermission { >+ my ($self, $permissionId) = @_; >+ >+ try { >+ return Koha::Auth::Permissions->cast($permissionId); >+ } catch { >+ if (blessed($_) && $_->isa('Koha::Exception::UnknownObject')) { >+ #We catch this type of exception, and simply return nothing, since there was no such Permission >+ } >+ else { >+ die $_; >+ } >+ }; >+} >+ >+=head delPermission >+ >+ $permissionManager->delPermission('edit_items'); #koha.permissions.code >+ $permissionManager->delPermission(12); #koha.permissions.permission_id >+ $permissionManager->delPermission($dbix_Permission); #Koha::Schema::Result::Permission >+ $permissionManager->delPermission($permission); #Koha::Auth::Permission >+ >+@THROWS Koha::Exception::UnknownObject if no given object in DB to delete. >+=cut >+ >+sub delPermission { >+ my ($self, $permissionId) = @_; >+ >+ my $permission = Koha::Auth::Permissions->cast($permissionId); >+ $permission->delete(); >+} >+ >+=head addPermissionModule >+ >+ $permissionManager->addPermissionModule({ module => "scotland", >+ description => "William Wallace is my hero!", >+ }); >+ >+INSERTs or UPDATEs a Koha::Auth::PermissionModule to the Koha DB. >+Very handy when introducing new features that need new permissions. >+ >+@PARAM1 Koha::Auth::PermissionModule >+ or >+ HASHRef of all the koha.permission_modules-table columns set. >+@THROWS Koha::Exception::BadParameter >+=cut >+ >+sub addPermissionModule { >+ my ($self, $permissionModule) = @_; >+ if (blessed($permissionModule) && not($permissionModule->isa('Koha::Auth::PermissionModule'))) { >+ Koha::Exception::BadParameter->throw(error => __PACKAGE__."::addPermission():> Given permissionModule is not a Koha::Auth::PermissionModule-object."); >+ } >+ elsif (ref($permissionModule) eq 'HASH') { >+ $permissionModule = Koha::Auth::PermissionModule->new($permissionModule); >+ } >+ unless (blessed($permissionModule)) { >+ Koha::Exception::BadParameter->throw(error => __PACKAGE__."::addPermission():> Given permissionModule '$permissionModule' is not of a recognized format."); >+ } >+ >+ $permissionModule->store(); >+} >+ >+=head getPermissionModule >+ >+ my $permission = $permissionManager->getPermissionModule('cataloguing'); #koha.permission_modules.module >+ my $permission = $permissionManager->getPermission(12); #koha.permission_modules.permission_module_id >+ my $permission = $permissionManager->getPermission($dbix_Permission); #Koha::Schema::Result::PermissionModule >+ >+@RETURNS Koha::Auth::PermissionModule-object >+@THROWS Koha::Exception::BadParameter >+=cut >+ >+sub getPermissionModule { >+ my ($self, $permissionModuleId) = @_; >+ >+ try { >+ return Koha::Auth::PermissionModules->cast($permissionModuleId); >+ } catch { >+ if (blessed($_) && $_->isa('Koha::Exception::UnknownObject')) { >+ #We catch this type of exception, and simply return nothing, since there was no such PermissionModule >+ } >+ else { >+ die $_; >+ } >+ }; >+} >+ >+=head delPermissionModule >+ >+ $permissionManager->delPermissionModule('cataloguing'); #koha.permission_modules.module >+ $permissionManager->delPermissionModule(12); #koha.permission_modules.permission_module_id >+ $permissionManager->delPermissionModule($dbix_Permission); #Koha::Schema::Result::PermissionModule >+ $permissionManager->delPermissionModule($permissionModule); #Koha::Auth::PermissionModule >+ >+@THROWS Koha::Exception::UnknownObject if no given object in DB to delete. >+@THROWS Koha::Exception::BadParameter >+=cut >+ >+sub delPermissionModule { >+ my ($self, $permissionModuleId) = @_; >+ >+ my $permissionModule = Koha::Auth::PermissionModules->cast($permissionModuleId); >+ $permissionModule->delete(); >+} >+ >+=head getKohaPermissions >+ >+ my $kohaPermissions = $permissionManager->getKohaPermissions(); >+ >+Gets all the PermissionModules and their related Permissions in one huge DB query. >+@RETURNS ARRAYRef of Koha::Auth::PermissionModule-objects with related objects prefetched. >+=cut >+ >+sub getKohaPermissions { >+ my ($self) = @_; >+ >+ my $schema = Koha::Database->new()->schema(); >+ my @permissionModules = $schema->resultset('PermissionModule')->search( >+ {}, >+ { join => ['permissions'], >+ prefetch => ['permissions'], >+ order_by => ['me.module', 'permissions.code'], >+ } >+ ); >+ #Cast DBIx to Koha::Object. >+ for (my $i=0 ; $i<scalar(@permissionModules) ; $i++) { >+ $permissionModules[$i] = Koha::Auth::PermissionModules->cast( $permissionModules[$i] ); >+ } >+ return \@permissionModules; >+} >+ >+=head listKohaPermissionsAsHASH >+ >+@RETURNS HASHRef, a HASH-representation of all the permissions and permission modules >+in Koha. Eg: >+ { >+ acquisitions => { >+ description => "Yada yada", >+ module => 'acquisitions', >+ permission_module_id => 21, >+ permissions => { >+ budget_add_del => { >+ description => "More yada yada", >+ code => 'budget_add_del', >+ permission_id => 12, >+ } >+ budget_manage => { >+ description => "Yaawn yadayawn", >+ ... >+ } >+ ... >+ } >+ }, >+ borrowers => { >+ ... >+ }, >+ ... >+ } >+=cut >+ >+sub listKohaPermissionsAsHASH { >+ my ($self) = @_; >+ my $permissionModules = $self->getKohaPermissions(); >+ my $hash = {}; >+ >+ foreach my $permissionModule (sort {$a->module cmp $b->module} @$permissionModules) { >+ my $module = $permissionModule->module; >+ >+ $hash->{$module} = $permissionModule->_result->{'_column_data'}; >+ $hash->{$module}->{permissions} = {}; >+ >+ my $permissions = $permissionModule->getPermissions; >+ foreach my $permission (sort {$a->code cmp $b->code} @$permissions) { >+ my $code = $permission->code; >+ >+ $hash->{$module}->{permissions}->{$code} = $permission->_result->{'_column_data'}; >+ } >+ } >+ return $hash; >+} >+ >+=head getBorrowerPermissions >+ >+ my $borrowerPermissions = $permissionManager->getBorrowerPermissions($borrower); #Koha::Borrower >+ my $borrowerPermissions = $permissionManager->getBorrowerPermissions($dbix_borrower);#Koha::Schema::Resultset::Borrower >+ my $borrowerPermissions = $permissionManager->getBorrowerPermissions(1012); #koha.borrowers.borrowernumber >+ my $borrowerPermissions = $permissionManager->getBorrowerPermissions('167A0012311'); #koha.borrowers.cardnumber >+ my $borrowerPermissions = $permissionManager->getBorrowerPermissions('bill69'); #koha.borrowers.userid >+ >+@RETURNS ARRAYRef of Koha::Auth::BorrowerPermission-objects >+@THROWS Koha::Exception::UnknownObject, if the given $borrower cannot be casted to Koha::Borrower >+@THROWS Koha::Exception::BadParameter >+=cut >+ >+sub getBorrowerPermissions { >+ my ($self, $borrower) = @_; >+ $borrower = Koha::Borrowers->cast($borrower); >+ >+ if ($borrower->isSuperuser()) { >+ return [Koha::Auth::BorrowerPermission->new({borrower => $borrower, permission => 'superlibrarian', permissionModule => 'superlibrarian'})]; >+ } >+ >+ my $schema = Koha::Database->new()->schema(); >+ >+ my @borrowerPermissions = $schema->resultset('BorrowerPermission')->search({borrowernumber => $borrower->borrowernumber}, >+ {join => ['permission','permission_module'], >+ prefetch => ['permission','permission_module'], >+ order_by => ['permission_module.module', 'permission.code']}); >+ for (my $i=0 ; $i<scalar(@borrowerPermissions) ; $i++) { >+ $borrowerPermissions[$i] = Koha::Auth::BorrowerPermissions->cast($borrowerPermissions[$i]); >+ } >+ return \@borrowerPermissions; >+} >+ >+=head grantPermissions >+ >+ $permissionManager->grantPermissions($borrower, {borrowers => 'view_borrowers', >+ reserveforothers => ['place_holds'], >+ tools => ['edit_news', 'edit_notices'], >+ acquisition => { >+ budger_add_del => 1, >+ budget_modify => 1, >+ }, >+ } >+ ); >+ >+Adds a group of permissions to one user. >+@THROWS Koha::Exception::UnknownObject, if the given $borrower cannot be casted to Koha::Borrower >+@THROWS Koha::Exception::BadParameter >+=cut >+ >+sub grantPermissions { >+ my ($self, $borrower, $permissionsGroup) = @_; >+ >+ while (my ($module, $permissions) = each(%$permissionsGroup)) { >+ if (ref($permissions) eq 'ARRAY') { >+ foreach my $permission (@$permissions) { >+ $self->grantPermission($borrower, $module, $permission); >+ } >+ } >+ elsif (ref($permissions) eq 'HASH') { >+ foreach my $permission (keys(%$permissions)) { >+ $self->grantPermission($borrower, $module, $permission); >+ } >+ } >+ else { >+ $self->grantPermission($borrower, $module, $permissions); >+ } >+ } >+} >+ >+=head grantPermission >+ >+ my $borrowerPermission = $permissionManager->grantPermission($borrower, $permissionModule, $permission); >+ >+@PARAM1 Koha::Borrower or >+ Scalar koha.borrowers.borrowernumber or >+ Scalar koha.borrowers.cardnumber or >+ Scalar koha.borrowers.userid or >+@PARAM2 Koha::Auth::PermissionModule-object >+ Scalar koha.permission_modules.module or >+ Scalar koha.permission_modules.permission_module_id >+@PARAM3 Koha::Auth::Permission-object or >+ Scalar koha.permissions.code or >+ Scalar koha.permissions.permission_id >+@RETURNS Koha::Auth::BorrowerPermissions >+@THROWS Koha::Exception::UnknownObject, if the given parameters cannot be casted to Koha::Object-subclasses >+@THROWS Koha::Exception::BadParameter >+=cut >+ >+sub grantPermission { >+ my ($self, $borrower, $permissionModule, $permission) = @_; >+ >+ my $borrowerPermission = Koha::Auth::BorrowerPermission->new({borrower => $borrower, permissionModule => $permissionModule, permission => $permission}); >+ $borrowerPermission->store(); >+ return $borrowerPermission; >+} >+ >+=head >+ >+ $permissionManager->revokePermission($borrower, $permissionModule, $permission); >+ >+Revokes a Permission from a Borrower >+same parameters as grantPermission() >+ >+@THROWS Koha::Exception::UnknownObject, if the given parameters cannot be casted to Koha::Object-subclasses >+@THROWS Koha::Exception::BadParameter >+=cut >+ >+sub revokePermission { >+ my ($self, $borrower, $permissionModule, $permission) = @_; >+ >+ my $borrowerPermission = Koha::Auth::BorrowerPermission->new({borrower => $borrower, permissionModule => $permissionModule, permission => $permission}); >+ $borrowerPermission->delete(); >+ return $borrowerPermission; >+} >+ >+=head revokeAllPermissions >+ >+ $permissionManager->revokeAllPermissions($borrower); >+ >+@THROWS Koha::Exception::UnknownObject, if the given $borrower cannot be casted to Koha::Borrower >+@THROWS Koha::Exception::BadParameter >+=cut >+ >+sub revokeAllPermissions { >+ my ($self, $borrower) = @_; >+ $borrower = Koha::Borrowers->cast($borrower); >+ >+ my $schema = Koha::Database->new()->schema(); >+ $schema->resultset('BorrowerPermission')->search({borrowernumber => $borrower->borrowernumber})->delete_all(); >+} >+ >+=head hasPermissions >+ >+See if the given Borrower has all of the given permissions >+@PARAM1 Koha::Borrower, or any of the koha.borrowers-table's unique identifiers. >+@PARAM2 HASHRef of needed permissions, >+ { >+ borrowers => 'view_borrowers', >+ reserveforothers => ['place_holds'], >+ tools => ['edit_news', 'edit_notices'], >+ acquisition => { >+ budger_add_del => 1, >+ budget_modify => 1, >+ }, >+ coursereserves => '*', #Means any Permission under this PermissionModule >+ } >+@RETURNS see hasPermission() >+@THROWS Koha::Exception::NoPermission, from hasPermission() if permission is missing. >+=cut >+ >+sub hasPermissions { >+ my ($self, $borrower, $requiredPermissions) = @_; >+ >+ foreach my $module (keys(%$requiredPermissions)) { >+ my $permissions = $requiredPermissions->{$module}; >+ if (ref($permissions) eq 'ARRAY') { >+ foreach my $permission (@$permissions) { >+ $self->hasPermission($borrower, $module, $permission); >+ } >+ } >+ elsif (ref($permissions) eq 'HASH') { >+ foreach my $permission (keys(%$permissions)) { >+ $self->hasPermission($borrower, $module, $permission); >+ } >+ } >+ else { >+ $self->hasPermission($borrower, $module, $permissions); >+ } >+ } >+ return 1; >+} >+ >+=head hasPermission >+ >+See if the given Borrower has the given permission >+@PARAM1 Koha::Borrower, or any of the koha.borrowers-table's unique identifiers. >+@PARAM2 Koha::Auth::PermissionModule or koha.permission_modules.module or koha.permission_modules.permission_module_id >+@PARAM3 Koha::Auth::Permission or koha.permissions.code or koha.permissions.permission_id or >+ '*' if we just need any permission for the given PermissionModule. >+@RETURNS Integer, 1 if permission check succeeded. >+ 2 if user is a superlibrarian. >+ Catch Exceptions if permission check fails. >+@THROWS Koha::Exception::NoPermission, if Borrower is missing the permission. >+ Exception tells which permission is missing. >+@THROWS Koha::Exception::UnknownObject, if the given parameters cannot be casted to Koha::Object-subclasses >+@THROWS Koha::Exception::BadParameter >+=cut >+ >+sub hasPermission { >+ my ($self, $borrower, $permissionModule, $permission) = @_; >+ >+ $borrower = Koha::Borrowers->cast($borrower); >+ $permissionModule = Koha::Auth::PermissionModules->cast($permissionModule); >+ $permission = Koha::Auth::Permissions->cast($permission) unless $permission eq '*'; >+ >+ my $error; >+ if ($permission eq '*') { >+ my $borrowerPermission = Koha::Auth::BorrowerPermissions->search({borrowernumber => $borrower->borrowernumber, >+ permission_module_id => $permissionModule->permission_module_id, >+ })->next(); >+ return 1 if ($borrowerPermission); >+ $error = "Borrower '".$borrower->borrowernumber."' lacks any permission under permission module '".$permissionModule->module."'."; >+ } >+ else { >+ my $borrowerPermission = Koha::Auth::BorrowerPermissions->search({borrowernumber => $borrower->borrowernumber, >+ permission_module_id => $permissionModule->permission_module_id, >+ permission_id => $permission->permission_id, >+ })->next(); >+ return 1 if ($borrowerPermission); >+ $error = "Borrower '".$borrower->borrowernumber."' lacks permission module '".$permissionModule->module."' and permission '".$permission->code."'."; >+ } >+ >+ return 2 if not($permissionModule->module eq 'superlibrarian') && $self->_isSuperuser($borrower); >+ return 2 if not($permissionModule->module eq 'superlibrarian') && $self->_isSuperlibrarian($borrower); >+ Koha::Exception::NoPermission->throw(error => $error); >+} >+ >+sub _isSuperuser { >+ my ($self, $borrower) = @_; >+ $borrower = Koha::Borrowers->cast($borrower); >+ >+ if ( $borrower->userid && $borrower->userid eq C4::Context->config('user') ) { >+ return 1; >+ } >+ elsif ( $borrower->userid && $borrower->userid eq 'demo' && C4::Context->config('demo') ) { >+ return 1; >+ } >+ return 0; >+} >+ >+sub _isSuperlibrarian { >+ my ($self, $borrower) = @_; >+ >+ try { >+ return $self->hasPermission($borrower, 'superlibrarian', 'superlibrarian'); >+ } catch { >+ if (blessed($_) && $_->isa('Koha::Exception::NoPermission')) { >+ return 0; >+ } >+ else { >+ die $_; >+ } >+ }; >+} >+ >+1; >\ No newline at end of file >diff --git a/Koha/Auth/PermissionModule.pm b/Koha/Auth/PermissionModule.pm >new file mode 100644 >index 0000000..8e72e31 >--- /dev/null >+++ b/Koha/Auth/PermissionModule.pm >@@ -0,0 +1,78 @@ >+package Koha::Auth::PermissionModule; >+ >+# Copyright 2015 Vaara-kirjastot >+# >+# This file is part of Koha. >+# >+# Koha is free software; you can redistribute it and/or modify it >+# under the terms of the GNU General Public License as published by >+# the Free Software Foundation; either version 3 of the License, or >+# (at your option) any later version. >+# >+# Koha is distributed in the hope that it will be useful, but >+# WITHOUT ANY WARRANTY; without even the implied warranty of >+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+# GNU General Public License for more details. >+# >+# You should have received a copy of the GNU General Public License >+# along with Koha; if not, see <http://www.gnu.org/licenses>. >+ >+use Modern::Perl; >+ >+use Koha::Auth::PermissionModules; >+ >+use Koha::Exception::BadParameter; >+ >+use base qw(Koha::Object); >+ >+sub type { >+ return 'PermissionModule'; >+} >+sub object_class { >+ return 'Koha::Auth::PermissionModule'; >+} >+ >+sub new { >+ my ($class, $params) = @_; >+ >+ _validateParams($params); >+ >+ my $self = Koha::Auth::PermissionModules->find({module => $params->{module}}); >+ $self = $class->SUPER::new() unless $self; >+ $self->set($params); >+ return $self; >+} >+ >+sub _validateParams { >+ my ($params) = @_; >+ >+ unless ($params->{description} && length $params->{description} > 0) { >+ Koha::Exception::BadParameter->throw(error => "Koha::Auth::Permission->new():> Parameter 'description' isn't defined or is empty."); >+ } >+ unless ($params->{module} && length $params->{module} > 0) { >+ Koha::Exception::BadParameter->throw(error => "Koha::Auth::Permission->new():> Parameter 'module' isn't defined or is empty."); >+ } >+} >+ >+=head getPermissions >+ >+ my $permissions = $permissionModule->getPermissions(); >+ >+@RETURNS List of Koha::Auth::Permission-objects >+=cut >+ >+sub getPermissions { >+ my ($self) = @_; >+ >+ unless ($self->{params}->{permissions}) { >+ $self->{params}->{permissions} = []; >+ my @dbix_objects = $self->_result()->permissions; >+ foreach my $dbix_object (@dbix_objects) { >+ my $object = Koha::Auth::Permission->_new_from_dbic($dbix_object); >+ push @{$self->{params}->{permissions}}, $object; >+ } >+ } >+ return $self->{params}->{permissions}; >+} >+ >+1; >\ No newline at end of file >diff --git a/Koha/Auth/PermissionModules.pm b/Koha/Auth/PermissionModules.pm >new file mode 100644 >index 0000000..a7bc088 >--- /dev/null >+++ b/Koha/Auth/PermissionModules.pm >@@ -0,0 +1,38 @@ >+package Koha::Auth::PermissionModules; >+ >+# Copyright 2015 Vaara-kirjastot >+# >+# This file is part of Koha. >+# >+# Koha is free software; you can redistribute it and/or modify it >+# under the terms of the GNU General Public License as published by >+# the Free Software Foundation; either version 3 of the License, or >+# (at your option) any later version. >+# >+# Koha is distributed in the hope that it will be useful, but >+# WITHOUT ANY WARRANTY; without even the implied warranty of >+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+# GNU General Public License for more details. >+# >+# You should have received a copy of the GNU General Public License >+# along with Koha; if not, see <http://www.gnu.org/licenses>. >+ >+use Modern::Perl; >+use Scalar::Util qw(blessed); >+ >+use Koha::Auth::PermissionModule; >+ >+use base qw(Koha::Objects); >+ >+sub type { >+ return 'PermissionModule'; >+} >+sub object_class { >+ return 'Koha::Auth::PermissionModule'; >+} >+ >+sub _get_castable_unique_columns { >+ return ['permission_module_id', 'module']; >+} >+ >+1; >\ No newline at end of file >diff --git a/Koha/Auth/Permissions.pm b/Koha/Auth/Permissions.pm >new file mode 100644 >index 0000000..76f4605 >--- /dev/null >+++ b/Koha/Auth/Permissions.pm >@@ -0,0 +1,42 @@ >+package Koha::Auth::Permissions; >+ >+# Copyright 2015 Vaara-kirjastot >+# >+# This file is part of Koha. >+# >+# Koha is free software; you can redistribute it and/or modify it >+# under the terms of the GNU General Public License as published by >+# the Free Software Foundation; either version 3 of the License, or >+# (at your option) any later version. >+# >+# Koha is distributed in the hope that it will be useful, but >+# WITHOUT ANY WARRANTY; without even the implied warranty of >+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+# GNU General Public License for more details. >+# >+# You should have received a copy of the GNU General Public License >+# along with Koha; if not, see <http://www.gnu.org/licenses>. >+ >+use Modern::Perl; >+use Scalar::Util qw(blessed); >+ >+use Koha::Auth::Permission; >+ >+use Koha::Exception::BadParameter; >+use Koha::Exception::UnknownObject; >+ >+use base qw(Koha::Objects); >+ >+sub type { >+ return 'Permission'; >+} >+ >+sub object_class { >+ return 'Koha::Auth::Permission'; >+} >+ >+sub _get_castable_unique_columns { >+ return ['permission_id', 'code']; >+} >+ >+1; >diff --git a/Koha/AuthUtils.pm b/Koha/AuthUtils.pm >index 5fa0afb..7d01e28 100644 >--- a/Koha/AuthUtils.pm >+++ b/Koha/AuthUtils.pm >@@ -166,7 +166,6 @@ sub _createTemporarySuperuser { > firstname => $superuserName, > surname => $superuserName, > branchcode => 'NO_LIBRARY_SET', >- flags => 1, > email => C4::Context->preference('KohaAdminEmailAddress') > }); > return $borrower; >diff --git a/Koha/Schema/Result/Borrower.pm b/Koha/Schema/Result/Borrower.pm >index e9f8838..5356dfd 100644 >--- a/Koha/Schema/Result/Borrower.pm >+++ b/Koha/Schema/Result/Borrower.pm >@@ -309,11 +309,6 @@ __PACKAGE__->table("borrowers"); > is_nullable: 1 > size: 60 > >-=head2 flags >- >- data_type: 'integer' >- is_nullable: 1 >- > =head2 userid > > data_type: 'varchar' >@@ -542,8 +537,6 @@ __PACKAGE__->add_columns( > { data_type => "varchar", is_nullable => 1, size => 1 }, > "password", > { data_type => "varchar", is_nullable => 1, size => 60 }, >- "flags", >- { data_type => "integer", is_nullable => 1 }, > "userid", > { data_type => "varchar", is_nullable => 1, size => 75 }, > "opacnote", >@@ -648,6 +641,36 @@ __PACKAGE__->has_many( > { cascade_copy => 0, cascade_delete => 0 }, > ); > >+=head2 api_keys >+ >+Type: has_many >+ >+Related object: L<Koha::Schema::Result::ApiKey> >+ >+=cut >+ >+__PACKAGE__->has_many( >+ "api_keys", >+ "Koha::Schema::Result::ApiKey", >+ { "foreign.borrowernumber" => "self.borrowernumber" }, >+ { cascade_copy => 0, cascade_delete => 0 }, >+); >+ >+=head2 api_timestamp >+ >+Type: might_have >+ >+Related object: L<Koha::Schema::Result::ApiTimestamp> >+ >+=cut >+ >+__PACKAGE__->might_have( >+ "api_timestamp", >+ "Koha::Schema::Result::ApiTimestamp", >+ { "foreign.borrowernumber" => "self.borrowernumber" }, >+ { cascade_copy => 0, cascade_delete => 0 }, >+); >+ > =head2 aqbasketusers > > Type: has_many >@@ -753,6 +776,21 @@ __PACKAGE__->has_many( > { cascade_copy => 0, cascade_delete => 0 }, > ); > >+=head2 borrower_permissions >+ >+Type: has_many >+ >+Related object: L<Koha::Schema::Result::BorrowerPermission> >+ >+=cut >+ >+__PACKAGE__->has_many( >+ "borrower_permissions", >+ "Koha::Schema::Result::BorrowerPermission", >+ { "foreign.borrowernumber" => "self.borrowernumber" }, >+ { cascade_copy => 0, cascade_delete => 0 }, >+); >+ > =head2 borrower_syncs > > Type: has_many >@@ -1053,21 +1091,6 @@ __PACKAGE__->has_many( > { cascade_copy => 0, cascade_delete => 0 }, > ); > >-=head2 user_permissions >- >-Type: has_many >- >-Related object: L<Koha::Schema::Result::UserPermission> >- >-=cut >- >-__PACKAGE__->has_many( >- "user_permissions", >- "Koha::Schema::Result::UserPermission", >- { "foreign.borrowernumber" => "self.borrowernumber" }, >- { cascade_copy => 0, cascade_delete => 0 }, >-); >- > =head2 virtualshelfcontents > > Type: has_many >@@ -1154,8 +1177,8 @@ Composing rels: L</aqorder_users> -> ordernumber > __PACKAGE__->many_to_many("ordernumbers", "aqorder_users", "ordernumber"); > > >-# Created by DBIx::Class::Schema::Loader v0.07039 @ 2015-04-27 16:08:40 >-# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:Z50zYBD3Hqlv5/EnoLnyZw >+# Created by DBIx::Class::Schema::Loader v0.07039 @ 2015-07-11 12:59:56 >+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:ZRxBjZb0KKxabonVI/2vjg > > > # You can replace this text with custom content, and it will be preserved on regeneration >diff --git a/Koha/Schema/Result/Permission.pm b/Koha/Schema/Result/Permission.pm >index e2444ee..47d8b83 100644 >--- a/Koha/Schema/Result/Permission.pm >+++ b/Koha/Schema/Result/Permission.pm >@@ -23,17 +23,22 @@ __PACKAGE__->table("permissions"); > > =head1 ACCESSORS > >-=head2 module_bit >+=head2 permission_id > > data_type: 'integer' >- default_value: 0 >+ is_auto_increment: 1 >+ is_nullable: 0 >+ >+=head2 module >+ >+ data_type: 'varchar' > is_foreign_key: 1 > is_nullable: 0 >+ size: 32 > > =head2 code > > data_type: 'varchar' >- default_value: (empty string) > is_nullable: 0 > size: 64 > >@@ -46,15 +51,12 @@ __PACKAGE__->table("permissions"); > =cut > > __PACKAGE__->add_columns( >- "module_bit", >- { >- data_type => "integer", >- default_value => 0, >- is_foreign_key => 1, >- is_nullable => 0, >- }, >+ "permission_id", >+ { data_type => "integer", is_auto_increment => 1, is_nullable => 0 }, >+ "module", >+ { data_type => "varchar", is_foreign_key => 1, is_nullable => 0, size => 32 }, > "code", >- { data_type => "varchar", default_value => "", is_nullable => 0, size => 64 }, >+ { data_type => "varchar", is_nullable => 0, size => 64 }, > "description", > { data_type => "varchar", is_nullable => 1, size => 255 }, > ); >@@ -63,7 +65,19 @@ __PACKAGE__->add_columns( > > =over 4 > >-=item * L</module_bit> >+=item * L</permission_id> >+ >+=back >+ >+=cut >+ >+__PACKAGE__->set_primary_key("permission_id"); >+ >+=head1 UNIQUE CONSTRAINTS >+ >+=head2 C<code> >+ >+=over 4 > > =item * L</code> > >@@ -71,46 +85,43 @@ __PACKAGE__->add_columns( > > =cut > >-__PACKAGE__->set_primary_key("module_bit", "code"); >+__PACKAGE__->add_unique_constraint("code", ["code"]); > > =head1 RELATIONS > >-=head2 module_bit >+=head2 borrower_permissions > >-Type: belongs_to >+Type: has_many > >-Related object: L<Koha::Schema::Result::Userflag> >+Related object: L<Koha::Schema::Result::BorrowerPermission> > > =cut > >-__PACKAGE__->belongs_to( >- "module_bit", >- "Koha::Schema::Result::Userflag", >- { bit => "module_bit" }, >- { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" }, >+__PACKAGE__->has_many( >+ "borrower_permissions", >+ "Koha::Schema::Result::BorrowerPermission", >+ { "foreign.permission_id" => "self.permission_id" }, >+ { cascade_copy => 0, cascade_delete => 0 }, > ); > >-=head2 user_permissions >+=head2 module > >-Type: has_many >+Type: belongs_to > >-Related object: L<Koha::Schema::Result::UserPermission> >+Related object: L<Koha::Schema::Result::PermissionModule> > > =cut > >-__PACKAGE__->has_many( >- "user_permissions", >- "Koha::Schema::Result::UserPermission", >- { >- "foreign.code" => "self.code", >- "foreign.module_bit" => "self.module_bit", >- }, >- { cascade_copy => 0, cascade_delete => 0 }, >+__PACKAGE__->belongs_to( >+ "module", >+ "Koha::Schema::Result::PermissionModule", >+ { module => "module" }, >+ { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" }, > ); > > >-# Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-10-14 20:56:21 >-# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:Ut3lzlxoPPoIIwmhJViV1Q >+# Created by DBIx::Class::Schema::Loader v0.07039 @ 2015-07-28 17:08:28 >+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:ugaurNx48ISDyRgoAlBk2A > > > # You can replace this text with custom content, and it will be preserved on regeneration >diff --git a/installer/data/mysql/en/mandatory/userflags.sql b/installer/data/mysql/en/mandatory/userflags.sql >index d8e3626..7148682 100644 >--- a/installer/data/mysql/en/mandatory/userflags.sql >+++ b/installer/data/mysql/en/mandatory/userflags.sql >@@ -1,21 +1,21 @@ >-INSERT INTO userflags (bit, flag, flagdesc, defaulton) VALUES >-(0,'superlibrarian','Access to all librarian functions',0), >-(1,'circulate','Check out and check in items',0), >-(2,'catalogue','<b>Required for staff login.</b> Staff access, allows viewing of catalogue in staff client.',0), >-(3,'parameters','Manage Koha system settings (Administration panel)',0), >-(4,'borrowers','Add or modify patrons',0), >-(5,'permissions','Set user permissions',0), >-(6,'reserveforothers','Place and modify holds for patrons',0), >-(9,'editcatalogue','Edit catalog (Modify bibliographic/holdings data)',0), >-(10,'updatecharges','Manage patrons fines and fees',0), >-(11,'acquisition','Acquisition and/or suggestion management',0), >-(12,'management','Set library management parameters (deprecated)',0), >-(13,'tools','Use all tools (expand for granular tools permissions)',0), >-(14,'editauthorities','Edit authorities',0), >-(15,'serials','Manage serial subscriptions',0), >-(16,'reports','Allow access to the reports module',0), >-(17,'staffaccess','Allow staff members to modify permissions for other staff members',0), >-(18,'coursereserves','Course reserves',0), >-(19, 'plugins', 'Koha plugins', '0'), >-(20, 'lists', 'Lists', 0) >+INSERT INTO permission_modules (module, description) VALUES >+('superlibrarian','Access to all librarian functions'), >+('circulate','Check out and check in items'), >+('catalogue','<b>Required for staff login.</b> Staff access, allows viewing of catalogue in staff client.'), >+('parameters','Manage Koha system settings (Administration panel)'), >+('borrowers','Add or modify patrons'), >+('permissions','Set user permissions'), >+('reserveforothers','Place and modify holds for patrons'), >+('editcatalogue','Edit catalog (Modify bibliographic/holdings data)'), >+('updatecharges','Manage patrons fines and fees'), >+('acquisition','Acquisition and/or suggestion management'), >+('management','Set library management parameters (deprecated)'), >+('tools','Use all tools (expand for granular tools permissions)'), >+('editauthorities','Edit authorities'), >+('serials','Manage serial subscriptions'), >+('reports','Allow access to the reports module'), >+('staffaccess','Allow staff members to modify permissions for other staff members'), >+('coursereserves','Course reserves'), >+('plugins', 'Koha plugins'), >+('lists', 'Lists') > ; >diff --git a/installer/data/mysql/en/mandatory/userpermissions.sql b/installer/data/mysql/en/mandatory/userpermissions.sql >index 7b50d51..c8cae26 100644 >--- a/installer/data/mysql/en/mandatory/userpermissions.sql >+++ b/installer/data/mysql/en/mandatory/userpermissions.sql >@@ -1,77 +1,84 @@ >-INSERT INTO permissions (module_bit, code, description) VALUES >- ( 1, 'circulate_remaining_permissions', 'Remaining circulation permissions'), >- ( 1, 'override_renewals', 'Override blocked renewals'), >- ( 1, 'overdues_report', 'Execute overdue items report'), >- ( 1, 'force_checkout', 'Force checkout if a limitation exists'), >- ( 1, 'manage_restrictions', 'Manage restrictions for accounts'), >- ( 3, 'parameters_remaining_permissions', 'Remaining system parameters permissions'), >- ( 3, 'manage_circ_rules', 'manage circulation rules'), >- ( 6, 'place_holds', 'Place holds for patrons'), >- ( 6, 'modify_holds_priority', 'Modify holds priority'), >- ( 9, 'edit_catalogue', 'Edit catalog (Modify bibliographic/holdings data)'), >- ( 9, 'fast_cataloging', 'Fast cataloging'), >- ( 9, 'edit_items', 'Edit items'), >- ( 9, 'edit_items_restricted', 'Limit item modification to subfields defined in the SubfieldsToAllowForRestrictedEditing preference (please note that edit_item is still required)'), >- ( 9, 'delete_all_items', 'Delete all items at once'), >- (10, 'writeoff', 'Write off fines and fees'), >- (10, 'remaining_permissions', 'Remaining permissions for managing fines and fees'), >- (11, 'vendors_manage', 'Manage vendors'), >- (11, 'contracts_manage', 'Manage contracts'), >- (11, 'period_manage', 'Manage periods'), >- (11, 'budget_manage', 'Manage budgets'), >- (11, 'budget_modify', 'Modify budget (can''t create lines, but can modify existing ones)'), >- (11, 'planning_manage', 'Manage budget plannings'), >- (11, 'order_manage', 'Manage orders & basket'), >- (11, 'order_manage_all', 'Manage all orders and baskets, regardless of restrictions on them'), >- (11, 'group_manage', 'Manage orders & basketgroups'), >- (11, 'order_receive', 'Manage orders & basket'), >- (11, 'budget_add_del', 'Add and delete budgets (but can''t modify budgets)'), >- (11, 'budget_manage_all', 'Manage all budgets'), >- (13, 'edit_news', 'Write news for the OPAC and staff interfaces'), >- (13, 'label_creator', 'Create printable labels and barcodes from catalog and patron data'), >- (13, 'edit_calendar', 'Define days when the library is closed'), >- (13, 'moderate_comments', 'Moderate patron comments'), >- (13, 'edit_notices', 'Define notices'), >- (13, 'edit_notice_status_triggers', 'Set notice/status triggers for overdue items'), >- (13, 'edit_quotes', 'Edit quotes for quote-of-the-day feature'), >- (13, 'view_system_logs', 'Browse the system logs'), >- (13, 'inventory', 'Perform inventory (stocktaking) of your catalog'), >- (13, 'stage_marc_import', 'Stage MARC records into the reservoir'), >- (13, 'manage_staged_marc', 'Managed staged MARC records, including completing and reversing imports'), >- (13, 'export_catalog', 'Export bibliographic and holdings data'), >- (13, 'import_patrons', 'Import patron data'), >- (13, 'edit_patrons', 'Perform batch modification of patrons'), >- (13, 'delete_anonymize_patrons', 'Delete old borrowers and anonymize circulation history (deletes borrower reading history)'), >- (13, 'batch_upload_patron_images', 'Upload patron images in a batch or one at a time'), >- (13, 'schedule_tasks', 'Schedule tasks to run'), >- (13, 'items_batchmod', 'Perform batch modification of items'), >- (13, 'items_batchmod_restricted', 'Limit batch item modification to subfields defined in the SubfieldsToAllowForRestrictedBatchmod preference (please note that items_batchmod is still required)'), >- (13, 'items_batchdel', 'Perform batch deletion of items'), >- (13, 'manage_csv_profiles', 'Manage CSV export profiles'), >- (13, 'moderate_tags', 'Moderate patron tags'), >- (13, 'rotating_collections', 'Manage rotating collections'), >- (13, 'upload_local_cover_images', 'Upload local cover images'), >- (13, 'manage_patron_lists', 'Add, edit and delete patron lists and their contents'), >- (13, 'records_batchmod', 'Perform batch modification of records (biblios or authorities)'), >- (13, 'marc_modification_templates', 'Manage marc modification templates'), >- (13, 'records_batchdel', 'Perform batch deletion of records (bibliographic or authority)'), >- (15, 'check_expiration', 'Check the expiration of a serial'), >- (15, 'claim_serials', 'Claim missing serials'), >- (15, 'create_subscription', 'Create a new subscription'), >- (15, 'delete_subscription', 'Delete an existing subscription'), >- (15, 'edit_subscription', 'Edit an existing subscription'), >- (15, 'receive_serials', 'Serials receiving'), >- (15, 'renew_subscription', 'Renew a subscription'), >- (15, 'routing', 'Routing'), >- (15, 'superserials', 'Manage subscriptions from any branch (only applies when IndependentBranches is used)'), >- (16, 'execute_reports', 'Execute SQL reports'), >- (16, 'create_reports', 'Create SQL reports'), >- (18, 'manage_courses', 'Add, edit and delete courses'), >- (18, 'add_reserves', 'Add course reserves'), >- (18, 'delete_reserves', 'Remove course reserves'), >- (19, 'manage', 'Manage plugins ( install / uninstall )'), >- (19, 'tool', 'Use tool plugins'), >- (19, 'report', 'Use report plugins'), >- (19, 'configure', 'Configure plugins'), >- (20, 'delete_public_lists', 'Delete public lists') >+INSERT INTO permissions (module, code, description) VALUES >+ ( 'superlibrarian', 'superlibrarian', 'Access to all librarian functions'), >+ ( 'circulate', 'circulate_remaining_permissions', 'Remaining circulation permissions'), >+ ( 'circulate', 'override_renewals', 'Override blocked renewals'), >+ ( 'circulate', 'overdues_report', 'Execute overdue items report'), >+ ( 'circulate', 'force_checkout', 'Force checkout if a limitation exists'), >+ ( 'circulate', 'manage_restrictions', 'Manage restrictions for accounts'), >+ ( 'catalogue', 'staff_login', 'Allow staff login.'), >+ ( 'parameters', 'parameters_remaining_permissions', 'Remaining system parameters permissions'), >+ ( 'parameters', 'manage_circ_rules', 'manage circulation rules'), >+ ( 'borrowers', 'view_borrowers', 'Show borrower details and search for borrowers.'), >+ ( 'permissions', 'set_permissions', 'Set user permissions'), >+ ( 'reserveforothers','place_holds', 'Place holds for patrons'), >+ ( 'reserveforothers','modify_holds_priority', 'Modify holds priority'), >+ ( 'editcatalogue', 'edit_catalogue', 'Edit catalog (Modify bibliographic/holdings data)'), >+ ( 'editcatalogue', 'fast_cataloging', 'Fast cataloging'), >+ ( 'editcatalogue', 'edit_items', 'Edit items'), >+ ( 'editcatalogue', 'edit_items_restricted', 'Limit item modification to subfields defined in the SubfieldsToAllowForRestrictedEditing preference (please note that edit_item is still required)'), >+ ( 'editcatalogue', 'delete_all_items', 'Delete all items at once'), >+ ( 'updatecharges', 'writeoff', 'Write off fines and fees'), >+ ( 'updatecharges', 'remaining_permissions', 'Remaining permissions for managing fines and fees'), >+ ( 'acquisition', 'vendors_manage', 'Manage vendors'), >+ ( 'acquisition', 'contracts_manage', 'Manage contracts'), >+ ( 'acquisition', 'period_manage', 'Manage periods'), >+ ( 'acquisition', 'budget_manage', 'Manage budgets'), >+ ( 'acquisition', 'budget_modify', 'Modify budget (can''t create lines, but can modify existing ones)'), >+ ( 'acquisition', 'planning_manage', 'Manage budget plannings'), >+ ( 'acquisition', 'order_manage', 'Manage orders & basket'), >+ ( 'acquisition', 'order_manage_all', 'Manage all orders and baskets, regardless of restrictions on them'), >+ ( 'acquisition', 'group_manage', 'Manage orders & basketgroups'), >+ ( 'acquisition', 'order_receive', 'Manage orders & basket'), >+ ( 'acquisition', 'budget_add_del', 'Add and delete budgets (but can''t modify budgets)'), >+ ( 'acquisition', 'budget_manage_all', 'Manage all budgets'), >+ ( 'management', 'management', 'Set library management parameters (deprecated)'), >+ ( 'tools', 'edit_news', 'Write news for the OPAC and staff interfaces'), >+ ( 'tools', 'label_creator', 'Create printable labels and barcodes from catalog and patron data'), >+ ( 'tools', 'edit_calendar', 'Define days when the library is closed'), >+ ( 'tools', 'moderate_comments', 'Moderate patron comments'), >+ ( 'tools', 'edit_notices', 'Define notices'), >+ ( 'tools', 'edit_notice_status_triggers', 'Set notice/status triggers for overdue items'), >+ ( 'tools', 'edit_quotes', 'Edit quotes for quote-of-the-day feature'), >+ ( 'tools', 'view_system_logs', 'Browse the system logs'), >+ ( 'tools', 'inventory', 'Perform inventory (stocktaking) of your catalog'), >+ ( 'tools', 'stage_marc_import', 'Stage MARC records into the reservoir'), >+ ( 'tools', 'manage_staged_marc', 'Managed staged MARC records, including completing and reversing imports'), >+ ( 'tools', 'export_catalog', 'Export bibliographic and holdings data'), >+ ( 'tools', 'import_patrons', 'Import patron data'), >+ ( 'tools', 'edit_patrons', 'Perform batch modification of patrons'), >+ ( 'tools', 'delete_anonymize_patrons', 'Delete old borrowers and anonymize circulation history (deletes borrower reading history)'), >+ ( 'tools', 'batch_upload_patron_images', 'Upload patron images in a batch or one at a time'), >+ ( 'tools', 'schedule_tasks', 'Schedule tasks to run'), >+ ( 'tools', 'items_batchmod', 'Perform batch modification of items'), >+ ( 'tools', 'items_batchmod_restricted', 'Limit batch item modification to subfields defined in the SubfieldsToAllowForRestrictedBatchmod preference (please note that items_batchmod is still required)'), >+ ( 'tools', 'items_batchdel', 'Perform batch deletion of items'), >+ ( 'tools', 'manage_csv_profiles', 'Manage CSV export profiles'), >+ ( 'tools', 'moderate_tags', 'Moderate patron tags'), >+ ( 'tools', 'rotating_collections', 'Manage rotating collections'), >+ ( 'tools', 'upload_local_cover_images', 'Upload local cover images'), >+ ( 'tools', 'manage_patron_lists', 'Add, edit and delete patron lists and their contents'), >+ ( 'tools', 'records_batchmod', 'Perform batch modification of records (biblios or authorities)'), >+ ( 'tools', 'marc_modification_templates', 'Manage marc modification templates'), >+ ( 'tools', 'records_batchdel', 'Perform batch deletion of records (bibliographic or authority)'), >+ ( 'editauthorities', 'edit_authorities', 'Edit authorities'), >+ ( 'serials', 'check_expiration', 'Check the expiration of a serial'), >+ ( 'serials', 'claim_serials', 'Claim missing serials'), >+ ( 'serials', 'create_subscription', 'Create a new subscription'), >+ ( 'serials', 'delete_subscription', 'Delete an existing subscription'), >+ ( 'serials', 'edit_subscription', 'Edit an existing subscription'), >+ ( 'serials', 'receive_serials', 'Serials receiving'), >+ ( 'serials', 'renew_subscription', 'Renew a subscription'), >+ ( 'serials', 'routing', 'Routing'), >+ ( 'serials', 'superserials', 'Manage subscriptions from any branch (only applies when IndependentBranches is used)'), >+ ( 'reports', 'execute_reports', 'Execute SQL reports'), >+ ( 'reports', 'create_reports', 'Create SQL reports'), >+ ( 'staffaccess', 'staff_access_permissions', 'Allow staff members to modify permissions for other staff members'), >+ ( 'coursereserves', 'manage_courses', 'Add, edit and delete courses'), >+ ( 'coursereserves', 'add_reserves', 'Add course reserves'), >+ ( 'coursereserves', 'delete_reserves', 'Remove course reserves'), >+ ( 'plugins', 'manage', 'Manage plugins ( install / uninstall )'), >+ ( 'plugins', 'tool', 'Use tool plugins'), >+ ( 'plugins', 'report', 'Use report plugins'), >+ ( 'plugins', 'configure', 'Configure plugins'), >+ ( 'lists', 'delete_public_lists', 'Delete public lists') > ; >diff --git a/installer/data/mysql/kohastructure.sql b/installer/data/mysql/kohastructure.sql >index 66895d1..a1c7510 100644 >--- a/installer/data/mysql/kohastructure.sql >+++ b/installer/data/mysql/kohastructure.sql >@@ -249,7 +249,6 @@ CREATE TABLE `borrowers` ( -- this table includes information about your patrons > `ethnotes` varchar(255) default NULL, -- unused in Koha > `sex` varchar(1) default NULL, -- patron/borrower's gender > `password` varchar(60) default NULL, -- patron/borrower's encrypted password >- `flags` int(11) default NULL, -- will include a number associated with the staff member's permissions > `userid` varchar(75) default NULL, -- patron/borrower's opac and/or staff client log in > `opacnote` mediumtext, -- a note on the patron/borrower's account that is visible in the OPAC and staff client > `contactnote` varchar(255) default NULL, -- a note related to the patron/borrower's alternate address >@@ -879,7 +878,6 @@ CREATE TABLE `deletedborrowers` ( -- stores data related to the patrons/borrower > `ethnotes` varchar(255) default NULL, -- unused in Koha > `sex` varchar(1) default NULL, -- patron/borrower's gender > `password` varchar(30) default NULL, -- patron/borrower's encrypted password >- `flags` int(11) default NULL, -- will include a number associated with the staff member's permissions > `userid` varchar(30) default NULL, -- patron/borrower's opac and/or staff client log in > `opacnote` mediumtext, -- a note on the patron/borrower's account that is visible in the OPAC and staff client > `contactnote` varchar(255) default NULL, -- a note related to the patron/borrower's alternate address >@@ -2292,19 +2290,6 @@ CREATE TABLE `tags_index` ( -- a weighted list of all tags and where they are us > ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; > > -- >--- Table structure for table `userflags` >--- >- >-DROP TABLE IF EXISTS `userflags`; >-CREATE TABLE `userflags` ( >- `bit` int(11) NOT NULL default 0, >- `flag` varchar(30) default NULL, >- `flagdesc` varchar(255) default NULL, >- `defaulton` int(11) default NULL, >- PRIMARY KEY (`bit`) >-) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; >- >--- > -- Table structure for table `virtualshelves` > -- > >@@ -2485,20 +2470,6 @@ CREATE TABLE language_script_mapping ( > ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; > > -- >--- Table structure for table `permissions` >--- >- >-DROP TABLE IF EXISTS `permissions`; >-CREATE TABLE `permissions` ( >- `module_bit` int(11) NOT NULL DEFAULT 0, >- `code` varchar(64) DEFAULT NULL, >- `description` varchar(255) DEFAULT NULL, >- PRIMARY KEY (`module_bit`, `code`), >- CONSTRAINT `permissions_ibfk_1` FOREIGN KEY (`module_bit`) REFERENCES `userflags` (`bit`) >- ON DELETE CASCADE ON UPDATE CASCADE >-) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; >- >--- > -- Table structure for table `serialitems` > -- > >@@ -2513,21 +2484,6 @@ CREATE TABLE `serialitems` ( > ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; > > -- >--- Table structure for table `user_permissions` >--- >- >-DROP TABLE IF EXISTS `user_permissions`; >-CREATE TABLE `user_permissions` ( >- `borrowernumber` int(11) NOT NULL DEFAULT 0, >- `module_bit` int(11) NOT NULL DEFAULT 0, >- `code` varchar(64) DEFAULT NULL, >- CONSTRAINT `user_permissions_ibfk_1` FOREIGN KEY (`borrowernumber`) REFERENCES `borrowers` (`borrowernumber`) >- ON DELETE CASCADE ON UPDATE CASCADE, >- CONSTRAINT `user_permissions_ibfk_2` FOREIGN KEY (`module_bit`, `code`) REFERENCES `permissions` (`module_bit`, `code`) >- ON DELETE CASCADE ON UPDATE CASCADE >-) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; >- >--- > -- Table structure for table `tmp_holdsqueue` > -- > >@@ -3339,7 +3295,6 @@ CREATE TABLE IF NOT EXISTS `borrower_modifications` ( > `ethnotes` varchar(255) DEFAULT NULL, > `sex` varchar(1) DEFAULT NULL, > `password` varchar(30) DEFAULT NULL, >- `flags` int(11) DEFAULT NULL, > `userid` varchar(75) DEFAULT NULL, > `opacnote` mediumtext, > `contactnote` varchar(255) DEFAULT NULL, >@@ -3362,6 +3317,55 @@ CREATE TABLE IF NOT EXISTS `borrower_modifications` ( > ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; > > -- >+-- Table structure for table permissions >+-- >+ >+DROP TABLE IF EXISTS permissions; >+CREATE TABLE permissions ( >+ permission_id int(11) NOT NULL auto_increment, >+ module varchar(32) NOT NULL, >+ code varchar(64) NOT NULL, >+ description varchar(255) DEFAULT NULL, >+ PRIMARY KEY (permission_id), >+ UNIQUE KEY (code), >+ CONSTRAINT permissions_to_modules_ibfk1 FOREIGN KEY (module) REFERENCES permission_modules (module) >+ ON DELETE CASCADE ON UPDATE CASCADE >+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; >+ >+-- >+-- Table structure for table permission_modules >+-- >+ >+DROP TABLE IF EXISTS permission_modules; >+CREATE TABLE permission_modules ( >+ permission_module_id int(11) NOT NULL auto_increment, >+ module varchar(32) NOT NULL, >+ description varchar(255) DEFAULT NULL, >+ PRIMARY KEY (permission_module_id), >+ UNIQUE KEY (module) >+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; >+ >+-- >+-- Table structure for table borrower_permissions >+-- >+ >+DROP TABLE IF EXISTS borrower_permissions; >+CREATE TABLE borrower_permissions ( >+ borrower_permission_id int(11) NOT NULL auto_increment, >+ borrowernumber int(11) NOT NULL, >+ permission_module_id int(11) NOT NULL, >+ permission_id int(11) NOT NULL, >+ PRIMARY KEY (borrower_permission_id), >+ UNIQUE KEY (borrowernumber, permission_module_id, permission_id), >+ CONSTRAINT borrower_permissions_ibfk_1 FOREIGN KEY (borrowernumber) REFERENCES borrowers (borrowernumber) >+ ON DELETE CASCADE ON UPDATE CASCADE, >+ CONSTRAINT borrower_permissions_ibfk_2 FOREIGN KEY (permission_id) REFERENCES permissions (permission_id) >+ ON DELETE CASCADE ON UPDATE CASCADE, >+ CONSTRAINT borrower_permissions_ibfk_3 FOREIGN KEY (permission_module_id) REFERENCES permission_modules (permission_module_id) >+ ON DELETE CASCADE ON UPDATE CASCADE >+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; >+ >+-- > -- Table structure for table linktracker > -- This stores clicks to external links > -- >diff --git a/installer/data/mysql/updatedatabase.pl b/installer/data/mysql/updatedatabase.pl >index 5171e8e..7392c2f 100755 >--- a/installer/data/mysql/updatedatabase.pl >+++ b/installer/data/mysql/updatedatabase.pl >@@ -7823,6 +7823,119 @@ if ( CheckVersion($DBversion) ) { > SetVersion($DBversion); > } > >+$DBversion = "3.21.00.XXX"; >+if ( CheckVersion($DBversion) ) { >+ my $upgradeDone; >+ my $permissionModule = $dbh->selectrow_hashref("SELECT * FROM permission_modules LIMIT 1"); >+ if ($permissionModule) { >+ print "Upgrade to $DBversion ALREADY DONE?!? (Bug 14540 - Move member-flags.pl to PermissionsManager to better manage permissions for testing.)\n"; >+ $upgradeDone = 1; >+ } >+ unless ($upgradeDone) { >+ ##CREATE new TABLEs >+ ##CREATing instead of ALTERing existing tables because this way the changes are more easy to understand. >+ $dbh->do("CREATE TABLE permission_modules ( >+ permission_module_id int(11) NOT NULL auto_increment, >+ module varchar(32) NOT NULL, >+ description varchar(255) DEFAULT NULL, >+ PRIMARY KEY (permission_module_id), >+ UNIQUE KEY (module) >+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;"); >+ $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 >+ $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. >+ >+ $dbh->do("ALTER TABLE permissions RENAME TO permissions_old"); >+ $dbh->do("CREATE TABLE permissions ( >+ permission_id int(11) NOT NULL auto_increment, >+ module varchar(32) NOT NULL, >+ code varchar(64) NOT NULL, >+ description varchar(255) DEFAULT NULL, >+ PRIMARY KEY (permission_id), >+ UNIQUE KEY (code), >+ CONSTRAINT permissions_to_modules_ibfk1 FOREIGN KEY (module) REFERENCES permission_modules (module) >+ ON DELETE CASCADE ON UPDATE CASCADE >+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;"); >+ $dbh->do("INSERT INTO permissions (module, code, description) >+ SELECT userflags.flag, code, description FROM permissions_old >+ LEFT JOIN userflags ON permissions_old.module_bit = userflags.bit;"); >+ >+ $dbh->do("CREATE TABLE borrower_permissions ( >+ borrower_permission_id int(11) NOT NULL auto_increment, >+ borrowernumber int(11) NOT NULL, >+ permission_module_id int(11) NOT NULL, >+ permission_id int(11) NOT NULL, >+ PRIMARY KEY (borrower_permission_id), >+ UNIQUE KEY (borrowernumber, permission_module_id, permission_id), >+ CONSTRAINT borrower_permissions_ibfk_1 FOREIGN KEY (borrowernumber) REFERENCES borrowers (borrowernumber) >+ ON DELETE CASCADE ON UPDATE CASCADE, >+ CONSTRAINT borrower_permissions_ibfk_2 FOREIGN KEY (permission_id) REFERENCES permissions (permission_id) >+ ON DELETE CASCADE ON UPDATE CASCADE, >+ CONSTRAINT borrower_permissions_ibfk_3 FOREIGN KEY (permission_module_id) REFERENCES permission_modules (permission_module_id) >+ ON DELETE CASCADE ON UPDATE CASCADE >+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;"); >+ $dbh->do("INSERT INTO borrower_permissions (borrowernumber, permission_module_id, permission_id) >+ SELECT user_permissions.borrowernumber, user_permissions.module_bit, permissions.permission_id >+ FROM user_permissions >+ LEFT JOIN permissions ON user_permissions.code = permissions.code >+ LEFT JOIN borrowers ON borrowers.borrowernumber = user_permissions.borrowernumber >+ 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. >+ >+ ##Add subpermissions to the stand-alone modules (modules with no subpermissions) >+ $dbh->do("INSERT INTO permissions (module, code, description) VALUES ('superlibrarian', 'superlibrarian', 'Access to all librarian functions.');"); >+ $dbh->do("INSERT INTO permissions (module, code, description) VALUES ('catalogue', 'staff_login', 'Allow staff login.');"); >+ $dbh->do("INSERT INTO permissions (module, code, description) VALUES ('borrowers', 'view_borrowers', 'Show borrower details and search for borrowers.');"); >+ $dbh->do("INSERT INTO permissions (module, code, description) VALUES ('permissions', 'set_permissions', 'Set user permissions.');"); >+ $dbh->do("INSERT INTO permissions (module, code, description) VALUES ('management', 'management', 'Set library management parameters (deprecated).');"); >+ $dbh->do("INSERT INTO permissions (module, code, description) VALUES ('editauthorities', 'edit_authorities', 'Edit authorities.');"); >+ $dbh->do("INSERT INTO permissions (module, code, description) VALUES ('staffaccess', 'staff_access_permissions', 'Allow staff members to modify permissions for other staff members.');"); >+ >+ ##Create borrower_permissions to replace singular userflags from borrowers.flags. >+ use Koha::Borrowers; >+ my $sth = $dbh->prepare(" >+ INSERT INTO borrower_permissions (borrowernumber, permission_module_id, permission_id) >+ VALUES (?, >+ (SELECT permission_module_id FROM permission_modules WHERE module = ?), >+ (SELECT permission_id FROM permissions WHERE code = ?) >+ ); >+ "); >+ my @borrowers = Koha::Borrowers->search({}); >+ foreach my $b (@borrowers) { >+ next unless $b->flags; >+ if ( ( $b->flags & ( 2**0 ) ) ) { >+ $sth->execute($b->borrowernumber, 'superlibrarian', 'superlibrarian'); >+ } >+ if ( ( $b->flags & ( 2**2 ) ) ) { >+ $sth->execute($b->borrowernumber, 'catalogue', 'staff_login'); >+ } >+ if ( ( $b->flags & ( 2**4 ) ) ) { >+ $sth->execute($b->borrowernumber, 'borrowers', 'view_borrowers'); >+ } >+ if ( ( $b->flags & ( 2**5 ) ) ) { >+ $sth->execute($b->borrowernumber, 'permissions', 'set_permissions'); >+ } >+ if ( ( $b->flags & ( 2**12 ) ) ) { >+ $sth->execute($b->borrowernumber, 'management', 'management'); >+ } >+ if ( ( $b->flags & ( 2**14 ) ) ) { >+ $sth->execute($b->borrowernumber, 'editauthorities', 'edit_authorities'); >+ } >+ if ( ( $b->flags & ( 2**17 ) ) ) { >+ $sth->execute($b->borrowernumber, 'staffaccess', 'staff_access_permissions'); >+ } >+ } >+ >+ ##Cleanup redundant tables. >+ $dbh->do("DELETE FROM userflags"); #Cascades to other tables. >+ $dbh->do("DROP TABLE user_permissions"); >+ $dbh->do("DROP TABLE permissions_old"); >+ $dbh->do("DROP TABLE userflags"); >+ $dbh->do("ALTER TABLE borrowers DROP COLUMN flags"); >+ >+ print "Upgrade to $DBversion done (Bug 14540 - Move member-flags.pl to PermissionsManager to better manage permissions for testing.)\n"; >+ SetVersion($DBversion); >+ } >+} >+ > $DBversion = "3.15.00.002"; > if(CheckVersion($DBversion)) { > $dbh->do("ALTER TABLE deleteditems MODIFY materials text;"); >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/member-flags.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/member-flags.tt >index c1e751e..6427e05 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/member-flags.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/member-flags.tt >@@ -9,23 +9,23 @@ > $("#permissionstree").treeview({animated: "fast", collapsed: true}); > > // Enforce Superlibrarian Privilege Mutual Exclusivity >- if($('input[id="flag-0"]:checked').length){ >+ if($('input[id="flag-superlibrarian"]:checked').length){ > if ($('input[name="flag"]:checked').length > 1){ > 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.'); > } > > $('input[name="flag"]').each(function() { >- if($(this).attr('id') != "flag-0"){ >+ if($(this).attr('id') != "flag-superlibrarian"){ > $(this).attr('disabled', 'disabled'); > $(this).removeAttr('checked', 'checked'); > } > }); > } > >- $('input#flag-0').click(function() { >- if($('input[id="flag-0"]:checked').length){ >+ $('input#flag-superlibrarian').click(function() { >+ if($('input[id="flag-superlibrarian"]:checked').length){ > $('input[name="flag"]').each(function() { >- if($(this).attr('id') != "flag-0"){ >+ if($(this).attr('id') != "flag-superlibrarian"){ > $(this).attr('disabled', 'disabled'); > $(this).removeAttr('checked', 'checked'); > } >@@ -121,9 +121,9 @@ > <!-- <li class="folder-close">One level down<ul> --> > [% FOREACH loo IN loop %] > [% IF ( loo.expand ) %] >- <li class="open"> >+ <li class="[% loo.flag %] open"> > [% ELSE %] >- <li> >+ <li class="[% loo.flag %]"> > [% END %] > [% IF ( loo.checked ) %] > <input type="checkbox" id="flag-[% loo.bit %]" name="flag" value="[% loo.flag %]" checked="checked" onclick="toggleChildren(this)" /> >diff --git a/members/member-flags.pl b/members/member-flags.pl >index 68c52aa..7a4dc8b 100755 >--- a/members/member-flags.pl >+++ b/members/member-flags.pl >@@ -14,7 +14,9 @@ use C4::Context; > use C4::Members; > use C4::Branch; > use C4::Members::Attributes qw(GetBorrowerAttributes); >-#use C4::Acquisitions; >+use Koha::Auth::PermissionManager; >+ >+use Koha::Exception::BadParameter; > > use C4::Output; > >@@ -35,121 +37,43 @@ my ($template, $loggedinuser, $cookie) = get_template_and_user({ > debug => 1, > }); > >- >+my $permissionManager = Koha::Auth::PermissionManager->new(); > my %member2; > $member2{'borrowernumber'}=$member; > > if ($input->param('newflags')) { > my $dbh=C4::Context->dbh(); > >+ #Cast CGI-params into a permissions HASH. > my @perms = $input->param('flag'); >- my %all_module_perms = (); > my %sub_perms = (); > foreach my $perm (@perms) { >- if ($perm !~ /:/) { >- $all_module_perms{$perm} = 1; >+ if ($perm eq 'superlibrarian') { >+ $sub_perms{superlibrarian}->{superlibrarian} = 1; >+ } >+ elsif ($perm !~ /:/) { >+ #DEPRECATED, GUI still sends the module flags here even though they have been removed from the DB. > } else { > my ($module, $sub_perm) = split /:/, $perm, 2; >- push @{ $sub_perms{$module} }, $sub_perm; >+ $sub_perms{$module}->{$sub_perm} = 1; > } > } > >- # construct flags >- my $module_flags = 0; >- my $sth=$dbh->prepare("SELECT bit,flag FROM userflags ORDER BY bit"); >- $sth->execute(); >- while (my ($bit, $flag) = $sth->fetchrow_array) { >- if (exists $all_module_perms{$flag}) { >- $module_flags += 2**$bit; >- } >- } >- >- $sth = $dbh->prepare("UPDATE borrowers SET flags=? WHERE borrowernumber=?"); >- $sth->execute($module_flags, $member); >- >- # deal with subpermissions >- $sth = $dbh->prepare("DELETE FROM user_permissions WHERE borrowernumber = ?"); >- $sth->execute($member); >- $sth = $dbh->prepare("INSERT INTO user_permissions (borrowernumber, module_bit, code) >- SELECT ?, bit, ? >- FROM userflags >- WHERE flag = ?"); >- foreach my $module (keys %sub_perms) { >- next if exists $all_module_perms{$module}; >- foreach my $sub_perm (@{ $sub_perms{$module} }) { >- $sth->execute($member, $sub_perm, $module); >- } >- } >- >+ $permissionManager->revokeAllPermissions($member); >+ $permissionManager->grantPermissions($member, \%sub_perms); >+ > print $input->redirect("/cgi-bin/koha/members/moremember.pl?borrowernumber=$member"); > } else { >-# my ($bor,$flags,$accessflags)=GetMemberDetails($member,''); >- my $flags = $bor->{'flags'}; >- my $accessflags = $bor->{'authflags'}; >- my $dbh=C4::Context->dbh(); >- my $all_perms = get_all_subpermissions(); >- my $user_perms = get_user_subpermissions($bor->{'userid'}); >- my $sth=$dbh->prepare("SELECT bit,flag,flagdesc FROM userflags ORDER BY bit"); >- $sth->execute; >+ my $all_perms = $permissionManager->listKohaPermissionsAsHASH(); >+ my $user_perms = $permissionManager->getBorrowerPermissions($member); >+ >+ $all_perms = markBorrowerGrantedPermissions($all_perms, $user_perms); >+ > my @loop; >- while (my ($bit, $flag, $flagdesc) = $sth->fetchrow) { >- my $checked=''; >- if ($accessflags->{$flag}) { >- $checked= 1; >- } >- >- my %row = ( bit => $bit, >- flag => $flag, >- checked => $checked, >- flagdesc => $flagdesc ); >- >- my @sub_perm_loop = (); >- my $expand_parent = 0; >- if ($checked) { >- if (exists $all_perms->{$flag}) { >- $expand_parent = 1; >- foreach my $sub_perm (sort keys %{ $all_perms->{$flag} }) { >- push @sub_perm_loop, { >- id => "${flag}_$sub_perm", >- perm => "$flag:$sub_perm", >- code => $sub_perm, >- description => $all_perms->{$flag}->{$sub_perm}, >- checked => 1 >- }; >- } >- } >- } else { >- if (exists $user_perms->{$flag}) { >- $expand_parent = 1; >- # put selected ones first >- foreach my $sub_perm (sort keys %{ $user_perms->{$flag} }) { >- push @sub_perm_loop, { >- id => "${flag}_$sub_perm", >- perm => "$flag:$sub_perm", >- code => $sub_perm, >- description => $all_perms->{$flag}->{$sub_perm}, >- checked => 1 >- }; >- } >- } >- # then ones not selected >- if (exists $all_perms->{$flag}) { >- foreach my $sub_perm (sort keys %{ $all_perms->{$flag} }) { >- push @sub_perm_loop, { >- id => "${flag}_$sub_perm", >- perm => "$flag:$sub_perm", >- code => $sub_perm, >- description => $all_perms->{$flag}->{$sub_perm}, >- checked => 0 >- } unless exists $user_perms->{$flag} and exists $user_perms->{$flag}->{$sub_perm}; >- } >- } >- } >- $row{expand} = $expand_parent; >- if ($#sub_perm_loop > -1) { >- $row{sub_perm_loop} = \@sub_perm_loop; >- } >- push @loop, \%row; >+ #Make sure the superlibrarian module is always on top. >+ push @loop, preparePermissionModuleForDisplay($all_perms, 'superlibrarian'); >+ foreach my $module (sort(keys(%$all_perms))) { >+ push @loop, preparePermissionModuleForDisplay($all_perms, $module) unless $module eq 'superlibrarian'; > } > > if ( $bor->{'category_type'} eq 'C') { >@@ -172,8 +96,8 @@ if (C4::Context->preference('ExtendedPatronAttributes')) { > } > > # Computes full borrower address >-my $roadtype = C4::Koha::GetAuthorisedValueByCode( 'ROADTYPE', $bor->{streettype} ); >-my $address = $bor->{'streetnumber'} . " $roadtype " . $bor->{'address'}; >+my $roadtype = C4::Koha::GetAuthorisedValueByCode( 'ROADTYPE', $bor->{streettype} ) || ''; >+my $address = ($bor->{'streetnumber'} || '') . " $roadtype " . ($bor->{'address'} || ''); > > $template->param( > borrowernumber => $bor->{'borrowernumber'}, >@@ -206,3 +130,75 @@ $template->param( > output_html_with_http_headers $input, $cookie, $template->output; > > } >+ >+=head markBorrowerGrantedPermissions >+ >+Adds a 'checked'-value for all subpermissions in the all-Koha-Permissions-list >+that the current borrower has been granted. >+@PARAM1 HASHRef of all Koha permissions and modules. >+@PARAM1 ARRAYRef of all the granted Koha::Auth::BorrowerPermission-objects. >+@RETURNS @PARAM1, slightly checked. >+=cut >+ >+sub markBorrowerGrantedPermissions { >+ my ($all_perms, $user_perms) = @_; >+ >+ foreach my $borrowerPermission (@$user_perms) { >+ my $module = $borrowerPermission->getPermissionModule->module; >+ my $code = $borrowerPermission->getPermission->code; >+ $all_perms->{$module}->{permissions}->{$code}->{checked} = 1; >+ } >+ return $all_perms; >+} >+ >+=head checkIfAllModulePermissionsGranted >+ >+@RETURNS Boolean, 1 if all permissions granted. >+=cut >+ >+sub checkIfAllModulePermissionsGranted { >+ my ($moduleHash) = @_; >+ foreach my $code (keys(%{$moduleHash->{permissions}})) { >+ unless ($moduleHash->{permissions}->{$code}->{checked}) { >+ return 0; >+ } >+ } >+ return 1; >+} >+ >+sub preparePermissionModuleForDisplay { >+ my ($all_perms, $module) = @_; >+ >+ my $moduleHash = $all_perms->{$module}; >+ my $checked = checkIfAllModulePermissionsGranted($moduleHash); >+ >+ my %row = ( >+ bit => $module, >+ flag => $module, >+ checked => $checked, >+ flagdesc => $moduleHash->{description} ); >+ >+ my @sub_perm_loop = (); >+ my $expand_parent = 0; >+ >+ if ($module ne 'superlibrarian') { >+ foreach my $sub_perm (sort keys %{ $all_perms->{$module}->{permissions} }) { >+ my $sub_perm_checked = $all_perms->{$module}->{permissions}->{$sub_perm}->{checked}; >+ $expand_parent = 1 if $sub_perm_checked; >+ >+ push @sub_perm_loop, { >+ id => "${module}_$sub_perm", >+ perm => "$module:$sub_perm", >+ code => $sub_perm, >+ description => $all_perms->{$module}->{permissions}->{$sub_perm}->{description}, >+ checked => $sub_perm_checked || 0, >+ }; >+ } >+ >+ $row{expand} = $expand_parent; >+ if ($#sub_perm_loop > -1) { >+ $row{sub_perm_loop} = \@sub_perm_loop; >+ } >+ } >+ return \%row; >+} >\ No newline at end of file >diff --git a/misc/devel/interactiveWebDriverShell.pl b/misc/devel/interactiveWebDriverShell.pl >index fdd5eb5..72f8c74 100755 >--- a/misc/devel/interactiveWebDriverShell.pl >+++ b/misc/devel/interactiveWebDriverShell.pl >@@ -115,13 +115,13 @@ my $supportedPageObjects = { > "members/moremember.pl" => > { package => "t::lib::Page::Members::Moremember", > urlEndpoint => "members/moremember.pl", >- status => "not implemented", >+ status => "OK", > params => ["borrowernumber"], > }, > "members/member-flags.pl" => > { package => "t::lib::Page::Members::MemberFlags", > urlEndpoint => "members/member-flags.pl", >- status => "not implemented", >+ status => "OK", > params => ["borrowernumber"], > }, > ################################################################################ >@@ -132,6 +132,11 @@ my $supportedPageObjects = { > urlEndpoint => "opac/opac-main.pl", > status => "OK", > }, >+ "opac/opac-search.pl" => >+ { package => "t::lib::Page::Opac::OpacSearch", >+ urlEndpoint => "opac/opac-search.pl", >+ status => "OK", >+ }, > }; > ################################################################################ > ########## END OF PAGE CONFIGURATIONS ########## >diff --git a/opac/opac-user.pl b/opac/opac-user.pl >index d4fbbe3..a653705 100755 >--- a/opac/opac-user.pl >+++ b/opac/opac-user.pl >@@ -349,7 +349,7 @@ foreach my $res (@reserves) { > $template->param( WAITING => \@waiting ); > > # current alert subscriptions >-my $alerts = getalert($borrowernumber); >+my $alerts = getalert($borrowernumber) if $borrowernumber; > foreach ( @$alerts ) { > $_->{ $_->{type} } = 1; > $_->{relatedto} = findrelatedto( $_->{type}, $_->{externalid} ); >diff --git a/t/db_dependent/Koha/Auth.t b/t/db_dependent/Koha/Auth.t >index 441070d..51d3af2 100644 >--- a/t/db_dependent/Koha/Auth.t >+++ b/t/db_dependent/Koha/Auth.t >@@ -22,7 +22,10 @@ use Modern::Perl; > use Test::More; > use Try::Tiny; #Even Selenium::Remote::Driver uses Try::Tiny :) > >+use Koha::Auth::PermissionManager; >+ > use t::lib::Page::Mainpage; >+use t::lib::Page::Opac::OpacMain; > > use t::lib::TestObjects::BorrowerFactory; > >@@ -36,17 +39,36 @@ my $borrowers = $borrowerFactory->createTestGroup([ > surname => 'Kivi', > cardnumber => '1A01', > branchcode => 'CPL', >- flags => '1', #superlibrarian, not exactly a very good way of doing permission testing? > userid => 'mini_admin', > password => $password, > }, >+ {firstname => 'Admin', >+ surname => 'Administrative', >+ cardnumber => 'maxi_admin', >+ branchcode => 'FPL', >+ userid => 'maxi_admin', >+ password => $password, >+ }, > ], undef, $testContext); > >+my $permissionManager = Koha::Auth::PermissionManager->new(); >+$permissionManager->grantPermission($borrowers->{'1A01'}, 'catalogue', 'staff_login'); >+$permissionManager->grantPermission($borrowers->{'maxi_admin'}, 'superlibrarian', 'superlibrarian'); >+ > ##Test context set, starting testing: > eval { #run in a eval-block so we don't die without tearing down the test context > >- testPasswordLogin(); >+ my $mainpage = t::lib::Page::Mainpage->new(); >+ testPasswordLoginLogout($mainpage); >+ testSuperuserPasswordLoginLogout($mainpage); >+ testSuperlibrarianPasswordLoginLogout($mainpage); >+ $mainpage->quit(); > >+ my $opacmain = t::lib::Page::Opac::OpacMain->new(); >+ testOpacPasswordLoginLogout($opacmain); >+ testSuperuserPasswordLoginLogout($opacmain); >+ testOpacSuperlibrarianPasswordLoginLogout($opacmain); >+ $opacmain->quit(); > }; > if ($@) { #Catch all leaking errors and gracefully terminate. > warn $@; >@@ -66,7 +88,30 @@ sub tearDown { > ### STARTING TEST IMPLEMENTATIONS ### > ###################################################### > >-sub testPasswordLogin { >- my $mainpage = t::lib::Page::Mainpage->new(); >- $mainpage->isPasswordLoginAvailable()->doPasswordLogin($borrowers->{'1A01'}->userid(), $password)->quit(); >-} >\ No newline at end of file >+sub testPasswordLoginLogout { >+ my ($mainpage) = @_; >+ $mainpage->isPasswordLoginAvailable()->doPasswordLogin($borrowers->{'1A01'}->userid(), $password) >+ ->isLoggedInBranchCode($borrowers->{'1A01'}->branchcode()) >+ ->doPasswordLogout(); >+} >+sub testOpacPasswordLoginLogout { >+ my ($mainpage) = @_; >+ $mainpage->isPasswordLoginAvailable()->doPasswordLogin($borrowers->{'1A01'}->userid(), $password) >+ ->doPasswordLogout(); >+} >+sub testSuperuserPasswordLoginLogout { >+ my ($mainpage) = @_; >+ $mainpage->isPasswordLoginAvailable()->doPasswordLogin(C4::Context->config('user'), C4::Context->config('pass')) >+ ->doPasswordLogout(); >+} >+sub testSuperlibrarianPasswordLoginLogout { >+ my ($mainpage) = @_; >+ $mainpage->isPasswordLoginAvailable()->doPasswordLogin($borrowers->{'maxi_admin'}->userid(), $password) >+ ->isLoggedInBranchCode($borrowers->{'maxi_admin'}->branchcode()) >+ ->doPasswordLogout(); >+} >+sub testOpacSuperlibrarianPasswordLoginLogout { >+ my ($mainpage) = @_; >+ $mainpage->isPasswordLoginAvailable()->doPasswordLogin($borrowers->{'maxi_admin'}->userid(), $password) >+ ->doPasswordLogout(); >+} >diff --git a/t/db_dependent/Koha/Auth/BorrowerPermission.t b/t/db_dependent/Koha/Auth/BorrowerPermission.t >new file mode 100644 >index 0000000..02dd0e7 >--- /dev/null >+++ b/t/db_dependent/Koha/Auth/BorrowerPermission.t >@@ -0,0 +1,102 @@ >+#!/usr/bin/perl >+ >+# Copyright 2015 Vaara-kirjastot >+# >+# This file is part of Koha. >+# >+# Koha is free software; you can redistribute it and/or modify it >+# under the terms of the GNU General Public License as published by >+# the Free Software Foundation; either version 3 of the License, or >+# (at your option) any later version. >+# >+# Koha is distributed in the hope that it will be useful, but >+# WITHOUT ANY WARRANTY; without even the implied warranty of >+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+# GNU General Public License for more details. >+# >+# You should have received a copy of the GNU General Public License >+# along with Koha; if not, see <http://www.gnu.org/licenses>. >+ >+use Modern::Perl; >+use Test::More; >+ >+use Koha::Auth::BorrowerPermission; >+use Koha::Auth::BorrowerPermissions; >+ >+use t::lib::TestObjects::ObjectFactory; >+use t::lib::TestObjects::BorrowerFactory; >+ >+##Setting up the test context >+my $testContext = {}; >+ >+my $borrowerFactory = t::lib::TestObjects::BorrowerFactory->new(); >+my $borrowers = $borrowerFactory->createTestGroup([ >+ {firstname => 'Olli-Antti', >+ surname => 'Kivi', >+ cardnumber => '1A01', >+ branchcode => 'CPL', >+ }, >+ {firstname => 'Alli-Ontti', >+ surname => 'Ivik', >+ cardnumber => '1A02', >+ branchcode => 'CPL', >+ }, >+ ], undef, $testContext); >+ >+##Test context set, starting testing: >+eval { #run in a eval-block so we don't die without tearing down the test context >+ ##Basic id-based creation. >+ my $borrowerPermissionById = Koha::Auth::BorrowerPermission->new({borrowernumber => $borrowers->{'1A01'}->borrowernumber, permission_module_id => 1, permission_id => 1}); >+ $borrowerPermissionById->store(); >+ my @borrowerPermissionById = Koha::Auth::BorrowerPermissions->search({borrowernumber => $borrowers->{'1A01'}->borrowernumber}); >+ is(scalar(@borrowerPermissionById), 1, "BorrowerPermissions, id-based creation:> Borrower has only one permission"); >+ is($borrowerPermissionById[0]->permission_module_id, 1, "BorrowerPermissions, id-based creation:> Same permission_module_id"); >+ is($borrowerPermissionById[0]->permission_id, 1, "BorrowerPermissions, id-based creation:> Same permission_id"); >+ >+ ##Basic name-based creation. >+ my $borrowerPermissionByName = Koha::Auth::BorrowerPermission->new({borrowernumber => $borrowers->{'1A02'}->borrowernumber, permissionModule => 'circulate', permission => 'manage_restrictions'}); >+ $borrowerPermissionByName->store(); >+ my @borrowerPermissionByName = Koha::Auth::BorrowerPermissions->search({borrowernumber => $borrowers->{'1A02'}->borrowernumber}); >+ is(scalar(@borrowerPermissionByName), 1, "BorrowerPermissions, name-based creation:> Borrower has only one permission"); >+ is($borrowerPermissionByName[0]->getPermissionModule->module, 'circulate', "BorrowerPermissions, name-based creation:> Same permission_module"); >+ is($borrowerPermissionByName[0]->getPermission->code, 'manage_restrictions', "BorrowerPermissions, name-based creation:> Same permission"); >+ >+ ##Testing setter/getter for Borrower >+ my $borrower1A01 = $borrowerPermissionById->getBorrower(); >+ is($borrower1A01->cardnumber, "1A01", "BorrowerPermissions, setter/getter:> getBorrower() 1A01"); >+ my $borrower1A02 = $borrowerPermissionByName->getBorrower(); >+ is($borrower1A02->cardnumber, "1A02", "BorrowerPermissions, setter/getter:> getBorrower() 1A02"); >+ >+ $borrowerPermissionById->setBorrower($borrower1A02); >+ is($borrowerPermissionById->getBorrower()->cardnumber, "1A02", "BorrowerPermissions, setter/getter:> setBorrower() 1A02"); >+ $borrowerPermissionByName->setBorrower($borrower1A01); >+ is($borrowerPermissionByName->getBorrower()->cardnumber, "1A01", "BorrowerPermissions, setter/getter:> setBorrower() 1A01"); >+ >+ ##Testing getter for PermissionModule >+ my $permissionModule1 = $borrowerPermissionById->getPermissionModule(); >+ is($permissionModule1->permission_module_id, 1, "BorrowerPermissions, setter/getter:> getPermissionModule() 1"); >+ my $permissionModuleCirculate = $borrowerPermissionByName->getPermissionModule(); >+ is($permissionModuleCirculate->module, "circulate", "BorrowerPermissions, setter/getter:> getPermissionModule() circulate"); >+ >+ #Not testing setters because changing the module might not make any sense. >+ #Then we would need to make sure we dont end up with bad permissionModule->permission combinations. >+ >+ ##Testing getter for Permission >+ my $permission1 = $borrowerPermissionById->getPermission(); >+ is($permission1->permission_id, 1, "BorrowerPermissions, setter/getter:> getPermission() 1"); >+ my $permissionManage_restrictions = $borrowerPermissionByName->getPermission(); >+ is($permissionManage_restrictions->code, "manage_restrictions", "BorrowerPermissions, setter/getter:> getPermission() manage_restrictions"); >+}; >+if ($@) { #Catch all leaking errors and gracefully terminate. >+ warn $@; >+ tearDown(); >+ exit 1; >+} >+ >+##All tests done, tear down test context >+$borrowerFactory->tearDownTestContext($testContext); >+done_testing; >+ >+sub tearDown { >+ t::lib::TestObjects::ObjectFactory->tearDownTestContext($testContext); >+} >\ No newline at end of file >diff --git a/t/db_dependent/Koha/Auth/PermissionManager.t b/t/db_dependent/Koha/Auth/PermissionManager.t >new file mode 100644 >index 0000000..513bb08 >--- /dev/null >+++ b/t/db_dependent/Koha/Auth/PermissionManager.t >@@ -0,0 +1,221 @@ >+#!/usr/bin/perl >+ >+# Copyright 2015 Vaara-kirjastot >+# >+# This file is part of Koha. >+# >+# Koha is free software; you can redistribute it and/or modify it >+# under the terms of the GNU General Public License as published by >+# the Free Software Foundation; either version 3 of the License, or >+# (at your option) any later version. >+# >+# Koha is distributed in the hope that it will be useful, but >+# WITHOUT ANY WARRANTY; without even the implied warranty of >+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+# GNU General Public License for more details. >+# >+# You should have received a copy of the GNU General Public License >+# along with Koha; if not, see <http://www.gnu.org/licenses>. >+ >+use Modern::Perl; >+use Test::More; >+use Try::Tiny; >+use Scalar::Util qw(blessed); >+ >+use Koha::Auth::PermissionManager; >+ >+use t::lib::TestObjects::ObjectFactory; >+use t::lib::TestObjects::BorrowerFactory; >+ >+ >+##Setting up the test context >+my $testContext = {}; >+ >+my $borrowerFactory = t::lib::TestObjects::BorrowerFactory->new(); >+my $borrowers = $borrowerFactory->createTestGroup([ >+ {firstname => 'Olli-Antti', >+ surname => 'Kivi', >+ cardnumber => '1A01', >+ branchcode => 'CPL', >+ }, >+ {firstname => 'Alli-Ontti', >+ surname => 'Ivik', >+ cardnumber => '1A02', >+ branchcode => 'CPL', >+ }, >+ ], undef, $testContext); >+ >+##Test context set, starting testing: >+eval { #run in a eval-block so we don't die without tearing down the test context >+ my $permissionManager = Koha::Auth::PermissionManager->new(); >+ my ($permissionModule, $permission, $failureCaughtFlag, $permissionsList); >+ >+ ##Test getBorrowerPermissions >+ $permissionManager->grantPermission($borrowers->{'1A01'}, 'circulate', 'force_checkout'); >+ $permissionManager->grantPermission($borrowers->{'1A01'}, 'circulate', 'manage_restrictions'); >+ $permissionsList = $permissionManager->getBorrowerPermissions($borrowers->{'1A01'}); >+ is($permissionsList->[0]->getPermission->code, 'force_checkout', "PermissionManager, getBorrowerPermissions:> Check 1."); >+ is($permissionsList->[1]->getPermission->code, 'manage_restrictions', "PermissionManager, getBorrowerPermissions:> Check 2."); >+ $permissionManager->revokePermission($borrowers->{'1A01'}, 'circulate', 'force_checkout'); >+ $permissionManager->revokePermission($borrowers->{'1A01'}, 'circulate', 'manage_restrictions'); >+ >+ ##Test grantPermissions && revokeAllPermissions >+ $permissionManager->grantPermissions($borrowers->{'1A01'}, >+ { borrowers => 'view_borrowers', >+ reserveforothers => ['place_holds'], >+ tools => ['edit_news', 'edit_notices'], >+ acquisition => { >+ budget_add_del => 1, >+ budget_modify => 1, >+ }, >+ }); >+ $permissionManager->hasPermission($borrowers->{'1A01'}, 'borrowers', 'view_borrowers'); >+ $permissionManager->hasPermission($borrowers->{'1A01'}, 'tools', 'edit_notices'); >+ $permissionManager->hasPermission($borrowers->{'1A01'}, 'acquisition', 'budget_modify'); >+ $permissionsList = $permissionManager->getBorrowerPermissions($borrowers->{'1A01'}); >+ is(scalar(@$permissionsList), 6, "PermissionManager, grantPermissions:> Permissions as HASH, ARRAY and Scalar."); >+ >+ $permissionManager->revokeAllPermissions($borrowers->{'1A01'}); >+ $permissionsList = $permissionManager->getBorrowerPermissions($borrowers->{'1A01'}); >+ is(scalar(@$permissionsList), 0, "PermissionManager, revokeAllPermissions:> No permissions left."); >+ >+ ##Test listKohaPermissionsAsHASH >+ my $listedPermissions = $permissionManager->listKohaPermissionsAsHASH(); >+ ok(ref($listedPermissions->{circulate}->{permissions}->{force_checkout}) eq 'HASH', "PermissionManager, listKohaPermissionsAsHASH:> Check 1."); >+ ok(ref($listedPermissions->{editcatalogue}->{permissions}->{edit_catalogue}) eq 'HASH', "PermissionManager, listKohaPermissionsAsHASH:> Check 2."); >+ ok(defined($listedPermissions->{reports}->{permissions}->{create_reports}->{description}), "PermissionManager, listKohaPermissionsAsHASH:> Check 3."); >+ ok(defined($listedPermissions->{permissions}->{description}), "PermissionManager, listKohaPermissionsAsHASH:> Check 4."); >+ >+ >+ >+ ### TESTING WITH unique keys, instead of the recommended Koha::Objects. ### >+ #Arguably this makes for more clear tests cases :) >+ ##Add/get PermissionModule >+ $permissionModule = $permissionManager->addPermissionModule({module => 'test', description => 'Just testing this module.'}); >+ is($permissionModule->module, "test", "PermissionManager from names, add/getPermissionModule:> Module added."); >+ $permissionModule = $permissionManager->getPermissionModule('test'); >+ is($permissionModule->module, "test", "PermissionManager from names, add/getPermissionModule:> Module got."); >+ >+ ##Add/get Permission >+ $permission = $permissionManager->addPermission({module => 'test', code => 'testperm', description => 'Just testing this permission.'}); >+ is($permission->code, "testperm", "PermissionManager from names, add/getPermission:> Permission added."); >+ $permission = $permissionManager->getPermission('testperm'); >+ is($permission->code, "testperm", "PermissionManager from names, add/getPermission:> Permission got."); >+ >+ ##Grant permission >+ $permissionManager->grantPermission($borrowers->{'1A01'}, 'test', 'testperm'); >+ ok($permissionManager->hasPermission($borrowers->{'1A01'}, 'test', 'testperm'), "PermissionManager from names, grant/hasPermission:> Borrower granted permission."); >+ >+ ##hasPermission with wildcard >+ ok($permissionManager->hasPermission($borrowers->{'1A01'}, 'test', '*'), "PermissionManager from names, hasPermission:> Wildcard permission."); >+ >+ ##hasPermissions with wildcard >+ ok($permissionManager->hasPermissions($borrowers->{'1A01'}, {test => ['*']}), "PermissionManager from names, hasPermission:> Wildcard permissions from array."); >+ >+ ##Revoke permission >+ $permissionManager->revokePermission($borrowers->{'1A01'}, 'test', 'testperm'); >+ $failureCaughtFlag = 0; >+ try { >+ $permissionManager->hasPermission($borrowers->{'1A01'}, 'test', 'testperm'); >+ } catch { >+ if (blessed($_) && $_->isa('Koha::Exception::NoPermission')) { >+ $failureCaughtFlag = 1; >+ } >+ else { >+ die $_; #Somekind of another problem arised and rethrow it. >+ } >+ }; >+ ok($failureCaughtFlag, "PermissionManager from names, revoke/hasPermission:> Borrower revoked permission."); >+ >+ ##Delete permissions and modules we just made. When we delete the module first, the permissions is ON CASCADE DELETEd >+ $permissionManager->delPermissionModule('test'); >+ $permissionModule = $permissionManager->getPermissionModule('test'); >+ ok(not(defined($permissionModule)), "PermissionManager from names, delPermissionModule:> Module deleted."); >+ >+ $failureCaughtFlag = 0; >+ try { >+ #This subpermission is now deleted due to cascading delete of the parent permissionModule >+ #We catch the exception gracefully and report test success >+ $permissionManager->delPermission('testperm'); >+ } catch { >+ if (blessed($_) && $_->isa('Koha::Exception::UnknownObject')) { >+ $failureCaughtFlag = 1; >+ } >+ else { >+ die $_; #Somekind of another problem arised and rethrow it. >+ } >+ }; >+ ok($failureCaughtFlag, "PermissionManager from names, delPermission:> Permission already deleted, exception caught."); >+ $permission = $permissionManager->getPermission('testperm'); >+ ok(not(defined($permission)), "PermissionManager from names, delPermission:> Permission deleted."); >+ >+ >+ >+ ### TESTING WITH Koha::Object parameters instead. ### >+ ##Add/get PermissionModule >+ $permissionModule = $permissionManager->addPermissionModule({module => 'test', description => 'Just testing this module.'}); >+ is($permissionModule->module, "test", "PermissionManager from objects, add/getPermissionModule:> Module added."); >+ $permissionModule = $permissionManager->getPermissionModule($permissionModule); >+ is($permissionModule->module, "test", "PermissionManager from objects, add/getPermissionModule:> Module got."); >+ >+ ##Add/get Permission >+ $permission = $permissionManager->addPermission({module => 'test', code => 'testperm', description => 'Just testing this permission.'}); >+ is($permission->code, "testperm", "PermissionManager from objects, add/getPermission:> Permission added."); >+ $permission = $permissionManager->getPermission($permission); >+ is($permission->code, "testperm", "PermissionManager from objects, add/getPermission:> Permission got."); >+ >+ ##Grant permission >+ $permissionManager->grantPermission($borrowers->{'1A01'}, $permissionModule, $permission); >+ ok($permissionManager->hasPermission($borrowers->{'1A01'}, $permissionModule, $permission), "PermissionManager from objects, grant/hasPermission:> Borrower granted permission."); >+ >+ ##hasPermission with wildcard >+ ok($permissionManager->hasPermission($borrowers->{'1A01'}, $permissionModule, '*'), "PermissionManager from objects, hasPermission:> Wildcard permission."); >+ >+ ##hasPermissions with wildcard, we quite cannot use a blessed Object as a HASH key >+ #ok($permissionManager->hasPermissions($borrowers->{'1A01'}, {$permissionModule->module() => ['*']}), "PermissionManager from objects, hasPermission:> Wildcard permissions from array."); >+ >+ ##Revoke permission >+ $permissionManager->revokePermission($borrowers->{'1A01'}, $permissionModule, $permission); >+ $failureCaughtFlag = 0; >+ try { >+ $permissionManager->hasPermission($borrowers->{'1A01'}, $permissionModule, $permission); >+ } catch { >+ if (blessed($_) && $_->isa('Koha::Exception::NoPermission')) { >+ $failureCaughtFlag = 1; >+ } >+ else { >+ die $_; #Somekind of another problem arised and rethrow it. >+ } >+ }; >+ ok($failureCaughtFlag, "PermissionManager from objects, revoke/hasPermission:> Borrower revoked permission."); >+ >+ ##Delete permissions and modules we just made >+ $permissionManager->delPermission($permission); >+ $permission = $permissionManager->getPermission('testperm'); >+ ok(not(defined($permission)), "PermissionManager from objects, delPermission:> Permission deleted."); >+ >+ $permissionManager->delPermissionModule($permissionModule); >+ $permissionModule = $permissionManager->getPermissionModule('test'); >+ ok(not(defined($permissionModule)), "PermissionManager from objects, delPermissionModule:> Module deleted."); >+ >+ >+ >+ ##Testing superlibrarian permission >+ $permissionManager->revokeAllPermissions($borrowers->{'1A01'}); >+ $permissionManager->grantPermission($borrowers->{'1A01'}, 'superlibrarian', 'superlibrarian'); >+ ok($permissionManager->hasPermission($borrowers->{'1A01'}, 'staffaccess', 'staff_access_permissions'), "PermissionManager, superuser permission:> Superuser has all permissions 1."); >+ ok($permissionManager->hasPermission($borrowers->{'1A01'}, 'tools', 'batch_upload_patron_images'), "PermissionManager, superuser permission:> Superuser has all permissions 2."); >+}; >+if ($@) { #Catch all leaking errors and gracefully terminate. >+ warn $@; >+ tearDown(); >+ exit 1; >+} >+ >+##All tests done, tear down test context >+tearDown(); >+done_testing; >+ >+sub tearDown { >+ t::lib::TestObjects::ObjectFactory->tearDownTestContext($testContext); >+} >\ No newline at end of file >diff --git a/t/db_dependent/Members/member-flags.t b/t/db_dependent/Members/member-flags.t >new file mode 100644 >index 0000000..e93579e >--- /dev/null >+++ b/t/db_dependent/Members/member-flags.t >@@ -0,0 +1,100 @@ >+#!/usr/bin/env perl >+ >+# Copyright 2015 Open Source Freedom Fighters >+# >+# This file is part of Koha. >+# >+# Koha is free software; you can redistribute it and/or modify it >+# under the terms of the GNU General Public License as published by >+# the Free Software Foundation; either version 3 of the License, or >+# (at your option) any later version. >+# >+# Koha is distributed in the hope that it will be useful, but >+# WITHOUT ANY WARRANTY; without even the implied warranty of >+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+# GNU General Public License for more details. >+# >+# You should have received a copy of the GNU General Public License >+# along with Koha; if not, see <http://www.gnu.org/licenses>. >+ >+use Modern::Perl; >+ >+use Test::More; >+use Try::Tiny; #Even Selenium::Remote::Driver uses Try::Tiny :) >+use Scalar::Util qw(blessed); >+ >+use t::lib::Page::Members::MemberFlags; >+use t::lib::TestObjects::BorrowerFactory; >+use Koha::Auth::PermissionManager; >+ >+ >+##Setting up the test context >+my $testContext = {}; >+ >+my $password = '1234'; >+my $borrowerFactory = t::lib::TestObjects::BorrowerFactory->new(); >+my $borrowers = $borrowerFactory->createTestGroup([ >+ {firstname => 'Olli-Antti', >+ surname => 'Kivi', >+ cardnumber => '1A01', >+ branchcode => 'CPL', >+ userid => 'mini_admin', >+ password => $password, >+ }, >+ ], undef, $testContext); >+ >+##Test context set, starting testing: >+eval { #run in a eval-block so we don't die without tearing down the test context >+ >+ testGrantRevokePermissions(); >+ >+}; >+if ($@) { #Catch all leaking errors and gracefully terminate. >+ warn $@; >+ tearDown(); >+ exit 1; >+} >+ >+##All tests done, tear down test context >+tearDown(); >+done_testing; >+ >+sub tearDown { >+ t::lib::TestObjects::ObjectFactory->tearDownTestContext($testContext); >+} >+ >+sub testGrantRevokePermissions { >+ my $permissionManager = Koha::Auth::PermissionManager->new(); >+ $permissionManager->grantPermissions($borrowers->{'1A01'}, {permissions => 'set_permissions', >+ catalogue => 'staff_login', >+ staffaccess => 'staff_access_permissions', >+ circulate => 'override_renewals', >+ borrowers => 'view_borrowers', >+ }); >+ >+ my $memberflags = t::lib::Page::Members::MemberFlags->new({borrowernumber => $borrowers->{'1A01'}->borrowernumber}); >+ >+ $memberflags->isPasswordLoginAvailable()->doPasswordLogin($borrowers->{'1A01'}->userid, $password) >+ ->togglePermission('editcatalogue', 'delete_all_items') #Add this >+ ->togglePermission('editcatalogue', 'edit_items') #Add this >+ ->togglePermission('circulate', 'override_renewals') #Remove this permission >+ ->submitPermissionTree(); >+ >+ ok($permissionManager->hasPermissions($borrowers->{'1A01'},{editcatalogue => ['delete_all_items', 'edit_items']}), >+ "member-flags.pl:> Granting new permissions succeeded."); >+ >+ my $failureCaughtFlag = 0; >+ try { >+ $permissionManager->hasPermission($borrowers->{'1A01'}, 'circulate', 'override_renewals'); >+ } catch { >+ if (blessed($_) && $_->isa('Koha::Exception::NoPermission')) { >+ $failureCaughtFlag = 1; >+ } >+ else { >+ die $_; #Somekind of another problem arised and rethrow it. >+ } >+ }; >+ ok($failureCaughtFlag, "member-flags.pl:> Revoking permissions succeeded."); >+ >+ $permissionManager->revokeAllPermissions($borrowers->{'1A01'}); >+} >\ No newline at end of file >diff --git a/t/db_dependent/Opac/opac-search.t b/t/db_dependent/Opac/opac-search.t >new file mode 100644 >index 0000000..fae1ce2 >--- /dev/null >+++ b/t/db_dependent/Opac/opac-search.t >@@ -0,0 +1,79 @@ >+#!/usr/bin/env perl >+ >+# Copyright 2015 Open Source Freedom Fighters >+# >+# This file is part of Koha. >+# >+# Koha is free software; you can redistribute it and/or modify it >+# under the terms of the GNU General Public License as published by >+# the Free Software Foundation; either version 3 of the License, or >+# (at your option) any later version. >+# >+# Koha is distributed in the hope that it will be useful, but >+# WITHOUT ANY WARRANTY; without even the implied warranty of >+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+# GNU General Public License for more details. >+# >+# You should have received a copy of the GNU General Public License >+# along with Koha; if not, see <http://www.gnu.org/licenses>. >+ >+use Modern::Perl; >+ >+use Test::More; >+ >+use t::lib::Page::Opac::OpacSearch; >+use t::lib::TestObjects::BorrowerFactory; >+ >+ >+##Setting up the test context >+my $testContext = {}; >+ >+my $password = '1234'; >+my $borrowerFactory = t::lib::TestObjects::BorrowerFactory->new(); >+my $borrowers = $borrowerFactory->createTestGroup([ >+ {firstname => 'Olli-Antti', >+ surname => 'Kivi', >+ cardnumber => '1A01', >+ branchcode => 'CPL', >+ userid => 'mini_admin', >+ password => $password, >+ }, >+ ], undef, $testContext); >+ >+##Test context set, starting testing: >+eval { #run in a eval-block so we don't die without tearing down the test context >+ >+ my $opacsearch = t::lib::Page::Opac::OpacSearch->new(); >+ testAnonymousSearchHistory($opacsearch); >+ >+}; >+if ($@) { #Catch all leaking errors and gracefully terminate. >+ warn $@; >+ tearDown(); >+ exit 1; >+} >+ >+##All tests done, tear down test context >+tearDown(); >+done_testing; >+ >+sub tearDown { >+ t::lib::TestObjects::ObjectFactory->tearDownTestContext($testContext); >+} >+ >+sub testAnonymousSearchHistory { >+ my $opacsearch = shift; >+ >+ $opacsearch->doSetSearchFieldTerm(1, 'Author', 'nengard')->doSearchSubmit()->navigateAdvancedSearch() >+ ->doSetSearchFieldTerm(1, 'Author', 'joubu')->doSearchSubmit()->navigateAdvancedSearch() >+ ->doSetSearchFieldTerm(1, 'Author', 'khall')->doSearchSubmit()->navigateHome() >+ ->doPasswordLogin($borrowers->{'1A01'}->userid, $password)->navigateAdvancedSearch() >+ ->doSetSearchFieldTerm(1, 'Author', 'magnuse')->doSearchSubmit()->navigateAdvancedSearch() >+ ->doSetSearchFieldTerm(1, 'Author', 'cait')->doSearchSubmit()->navigateSearchHistory() >+ ->testDoSearchHistoriesExist(['nengard', >+ 'joubu', >+ 'khall', >+ 'magnuse', >+ 'cait']) >+ ->quit(); >+} >\ No newline at end of file >-- >1.9.1
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 14540
:
41030
|
41051
|
41055
|
41056
|
41059
|
41062
|
41071
|
41123
|
41158
|
41255
|
41258
|
41310
|
41402
|
41535
|
42390
|
42410
|
42432
|
42434
|
42550
|
44490
|
63252
|
63253
|
63254