From 24a60734885deb8128a9640d26e49e173b065a56 Mon Sep 17 00:00:00 2001 From: ElgarL Date: Fri, 25 Nov 2011 15:49:35 +0000 Subject: Fix superperms to pass all tests http://dev.bukkit.org/server-mods/superpermstest/ --- EssentialsGroupManager/src/Changelog.txt | 3 +- .../permissions/AnjoPermissionsHandler.java | 74 ++- .../permissions/BukkitPermissions.java | 522 +++++++++++---------- 3 files changed, 340 insertions(+), 259 deletions(-) (limited to 'EssentialsGroupManager/src') diff --git a/EssentialsGroupManager/src/Changelog.txt b/EssentialsGroupManager/src/Changelog.txt index d12f96cda..d942a470e 100644 --- a/EssentialsGroupManager/src/Changelog.txt +++ b/EssentialsGroupManager/src/Changelog.txt @@ -76,4 +76,5 @@ v 1.5: v 1.6: - Prevent Group.equals tests throwing a NullPointerException for GlobalGroups. - Stop throwing errors on an empty users file. - - Optimize sorting to speedup permission tests. \ No newline at end of file + - Optimize sorting to speedup permission tests. + - Fix superperms to pass all tests http://dev.bukkit.org/server-mods/superpermstest/ \ No newline at end of file diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/permissions/AnjoPermissionsHandler.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/permissions/AnjoPermissionsHandler.java index 9387f13ac..acfc65232 100644 --- a/EssentialsGroupManager/src/org/anjocaido/groupmanager/permissions/AnjoPermissionsHandler.java +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/permissions/AnjoPermissionsHandler.java @@ -97,43 +97,59 @@ public class AnjoPermissionsHandler extends PermissionsReaderInterface { @Override public List getAllPlayersPermissions(String userName) { - List playerPermArray = new ArrayList(ph.getUser(userName).getPermissionList()); - + List playerPermArray = new ArrayList(); + + for (String perm : ph.getUser(userName).getPermissionList()) { + if ((!playerPermArray.contains(perm)) && (!playerPermArray.contains("-" + perm))) { + playerPermArray.add(perm); + + Map children = GroupManager.BukkitPermissions.getAllChildren(perm, playerPermArray); + + if (children != null) { + for (String child : children.keySet()) { + if (children.get(child)) + if ((!playerPermArray.contains(child)) && (!playerPermArray.contains("-" + child))) { + playerPermArray.add(child); + } + } + } + } + } for (String group : getGroups(userName)) { if (group.startsWith("g:") && GroupManager.getGlobalGroups().hasGroup(group)) { for (String perm : GroupManager.getGlobalGroups().getGroupsPermissions(group)) { if ((!playerPermArray.contains(perm)) && (!playerPermArray.contains("-" + perm))) { playerPermArray.add(perm); - Map children = GroupManager.BukkitPermissions.getChildren(perm); + Map children = GroupManager.BukkitPermissions.getAllChildren(perm, playerPermArray); if (children != null) { for (String child : children.keySet()) { if (children.get(child)) - if ((!playerPermArray.contains(perm)) && (!playerPermArray.contains("-" + perm))) + if ((!playerPermArray.contains(child)) && (!playerPermArray.contains("-" + child))) playerPermArray.add(child); } } } } - } else { for (String perm : ph.getGroup(group).getPermissionList()) { if ((!playerPermArray.contains(perm)) && (!playerPermArray.contains("-" + perm))) { playerPermArray.add(perm); - - Map children = GroupManager.BukkitPermissions.getChildren(perm); + + Map children = GroupManager.BukkitPermissions.getAllChildren(perm, playerPermArray); if (children != null) { for (String child : children.keySet()) { if (children.get(child)) - if ((!playerPermArray.contains(perm)) && (!playerPermArray.contains("-" + perm))) + if ((!playerPermArray.contains(child)) && (!playerPermArray.contains("-" + child))) { playerPermArray.add(child); + } } } - } } } } + //Collections.sort(playerPermArray, StringPermissionComparator.getInstance()); return playerPermArray; } @@ -670,8 +686,22 @@ public class AnjoPermissionsHandler extends PermissionsReaderInterface { * @return PermissionCheckResult */ public PermissionCheckResult checkFullUserPermission(User user, String targetPermission) { + + return checkFullGMPermission(user, targetPermission, true); + } + + /** + * Check user and groups with inheritance and Bukkit if bukkit = true + * return a PermissionCheckResult. + * + * @param user + * @param targetPermission + * @param checkBukkit + * @return PermissionCheckResult + */ + public PermissionCheckResult checkFullGMPermission(User user, String targetPermission, Boolean checkBukkit) { PermissionCheckResult result = new PermissionCheckResult(); - result.askedPermission = targetPermission; + result.accessLevel = targetPermission; result.resultType = PermissionCheckResult.Type.NOTFOUND; if (user == null || targetPermission == null || targetPermission.isEmpty()) { @@ -697,12 +727,14 @@ public class AnjoPermissionsHandler extends PermissionsReaderInterface { } } - // Check Bukkit perms to support plugins which add perms via code (Heroes). - final Player player = Bukkit.getPlayer(user.getName()); - if ((player != null) && (player.hasPermission(targetPermission))) { - result.resultType = PermissionCheckResult.Type.FOUND; - result.owner = user; - return result; + if (checkBukkit == true) { + // Check Bukkit perms to support plugins which add perms via code (Heroes). + final Player player = Bukkit.getPlayer(user.getName()); + if ((player != null) && (player.hasPermission(targetPermission))) { + result.resultType = PermissionCheckResult.Type.FOUND; + result.owner = user; + return result; + } } // THEN IT RETURNS A NOT FOUND @@ -960,7 +992,7 @@ public class AnjoPermissionsHandler extends PermissionsReaderInterface { * Every '-' or '+' in the beginning is ignored. It will match only node * names. * - * @param userAcessLevel + * @param userAccessLevel * @param fullPermissionName * @return true if found a matching token. false if not. */ @@ -986,9 +1018,11 @@ public class AnjoPermissionsHandler extends PermissionsReaderInterface { } if (userAccessLevel.charAt(userAccessLevel.length() - 1) == '*') { - userAccessLevelLength--; - } - return userAccessLevel.regionMatches(true, userAccessLevelOffset, fullPermissionName, fullPermissionNameOffset, userAccessLevelLength - userAccessLevelOffset); + return userAccessLevel.regionMatches(true, userAccessLevelOffset, fullPermissionName, fullPermissionNameOffset, userAccessLevelLength - userAccessLevelOffset - 1); + } else { + return userAccessLevel.regionMatches(true, userAccessLevelOffset, fullPermissionName, fullPermissionNameOffset, + Math.max(userAccessLevelLength - userAccessLevelOffset, fullPermissionName.length() - fullPermissionNameOffset)); + } } diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/permissions/BukkitPermissions.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/permissions/BukkitPermissions.java index abfb73bfd..202e27e3a 100644 --- a/EssentialsGroupManager/src/org/anjocaido/groupmanager/permissions/BukkitPermissions.java +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/permissions/BukkitPermissions.java @@ -18,14 +18,14 @@ package org.anjocaido.groupmanager.permissions; import java.util.ArrayList; import java.util.HashMap; -import java.util.HashSet; +import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.Set; import org.anjocaido.groupmanager.GroupManager; import org.anjocaido.groupmanager.data.User; import org.anjocaido.groupmanager.dataholder.OverloadedWorldHolder; +import org.anjocaido.groupmanager.utils.PermissionCheckResult; import org.bukkit.Bukkit; import org.bukkit.entity.Player; @@ -49,246 +49,292 @@ import org.bukkit.plugin.PluginManager; /** - * + * * BukkitPermissions overrides to force GM reponses to Superperms - * + * * @author ElgarL, based upon PermissionsEX implementation */ public class BukkitPermissions { - protected Map attachments = new HashMap(); - protected Set registeredPermissions = new HashSet(); - protected GroupManager plugin; - protected boolean dumpAllPermissions = true; - protected boolean dumpMatchedPermissions = true; - public boolean player_join = false; - - public BukkitPermissions(GroupManager plugin) { - this.plugin = plugin; - - this.collectPermissions(); - this.registerEvents(); - - this.updateAllPlayers(); - - GroupManager.logger.info("Superperms support enabled."); - } - - private void registerEvents() { - PluginManager manager = plugin.getServer().getPluginManager(); - - PlayerEvents playerEventListener = new PlayerEvents(); - - manager.registerEvent(Event.Type.PLAYER_JOIN, playerEventListener, Event.Priority.Lowest, plugin); - manager.registerEvent(Event.Type.PLAYER_KICK, playerEventListener, Event.Priority.Lowest, plugin); - manager.registerEvent(Event.Type.PLAYER_QUIT, playerEventListener, Event.Priority.Lowest, plugin); - - manager.registerEvent(Event.Type.PLAYER_RESPAWN, playerEventListener, Event.Priority.Lowest, plugin); - manager.registerEvent(Event.Type.PLAYER_TELEPORT, playerEventListener, Event.Priority.Lowest, plugin); - manager.registerEvent(Event.Type.PLAYER_PORTAL, playerEventListener, Event.Priority.Lowest, plugin); - - ServerListener serverListener = new BukkitEvents(); - - manager.registerEvent(Event.Type.PLUGIN_ENABLE, serverListener, Event.Priority.Normal, plugin); - manager.registerEvent(Event.Type.PLUGIN_DISABLE, serverListener, Event.Priority.Normal, plugin); - } - - public void collectPermissions() { - registeredPermissions.clear(); - for (Plugin bukkitPlugin : Bukkit.getServer().getPluginManager().getPlugins()) { - for(Permission permission : bukkitPlugin.getDescription().getPermissions()) - registeredPermissions.add(permission); - } - } - - public void updatePermissions(Player player){ - this.updatePermissions(player, null); - } - - public void updatePermissions(Player player, String world) { - if (player == null || !GroupManager.isLoaded()) { - return; - } - - if (!this.attachments.containsKey(player)) { - this.attachments.put(player, player.addAttachment(plugin)); - } - - if(world == null){ - world = player.getWorld().getName(); - } - - // All permissions registered with Bukkit for this player - PermissionAttachment attachment = this.attachments.get(player); - - OverloadedWorldHolder worldData = plugin.getWorldsHolder().getWorldData(world); - - User user = worldData.getUser(player.getName()); - - // clear permissions - for (String permission : attachment.getPermissions().keySet()) - attachment.unsetPermission(permission); - - /* - * find matching permissions - * - * and base bukkit perms if we are set to allow bukkit permissions to override. - */ - Boolean value; - for (Permission permission : registeredPermissions) { - - value = worldData.getPermissionsHandler().checkUserPermission(user, permission.getName()); - - // Only check bukkit override IF we don't have the permission directly. - if (value = false) { - PermissionDefault permDefault = permission.getDefault(); - - if ((plugin.getGMConfig().isBukkitPermsOverride()) - && ((permDefault == PermissionDefault.TRUE) - || ((permDefault == PermissionDefault.NOT_OP) && !player.isOp()) - || ((permDefault == PermissionDefault.OP) && player.isOp()))) - value = true; - } - - if (value == true){ - // Set the root permission - attachment.setPermission(permission, value); - // fetch and set all children of this permission node - Map children = permission.getChildren(); - if (children != null) { - for (String child : children.keySet()) { - if (children.get(child)) - attachment.setPermission(child, true); - } - } - - } - } - - // Add any missing permissions for this player (non bukkit plugins) - List playerPermArray = new ArrayList(worldData.getPermissionsHandler().getAllPlayersPermissions(player.getName())); - - for (String permission : playerPermArray) { - value = true; - if (permission.startsWith("-")) { - permission = permission.substring(1); // cut off - - value = false; - } - - if (!attachment.getPermissions().containsKey(permission)) { - attachment.setPermission(permission, value); - } - } - player.recalculatePermissions(); - } - - /** - * Returns a map of the child permissions as defined by the supplying plugin - * null is empty - * - * @param node - * @return Map of child permissions - */ - public Map getChildren(String node) { - for (Permission permission : registeredPermissions) { - if (permission.getName() == node) { - return permission.getChildren(); - } - } - return null; - } - - public List listPerms(Player player) { - List perms = new ArrayList(); - - /* - // All permissions registered with Bukkit for this player - PermissionAttachment attachment = this.attachments.get(player); - - // List perms for this player - perms.add("Attachment Permissions:"); - for(Map.Entry entry : attachment.getPermissions().entrySet()){ - perms.add(" " + entry.getKey() + " = " + entry.getValue()); - } - */ - - perms.add("Effective Permissions:"); - for(PermissionAttachmentInfo info : player.getEffectivePermissions()){ - if (info.getValue() == true) - perms.add(" " + info.getPermission() + " = " + info.getValue()); - } - return perms; - } - - public void updateAllPlayers() { - for (Player player : Bukkit.getServer().getOnlinePlayers()) { - updatePermissions(player); - } - } - - protected class PlayerEvents extends PlayerListener { - - @Override - public void onPlayerJoin(PlayerJoinEvent event) { - player_join = true; - Player player = event.getPlayer(); - //force GM to create the player if they are not already listed. - if (plugin.getWorldsHolder().getWorldData(player.getWorld().getName()).getUser(player.getName()) != null) { - player_join = false; - updatePermissions(event.getPlayer()); - } else - player_join = false; - } - - @Override - public void onPlayerPortal(PlayerPortalEvent event) { // will portal into another world - if(event.getTo() != null && !event.getFrom().getWorld().equals(event.getTo().getWorld())){ // only if world actually changed - updatePermissions(event.getPlayer(), event.getTo().getWorld().getName()); - } - } - - @Override - public void onPlayerRespawn(PlayerRespawnEvent event) { // can be respawned in another world - updatePermissions(event.getPlayer(), event.getRespawnLocation().getWorld().getName()); - } - - @Override - public void onPlayerTeleport(PlayerTeleportEvent event) { // can be teleported into another world - if (event.getTo() != null && !event.getFrom().getWorld().equals(event.getTo().getWorld())) { // only if world actually changed - updatePermissions(event.getPlayer(), event.getTo().getWorld().getName()); - } - } - - @Override - public void onPlayerQuit(PlayerQuitEvent event) { - if (!GroupManager.isLoaded()) - return; - - attachments.remove(event.getPlayer()); - } - - @Override - public void onPlayerKick(PlayerKickEvent event) { - attachments.remove(event.getPlayer()); - } - } - - protected class BukkitEvents extends ServerListener { - - @Override - public void onPluginEnable(PluginEnableEvent event) { - if (!GroupManager.isLoaded()) - return; - - collectPermissions(); - updateAllPlayers(); - } - - @Override - public void onPluginDisable(PluginDisableEvent event) { - //collectPermissions(); - //updateAllPlayers(); - } - } + protected Map attachments = new HashMap(); + protected LinkedList registeredPermissions = new LinkedList(); + protected GroupManager plugin; + protected boolean dumpAllPermissions = true; + protected boolean dumpMatchedPermissions = true; + public boolean player_join = false; + + public BukkitPermissions(GroupManager plugin) { + this.plugin = plugin; + + this.collectPermissions(); + this.registerEvents(); + + this.updateAllPlayers(); + + GroupManager.logger.info("Superperms support enabled."); + } + + private void registerEvents() { + PluginManager manager = plugin.getServer().getPluginManager(); + + PlayerEvents playerEventListener = new PlayerEvents(); + + manager.registerEvent(Event.Type.PLAYER_JOIN, playerEventListener, Event.Priority.Lowest, plugin); + manager.registerEvent(Event.Type.PLAYER_KICK, playerEventListener, Event.Priority.Lowest, plugin); + manager.registerEvent(Event.Type.PLAYER_QUIT, playerEventListener, Event.Priority.Lowest, plugin); + + manager.registerEvent(Event.Type.PLAYER_RESPAWN, playerEventListener, Event.Priority.Lowest, plugin); + manager.registerEvent(Event.Type.PLAYER_TELEPORT, playerEventListener, Event.Priority.Lowest, plugin); + manager.registerEvent(Event.Type.PLAYER_PORTAL, playerEventListener, Event.Priority.Lowest, plugin); + + ServerListener serverListener = new BukkitEvents(); + + manager.registerEvent(Event.Type.PLUGIN_ENABLE, serverListener, Event.Priority.Normal, plugin); + manager.registerEvent(Event.Type.PLUGIN_DISABLE, serverListener, Event.Priority.Normal, plugin); + } + + public void collectPermissions() { + registeredPermissions.clear(); + for (Plugin bukkitPlugin : Bukkit.getServer().getPluginManager().getPlugins()) { + for (Permission permission : bukkitPlugin.getDescription().getPermissions()) + registeredPermissions.push(permission); + } + } + + public void updatePermissions(Player player) { + this.updatePermissions(player, null); + } + + public void updatePermissions(Player player, String world) { + if (player == null || !GroupManager.isLoaded()) { + return; + } + + if (!this.attachments.containsKey(player)) { + this.attachments.put(player, player.addAttachment(plugin)); + } + + if (world == null) { + world = player.getWorld().getName(); + } + + // All permissions registered with Bukkit for this player + PermissionAttachment attachment = this.attachments.get(player); + + OverloadedWorldHolder worldData = plugin.getWorldsHolder().getWorldData(world); + + User user = worldData.getUser(player.getName()); + + // clear permissions + for (String permission : attachment.getPermissions().keySet()) + attachment.unsetPermission(permission); + + /* + * find matching permissions + * + * and base bukkit perms if we are set to allow bukkit permissions to + * override. + */ + Boolean value = false; + + for (Permission permission : registeredPermissions) { + + PermissionCheckResult result = worldData.getPermissionsHandler().checkFullGMPermission(user, permission.getName(), false); + + // Only check bukkit override IF we don't have the permission + // directly. + if (result.resultType == PermissionCheckResult.Type.NOTFOUND) { + PermissionDefault permDefault = permission.getDefault(); + + if ((plugin.getGMConfig().isBukkitPermsOverride()) && ((permDefault == PermissionDefault.TRUE) + || ((permDefault == PermissionDefault.NOT_OP) && !player.isOp()) + || ((permDefault == PermissionDefault.OP) && player.isOp()))) { + value = true; + } else { + value = false; + } + } else if (result.resultType == PermissionCheckResult.Type.NEGATION) { + value = false; + } else { + value = true; + } + + // Set the root permission + if ((value == true) || (result.resultType == PermissionCheckResult.Type.NEGATION)) { + attachment.setPermission(permission, value); + } + /* + if ((value == true) || (result.resultType == PermissionCheckResult.Type.NOTFOUND)) { + // fetch and set all children of this permission node + Map children = permission.getChildren(); + if (children != null) { + for (String child : children.keySet()) { + if (children.get(child)) + attachment.setPermission(child, value); + } + } + }*/ + + } + + // Add any missing permissions for this player (non bukkit plugins and child nodes) + List playerPermArray = worldData.getPermissionsHandler().getAllPlayersPermissions(player.getName()); + + for (String permission : playerPermArray) { + value = true; + if (permission.startsWith("-")) { + permission = permission.substring(1); // cut off - + value = false; + } + + if (!attachment.getPermissions().containsKey(permission)) { + attachment.setPermission(permission, value); + } + } + player.recalculatePermissions(); + } + + /** + * Returns a map of the ALL child permissions as defined by the supplying plugin + * null is empty + * + * @param node + * @return Map of child permissions + */ + public Map getAllChildren(String node, List playerPermArray) { + + LinkedList stack = new LinkedList(); + Map alreadyVisited = new HashMap(); + stack.push(node); + alreadyVisited.put(node, true); + + while (!stack.isEmpty()) { + String now = stack.pop(); + + Map children = getChildren(now); + + if ((children != null) && (!playerPermArray.contains("-"+now))) { + for (String childName : children.keySet()) { + if (!alreadyVisited.containsKey(childName)) { + stack.push(childName); + alreadyVisited.put(childName, children.get(childName)); + } + } + } + } + alreadyVisited.remove(node); + if (!alreadyVisited.isEmpty()) return alreadyVisited; + + return null; + } + + /** + * Returns a map of the child permissions (1 node deep) as defined by the supplying plugin + * null is empty + * + * @param node + * @return Map of child permissions + */ + public Map getChildren(String node) { + for (Permission permission : registeredPermissions) { + if (permission.getName().equalsIgnoreCase(node)) { + return permission.getChildren(); + } + } + + return null; + } + + public List listPerms(Player player) { + List perms = new ArrayList(); + + /* + * // All permissions registered with Bukkit for this player + * PermissionAttachment attachment = this.attachments.get(player); + * + * // List perms for this player perms.add("Attachment Permissions:"); + * for(Map.Entry entry : + * attachment.getPermissions().entrySet()){ perms.add(" " + + * entry.getKey() + " = " + entry.getValue()); } + */ + + perms.add("Effective Permissions:"); + for (PermissionAttachmentInfo info : player.getEffectivePermissions()) { + if (info.getValue() == true) + perms.add(" " + info.getPermission() + " = " + info.getValue()); + } + return perms; + } + + public void updateAllPlayers() { + for (Player player : Bukkit.getServer().getOnlinePlayers()) { + updatePermissions(player); + } + } + + protected class PlayerEvents extends PlayerListener { + + @Override + public void onPlayerJoin(PlayerJoinEvent event) { + player_join = true; + Player player = event.getPlayer(); + // force GM to create the player if they are not already listed. + if (plugin.getWorldsHolder().getWorldData(player.getWorld().getName()).getUser(player.getName()) != null) { + player_join = false; + updatePermissions(event.getPlayer()); + } else + player_join = false; + } + + @Override + public void onPlayerPortal(PlayerPortalEvent event) { // will portal into another world + if (event.getTo() != null && !event.getFrom().getWorld().equals(event.getTo().getWorld())) { // only if world actually changed + updatePermissions(event.getPlayer(), event.getTo().getWorld().getName()); + } + } + + @Override + public void onPlayerRespawn(PlayerRespawnEvent event) { // can be respawned in another world + updatePermissions(event.getPlayer(), event.getRespawnLocation().getWorld().getName()); + } + + @Override + public void onPlayerTeleport(PlayerTeleportEvent event) { // can be teleported into another world + if (event.getTo() != null && !event.getFrom().getWorld().equals(event.getTo().getWorld())) { // only if world actually changed + updatePermissions(event.getPlayer(), event.getTo().getWorld().getName()); + } + } + + @Override + public void onPlayerQuit(PlayerQuitEvent event) { + if (!GroupManager.isLoaded()) + return; + + attachments.remove(event.getPlayer()); + } + + @Override + public void onPlayerKick(PlayerKickEvent event) { + attachments.remove(event.getPlayer()); + } + } + + protected class BukkitEvents extends ServerListener { + + @Override + public void onPluginEnable(PluginEnableEvent event) { + if (!GroupManager.isLoaded()) + return; + + collectPermissions(); + updateAllPlayers(); + } + + @Override + public void onPluginDisable(PluginDisableEvent event) { + // collectPermissions(); + // updateAllPlayers(); + } + } } \ No newline at end of file -- cgit v1.2.3