diff --git a/admin/roles/classes/permissions_table.php b/admin/roles/classes/permissions_table.php index 80e4b2067ce..b877a70c769 100644 --- a/admin/roles/classes/permissions_table.php +++ b/admin/roles/classes/permissions_table.php @@ -96,7 +96,7 @@ class core_role_permissions_table extends core_role_capability_table_base { "linkclass" => "preventlink", "adminurl" => $adminurl->out(), "icon" => "", "iconalt" => ""); if (isset($overridableroles[$id]) and ($allowoverrides or ($allowsafeoverrides and is_safe_capability($capability)))) { $templatecontext['icon'] = 't/delete'; - $templatecontext['iconalt'] = get_string('delete'); + $templatecontext['iconalt'] = get_string('deletexrole', 'core_role', $name); } $neededroles[$id] = $renderer->render_from_template('core/permissionmanager_role', $templatecontext); } @@ -109,7 +109,7 @@ class core_role_permissions_table extends core_role_capability_table_base { "icon" => "", "iconalt" => ""); if (isset($overridableroles[$id]) and prohibit_is_removable($id, $context, $capability->name)) { $templatecontext['icon'] = 't/delete'; - $templatecontext['iconalt'] = get_string('delete'); + $templatecontext['iconalt'] = get_string('deletexrole', 'core_role', $name); } $forbiddenroles[$id] = $renderer->render_from_template('core/permissionmanager_role', $templatecontext); } diff --git a/admin/roles/permissions.php b/admin/roles/permissions.php index 89668dc53c5..bc549484400 100644 --- a/admin/roles/permissions.php +++ b/admin/roles/permissions.php @@ -213,7 +213,7 @@ $arguments = array('contextid' => $contextid, $PAGE->requires->strings_for_js( array('roleprohibitinfo', 'roleprohibitheader', 'roleallowinfo', 'roleallowheader', 'confirmunassigntitle', 'confirmroleunprohibit', 'confirmroleprevent', 'confirmunassignyes', - 'confirmunassignno'), 'core_role'); + 'confirmunassignno', 'deletexrole'), 'core_role'); $PAGE->requires->js_call_amd('core/permissionmanager', 'initialize', array($arguments)); $table = new core_role_permissions_table($context, $contextname, $allowoverrides, $allowsafeoverrides, $overridableroles); echo $OUTPUT->box_start('generalbox capbox'); diff --git a/lib/amd/build/permissionmanager.min.js b/lib/amd/build/permissionmanager.min.js index 4a6c31bc1d1..0ed75d13768 100644 --- a/lib/amd/build/permissionmanager.min.js +++ b/lib/amd/build/permissionmanager.min.js @@ -1 +1 @@ -define(["jquery","core/config","core/notification","core/templates","core/yui"],function(a,b,c,d,e){var f,g,h,i,j={ADDROLE:"a.allowlink, a.prohibitlink",REMOVEROLE:"a.preventlink, a.unprohibitlink",UNPROHIBIT:"a.unprohibitlink"},k=a.Event("rolesloaded"),l=null,m=function(){var d={contextid:f,getroles:1,sesskey:b.sesskey};a.post(h+"roles/ajax.php",d,null,"json").done(function(b){try{i=b,m=function(){a("body").trigger(k)},m()}catch(d){c.exception(d)}}).fail(function(a,b,d){c.exception(d)})},n=function(b,e,g){var j={contextid:f,roleid:e,sesskey:M.cfg.sesskey,action:g,capability:b.data("name")};a.post(h+"roles/ajax.php",j,null,"json").done(function(f){var g=f;try{var j={rolename:i[e],roleid:e,adminurl:h,imageurl:M.util.image_url("t/delete","moodle")};switch(g){case"allow":j.spanclass="allowed",j.linkclass="preventlink",j.action="prevent",j.icon="t/delete";break;case"prohibit":j.spanclass="forbidden",j.linkclass="unprohibitlink",j.action="unprohibit",j.icon="t/delete";break;case"prevent":return void b.find('a[data-role-id="'+e+'"]').first().closest(".allowed").remove();case"unprohibit":return void b.find('a[data-role-id="'+e+'"]').first().closest(".forbidden").remove();default:return}d.render("core/permissionmanager_role",j).done(function(c){if("allow"==g)a(c).insertBefore(b.find(".allowmore:first"));else if("prohibit"==g){a(c).insertBefore(b.find(".prohibitmore:first"));var d=b.find(".allowedroles").first().find('a[data-role-id="'+e+'"]');d&&d.first().closest(".allowed").remove()}l.hide()}).fail(c.exception)}catch(k){c.exception(k)}}).fail(function(a,b,d){c.exception(d)})},o=function(b){b.preventDefault(),e.use("moodle-core-notification-dialogue",function(){a("body").one("rolesloaded",function(){var e=a(b.currentTarget),f=e.data("action"),h=e.closest("tr.rolecap"),k={cap:h.data("humanname"),context:g},m=M.util.get_string("role"+f+"info","core_role",k);null===l&&(l=new M.core.dialogue({draggable:!0,modal:!0,closeButton:!0,width:"450px"})),l.set("headerContent",M.util.get_string("role"+f+"header","core_role"));var o,p,q=[];switch(f){case"allow":p=h.find(j.REMOVEROLE);break;case"prohibit":p=h.find(j.UNPROHIBIT)}for(o in i){var r="",s=p.filter("[data-role-id='"+o+"']").length;s&&(r="disabled");var t={roleid:o,rolename:i[o],disabled:r};q.push(t)}d.render("core/permissionmanager_panelcontent",{message:m,roles:q}).done(function(b){l.set("bodyContent",b),l.show(),a("div.role_buttons").delegate("input","click",function(b){var c=a(b.currentTarget).data("role-id");n(h,c,f)})}).fail(c.exception)})}),m()},p=function(b){b.preventDefault(),a("body").one("rolesloaded",function(){var d=a(b.currentTarget),e=d.data("action"),f=d.data("role-id"),h=d.closest("tr.rolecap"),j={role:i[f],cap:h.data("humanname"),context:g};c.confirm(M.util.get_string("confirmunassigntitle","core_role"),M.util.get_string("confirmrole"+e,"core_role",j),M.util.get_string("confirmunassignyes","core_role"),M.util.get_string("confirmunassignno","core_role"),function(){n(h,f,e)})}),m()};return{initialize:function(b){f=b.contextid,g=b.contextname,h=b.adminurl;var c=a("body");c.delegate(j.ADDROLE,"click",o),c.delegate(j.REMOVEROLE,"click",p)}}}); \ No newline at end of file +define(["jquery","core/config","core/notification","core/templates","core/yui"],function(a,b,c,d,e){var f,g,h,i,j={ADDROLE:"a.allowlink, a.prohibitlink",REMOVEROLE:"a.preventlink, a.unprohibitlink",UNPROHIBIT:"a.unprohibitlink"},k=a.Event("rolesloaded"),l=null,m=function(){var d={contextid:f,getroles:1,sesskey:b.sesskey};a.post(h+"roles/ajax.php",d,null,"json").done(function(b){try{i=b,m=function(){a("body").trigger(k)},m()}catch(d){c.exception(d)}}).fail(function(a,b,d){c.exception(d)})},n=function(b,e,g){var j={contextid:f,roleid:e,sesskey:M.cfg.sesskey,action:g,capability:b.data("name")};a.post(h+"roles/ajax.php",j,null,"json").done(function(f){var g=f;try{var j={rolename:i[e],roleid:e,adminurl:h,imageurl:M.util.image_url("t/delete","moodle")};switch(g){case"allow":j.spanclass="allowed",j.linkclass="preventlink",j.action="prevent",j.icon="t/delete",j.iconalt=M.util.get_string("deletexrole","core_role",i[e]);break;case"prohibit":j.spanclass="forbidden",j.linkclass="unprohibitlink",j.action="unprohibit",j.icon="t/delete",j.iconalt=M.util.get_string("deletexrole","core_role",i[e]);break;case"prevent":return void b.find('a[data-role-id="'+e+'"]').first().closest(".allowed").remove();case"unprohibit":return void b.find('a[data-role-id="'+e+'"]').first().closest(".forbidden").remove();default:return}d.render("core/permissionmanager_role",j).done(function(c){if("allow"==g)a(c).insertBefore(b.find(".allowmore:first"));else if("prohibit"==g){a(c).insertBefore(b.find(".prohibitmore:first"));var d=b.find(".allowedroles").first().find('a[data-role-id="'+e+'"]');d&&d.first().closest(".allowed").remove()}l.hide()}).fail(c.exception)}catch(k){c.exception(k)}}).fail(function(a,b,d){c.exception(d)})},o=function(b){b.preventDefault();var f=a(b.currentTarget);a("body").one("rolesloaded",function(){e.use("moodle-core-notification-dialogue",function(){var b=f.data("action"),e=f.closest("tr.rolecap"),h={cap:e.data("humanname"),context:g},k=M.util.get_string("role"+b+"info","core_role",h);null===l&&(l=new M.core.dialogue({draggable:!0,modal:!0,closeButton:!0,width:"450px"})),l.set("headerContent",M.util.get_string("role"+b+"header","core_role"));var m,o,p=[];switch(b){case"allow":o=e.find(j.REMOVEROLE);break;case"prohibit":o=e.find(j.UNPROHIBIT)}for(m in i){var q="",r=o.filter("[data-role-id='"+m+"']").length;r&&(q="disabled");var s={roleid:m,rolename:i[m],disabled:q};p.push(s)}d.render("core/permissionmanager_panelcontent",{message:k,roles:p}).done(function(c){l.set("bodyContent",c),l.show(),a("div.role_buttons").on("click","input",function(c){var d=a(c.currentTarget).data("role-id");n(e,d,b)})}).fail(c.exception)})}),m()},p=function(b){b.preventDefault();var d=a(b.currentTarget);a("body").one("rolesloaded",function(){var a=d.data("action"),b=d.data("role-id"),e=d.closest("tr.rolecap"),f={role:i[b],cap:e.data("humanname"),context:g};c.confirm(M.util.get_string("confirmunassigntitle","core_role"),M.util.get_string("confirmrole"+a,"core_role",f),M.util.get_string("confirmunassignyes","core_role"),M.util.get_string("confirmunassignno","core_role"),function(){n(e,b,a)})}),m()};return{initialize:function(b){f=b.contextid,g=b.contextname,h=b.adminurl;var c=a("body");c.on("click",j.ADDROLE,o),c.on("click",j.REMOVEROLE,p)}}}); \ No newline at end of file diff --git a/lib/amd/src/permissionmanager.js b/lib/amd/src/permissionmanager.js index dcd8712bbbb..07721043e58 100644 --- a/lib/amd/src/permissionmanager.js +++ b/lib/amd/src/permissionmanager.js @@ -105,12 +105,14 @@ define(['jquery', 'core/config', 'core/notification', 'core/templates', 'core/yu templatedata.linkclass = 'preventlink'; templatedata.action = 'prevent'; templatedata.icon = 't/delete'; + templatedata.iconalt = M.util.get_string('deletexrole', 'core_role', overideableroles[roleid]); break; case 'prohibit': templatedata.spanclass = 'forbidden'; templatedata.linkclass = 'unprohibitlink'; templatedata.action = 'unprohibit'; templatedata.icon = 't/delete'; + templatedata.iconalt = M.util.get_string('deletexrole', 'core_role', overideableroles[roleid]); break; case 'prevent': row.find('a[data-role-id="' + roleid + '"]').first().closest('.allowed').remove(); @@ -155,10 +157,11 @@ define(['jquery', 'core/config', 'core/notification', 'core/templates', 'core/yu var handleAddRole = function(e) { e.preventDefault(); + var link = $(e.currentTarget); + // TODO: MDL-57778 Convert to core/modal. - Y.use('moodle-core-notification-dialogue', function() { - $('body').one('rolesloaded', function() { - var link = $(e.currentTarget); + $('body').one('rolesloaded', function() { + Y.use('moodle-core-notification-dialogue', function() { var action = link.data('action'); var row = link.closest('tr.rolecap'); var confirmationDetails = { @@ -201,7 +204,7 @@ define(['jquery', 'core/config', 'core/notification', 'core/templates', 'core/yu .done(function(content) { panel.set('bodyContent', content); panel.show(); - $('div.role_buttons').delegate('input', 'click', function(e) { + $('div.role_buttons').on('click', 'input', function(e) { var roleid = $(e.currentTarget).data('role-id'); changePermissions(row, roleid, action); }); @@ -222,8 +225,8 @@ define(['jquery', 'core/config', 'core/notification', 'core/templates', 'core/yu */ var handleRemoveRole = function(e) { e.preventDefault(); + var link = $(e.currentTarget); $('body').one('rolesloaded', function() { - var link = $(e.currentTarget); var action = link.data('action'); var roleid = link.data('role-id'); var row = link.closest('tr.rolecap'); @@ -256,8 +259,8 @@ define(['jquery', 'core/config', 'core/notification', 'core/templates', 'core/yu contextname = args.contextname; adminurl = args.adminurl; var body = $('body'); - body.delegate(SELECTORS.ADDROLE, 'click', handleAddRole); - body.delegate(SELECTORS.REMOVEROLE, 'click', handleRemoveRole); + body.on('click', SELECTORS.ADDROLE, handleAddRole); + body.on('click', SELECTORS.REMOVEROLE, handleRemoveRole); } }; }); diff --git a/lib/tests/behat/permissionmanager.feature b/lib/tests/behat/permissionmanager.feature new file mode 100644 index 00000000000..bd96363e0b9 --- /dev/null +++ b/lib/tests/behat/permissionmanager.feature @@ -0,0 +1,51 @@ +@core @javascript +Feature: Override permissions on a context + In order to extend and restrict moodle features + As an admin or a teacher + I need to allow/deny the existing capabilities at different levels + + Background: + Given the following "users" exist: + | username | firstname | lastname | email | + | teacher1 | Teacher | 1 | t1@example.com | + And the following "courses" exist: + | fullname | shortname | + | Course 1 | C1 | + And the following "course enrolments" exist: + | user | course | role | + | teacher1 | C1 | editingteacher | + + Scenario: Default system capabilities modification + Given I log in as "admin" + And I am on "Course 1" course homepage + And I navigate to "Users > Permissions" in current page administration + When I click on "Allow" "icon" in the "mod/forum:addnews" "table_row" + And I press "Student" + Then "Add announcementsmod/forum:addnews" row "Roles with permission" column of "permissions" table should contain "Student" + When I reload the page + And I click on "Delete Student role" "link" in the "mod/forum:addnews" "table_row" + And I click on "Remove" "button" in the "Confirm role change" "dialogue" + Then "Add announcementsmod/forum:addnews" row "Roles with permission" column of "permissions" table should not contain "Student" + When I reload the page + And I click on "Prohibit" "icon" in the "mod/forum:addnews" "table_row" + And I press "Student" + Then "Add announcementsmod/forum:addnews" row "Prohibited" column of "permissions" table should contain "Student" + + Scenario: Module capabilities overrides + Given I log in as "teacher1" + And I am on "Course 1" course homepage with editing mode on + And I add a "Forum" to section "1" and I fill the form with: + | Forum name | Forum 1 | + And I follow "Forum 1" + And I navigate to "Permissions" in current page administration + When I click on "Allow" "icon" in the "mod/forum:addnews" "table_row" + And I press "Student" + Then "Add announcementsmod/forum:addnews" row "Roles with permission" column of "permissions" table should contain "Student" + When I reload the page + And I click on "Delete Student role" "link" in the "mod/forum:addnews" "table_row" + And I click on "Remove" "button" in the "Confirm role change" "dialogue" + Then "Add announcementsmod/forum:addnews" row "Roles with permission" column of "permissions" table should not contain "Student" + When I reload the page + And I click on "Prohibit" "icon" in the "mod/forum:addnews" "table_row" + And I press "Student" + Then "Add announcementsmod/forum:addnews" row "Prohibited" column of "permissions" table should contain "Student"