From 185e5b72703413498fe91be602d6cb9b6bba7cb6 Mon Sep 17 00:00:00 2001 From: Gabriele C Date: Thu, 22 Mar 2018 12:25:20 +0100 Subject: [PATCH] Some progress --- .../authme/debug/HasPermissionChecker.java | 2 +- .../xephi/authme/listener/JoiningPlayer.java | 1 - .../{ => listener}/OfflinePlayerInfo.java | 11 +- .../xephi/authme/listener/PlayerListener.java | 15 +- .../authme/permission/PermissionsManager.java | 220 +++++++++++++++--- .../handlers/BPermissionsHandler.java | 33 +-- .../permission/handlers/LuckPermsHandler.java | 98 ++++---- .../handlers/PermissionHandler.java | 2 +- .../handlers/PermissionsExHandler.java | 60 ++--- .../handlers/SimplePermissionHandler.java | 41 ++++ .../permission/handlers/VaultHandler.java | 74 ++++-- .../authme/task/purge/PurgeExecutor.java | 13 +- .../fr/xephi/authme/task/purge/PurgeTask.java | 5 - .../fr/xephi/authme/util/OptionalUtils.java | 19 ++ src/main/java/fr/xephi/authme/util/Utils.java | 16 ++ 15 files changed, 413 insertions(+), 197 deletions(-) rename src/main/java/fr/xephi/authme/{ => listener}/OfflinePlayerInfo.java (55%) create mode 100644 src/main/java/fr/xephi/authme/permission/handlers/SimplePermissionHandler.java diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/debug/HasPermissionChecker.java b/src/main/java/fr/xephi/authme/command/executable/authme/debug/HasPermissionChecker.java index e8a15b795..1b5ede0fa 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/debug/HasPermissionChecker.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/debug/HasPermissionChecker.java @@ -68,7 +68,7 @@ class HasPermissionChecker implements DebugSection { performPermissionCheck(offlinePlayer, permissionNode, permissionsManager::hasPermissionOffline, sender); } } else { - performPermissionCheck(player, permissionNode, permissionsManager::hasPermission, sender); + performPermissionCheck(player, permissionNode, permissionsManager.hasPermission(player, permissionNode), sender); } } diff --git a/src/main/java/fr/xephi/authme/listener/JoiningPlayer.java b/src/main/java/fr/xephi/authme/listener/JoiningPlayer.java index 8831cac16..08a4831dc 100644 --- a/src/main/java/fr/xephi/authme/listener/JoiningPlayer.java +++ b/src/main/java/fr/xephi/authme/listener/JoiningPlayer.java @@ -1,6 +1,5 @@ package fr.xephi.authme.listener; -import fr.xephi.authme.OfflinePlayerInfo; import fr.xephi.authme.permission.PermissionNode; import fr.xephi.authme.permission.PermissionsManager; import org.bukkit.entity.Player; diff --git a/src/main/java/fr/xephi/authme/OfflinePlayerInfo.java b/src/main/java/fr/xephi/authme/listener/OfflinePlayerInfo.java similarity index 55% rename from src/main/java/fr/xephi/authme/OfflinePlayerInfo.java rename to src/main/java/fr/xephi/authme/listener/OfflinePlayerInfo.java index cdfcb1a78..4b3623c59 100644 --- a/src/main/java/fr/xephi/authme/OfflinePlayerInfo.java +++ b/src/main/java/fr/xephi/authme/listener/OfflinePlayerInfo.java @@ -1,4 +1,7 @@ -package fr.xephi.authme; +package fr.xephi.authme.listener; + +import fr.xephi.authme.util.Utils; +import org.bukkit.OfflinePlayer; import java.util.Optional; import java.util.UUID; @@ -21,4 +24,10 @@ public class OfflinePlayerInfo { return uniqueId; } + public static OfflinePlayerInfo fromPlayer(OfflinePlayer player) { + return new OfflinePlayerInfo(player.getName(), + Utils.hasUniqueIdSupport() ? Optional.of(player.getUniqueId()) : Optional.empty() + ); + } + } diff --git a/src/main/java/fr/xephi/authme/listener/PlayerListener.java b/src/main/java/fr/xephi/authme/listener/PlayerListener.java index 93ac3746d..4c40bc2cd 100644 --- a/src/main/java/fr/xephi/authme/listener/PlayerListener.java +++ b/src/main/java/fr/xephi/authme/listener/PlayerListener.java @@ -1,6 +1,5 @@ package fr.xephi.authme.listener; -import fr.xephi.authme.OfflinePlayerWrapper; import fr.xephi.authme.data.QuickCommandsProtectionManager; import fr.xephi.authme.data.auth.PlayerAuth; import fr.xephi.authme.datasource.DataSource; @@ -21,7 +20,7 @@ import fr.xephi.authme.settings.properties.HooksSettings; import fr.xephi.authme.settings.properties.PluginSettings; import fr.xephi.authme.settings.properties.RegistrationSettings; import fr.xephi.authme.settings.properties.RestrictionSettings; -import org.bukkit.Bukkit; +import fr.xephi.authme.util.Utils; import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.entity.HumanEntity; @@ -54,7 +53,7 @@ import org.bukkit.event.player.PlayerShearEntityEvent; import javax.inject.Inject; -import java.util.UUID; +import java.util.Optional; import static fr.xephi.authme.settings.properties.RestrictionSettings.ALLOWED_MOVEMENT_RADIUS; import static fr.xephi.authme.settings.properties.RestrictionSettings.ALLOW_UNAUTHED_MOVEMENT; @@ -256,17 +255,21 @@ public class PlayerListener implements Listener { return; } - final UUID uuid = event.getUniqueId(); final String name = event.getName(); if (validationService.isUnrestricted(name)) { return; } - final OfflinePlayerWrapper player = new OfflinePlayerWrapper(uuid, name); + OfflinePlayerInfo offlineInfo; + if(Utils.hasUniqueIdSupport()) { + offlineInfo = new OfflinePlayerInfo(name, Optional.of(event.getUniqueId())); + } else { + offlineInfo = new OfflinePlayerInfo(name, Optional.empty()); + } try { - runOnJoinChecks(JoiningPlayer.fromOfflinePlayer(player), event.getAddress().getHostAddress()); + runOnJoinChecks(JoiningPlayer.fromOfflinePlayerInfo(offlineInfo), event.getAddress().getHostAddress()); } catch (FailedVerificationException e) { event.setKickMessage(m.retrieveSingle(name, e.getReason(), e.getArgs())); event.setLoginResult(AsyncPlayerPreLoginEvent.Result.KICK_OTHER); diff --git a/src/main/java/fr/xephi/authme/permission/PermissionsManager.java b/src/main/java/fr/xephi/authme/permission/PermissionsManager.java index 3bbf9e0ca..33083c964 100644 --- a/src/main/java/fr/xephi/authme/permission/PermissionsManager.java +++ b/src/main/java/fr/xephi/authme/permission/PermissionsManager.java @@ -2,7 +2,7 @@ package fr.xephi.authme.permission; import com.google.common.annotations.VisibleForTesting; import fr.xephi.authme.ConsoleLogger; -import fr.xephi.authme.OfflinePlayerWrapper; +import fr.xephi.authme.listener.OfflinePlayerInfo; import fr.xephi.authme.initialization.Reloadable; import fr.xephi.authme.listener.JoiningPlayer; import fr.xephi.authme.permission.handlers.BPermissionsHandler; @@ -14,7 +14,6 @@ import fr.xephi.authme.permission.handlers.VaultHandler; import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.properties.PluginSettings; import fr.xephi.authme.util.StringUtils; -import org.bukkit.OfflinePlayer; import org.bukkit.Server; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -114,7 +113,9 @@ public class PermissionsManager implements Reloadable { * Creates a permission handler for the provided permission systems if possible. * * @param type the permission systems type for which to create a corresponding permission handler + * * @return the permission handler, or {@code null} if not possible + * * @throws PermissionHandlerException during initialization of the permission handler */ private PermissionHandler createPermissionHandler(PermissionsSystemType type) throws PermissionHandlerException { @@ -230,11 +231,12 @@ public class PermissionsManager implements Reloadable { /** * Check if the given player has permission for the given permission node. * - * @param joiningPlayer The player to check + * @param joiningPlayer The player to check * @param permissionNode The permission node to verify + * * @return true if the player has permission, false otherwise */ - public boolean hasPermission(JoiningPlayer joiningPlayer, PermissionNode permissionNode) { + public CompletableFuture hasPermission(JoiningPlayer joiningPlayer, PermissionNode permissionNode) { return joiningPlayer.getPermissionLookupFunction().apply(this, permissionNode); } @@ -242,22 +244,22 @@ public class PermissionsManager implements Reloadable { * Check if a player has permission for the given permission node. This is for offline player checks. * If no permissions system is used, then the player will not have permission. * - * @param player The offline player + * @param offlineInfo The offline player * @param permissionNode The permission node to verify * * @return true if the player has permission, false otherwise */ - public CompletableFuture hasPermissionOffline(OfflinePlayerWrapper player, PermissionNode permissionNode) { + public CompletableFuture hasPermissionOffline(OfflinePlayerInfo offlineInfo, PermissionNode permissionNode) { // Check if the permission node is null if (permissionNode == null) { return completedFuture(true); } if (!isEnabled()) { - return completedFuture(permissionNode.getDefaultPermission().evaluate(player)); //FIXME: find a way to use the bukkitService to access Bukkit.getOperators and check the uuid + return completedFuture(permissionNode.getDefaultPermission().evaluate(offlineInfo)); //FIXME: find a way to use the bukkitService to access Bukkit.getOperators and check the uuid } - return handler.hasPermissionOffline(player, permissionNode); + return handler.hasPermissionOffline(offlineInfo, permissionNode); } /** @@ -277,8 +279,19 @@ public class PermissionsManager implements Reloadable { * * @return Permission groups, or an empty collection if this feature is not supported. */ - public CompletableFuture> getGroups(OfflinePlayer player) { - return isEnabled() ? handler.getGroups(player) : completedFuture(Collections.emptyList()); + public List getGroups(Player player) { + return isEnabled() ? handler.getGroups(player) : Collections.emptyList(); + } + + /** + * Get the permission groups of an offline player, if available. + * + * @param offlineInfo The offline player info. + * + * @return Permission groups, or an empty collection if this feature is not supported. + */ + public CompletableFuture> getGroupsOffline(OfflinePlayerInfo offlineInfo) { + return isEnabled() ? handler.getGroupsOffline(offlineInfo) : completedFuture(Collections.emptyList()); } /** @@ -288,8 +301,19 @@ public class PermissionsManager implements Reloadable { * * @return The name of the primary permission group. */ - public CompletableFuture> getPrimaryGroup(OfflinePlayer player) { - return isEnabled() ? handler.getPrimaryGroup(player) : completedFuture(Optional.empty()); + public Optional getPrimaryGroup(Player player) { + return isEnabled() ? handler.getPrimaryGroup(player) : Optional.empty(); + } + + /** + * Get the primary group of an offline player, if available. + * + * @param offlineInfo The offline player info. + * + * @return The name of the primary permission group. + */ + public CompletableFuture> getPrimaryGroupOffline(OfflinePlayerInfo offlineInfo) { + return isEnabled() ? handler.getPrimaryGroupOffline(offlineInfo) : completedFuture(Optional.empty()); } /** @@ -299,29 +323,55 @@ public class PermissionsManager implements Reloadable { * @param groupName The group name. * * @return True if the player is in the specified group, false otherwise. - * False is also returned if groups aren't supported by the used permissions system. + * False is also returned if groups aren't supported by the used permissions system. */ - public CompletableFuture isInGroup(OfflinePlayer player, String groupName) { - if(!isEnabled()) { + public boolean isInGroup(Player player, String groupName) { + return isEnabled() && handler.isInGroup(player, groupName); + } + + /** + * Check whether the offline player is in the specified group. + * + * @param offlineInfo The offline player info. + * @param groupName The group name. + * + * @return True if the player is in the specified group, false otherwise. + * False is also returned if groups aren't supported by the used permissions system. + */ + public CompletableFuture isInGroup(OfflinePlayerInfo offlineInfo, String groupName) { + if (!isEnabled()) { return completedFuture(false); } - return handler.isInGroup(player, groupName); + return handler.isInGroupOffline(offlineInfo, groupName); } /** * Add the permission group of a player, if supported. * - * @param player The player + * @param player The player. * @param groupName The name of the group. * * @return True if succeed, false otherwise. - * False is also returned if this feature isn't supported for the current permissions system. + * False is also returned if this feature isn't supported for the current permissions system. */ - public CompletableFuture addGroup(OfflinePlayer player, String groupName) { + public boolean addGroup(Player player, String groupName) { + return isEnabled() && !StringUtils.isEmpty(groupName) && handler.addToGroup(player, groupName); + } + + /** + * Add the permission group of an offline player, if supported. + * + * @param offlineInfo The offline player info. + * @param groupName The name of the group. + * + * @return True if succeed, false otherwise. + * False is also returned if this feature isn't supported for the current permissions system. + */ + public CompletableFuture addGroupOffline(OfflinePlayerInfo offlineInfo, String groupName) { if (!isEnabled() || StringUtils.isEmpty(groupName)) { return completedFuture(false); } - return handler.addToGroup(player, groupName); + return handler.addToGroupOffline(offlineInfo, groupName); } /** @@ -331,12 +381,12 @@ public class PermissionsManager implements Reloadable { * @param groupNames The name of the groups to add. * * @return True if at least one group was added, false otherwise. - * False is also returned if this feature isn't supported for the current permissions system. + * False is also returned if this feature isn't supported for the current permissions system. */ - public CompletableFuture addGroups(OfflinePlayer player, Collection groupNames) { + public boolean addGroups(Player player, Collection groupNames) { // If no permissions system is used, return false if (!isEnabled()) { - return completedFuture(false); + return false; } // Add each group to the user @@ -352,35 +402,74 @@ public class PermissionsManager implements Reloadable { } /** + * Add the permission groups of an offline player, if supported. * + * @param offlineInfo The offline player info. + * @param groupNames The name of the groups to add. + * + * @return True if at least one group was added, false otherwise. + * False is also returned if this feature isn't supported for the current permissions system. + */ + public CompletableFuture addGroupsOffline(OfflinePlayerInfo offlineInfo, Collection groupNames) { + // If no permissions system is used, return false + if (!isEnabled()) { + return completedFuture(false); + } + + // Add each group to the user + boolean result = false; + for (String groupName : groupNames) { + if (!groupName.isEmpty()) { + result |= handler.addToGroupOffline(offlineInfo, groupName).join(); + } + } + + // Return the result + return completedFuture(result); + } + + /** * Remove the permission group of a player, if supported. * * @param player The player * @param groupName The name of the group. * * @return True if succeed, false otherwise. - * False is also returned if this feature isn't supported for the current permissions system. + * False is also returned if this feature isn't supported for the current permissions system. */ - public CompletableFuture removeGroup(OfflinePlayer player, String groupName) { - if(!isEnabled()) { + public boolean removeGroup(Player player, String groupName) { + return isEnabled() && handler.removeFromGroup(player, groupName); + } + + /** + * Remove the permission group of an offline player, if supported. + * + * @param offlineInfo The offline player info. + * @param groupName The name of the group. + * + * @return True if succeed, false otherwise. + * False is also returned if this feature isn't supported for the current permissions system. + */ + public CompletableFuture removeGroupOffline(OfflinePlayerInfo offlineInfo, String groupName) { + if (!isEnabled()) { return completedFuture(false); } - return handler.removeFromGroup(player, groupName); + return handler.removeFromGroupOffline(offlineInfo, groupName); } /** * Remove the permission groups of a player, if supported. * - * @param player The player + * @param player The player. * @param groupNames The name of the groups to remove. * * @return True if at least one group was removed, false otherwise. - * False is also returned if this feature isn't supported for the current permissions system. + * False is also returned if this feature isn't supported for the current permissions system. */ - public CompletableFuture removeGroups(OfflinePlayer player, Collection groupNames) { + public boolean removeGroups(Player player, Collection groupNames) { // If no permissions system is used, return false if (!isEnabled()) { - return completedFuture(false); + return false; } // Add each group to the user @@ -395,6 +484,33 @@ public class PermissionsManager implements Reloadable { return result; } + /** + * Remove the permission groups of an offline player, if supported. + * + * @param offlineInfo The offline player info. + * @param groups The name of the groups to remove. + * + * @return True if at least one group was removed, false otherwise. + * False is also returned if this feature isn't supported for the current permissions system. + */ + public CompletableFuture removeGroupsOffline(OfflinePlayerInfo offlineInfo, Collection groups) { + // If no permissions system is used, return false + if (!isEnabled()) { + return completedFuture(false); + } + + // Add each group to the user + boolean result = false; + for (String groupName : groups) { + if (!groupName.isEmpty()) { + result |= handler.removeFromGroupOffline(offlineInfo, groupName).join(); + } + } + + // Return the result + return completedFuture(result); + } + /** * Set the permission group of a player, if supported. * This clears the current groups of the player. @@ -403,13 +519,27 @@ public class PermissionsManager implements Reloadable { * @param groupName The name of the group. * * @return True if succeed, false otherwise. - * False is also returned if this feature isn't supported for the current permissions system. + * False is also returned if this feature isn't supported for the current permissions system. */ - public CompletableFuture setGroup(OfflinePlayer player, String groupName) { - if(!isEnabled()) { + public boolean setGroup(Player player, String groupName) { + return isEnabled() && handler.setGroup(player, groupName); + } + + /** + * Set the permission group of an offline player, if supported. + * This clears the current groups of the player. + * + * @param offlineInfo The offline player info. + * @param groupName The name of the group. + * + * @return True if succeed, false otherwise. + * False is also returned if this feature isn't supported for the current permissions system. + */ + public CompletableFuture setGroupOffline(OfflinePlayerInfo offlineInfo, String groupName) { + if (!isEnabled()) { return completedFuture(false); } - return handler.setGroup(player, groupName); + return handler.setGroupOffline(offlineInfo, groupName); } /** @@ -420,16 +550,30 @@ public class PermissionsManager implements Reloadable { * @param player The player to remove all groups from. * * @return True if succeed, false otherwise. - * False will also be returned if this feature isn't supported for the used permissions system. + * False will also be returned if this feature isn't supported for the used permissions system. */ - public CompletableFuture removeAllGroups(OfflinePlayer player) { + public boolean removeAllGroups(Player player) { + return isEnabled() && removeGroups(player, getGroups(player)); + } + + /** + * Remove all groups of the specified offline player, if supported. + * Systems like Essentials GroupManager don't allow all groups to be removed from a player, thus the user will stay + * in its primary group. All the subgroups are removed just fine. + * + * @param offlineInfo The offline player info to remove all groups from. + * + * @return True if succeed, false otherwise. + * False will also be returned if this feature isn't supported for the used permissions system. + */ + public CompletableFuture removeAllGroupsOffline(OfflinePlayerInfo offlineInfo) { // If no permissions system is used, return false if (!isEnabled()) { return completedFuture(false); } // Get a list of current groups and remove them - return getGroups(player).thenApply(groups -> removeGroups(player, groups).join()); + return getGroupsOffline(offlineInfo).thenApply(groups -> removeGroupsOffline(offlineInfo, groups).join()); } } diff --git a/src/main/java/fr/xephi/authme/permission/handlers/BPermissionsHandler.java b/src/main/java/fr/xephi/authme/permission/handlers/BPermissionsHandler.java index aee4a97bf..ba402ac27 100644 --- a/src/main/java/fr/xephi/authme/permission/handlers/BPermissionsHandler.java +++ b/src/main/java/fr/xephi/authme/permission/handlers/BPermissionsHandler.java @@ -2,10 +2,9 @@ package fr.xephi.authme.permission.handlers; import de.bananaco.bpermissions.api.ApiLayer; import de.bananaco.bpermissions.api.CalculableType; -import fr.xephi.authme.OfflinePlayerInfo; +import fr.xephi.authme.listener.OfflinePlayerInfo; import fr.xephi.authme.permission.PermissionNode; import fr.xephi.authme.permission.PermissionsSystemType; -import org.bukkit.entity.Player; import java.util.Arrays; import java.util.List; @@ -19,7 +18,7 @@ import static java.util.concurrent.CompletableFuture.completedFuture; * @see bPermissions Bukkit page * @see bPermissions on Github */ -public class BPermissionsHandler implements PermissionHandler { +public class BPermissionsHandler implements SimplePermissionHandler { @Override public PermissionsSystemType getPermissionSystem() { @@ -36,56 +35,28 @@ public class BPermissionsHandler implements PermissionHandler { return completedFuture(ApiLayer.hasPermission(null, CalculableType.USER, offlineInfo.getName(), node.getNode())); } - @Override - public List getGroups(Player player) { - return Arrays.asList(ApiLayer.getGroups(null, CalculableType.USER, player.getName())); - } - @Override public CompletableFuture> getGroupsOffline(OfflinePlayerInfo offlineInfo) { return completedFuture(Arrays.asList(ApiLayer.getGroups(null, CalculableType.USER, offlineInfo.getName()))); } - @Override - public boolean isInGroup(Player player, String groupName) { - return ApiLayer.hasGroup(null, CalculableType.USER, player.getName(), groupName); - } - @Override public CompletableFuture isInGroupOffline(OfflinePlayerInfo offlineInfo, String groupName) { return completedFuture(ApiLayer.hasGroup(null, CalculableType.USER, offlineInfo.getName(), groupName)); } - @Override - public boolean addToGroup(Player player, String groupName) { - ApiLayer.addGroup(null, CalculableType.USER, player.getName(), groupName); - return true; - } - @Override public CompletableFuture addToGroupOffline(OfflinePlayerInfo offlineInfo, String groupName) { ApiLayer.addGroup(null, CalculableType.USER, offlineInfo.getName(), groupName); return completedFuture(true); } - @Override - public boolean removeFromGroup(Player player, String groupName) { - ApiLayer.removeGroup(null, CalculableType.USER, player.getName(), groupName); - return true; - } - @Override public CompletableFuture removeFromGroupOffline(OfflinePlayerInfo playerInfo, String groupName) { ApiLayer.removeGroup(null, CalculableType.USER, playerInfo.getName(), groupName); return completedFuture(true); } - @Override - public boolean setGroup(Player player, String group) { - ApiLayer.setGroup(null, CalculableType.USER, player.getName(), group); - return true; - } - @Override public CompletableFuture setGroupOffline(OfflinePlayerInfo offlineInfo, String group) { ApiLayer.setGroup(null, CalculableType.USER, offlineInfo.getName(), group); diff --git a/src/main/java/fr/xephi/authme/permission/handlers/LuckPermsHandler.java b/src/main/java/fr/xephi/authme/permission/handlers/LuckPermsHandler.java index f3a968815..26a74adb4 100644 --- a/src/main/java/fr/xephi/authme/permission/handlers/LuckPermsHandler.java +++ b/src/main/java/fr/xephi/authme/permission/handlers/LuckPermsHandler.java @@ -1,9 +1,10 @@ package fr.xephi.authme.permission.handlers; -import fr.xephi.authme.OfflinePlayerInfo; +import fr.xephi.authme.listener.OfflinePlayerInfo; import fr.xephi.authme.permission.PermissionNode; import fr.xephi.authme.permission.PermissionsSystemType; import fr.xephi.authme.util.OptionalUtils; +import fr.xephi.authme.util.Utils; import me.lucko.luckperms.LuckPerms; import me.lucko.luckperms.api.Contexts; import me.lucko.luckperms.api.DataMutateResult; @@ -37,6 +38,9 @@ public class LuckPermsHandler implements PermissionHandler { private LuckPermsApi luckPermsApi; public LuckPermsHandler() throws PermissionHandlerException { + if(!Utils.hasUniqueIdSupport()) { + throw new PermissionHandlerException("LuckPerms handler can't be used on server instances that doesn't support UUIDs."); + } try { luckPermsApi = LuckPerms.getApi(); } catch (IllegalStateException e) { @@ -59,11 +63,10 @@ public class LuckPermsHandler implements PermissionHandler { } private CompletableFuture getUserOffline(OfflinePlayerInfo offlineInfo) { - if (!offlineInfo.getUniqueId().isPresent()) { - throw new IllegalStateException("Tried to obtain an offline LuckPerms User but the" + - "server doesn't support UUIDs!"); - } - return luckPermsApi.getUserManager().loadUser(offlineInfo.getUniqueId().get(), offlineInfo.getName()); + return luckPermsApi.getUserManager().loadUser( + offlineInfo.getUniqueId().orElseThrow(() -> new IllegalStateException("OfflinePlayerInfo UUID was empty")), + offlineInfo.getName() + ); } private Optional getGroup(String groupName) { @@ -74,23 +77,20 @@ public class LuckPermsHandler implements PermissionHandler { return luckPermsApi.getNodeFactory().makeGroupNode(group).build(); } - private T processUser(Player player, String groupName, BiFunction action, T failed) { + private boolean processUser(Player player, String groupName, BiFunction action) { return handleOptional(getGroup(groupName), group -> OptionalUtils.handleOptional(getUser(player), user -> action.apply(user, group), - () -> failed + false ), - () -> failed + false ); } - private CompletableFuture processUser(OfflinePlayerInfo offlineInfo, String groupName, BiFunction action, T failed) { + private CompletableFuture processUserOffline(OfflinePlayerInfo offlineInfo, String groupName, BiFunction action) { return handleOptional(getGroup(groupName), - group -> OptionalUtils.handleOptional(getUser(player), - user -> action.apply(user, group), - () -> failed - ), - () -> failed + group -> getUserOffline(offlineInfo).thenApply(user -> action.apply(user, group)), + completedFuture(false) ); } @@ -134,34 +134,28 @@ public class LuckPermsHandler implements PermissionHandler { } saveUser(user); return true; - }), false); + })); } @Override public CompletableFuture addToGroupOffline(OfflinePlayerInfo offlineInfo, String groupName) { - return handleOptional(getGroup(groupName), - group -> getUserOffline(offlineInfo).thenApply(user -> { - if (user.setPermission(getGroupNode(group)).wasFailure()) { - return false; - } - saveUser(user); - return true; - }), - () -> completedFuture(false) - ); + return processUserOffline(offlineInfo, groupName, (user, group) -> { + if (user.setPermission(getGroupNode(group)).wasFailure()) { + return false; + } + saveUser(user); + return true; + }); } @Override public boolean isInGroup(Player player, String groupName) { - return processUser(player, groupName, (PermissionHolder::inheritsGroup), false); + return processUser(player, groupName, (PermissionHolder::inheritsGroup)); } @Override public CompletableFuture isInGroupOffline(OfflinePlayerInfo offlineInfo, String groupName) { - return handleOptional(luckPermsApi.getGroupSafe(groupName), - group -> getUserOffline(offlineInfo).thenApply(user -> user.inheritsGroup(group)), - () -> completedFuture(false) - ); + return processUserOffline(offlineInfo, groupName, PermissionHolder::inheritsGroup); } @Override @@ -172,21 +166,18 @@ public class LuckPermsHandler implements PermissionHandler { } saveUser(user); return true; - }), false); + })); } @Override public CompletableFuture removeFromGroupOffline(OfflinePlayerInfo offlineInfo, String groupName) { - return handleOptional(getGroup(groupName), - group -> getUserOffline(offlineInfo).thenApply(user -> { - if (user.unsetPermission(getGroupNode(group)).wasFailure()) { - return false; - } - saveUser(user); - return true; - }), - () -> completedFuture(false) - ); + return processUserOffline(offlineInfo, groupName, (user, group) -> { + if (user.unsetPermission(getGroupNode(group)).wasFailure()) { + return false; + } + saveUser(user); + return true; + }); } @Override @@ -198,27 +189,24 @@ public class LuckPermsHandler implements PermissionHandler { user.clearMatching(node -> node.isGroupNode() && !node.getGroupName().equals(group.getName())); saveUser(user); return true; - }, false); + }); } @Override public CompletableFuture setGroupOffline(OfflinePlayerInfo offlineInfo, String groupName) { - return handleOptional(getGroup(groupName), - group -> getUserOffline(offlineInfo).thenApply(user -> { - if (user.setPermission(getGroupNode(group)) == DataMutateResult.FAIL) { - return false; - } - user.clearMatching(node -> node.isGroupNode() && !node.getGroupName().equals(group.getName())); - saveUser(user); - return true; - }), - () -> completedFuture(false) - ); + return processUserOffline(offlineInfo, groupName, (user, group) -> { + if (user.setPermission(getGroupNode(group)) == DataMutateResult.FAIL) { + return false; + } + user.clearMatching(node -> node.isGroupNode() && !node.getGroupName().equals(group.getName())); + saveUser(user); + return true; + }); } @Override public List getGroups(Player player) { - return handleOptional(getUser(player), this::getGroupsOrdered, Collections::emptyList); + return handleOptional(getUser(player), this::getGroupsOrdered, Collections.emptyList()); } @Override diff --git a/src/main/java/fr/xephi/authme/permission/handlers/PermissionHandler.java b/src/main/java/fr/xephi/authme/permission/handlers/PermissionHandler.java index 39d378e00..2c4f73dbc 100644 --- a/src/main/java/fr/xephi/authme/permission/handlers/PermissionHandler.java +++ b/src/main/java/fr/xephi/authme/permission/handlers/PermissionHandler.java @@ -1,6 +1,6 @@ package fr.xephi.authme.permission.handlers; -import fr.xephi.authme.OfflinePlayerInfo; +import fr.xephi.authme.listener.OfflinePlayerInfo; import fr.xephi.authme.permission.PermissionNode; import fr.xephi.authme.permission.PermissionsSystemType; import org.bukkit.entity.Player; diff --git a/src/main/java/fr/xephi/authme/permission/handlers/PermissionsExHandler.java b/src/main/java/fr/xephi/authme/permission/handlers/PermissionsExHandler.java index a9a5b49e2..7e6ab6ecb 100644 --- a/src/main/java/fr/xephi/authme/permission/handlers/PermissionsExHandler.java +++ b/src/main/java/fr/xephi/authme/permission/handlers/PermissionsExHandler.java @@ -1,9 +1,8 @@ package fr.xephi.authme.permission.handlers; -import fr.xephi.authme.OfflinePlayerWrapper; +import fr.xephi.authme.listener.OfflinePlayerInfo; import fr.xephi.authme.permission.PermissionNode; import fr.xephi.authme.permission.PermissionsSystemType; -import org.bukkit.OfflinePlayer; import ru.tehkode.permissions.PermissionManager; import ru.tehkode.permissions.PermissionUser; import ru.tehkode.permissions.bukkit.PermissionsEx; @@ -12,6 +11,7 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.CompletableFuture; +import static fr.xephi.authme.util.OptionalUtils.handleOptional; import static java.util.concurrent.CompletableFuture.completedFuture; /** @@ -20,7 +20,7 @@ import static java.util.concurrent.CompletableFuture.completedFuture; * @see PermissionsEx Bukkit page * @see PermissionsEx on Github */ -public class PermissionsExHandler implements PermissionHandler { +public class PermissionsExHandler implements SimplePermissionHandler { private PermissionManager permissionManager; @@ -31,20 +31,25 @@ public class PermissionsExHandler implements PermissionHandler { } } - private PermissionUser getUser(OfflinePlayerWrapper player) { - try { - return permissionManager.getUser(player.getUniqueId()); - } catch (NoSuchMethodError e) { - return permissionManager.getUser(player.getName()); - } + private boolean isGroupValid(String groupName) { + return permissionManager.getGroupNames().contains(groupName); + } + + private PermissionUser getUserOffline(OfflinePlayerInfo player) { + return handleOptional(player.getUniqueId(), uuid -> permissionManager.getUser(uuid), permissionManager.getUser(player.getName())); } @Override - public CompletableFuture addToGroup(OfflinePlayerWrapper player, String groupName) { - if (!permissionManager.getGroupNames().contains(groupName)) { + public CompletableFuture hasPermissionOffline(OfflinePlayerInfo offlinePlayerInfo, PermissionNode node) { + return completedFuture(getUserOffline(offlinePlayerInfo).has(node.getNode())); + } + + @Override + public CompletableFuture addToGroupOffline(OfflinePlayerInfo offlineInfo, String groupName) { + if (!isGroupValid(groupName)) { return completedFuture(false); } - permissionManager.getUser(player.getName()).addGroup(groupName); + getUserOffline(offlineInfo).addGroup(groupName); return completedFuture(true); } @@ -54,37 +59,38 @@ public class PermissionsExHandler implements PermissionHandler { } @Override - public CompletableFuture hasPermissionOffline(OfflinePlayerWrapper player, PermissionNode node) { - return completedFuture(getUser(player).has(node.getNode())); + public CompletableFuture isInGroupOffline(OfflinePlayerInfo offlineInfo, String groupName) { + return completedFuture(getUserOffline(offlineInfo).inGroup(groupName)); } @Override - public CompletableFuture isInGroup(OfflinePlayerWrapper player, String groupName) { - return completedFuture(getUser(player).inGroup(groupName)); - } - - @Override - public CompletableFuture removeFromGroup(OfflinePlayerWrapper player, String groupName) { - getUser(player).removeGroup(groupName); + public CompletableFuture removeFromGroupOffline(OfflinePlayerInfo offlineInfo, String groupName) { + if (!isGroupValid(groupName)) { + return completedFuture(false); + } + getUserOffline(offlineInfo).removeGroup(groupName); return completedFuture(true); } @Override - public CompletableFuture setGroup(OfflinePlayerWrapper player, String group) { + public CompletableFuture setGroupOffline(OfflinePlayerInfo offlineInfo, String groupName) { + if (!isGroupValid(groupName)) { + return completedFuture(false); + } List groups = new ArrayList<>(); - groups.add(group); - - getUser(player).setParentsIdentifier(groups); + groups.add(groupName); + getUserOffline(offlineInfo).setParentsIdentifier(groups); return completedFuture(true); } @Override - public CompletableFuture> getGroups(OfflinePlayerWrapper player) { - return completedFuture(getUser(player).getParentIdentifiers(null)); + public CompletableFuture> getGroupsOffline(OfflinePlayerInfo offlineInfo) { + return completedFuture(getUserOffline(offlineInfo).getParentIdentifiers(null)); } @Override public PermissionsSystemType getPermissionSystem() { return PermissionsSystemType.PERMISSIONS_EX; } + } diff --git a/src/main/java/fr/xephi/authme/permission/handlers/SimplePermissionHandler.java b/src/main/java/fr/xephi/authme/permission/handlers/SimplePermissionHandler.java new file mode 100644 index 000000000..b6d95838c --- /dev/null +++ b/src/main/java/fr/xephi/authme/permission/handlers/SimplePermissionHandler.java @@ -0,0 +1,41 @@ +package fr.xephi.authme.permission.handlers; + +import fr.xephi.authme.listener.OfflinePlayerInfo; +import org.bukkit.entity.Player; + +import java.util.List; +import java.util.Optional; + +public interface SimplePermissionHandler extends PermissionHandler { + + @Override + default List getGroups(Player player) { + return getGroupsOffline(OfflinePlayerInfo.fromPlayer(player)).join(); + } + + @Override + default Optional getPrimaryGroup(Player player) { + return getPrimaryGroupOffline(OfflinePlayerInfo.fromPlayer(player)).join(); + } + + @Override + default boolean isInGroup(Player player, String groupName) { + return isInGroupOffline(OfflinePlayerInfo.fromPlayer(player), groupName).join(); + } + + @Override + default boolean addToGroup(Player player, String groupName) { + return addToGroupOffline(OfflinePlayerInfo.fromPlayer(player), groupName).join(); + } + + @Override + default boolean removeFromGroup(Player player, String groupName) { + return removeFromGroupOffline(OfflinePlayerInfo.fromPlayer(player), groupName).join(); + } + + @Override + default boolean setGroup(Player player, String groupName) { + return setGroupOffline(OfflinePlayerInfo.fromPlayer(player), groupName).join(); + } + +} diff --git a/src/main/java/fr/xephi/authme/permission/handlers/VaultHandler.java b/src/main/java/fr/xephi/authme/permission/handlers/VaultHandler.java index 697f7e230..082f2fbcb 100644 --- a/src/main/java/fr/xephi/authme/permission/handlers/VaultHandler.java +++ b/src/main/java/fr/xephi/authme/permission/handlers/VaultHandler.java @@ -1,11 +1,11 @@ package fr.xephi.authme.permission.handlers; -import fr.xephi.authme.OfflinePlayerWrapper; +import fr.xephi.authme.listener.OfflinePlayerInfo; import fr.xephi.authme.permission.PermissionNode; import fr.xephi.authme.permission.PermissionsSystemType; import net.milkbowl.vault.permission.Permission; -import org.bukkit.OfflinePlayer; import org.bukkit.Server; +import org.bukkit.entity.Player; import org.bukkit.plugin.RegisteredServiceProvider; import java.util.Arrays; @@ -45,48 +45,78 @@ public class VaultHandler implements PermissionHandler { return vaultPerms; } - @Override - @SuppressWarnings("deprecated") - public CompletableFuture addToGroup(OfflinePlayerWrapper player, String groupName) { - return completedFuture(vaultProvider.playerAddGroup((String)null, player.getName(), groupName)); - } - @Override public boolean hasGroupSupport() { return vaultProvider.hasGroupSupport(); } @Override - public CompletableFuture hasPermissionOffline(OfflinePlayerWrapper player, PermissionNode node) { - return completedFuture(vaultProvider.playerHas((String)null, player.getName(), node.getNode())); + public CompletableFuture hasPermissionOffline(OfflinePlayerInfo offlineInfo, PermissionNode node) { + return completedFuture(vaultProvider.playerHas((String) null, offlineInfo.getName(), node.getNode())); } @Override - public CompletableFuture isInGroup(OfflinePlayerWrapper player, String groupName) { - return completedFuture(vaultProvider.playerInGroup(null, player, groupName)); + public boolean isInGroup(Player player, String groupName) { + return vaultProvider.playerInGroup(null, player, groupName); } @Override - public CompletableFuture removeFromGroup(OfflinePlayerWrapper player, String groupName) { - return completedFuture(vaultProvider.playerRemoveGroup(null, player, groupName)); + public CompletableFuture isInGroupOffline(OfflinePlayerInfo offlineInfo, String groupName) { + return completedFuture(vaultProvider.playerInGroup((String) null, offlineInfo.getName(), groupName)); } @Override - public CompletableFuture setGroup(OfflinePlayerWrapper player, String groupName) { - return getGroups(player).thenApply(groups -> { - groups.forEach(group -> removeFromGroup(player, group)); - return vaultProvider.playerAddGroup(null, player, groupName); + public boolean removeFromGroup(Player player, String groupName) { + return vaultProvider.playerRemoveGroup(null, player, groupName); + } + + @Override + public CompletableFuture removeFromGroupOffline(OfflinePlayerInfo offlinePlayerInfo, String groupName) { + return completedFuture(vaultProvider.playerRemoveGroup((String) null, offlinePlayerInfo.getName(), groupName)); + } + + @Override + public boolean setGroup(Player player, String groupName) { + getGroups(player).forEach(group -> removeFromGroup(player, group)); + return addToGroup(player, groupName); + } + + @Override + public CompletableFuture setGroupOffline(OfflinePlayerInfo offlineInfo, String groupName) { + return getGroupsOffline(offlineInfo).thenApply(groups -> { + groups.forEach(group -> removeFromGroupOffline(offlineInfo, group)); + return addToGroupOffline(offlineInfo, groupName).join(); }); } @Override - public CompletableFuture> getGroups(OfflinePlayerWrapper player) { - return completedFuture(Arrays.asList(vaultProvider.getPlayerGroups(null, player))); + public List getGroups(Player player) { + return Arrays.asList(vaultProvider.getPlayerGroups((String) null, player)); } @Override - public CompletableFuture> getPrimaryGroup(OfflinePlayerWrapper player) { - return completedFuture(Optional.ofNullable(vaultProvider.getPrimaryGroup(null, player))); + public CompletableFuture> getGroupsOffline(OfflinePlayerInfo offlineInfo) { + return completedFuture(Arrays.asList(vaultProvider.getPlayerGroups((String) null, offlineInfo.getName()))); + } + + @Override + public Optional getPrimaryGroup(Player player) { + return Optional.ofNullable(vaultProvider.getPrimaryGroup(null, player)); + } + + @Override + public CompletableFuture> getPrimaryGroupOffline(OfflinePlayerInfo offlineInfo) { + return completedFuture(Optional.ofNullable(vaultProvider.getPrimaryGroup((String) null, offlineInfo.getName()))); + } + + @Override + public boolean addToGroup(Player player, String groupName) { + return vaultProvider.playerAddGroup(null, player, groupName); + } + + @Override + public CompletableFuture addToGroupOffline(OfflinePlayerInfo offlineInfo, String groupName) { + return completedFuture(vaultProvider.playerAddGroup((String) null, offlineInfo.getName(), groupName)); } @Override diff --git a/src/main/java/fr/xephi/authme/task/purge/PurgeExecutor.java b/src/main/java/fr/xephi/authme/task/purge/PurgeExecutor.java index a3e42f756..331e01612 100644 --- a/src/main/java/fr/xephi/authme/task/purge/PurgeExecutor.java +++ b/src/main/java/fr/xephi/authme/task/purge/PurgeExecutor.java @@ -1,6 +1,7 @@ package fr.xephi.authme.task.purge; import fr.xephi.authme.ConsoleLogger; +import fr.xephi.authme.listener.OfflinePlayerInfo; import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.permission.PermissionsManager; import fr.xephi.authme.service.BukkitService; @@ -211,16 +212,10 @@ public class PurgeExecutor { return; } - for (OfflinePlayer offlinePlayer : cleared) { - try { - permissionsManager.loadUserData(offlinePlayer.getUniqueId()); - } catch (NoSuchMethodError e) { - permissionsManager.loadUserData(offlinePlayer.getName()); - } - permissionsManager.removeAllGroups(offlinePlayer); - } + cleared.stream().map(OfflinePlayerInfo::fromPlayer) + .forEach(offlineInfo -> permissionsManager.removeAllGroupsOffline(offlineInfo)); - ConsoleLogger.info("AutoPurge: Removed permissions from " + cleared.size() + " player(s)."); + ConsoleLogger.info("AutoPurge: Removing permissions from " + cleared.size() + " player(s)."); } } diff --git a/src/main/java/fr/xephi/authme/task/purge/PurgeTask.java b/src/main/java/fr/xephi/authme/task/purge/PurgeTask.java index 27b424150..92391af90 100644 --- a/src/main/java/fr/xephi/authme/task/purge/PurgeTask.java +++ b/src/main/java/fr/xephi/authme/task/purge/PurgeTask.java @@ -73,11 +73,6 @@ class PurgeTask extends BukkitRunnable { OfflinePlayer offlinePlayer = offlinePlayers[nextPosition]; if (offlinePlayer.getName() != null && toPurge.remove(offlinePlayer.getName().toLowerCase())) { - try { - permissionsManager.loadUserData(offlinePlayer.getUniqueId()); - } catch (NoSuchMethodError e) { - permissionsManager.loadUserData(offlinePlayer.getName()); - } if (!permissionsManager.hasPermissionOffline(offlinePlayer, PlayerStatePermission.BYPASS_PURGE)) { playerPortion.add(offlinePlayer); namePortion.add(offlinePlayer.getName()); diff --git a/src/main/java/fr/xephi/authme/util/OptionalUtils.java b/src/main/java/fr/xephi/authme/util/OptionalUtils.java index 88dd8696c..0fc746107 100644 --- a/src/main/java/fr/xephi/authme/util/OptionalUtils.java +++ b/src/main/java/fr/xephi/authme/util/OptionalUtils.java @@ -32,4 +32,23 @@ public final class OptionalUtils { } } + /** + * Handles the value of an Optional object. + * + * @param optional the optional object + * @param ifPresent the Function invoked when the Optional is filled + * @param ifAbsent the result when the Optional is empty + * @param the Optional object type + * @param the return type + * + * @return the object returned by the Function or Supplier + */ + public static R handleOptional(Optional optional, Function ifPresent, R ifAbsent) { + if (optional.isPresent()) { + return ifPresent.apply(optional.get()); + } else { + return ifAbsent; + } + } + } diff --git a/src/main/java/fr/xephi/authme/util/Utils.java b/src/main/java/fr/xephi/authme/util/Utils.java index 4db7f61bc..3f1b85d9b 100644 --- a/src/main/java/fr/xephi/authme/util/Utils.java +++ b/src/main/java/fr/xephi/authme/util/Utils.java @@ -4,6 +4,7 @@ import fr.xephi.authme.ConsoleLogger; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import org.bukkit.command.ConsoleCommandSender; +import org.bukkit.entity.Player; import java.util.Collection; import java.util.regex.Pattern; @@ -106,4 +107,19 @@ public final class Utils { public static boolean isEmailEmpty(String email) { return StringUtils.isEmpty(email) || "your@email.com".equalsIgnoreCase(email); } + + /** + * Returns whether the running server instance supports player UUIDs. + * + * @return true if the server supports player UUIDs + */ + public static boolean hasUniqueIdSupport() { + try { + Player.class.getMethod("getUniqueId"); + return true; + } catch (NoSuchMethodException ignored) { + } + return false; + } + }