Koha/koha-tmpl/intranet-tmpl/prog/en/modules/members/member-flags.tt
Jonathan Druart 3f58ecb609 Bug 28882: permission UI allows selection of superlibrarian permission
With bug 20100 and 22150 we allow to select all the permissions but the
superlibrarian permission, to ease the selection. And we also forbid a
non-superlibrarian user to add superlibrarian permission.

However there is something wrong in the JS code and it's possible to add
the superlibrarian permission. The user is getting an ugly 500 and so
the permission change is not done, but the UI checks must be fixed.

To recreate:
Login with a non-superlibrarian user
Edit permission
Clear all
=> You can select the "superlibrarian" permission

Test plan:
Login with a non-superlibrarian user
Try to set the superlibrarian permissions to a user
=> not possible
Try the select all/clear all
=> still cannot set the superlibrarian permission

Work to be done:
Login with a non-superlibrarian user
Edit permissions for a superlibrarian user
=> You can remove it, then cannot add it back
Should we allow removal of superlibrarian permission by
non-superlibrarian user?

Signed-off-by: Hayley Pelham <hayleypelham@catalyst.net.nz>

Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
2021-09-09 10:59:37 +02:00

279 lines
13 KiB
Text

[% USE raw %]
[% USE Asset %]
[% USE Branches %]
[% SET footerjs = 1 %]
[% PROCESS 'permissions.inc' %]
[% INCLUDE 'doc-head-open.inc' %]
<title>
Set permissions for [% patron.surname | html %], [% patron.firstname | html %] &rsaquo; Patrons &rsaquo; Koha
</title>
[% INCLUDE 'doc-head-close.inc' %]
</head>
<body id="pat_member-flags" class="pat">
[% INCLUDE 'header.inc' %]
[% INCLUDE 'patron-search.inc' %]
<nav id="breadcrumbs" aria-label="Breadcrumb" class="breadcrumb">
<ol>
<li>
<a href="/cgi-bin/koha/mainpage.pl">Home</a>
</li>
<li>
<a href="/cgi-bin/koha/members/members-home.pl">Patrons</a>
</li>
<li>
<a href="#" aria-current="page">
Set permissions for [% patron.surname | html %], [% patron.firstname | html %]
</a>
</li>
</ol>
</nav>
<div class="main container-fluid">
<div class="row">
<div class="col-sm-10 col-sm-push-2">
<main>
[% INCLUDE 'members-toolbar.inc' %]
<form id="flag_form" method="post" action="/cgi-bin/koha/members/member-flags.pl">
<input type="hidden" name="csrf_token" value="[% csrf_token | html %]" />
<input type="hidden" name="member" id="borrowernumber" value="[% patron.borrowernumber | html %]" />
<input type="hidden" name="newflags" value="1" />
<h1>Set permissions for [% patron.surname | html %], [% patron.firstname | html %]</h1>
<div id="permissionstree">
<div id="permissions_toolbar" class="btn-toolbar">
<button type="submit" class="btn btn-default"><i class="fa fa-save"></i> Save</button>
<a class="btn btn-default" href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% patron.borrowernumber | html %]"><i class="fa fa-remove"></i> Cancel</a>
<a class="toggleall toggleall_on btn btn-link" href="#"><i class="fa fa-plus-square-o"></i> Show all</a>
<a class="toggleall toggleall_off btn btn-link" href="#"><i class="fa fa-minus-square-o"></i> Hide all</a>
<a id="CheckAllFlags" class="btn btn-link" href="#">
<i class="fa fa-check"></i> Select all
</a>
<a id="UncheckAllFlags" class="btn btn-link" href="#">
<i class="fa fa-remove"></i> Clear all
</a>
<div class="btn-group pull-right">
Filter: <input type="text" name="permissions_filter" id="permissions_filter" size="20" />
<a href="#" id="clear_filter" style="display:none"><i class="fa fa-remove"></i></a>
</div>
</div>
<div class="permissions">
[% FOREACH loo IN loop %]
[% IF ( loo.expand ) %]
<div id="parent-flag-[% loo.flag | html %]" class="open parent">
[% ELSE %]
<div id="parent-flag-[% loo.flag | html %]" class="parent">
[% END %]
[% IF ( loo.checked ) %]
[% IF disable_superlibrarian_privs && loo.bit == 0 %]
<input type="checkbox" disabled="disabled" data-bit="0" id="flag-0" class="parent flag superlib" name="flag" value="[% loo.flag | html %]" checked="checked" title="The system preference ProtectSuperlibrarianPrivileges is enabled" />
<input type="hidden" id="flag-0" name="flag" value="[% loo.flag | html %]" >
[% ELSE %]
<input type="checkbox" data-bit="[% loo.bit | html %]" id="flag-[% loo.bit | html %]" class="parent flag" name="flag" value="[% loo.flag | html %]" checked="checked" />
[% END %]
[% ELSE %]
[% IF disable_superlibrarian_privs && loo.bit == 0 %]
<input type="checkbox" disabled="disabled" class="flag parent" data-bit="0" id="flag-0" name="flag" value="[% loo.flag | html %]" title="The system preference ProtectSuperlibrarianPrivileges is enabled" />
[% ELSE %]
<input type="checkbox" class="flag parent" data-bit="[% loo.bit | html %]" id="flag-[% loo.bit | html %]" name="flag" value="[% loo.flag | html %]" />
[% END %]
[% END # /IF loo.checked %]
<label class="permissiondesc" for="flag-[% loo.bit | html %]">
[% PROCESS main_permissions name=loo.flag %]
</label>
[% IF ( loo.flag == "superlibrarian" ) %]<div class="hint superlibrarian-hint">This permission grants access to all areas. If selected, specific sub-permissions cannot be selected.</div>[% END %]
[% IF ( loo.sub_perm_loop ) %]
<a class="toggle-[% loo.bit | html %] togglechildren_off" href="#" data-bit="[% loo.bit | html %]"><i class="fa fa-minus-square-o"></i> Hide details</a>
<a class="toggle-[% loo.bit | html %] togglechildren_on" href="#" data-bit="[% loo.bit | html %]"><i class="fa fa-plus-square-o"></i> Show details</a>
<div class="children" id="flag-[% loo.bit | html %]-children">
[% FOREACH sub_perm_loo IN loo.sub_perm_loop %]
<div class="child-flags">
[% IF ( sub_perm_loo.checked ) %]
<input type="checkbox" id="[% sub_perm_loo.id | html %]" class="child flag" name="flag" value="[% sub_perm_loo.perm | html %]" checked="checked" />
[% ELSE %]
<input type="checkbox" id="[% sub_perm_loo.id | html %]" class="child flag" name="flag" value="[% sub_perm_loo.perm | html %]" />
[% END %]
<label class="permissiondesc" for="[% sub_perm_loo.id | html %]">
[% PROCESS sub_permissions name=sub_perm_loo.code %]
</label>
</div>
[% END %]
</div> <!-- /#flag-[% loo.bit | html %]-children -->
[% END # /IF loo.sub_perm_loop %]
</div> <!-- /.parent -->
[% END # /FOREACH loo %]
</div>
</div> <!-- /#permissionstree -->
</form>
</main>
</div> <!-- /.col-sm-10.col-sm-push-2 -->
<div class="col-sm-2 col-sm-pull-10">
<aside>
[% INCLUDE 'circ-menu.inc' %]
</aside>
</div> <!-- /.col-sm-2.col-sm-pull-10 -->
</div> <!-- /.row -->
[% MACRO jsinclude BLOCK %]
[% INCLUDE 'str/members-menu.inc' %]
[% Asset.js("js/members-menu.js") | $raw %]
[% Asset.js("lib/hc-sticky.js") | $raw %]
<script>
var Sticky;
$(document).ready(function() {
$("#CheckAllFlags").on("click",function(){
$(".flag").attr("disabled", false);
$(".flag").prop("checked", true);
$("#flag-0").prop("checked", false);
[% IF disable_superlibrarian_privs %]
$("#flag-0").prop("disabled", true);
[% END %]
return false;
});
$("#UncheckAllFlags").on("click",function(){
$(".flag").attr("disabled", false);
[% IF disable_superlibrarian_privs %]
$("#flag-0").prop("disabled", true);
[% END %]
$(".flag").prop("checked", false);
return false;
});
$(".flag").change(function(){
if(!$(this).is(':checked')){
$("input#flag-0").prop("checked", false);
}
});
Sticky = $("#permissions_toolbar");
Sticky.hcSticky({
stickTo: "#permissionstree",
stickyClass: "floating"
});
$(".open div").show();
$("#permissions_filter").on("keyup", function(){
$("#clear_filter").css("display","inline-block");
$("a[class^=toggle-]").hide();
var string = $(this).val();
var divs = $("div[id!='parent-flag-superlibrarian']", ".permissions");
if( string != "" && string.length > 3 ){
divs.each(function(){
if ( $(this).text().search(new RegExp( string, "i")) < 0 ) {
$(this).hide();
} else {
$(this).show();
}
});
} else {
divs.show();
}
});
$("#clear_filter").on("click", function(){
$(".togglechildren_off").show();
$("#permissions_filter").val("");
$("div", "#permissionstree").show();
$(this).css("display","none");
});
// Enforce Superlibrarian Privilege Mutual Exclusivity
if( $('input[id="flag-0"]:checked').length || $(".superlib:checked").length ){
if ($('input[name="flag"]:checked').length > 1){
alert(_("Inconsistency detected!") + "\n\n" + _("The superlibrarian privilege is mutually exclusive of other privileges, as it includes them all.") + "\n\n" + _("This patron's privileges will now be reset to include only superlibrarian."));
}
setLibrarian();
}
$('input#flag-0').click(function() {
if( $('input[id="flag-0"]:checked').length || $(".superlib:checked").length ){
$('input[name="flag"]').each(function() {
if($(this).attr('id') != "flag-0" && !$(this).hasClass('superlib') ){
$(this).prop('disabled', true);
$(this).prop('checked', false);
}
});
}
else {
$('input[name="flag"]').each(function() {
$(this).prop('disabled', false);
});
}
});
$(".toggleall_off, .toggleall_on").on('click', function(e) {
e.preventDefault();
if( $(this).hasClass("toggleall_on")){
$(".children,.togglechildren_off").show();
$(".togglechildren_on").hide();
} else {
$(".children,.togglechildren_off").hide();
$(".togglechildren_on").show();
}
});
$(".togglechildren_off, .togglechildren_on").on('click', function(e) {
e.preventDefault();
var bit = $(this).data("bit");
$("#flag-" + bit + "-children").toggle();
$(".toggle-" + bit).toggle();
});
$(".togglechildren_off, .togglechildren_on").hover( function(){
$(this).parent().addClass("permission-highlight");
}, function(){
$(this).parent().removeClass("permission-highlight");
});
$(".flag").on("change",function(e){
e.preventDefault();
if( $(this).hasClass("child") ){
if( $(this).prop("checked") ){
// If this is the last of all the child boxes to be checked the parent should be checked too
var unchecked = 0;
$(this).closest(".children").find(".child").each(function(){
if( !$(this).prop("checked") ){
// There are still unchecked checkboxes in this group
unchecked = 1;
}
});
if( unchecked === 0 ){
$(this).closest(".parent").find(".flag.parent").prop("checked", true);
}
} else {
$(this).closest(".parent").find(".flag.parent").prop("checked", false);
}
} else {
var bit = $(this).data("bit");
if( $(this).is(":checked") ){
$("#flag-" + bit + "-children").show().find(".flag").prop("checked", true);
$(".toggle-" + bit + ".togglechildren_on").hide();
$(".toggle-" + bit + ".togglechildren_off").show();
} else {
$("#flag-" + bit + "-children").show().find(".flag").prop("checked", false);
}
}
});
});
function setLibrarian(){
$('input[name="flag"]').each(function() {
if($(this).attr('id') != "flag-0" && !$(this).hasClass('superlib') ){
$(this).prop('disabled', true);
$(this).prop('checked', false);
}
});
}
</script>
[% END %]
[% INCLUDE 'intranet-bottom.inc' %]