mirror of
https://github.com/AuthMe/AuthMeReloaded.git
synced 2024-11-16 07:15:16 +01:00
Listener optimizations (#1884)
* Drop CraftBukkit support, listeners cleanup * Codestyle * Codestyle * Remove useless player.saveData() calls * Micro optimization on the join process * Requested changes * Fix unit test * Test onPlayerHeldItem listener * Requested changes * Remove unused import
This commit is contained in:
parent
e2f2ff0763
commit
d30580d5d4
@ -125,8 +125,10 @@ public class AuthMe extends JavaPlugin {
|
||||
logger = ConsoleLoggerFactory.get(AuthMe.class);
|
||||
|
||||
// Check server version
|
||||
if (!isClassLoaded("org.bukkit.event.player.PlayerInteractAtEntityEvent")) {
|
||||
logger.warning("You are running an unsupported server version! AuthMe requires MC 1.8.X or later!");
|
||||
if (!isClassLoaded("org.spigotmc.event.player.PlayerSpawnLocationEvent")
|
||||
|| !isClassLoaded("org.bukkit.event.player.PlayerInteractAtEntityEvent")) {
|
||||
logger.warning("You are running an unsupported server version!"
|
||||
+ "AuthMe requires Spigot 1.8.X or later!");
|
||||
stopOrUnload();
|
||||
return;
|
||||
}
|
||||
|
@ -25,5 +25,4 @@ public class BlockListener implements Listener {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,8 +1,5 @@
|
||||
package fr.xephi.authme.listener;
|
||||
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Projectile;
|
||||
import org.bukkit.event.EventHandler;
|
||||
@ -16,32 +13,19 @@ import org.bukkit.event.entity.EntityShootBowEvent;
|
||||
import org.bukkit.event.entity.EntityTargetEvent;
|
||||
import org.bukkit.event.entity.FoodLevelChangeEvent;
|
||||
import org.bukkit.event.entity.ProjectileLaunchEvent;
|
||||
import org.bukkit.projectiles.ProjectileSource;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class EntityListener implements Listener {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(EntityListener.class);
|
||||
private final ListenerService listenerService;
|
||||
|
||||
private Method getShooter;
|
||||
private boolean shooterIsLivingEntity;
|
||||
|
||||
@Inject
|
||||
EntityListener(ListenerService listenerService) {
|
||||
this.listenerService = listenerService;
|
||||
|
||||
try {
|
||||
getShooter = Projectile.class.getDeclaredMethod("getShooter");
|
||||
shooterIsLivingEntity = getShooter.getReturnType() == LivingEntity.class;
|
||||
} catch (NoSuchMethodException | SecurityException e) {
|
||||
logger.logException("Cannot load getShooter() method on Projectile class", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Note #360: npc status can be used to bypass security!!!
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onDamage(EntityDamageEvent event) {
|
||||
if (listenerService.shouldCancelEvent(event)) {
|
||||
@ -81,6 +65,7 @@ public class EntityListener implements Listener {
|
||||
}
|
||||
}
|
||||
|
||||
//TODO sgdc3 20190808: We listen at the same event twice, does it make any sense?
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
|
||||
public void onEntityInteract(EntityInteractEvent event) {
|
||||
if (listenerService.shouldCancelEvent(event)) {
|
||||
@ -97,26 +82,10 @@ public class EntityListener implements Listener {
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onProjectileLaunch(ProjectileLaunchEvent event) {
|
||||
if (event.getEntity() == null) {
|
||||
return;
|
||||
}
|
||||
final Projectile projectile = event.getEntity();
|
||||
|
||||
Projectile projectile = event.getEntity();
|
||||
// In the Bukkit API prior to 1.7, getShooter() returns a LivingEntity instead of a ProjectileSource
|
||||
Object shooterRaw = null;
|
||||
if (shooterIsLivingEntity) {
|
||||
try {
|
||||
if (getShooter == null) {
|
||||
getShooter = Projectile.class.getMethod("getShooter");
|
||||
}
|
||||
shooterRaw = getShooter.invoke(projectile);
|
||||
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
|
||||
logger.logException("Error getting shooter", e);
|
||||
}
|
||||
} else {
|
||||
shooterRaw = projectile.getShooter();
|
||||
}
|
||||
if (shooterRaw instanceof Player && listenerService.shouldCancelEvent((Player) shooterRaw)) {
|
||||
ProjectileSource shooter = projectile.getShooter();
|
||||
if (shooter instanceof Player && listenerService.shouldCancelEvent((Player) shooter)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
@ -127,5 +96,4 @@ public class EntityListener implements Listener {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,66 +0,0 @@
|
||||
package fr.xephi.authme.listener;
|
||||
|
||||
import fr.xephi.authme.permission.PermissionNode;
|
||||
import fr.xephi.authme.permission.PermissionsManager;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
/**
|
||||
* Represents a player joining the server, which depending on the available
|
||||
* information may be his name or the actual Player object.
|
||||
*/
|
||||
public final class JoiningPlayer {
|
||||
|
||||
private final String name;
|
||||
private final BiFunction<PermissionsManager, PermissionNode, Boolean> permissionLookupFunction;
|
||||
|
||||
/**
|
||||
* Hidden constructor.
|
||||
*
|
||||
* @param name the player's name
|
||||
* @param permFunction the function to use for permission lookups
|
||||
*/
|
||||
private JoiningPlayer(String name, BiFunction<PermissionsManager, PermissionNode, Boolean> permFunction) {
|
||||
this.name = name;
|
||||
this.permissionLookupFunction = permFunction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link JoiningPlayer} instance from the given name.
|
||||
*
|
||||
* @param name the player's name
|
||||
* @return the created instance
|
||||
*/
|
||||
public static JoiningPlayer fromName(String name) {
|
||||
return new JoiningPlayer(name, (manager, perm) -> manager.hasPermissionOffline(name, perm));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link JoiningPlayer} instance from the given Player object.
|
||||
*
|
||||
* @param player the player
|
||||
* @return the created instance
|
||||
*/
|
||||
public static JoiningPlayer fromPlayerObject(Player player) {
|
||||
return new JoiningPlayer(player.getName(), (manager, perm) -> manager.hasPermission(player, perm));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the player's name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the function to use for permission lookups. Takes two arguments: the PermissionsManager instance,
|
||||
* and the permission node to look up. The result is a boolean indicating whether or not this joining player
|
||||
* has permission.
|
||||
*
|
||||
* @return the permissions lookup function to use
|
||||
*/
|
||||
public BiFunction<PermissionsManager, PermissionNode, Boolean> getPermissionLookupFunction() {
|
||||
return permissionLookupFunction;
|
||||
}
|
||||
}
|
@ -31,7 +31,7 @@ import java.util.regex.Pattern;
|
||||
* Service for performing various verifications when a player joins.
|
||||
*/
|
||||
public class OnJoinVerifier implements Reloadable {
|
||||
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(OnJoinVerifier.class);
|
||||
|
||||
@Inject
|
||||
@ -67,16 +67,16 @@ public class OnJoinVerifier implements Reloadable {
|
||||
/**
|
||||
* Checks if Antibot is enabled.
|
||||
*
|
||||
* @param joiningPlayer the joining player to check
|
||||
* @param name the joining player name to check
|
||||
* @param isAuthAvailable whether or not the player is registered
|
||||
* @throws FailedVerificationException if the verification fails
|
||||
*/
|
||||
public void checkAntibot(JoiningPlayer joiningPlayer, boolean isAuthAvailable) throws FailedVerificationException {
|
||||
if (isAuthAvailable || permissionsManager.hasPermission(joiningPlayer, PlayerStatePermission.BYPASS_ANTIBOT)) {
|
||||
public void checkAntibot(String name, boolean isAuthAvailable) throws FailedVerificationException {
|
||||
if (isAuthAvailable || permissionsManager.hasPermissionOffline(name, PlayerStatePermission.BYPASS_ANTIBOT)) {
|
||||
return;
|
||||
}
|
||||
if (antiBotService.shouldKick()) {
|
||||
antiBotService.addPlayerKick(joiningPlayer.getName());
|
||||
antiBotService.addPlayerKick(name);
|
||||
throw new FailedVerificationException(MessageKey.KICK_ANTIBOT);
|
||||
}
|
||||
}
|
||||
@ -170,16 +170,16 @@ public class OnJoinVerifier implements Reloadable {
|
||||
/**
|
||||
* Checks that the player's country is admitted.
|
||||
*
|
||||
* @param joiningPlayer the joining player to verify
|
||||
* @param name the joining player name to verify
|
||||
* @param address the player address
|
||||
* @param isAuthAvailable whether or not the user is registered
|
||||
* @throws FailedVerificationException if the verification fails
|
||||
*/
|
||||
public void checkPlayerCountry(JoiningPlayer joiningPlayer, String address,
|
||||
public void checkPlayerCountry(String name, String address,
|
||||
boolean isAuthAvailable) throws FailedVerificationException {
|
||||
if ((!isAuthAvailable || settings.getProperty(ProtectionSettings.ENABLE_PROTECTION_REGISTERED))
|
||||
&& settings.getProperty(ProtectionSettings.ENABLE_PROTECTION)
|
||||
&& !permissionsManager.hasPermission(joiningPlayer, PlayerStatePermission.BYPASS_COUNTRY_CHECK)
|
||||
&& !permissionsManager.hasPermissionOffline(name, PlayerStatePermission.BYPASS_COUNTRY_CHECK)
|
||||
&& !validationService.isCountryAdmitted(address)) {
|
||||
throw new FailedVerificationException(MessageKey.COUNTRY_BANNED_ERROR);
|
||||
}
|
||||
|
@ -1,30 +1,23 @@
|
||||
package fr.xephi.authme.listener;
|
||||
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.data.QuickCommandsProtectionManager;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.message.Messages;
|
||||
import fr.xephi.authme.permission.PermissionsManager;
|
||||
import fr.xephi.authme.permission.PlayerStatePermission;
|
||||
import fr.xephi.authme.permission.handlers.PermissionLoadUserException;
|
||||
import fr.xephi.authme.process.Management;
|
||||
import fr.xephi.authme.service.AntiBotService;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.service.JoinMessageService;
|
||||
import fr.xephi.authme.service.TeleportationService;
|
||||
import fr.xephi.authme.service.ValidationService;
|
||||
import fr.xephi.authme.service.bungeecord.BungeeSender;
|
||||
import fr.xephi.authme.service.bungeecord.MessageType;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.SpawnLoader;
|
||||
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 fr.xephi.authme.util.PlayerUtils;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
@ -59,7 +52,6 @@ import org.bukkit.event.player.PlayerShearEntityEvent;
|
||||
import org.bukkit.inventory.InventoryView;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static fr.xephi.authme.settings.properties.RestrictionSettings.ALLOWED_MOVEMENT_RADIUS;
|
||||
@ -70,8 +62,6 @@ import static fr.xephi.authme.settings.properties.RestrictionSettings.ALLOW_UNAU
|
||||
*/
|
||||
public class PlayerListener implements Listener {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(PlayerListener.class);
|
||||
|
||||
@Inject
|
||||
private Settings settings;
|
||||
@Inject
|
||||
@ -100,106 +90,104 @@ public class PlayerListener implements Listener {
|
||||
private PermissionsManager permissionsManager;
|
||||
@Inject
|
||||
private QuickCommandsProtectionManager quickCommandsProtectionManager;
|
||||
@Inject
|
||||
private BungeeSender bungeeSender;
|
||||
|
||||
private boolean isAsyncPlayerPreLoginEventCalled = false;
|
||||
private Set<String> unresolvedPlayerHostname = new HashSet<>();
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) {
|
||||
String cmd = event.getMessage().split(" ")[0].toLowerCase();
|
||||
if (settings.getProperty(HooksSettings.USE_ESSENTIALS_MOTD) && "/motd".equals(cmd)) {
|
||||
// Lowest priority to apply fast protection checks
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onAsyncPlayerPreLoginEventLowest(AsyncPlayerPreLoginEvent event) {
|
||||
if (event.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) {
|
||||
return;
|
||||
}
|
||||
if (settings.getProperty(RestrictionSettings.ALLOW_COMMANDS).contains(cmd)) {
|
||||
final String name = event.getName();
|
||||
|
||||
// NOTE: getAddress() sometimes returning null, we don't want to handle this race condition
|
||||
if (event.getAddress() == null) {
|
||||
event.disallow(AsyncPlayerPreLoginEvent.Result.KICK_OTHER,
|
||||
messages.retrieveSingle(name, MessageKey.KICK_UNRESOLVED_HOSTNAME));
|
||||
return;
|
||||
}
|
||||
|
||||
if (validationService.isUnrestricted(name)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Non-blocking checks
|
||||
try {
|
||||
onJoinVerifier.checkSingleSession(name);
|
||||
onJoinVerifier.checkIsValidName(name);
|
||||
} catch (FailedVerificationException e) {
|
||||
event.setKickMessage(messages.retrieveSingle(name, e.getReason(), e.getArgs()));
|
||||
event.setLoginResult(AsyncPlayerPreLoginEvent.Result.KICK_OTHER);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Login/join/leave events
|
||||
*/
|
||||
|
||||
// Note: at this stage (HIGHEST priority) the user's permission data should already have been loaded by
|
||||
// the permission handler, we don't need to call permissionsManager.loadUserData()
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onAsyncPlayerPreLoginEventHighest(AsyncPlayerPreLoginEvent event) {
|
||||
if (event.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) {
|
||||
return;
|
||||
}
|
||||
final String name = event.getName();
|
||||
|
||||
if (validationService.isUnrestricted(name)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Slow, blocking checks
|
||||
try {
|
||||
final PlayerAuth auth = dataSource.getAuth(name);
|
||||
final boolean isAuthAvailable = auth != null;
|
||||
onJoinVerifier.checkKickNonRegistered(isAuthAvailable);
|
||||
onJoinVerifier.checkAntibot(name, isAuthAvailable);
|
||||
onJoinVerifier.checkNameCasing(name, auth);
|
||||
final String ip = event.getAddress().getHostAddress();
|
||||
onJoinVerifier.checkPlayerCountry(name, ip, isAuthAvailable);
|
||||
} catch (FailedVerificationException e) {
|
||||
event.setKickMessage(messages.retrieveSingle(name, e.getReason(), e.getArgs()));
|
||||
event.setLoginResult(AsyncPlayerPreLoginEvent.Result.KICK_OTHER);
|
||||
}
|
||||
}
|
||||
|
||||
// Note: We can't teleport the player in the PlayerLoginEvent listener
|
||||
// as the new player location will be reverted by the server.
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
public void onPlayerLogin(PlayerLoginEvent event) {
|
||||
final Player player = event.getPlayer();
|
||||
if (!quickCommandsProtectionManager.isAllowed(player.getName())) {
|
||||
event.setCancelled(true);
|
||||
player.kickPlayer(messages.retrieveSingle(player, MessageKey.QUICK_COMMAND_PROTECTION_KICK));
|
||||
final String name = player.getName();
|
||||
|
||||
if (validationService.isUnrestricted(name)) {
|
||||
return;
|
||||
}
|
||||
if (listenerService.shouldCancelEvent(player)) {
|
||||
event.setCancelled(true);
|
||||
messages.send(player, MessageKey.DENIED_COMMAND);
|
||||
}
|
||||
|
||||
onJoinVerifier.refusePlayerForFullServer(event);
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onPlayerChat(AsyncPlayerChatEvent event) {
|
||||
if (settings.getProperty(RestrictionSettings.ALLOW_CHAT)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||
final Player player = event.getPlayer();
|
||||
final boolean mayPlayerSendChat = !listenerService.shouldCancelEvent(player)
|
||||
|| permissionsManager.hasPermission(player, PlayerStatePermission.ALLOW_CHAT_BEFORE_LOGIN);
|
||||
if (mayPlayerSendChat) {
|
||||
removeUnauthorizedRecipients(event);
|
||||
} else {
|
||||
event.setCancelled(true);
|
||||
messages.send(player, MessageKey.DENIED_CHAT);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeUnauthorizedRecipients(AsyncPlayerChatEvent event) {
|
||||
if (settings.getProperty(RestrictionSettings.HIDE_CHAT)) {
|
||||
event.getRecipients().removeIf(listenerService::shouldCancelEvent);
|
||||
if (event.getRecipients().isEmpty()) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
|
||||
public void onPlayerMove(PlayerMoveEvent event) {
|
||||
if (settings.getProperty(ALLOW_UNAUTHED_MOVEMENT) && settings.getProperty(ALLOWED_MOVEMENT_RADIUS) <= 0) {
|
||||
return;
|
||||
if (!PlayerListener19Spigot.isPlayerSpawnLocationEventCalled()) {
|
||||
teleportationService.teleportOnJoin(player);
|
||||
}
|
||||
|
||||
/*
|
||||
* Limit player X and Z movements to 1 block
|
||||
* Deny player Y+ movements (allows falling)
|
||||
*/
|
||||
Location from = event.getFrom();
|
||||
Location to = event.getTo();
|
||||
if (from.getBlockX() == to.getBlockX()
|
||||
&& from.getBlockZ() == to.getBlockZ()
|
||||
&& from.getY() - to.getY() >= 0) {
|
||||
return;
|
||||
}
|
||||
quickCommandsProtectionManager.processJoin(player);
|
||||
|
||||
Player player = event.getPlayer();
|
||||
if (!listenerService.shouldCancelEvent(player)) {
|
||||
return;
|
||||
}
|
||||
management.performJoin(player);
|
||||
|
||||
if (!settings.getProperty(RestrictionSettings.ALLOW_UNAUTHED_MOVEMENT)) {
|
||||
// "cancel" the event
|
||||
event.setTo(event.getFrom());
|
||||
return;
|
||||
}
|
||||
|
||||
if (settings.getProperty(RestrictionSettings.NO_TELEPORT)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Location spawn = spawnLoader.getSpawnLocation(player);
|
||||
if (spawn != null && spawn.getWorld() != null) {
|
||||
if (!player.getWorld().equals(spawn.getWorld())) {
|
||||
player.teleport(spawn);
|
||||
} else if (spawn.distance(player.getLocation()) > settings.getProperty(ALLOWED_MOVEMENT_RADIUS)) {
|
||||
player.teleport(spawn);
|
||||
}
|
||||
}
|
||||
teleportationService.teleportNewPlayerToFirstSpawn(player);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onJoinMessage(PlayerJoinEvent event) {
|
||||
final Player player = event.getPlayer();
|
||||
|
||||
// Note: join message can be null, despite api documentation says not
|
||||
if (settings.getProperty(RegistrationSettings.REMOVE_JOIN_MESSAGE)) {
|
||||
event.setJoinMessage(null);
|
||||
return;
|
||||
@ -229,131 +217,11 @@ public class PlayerListener implements Listener {
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||
final Player player = event.getPlayer();
|
||||
|
||||
if (unresolvedPlayerHostname.remove(player.getName())) {
|
||||
try {
|
||||
runOnJoinChecks(JoiningPlayer.fromPlayerObject(player), PlayerUtils.getPlayerIp(player));
|
||||
} catch (FailedVerificationException e) {
|
||||
player.kickPlayer(messages.retrieveSingle(player, e.getReason(), e.getArgs()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PlayerListener19Spigot.isPlayerSpawnLocationEventCalled()) {
|
||||
teleportationService.teleportOnJoin(player);
|
||||
}
|
||||
|
||||
quickCommandsProtectionManager.processJoin(player);
|
||||
|
||||
management.performJoin(player);
|
||||
|
||||
teleportationService.teleportNewPlayerToFirstSpawn(player);
|
||||
}
|
||||
|
||||
private void runOnJoinChecks(JoiningPlayer joiningPlayer, String ip) throws FailedVerificationException {
|
||||
// Fast stuff
|
||||
final String name = joiningPlayer.getName();
|
||||
onJoinVerifier.checkSingleSession(name);
|
||||
onJoinVerifier.checkIsValidName(name);
|
||||
|
||||
// Get the auth later as this may cause the single session check to fail
|
||||
// Slow stuff
|
||||
final PlayerAuth auth = dataSource.getAuth(name);
|
||||
final boolean isAuthAvailable = auth != null;
|
||||
onJoinVerifier.checkKickNonRegistered(isAuthAvailable);
|
||||
onJoinVerifier.checkAntibot(joiningPlayer, isAuthAvailable);
|
||||
onJoinVerifier.checkNameCasing(name, auth);
|
||||
onJoinVerifier.checkPlayerCountry(joiningPlayer, ip, isAuthAvailable);
|
||||
}
|
||||
|
||||
// Note #831: AsyncPlayerPreLoginEvent is not fired by all servers in offline mode
|
||||
// e.g. CraftBukkit does not fire it. So we need to run crucial things with PlayerLoginEvent.
|
||||
// Single session feature can be implemented for Spigot and CraftBukkit by canceling a kick
|
||||
// event caused by "logged in from another location". The nicer way, but only for Spigot, would be
|
||||
// to check in the AsyncPlayerPreLoginEvent. To support all servers, we use the less nice way.
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onAsyncPlayerPreLoginEvent(AsyncPlayerPreLoginEvent event) {
|
||||
isAsyncPlayerPreLoginEventCalled = true;
|
||||
if (!settings.getProperty(PluginSettings.USE_ASYNC_PRE_LOGIN_EVENT)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final String name = event.getName();
|
||||
|
||||
if (validationService.isUnrestricted(name)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Keep pre-UUID compatibility
|
||||
try {
|
||||
permissionsManager.loadUserData(event.getUniqueId());
|
||||
} catch (PermissionLoadUserException e) {
|
||||
logger.logException("Unable to load the permission data of user " + name, e);
|
||||
}
|
||||
|
||||
// getAddress() sometimes returning null if not yet resolved
|
||||
// skip it and let PlayerLoginEvent to handle it
|
||||
if (event.getAddress() == null) {
|
||||
unresolvedPlayerHostname.add(event.getName());
|
||||
return;
|
||||
} else {
|
||||
unresolvedPlayerHostname.remove(event.getName());
|
||||
}
|
||||
|
||||
try {
|
||||
runOnJoinChecks(JoiningPlayer.fromName(name), event.getAddress().getHostAddress());
|
||||
} catch (FailedVerificationException e) {
|
||||
event.setKickMessage(messages.retrieveSingle(name, e.getReason(), e.getArgs()));
|
||||
event.setLoginResult(AsyncPlayerPreLoginEvent.Result.KICK_OTHER);
|
||||
}
|
||||
}
|
||||
|
||||
//Note: We can't teleport the player in the PlayerLoginEvent listener
|
||||
//as the new player location will be reverted by the server.
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
public void onPlayerLogin(PlayerLoginEvent event) {
|
||||
final Player player = event.getPlayer();
|
||||
final String name = player.getName();
|
||||
|
||||
if (validationService.isUnrestricted(name)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (onJoinVerifier.refusePlayerForFullServer(event)) {
|
||||
return;
|
||||
}
|
||||
if (event.getResult() != PlayerLoginEvent.Result.ALLOWED) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (event.getAddress() == null) { // Address still null
|
||||
unresolvedPlayerHostname.add(name);
|
||||
return;
|
||||
} else {
|
||||
unresolvedPlayerHostname.remove(name);
|
||||
}
|
||||
|
||||
if (!isAsyncPlayerPreLoginEventCalled || !settings.getProperty(PluginSettings.USE_ASYNC_PRE_LOGIN_EVENT)) {
|
||||
try {
|
||||
// Player.getAddress() can be null at this event, use event.getAddress()
|
||||
runOnJoinChecks(JoiningPlayer.fromPlayerObject(player), event.getAddress().getHostAddress());
|
||||
} catch (FailedVerificationException e) {
|
||||
event.setKickMessage(messages.retrieveSingle(player, e.getReason(), e.getArgs()));
|
||||
event.setResult(PlayerLoginEvent.Result.KICK_OTHER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
|
||||
// Note: quit message can be null, despite api documentation says not
|
||||
if (settings.getProperty(RegistrationSettings.REMOVE_LEAVE_MESSAGE)) {
|
||||
event.setQuitMessage(null);
|
||||
} else if (settings.getProperty(RegistrationSettings.REMOVE_UNLOGGED_LEAVE_MESSAGE)) {
|
||||
@ -385,6 +253,195 @@ public class PlayerListener implements Listener {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Chat/command events
|
||||
*/
|
||||
|
||||
private void removeUnauthorizedRecipients(AsyncPlayerChatEvent event) {
|
||||
if (settings.getProperty(RestrictionSettings.HIDE_CHAT)) {
|
||||
event.getRecipients().removeIf(listenerService::shouldCancelEvent);
|
||||
if (event.getRecipients().isEmpty()) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onPlayerChat(AsyncPlayerChatEvent event) {
|
||||
if (settings.getProperty(RestrictionSettings.ALLOW_CHAT)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Player player = event.getPlayer();
|
||||
final boolean mayPlayerSendChat = !listenerService.shouldCancelEvent(player)
|
||||
|| permissionsManager.hasPermission(player, PlayerStatePermission.ALLOW_CHAT_BEFORE_LOGIN);
|
||||
if (mayPlayerSendChat) {
|
||||
removeUnauthorizedRecipients(event);
|
||||
} else {
|
||||
event.setCancelled(true);
|
||||
messages.send(player, MessageKey.DENIED_CHAT);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) {
|
||||
String cmd = event.getMessage().split(" ")[0].toLowerCase();
|
||||
if (settings.getProperty(HooksSettings.USE_ESSENTIALS_MOTD) && "/motd".equals(cmd)) {
|
||||
return;
|
||||
}
|
||||
if (settings.getProperty(RestrictionSettings.ALLOW_COMMANDS).contains(cmd)) {
|
||||
return;
|
||||
}
|
||||
final Player player = event.getPlayer();
|
||||
if (!quickCommandsProtectionManager.isAllowed(player.getName())) {
|
||||
event.setCancelled(true);
|
||||
player.kickPlayer(messages.retrieveSingle(player, MessageKey.QUICK_COMMAND_PROTECTION_KICK));
|
||||
return;
|
||||
}
|
||||
if (listenerService.shouldCancelEvent(player)) {
|
||||
event.setCancelled(true);
|
||||
messages.send(player, MessageKey.DENIED_COMMAND);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Movement events
|
||||
*/
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
|
||||
public void onPlayerMove(PlayerMoveEvent event) {
|
||||
if (settings.getProperty(ALLOW_UNAUTHED_MOVEMENT) && settings.getProperty(ALLOWED_MOVEMENT_RADIUS) <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
Location from = event.getFrom();
|
||||
Location to = event.getTo();
|
||||
if (to == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Limit player X and Z movements to 1 block
|
||||
* Deny player Y+ movements (allows falling)
|
||||
*/
|
||||
|
||||
if (from.getBlockX() == to.getBlockX()
|
||||
&& from.getBlockZ() == to.getBlockZ()
|
||||
&& from.getY() - to.getY() >= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
Player player = event.getPlayer();
|
||||
if (!listenerService.shouldCancelEvent(player)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!settings.getProperty(RestrictionSettings.ALLOW_UNAUTHED_MOVEMENT)) {
|
||||
// "cancel" the event
|
||||
event.setTo(event.getFrom());
|
||||
return;
|
||||
}
|
||||
|
||||
if (settings.getProperty(RestrictionSettings.NO_TELEPORT)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Location spawn = spawnLoader.getSpawnLocation(player);
|
||||
if (spawn != null && spawn.getWorld() != null) {
|
||||
if (!player.getWorld().equals(spawn.getWorld())) {
|
||||
player.teleport(spawn);
|
||||
} else if (spawn.distance(player.getLocation()) > settings.getProperty(ALLOWED_MOVEMENT_RADIUS)) {
|
||||
player.teleport(spawn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
|
||||
public void onPlayerRespawn(PlayerRespawnEvent event) {
|
||||
if (settings.getProperty(RestrictionSettings.NO_TELEPORT)) {
|
||||
return;
|
||||
}
|
||||
if (!listenerService.shouldCancelEvent(event)) {
|
||||
return;
|
||||
}
|
||||
Location spawn = spawnLoader.getSpawnLocation(event.getPlayer());
|
||||
if (spawn != null && spawn.getWorld() != null) {
|
||||
event.setRespawnLocation(spawn);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Entity/block interaction events
|
||||
*/
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onPlayerInteract(PlayerInteractEvent event) {
|
||||
if (listenerService.shouldCancelEvent(event)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onPlayerInteractEntity(PlayerInteractEntityEvent event) {
|
||||
if (listenerService.shouldCancelEvent(event)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onPlayerInteractAtEntity(PlayerInteractAtEntityEvent event) {
|
||||
if (listenerService.shouldCancelEvent(event)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onPlayerHitPlayerEvent(EntityDamageByEntityEvent event) {
|
||||
if (listenerService.shouldCancelEvent(event)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onPlayerShear(PlayerShearEntityEvent event) {
|
||||
if (listenerService.shouldCancelEvent(event)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onPlayerFish(PlayerFishEvent event) {
|
||||
if (listenerService.shouldCancelEvent(event)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onPlayerBedEnter(PlayerBedEnterEvent event) {
|
||||
if (listenerService.shouldCancelEvent(event)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onPlayerEditBook(PlayerEditBookEvent event) {
|
||||
if (listenerService.shouldCancelEvent(event)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onSignChange(SignChangeEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
if (listenerService.shouldCancelEvent(player)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Inventory interactions
|
||||
*/
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onPlayerPickupItem(PlayerPickupItemEvent event) {
|
||||
if (listenerService.shouldCancelEvent(event)) {
|
||||
@ -393,14 +450,14 @@ public class PlayerListener implements Listener {
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onPlayerHeldItem(PlayerItemHeldEvent event) {
|
||||
public void onPlayerDropItem(PlayerDropItemEvent event) {
|
||||
if (listenerService.shouldCancelEvent(event)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onPlayerInteract(PlayerInteractEvent event) {
|
||||
public void onPlayerHeldItem(PlayerItemHeldEvent event) {
|
||||
if (listenerService.shouldCancelEvent(event)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
@ -444,95 +501,4 @@ public class PlayerListener implements Listener {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onPlayerHitPlayerEvent(EntityDamageByEntityEvent event) {
|
||||
if (listenerService.shouldCancelEvent(event)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onPlayerInteractEntity(PlayerInteractEntityEvent event) {
|
||||
if (listenerService.shouldCancelEvent(event)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onPlayerDropItem(PlayerDropItemEvent event) {
|
||||
if (listenerService.shouldCancelEvent(event)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onPlayerBedEnter(PlayerBedEnterEvent event) {
|
||||
if (listenerService.shouldCancelEvent(event)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onSignChange(SignChangeEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
if (listenerService.shouldCancelEvent(player)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: check this, why do we need to update the quit loc? -sgdc3
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
|
||||
public void onPlayerRespawn(PlayerRespawnEvent event) {
|
||||
if (settings.getProperty(RestrictionSettings.NO_TELEPORT)) {
|
||||
return;
|
||||
}
|
||||
if (!listenerService.shouldCancelEvent(event)) {
|
||||
return;
|
||||
}
|
||||
Player player = event.getPlayer();
|
||||
String name = player.getName().toLowerCase();
|
||||
Location spawn = spawnLoader.getSpawnLocation(player);
|
||||
if (settings.getProperty(RestrictionSettings.SAVE_QUIT_LOCATION) && dataSource.isAuthAvailable(name)) {
|
||||
PlayerAuth auth = PlayerAuth.builder()
|
||||
.name(name)
|
||||
.realName(player.getName())
|
||||
.location(spawn)
|
||||
.build();
|
||||
dataSource.updateQuitLoc(auth);
|
||||
bungeeSender.sendAuthMeBungeecordMessage(MessageType.REFRESH_QUITLOC, name);
|
||||
}
|
||||
if (spawn != null && spawn.getWorld() != null) {
|
||||
event.setRespawnLocation(spawn);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onPlayerShear(PlayerShearEntityEvent event) {
|
||||
if (listenerService.shouldCancelEvent(event)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onPlayerFish(PlayerFishEvent event) {
|
||||
if (listenerService.shouldCancelEvent(event)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onPlayerEditBook(PlayerEditBookEvent event) {
|
||||
if (listenerService.shouldCancelEvent(event)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onPlayerInteractAtEntity(PlayerInteractAtEntityEvent event) {
|
||||
if (listenerService.shouldCancelEvent(event)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -21,5 +21,4 @@ public class PlayerListener19 implements Listener {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -33,5 +33,4 @@ public class PlayerListener19Spigot implements Listener {
|
||||
event.setSpawnLocation(customSpawnLocation);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -32,11 +32,6 @@ public class ServerListener implements Listener {
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onPluginDisable(PluginDisableEvent event) {
|
||||
// Make sure the plugin instance isn't null
|
||||
if (event.getPlugin() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final String pluginName = event.getPlugin().getName();
|
||||
|
||||
// Call the onPluginDisable method in the permissions manager
|
||||
@ -63,11 +58,6 @@ public class ServerListener implements Listener {
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onPluginEnable(PluginEnableEvent event) {
|
||||
// Make sure the plugin instance isn't null
|
||||
if (event.getPlugin() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final String pluginName = event.getPlugin().getName();
|
||||
|
||||
// Call the onPluginEnable method in the permissions manager
|
||||
|
@ -146,6 +146,9 @@ public enum MessageKey {
|
||||
/** The server is full, try again later! */
|
||||
KICK_FULL_SERVER("on_join_validation.kick_full_server"),
|
||||
|
||||
/** An error occurred: unresolved player hostname! **/
|
||||
KICK_UNRESOLVED_HOSTNAME("error.kick_unresolved_hostname"),
|
||||
|
||||
/** Usage: /email add <email> <confirmEmail> */
|
||||
USAGE_ADD_EMAIL("email.usage_email_add"),
|
||||
|
||||
|
@ -4,7 +4,6 @@ import com.google.common.annotations.VisibleForTesting;
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.initialization.Reloadable;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.listener.JoiningPlayer;
|
||||
import fr.xephi.authme.permission.handlers.LuckPermsHandler;
|
||||
import fr.xephi.authme.permission.handlers.PermissionHandler;
|
||||
import fr.xephi.authme.permission.handlers.PermissionHandlerException;
|
||||
@ -227,18 +226,6 @@ public class PermissionsManager implements Reloadable {
|
||||
return player.hasPermission(permissionNode.getNode());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given player has permission for the given permission node.
|
||||
*
|
||||
* @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) {
|
||||
return joiningPlayer.getPermissionLookupFunction().apply(this, permissionNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
|
@ -89,8 +89,9 @@ public class AsynchronousJoin implements AsynchronousProcess {
|
||||
}
|
||||
|
||||
if (service.getProperty(RestrictionSettings.FORCE_SURVIVAL_MODE)
|
||||
&& player.getGameMode() != GameMode.SURVIVAL
|
||||
&& !service.hasPermission(player, PlayerStatePermission.BYPASS_FORCE_SURVIVAL)) {
|
||||
bukkitService.runTask(() -> player.setGameMode(GameMode.SURVIVAL));
|
||||
bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(() -> player.setGameMode(GameMode.SURVIVAL));
|
||||
}
|
||||
|
||||
if (service.getProperty(HooksSettings.DISABLE_SOCIAL_SPY)) {
|
||||
|
@ -100,7 +100,6 @@ public class ProcessSyncPlayerLogin implements SynchronousProcess {
|
||||
|
||||
// The Login event now fires (as intended) after everything is processed
|
||||
bukkitService.callEvent(new LoginEvent(player));
|
||||
player.saveData();
|
||||
|
||||
// Login is done, display welcome message
|
||||
welcomeMessageConfiguration.sendWelcomeMessage(player);
|
||||
|
@ -41,7 +41,6 @@ public class ProcessSyncEmailRegister implements SynchronousProcess {
|
||||
service.send(player, MessageKey.ACCOUNT_NOT_ACTIVATED);
|
||||
limboService.replaceTasksAfterRegistration(player);
|
||||
|
||||
player.saveData();
|
||||
bukkitService.callEvent(new RegisterEvent(player));
|
||||
logger.fine(player.getName() + " registered " + PlayerUtils.getPlayerIp(player));
|
||||
}
|
||||
|
@ -67,7 +67,6 @@ public class ProcessSyncPasswordRegister implements SynchronousProcess {
|
||||
service.send(player, MessageKey.ADD_EMAIL_MESSAGE);
|
||||
}
|
||||
|
||||
player.saveData();
|
||||
bukkitService.callEvent(new RegisterEvent(player));
|
||||
logger.fine(player.getName() + " registered " + PlayerUtils.getPlayerIp(player));
|
||||
|
||||
|
@ -128,7 +128,6 @@ public class AsynchronousUnregister implements AsynchronousProcess {
|
||||
|
||||
if (service.getProperty(RegistrationSettings.FORCE)) {
|
||||
teleportationService.teleportOnJoin(player);
|
||||
player.saveData();
|
||||
|
||||
bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(() -> {
|
||||
limboService.createLimboPlayer(player, false);
|
||||
|
@ -82,14 +82,6 @@ public final class PluginSettings implements SettingsHolder {
|
||||
public static final Property<Boolean> USE_ASYNC_TASKS =
|
||||
newProperty("settings.useAsyncTasks", true);
|
||||
|
||||
@Comment({
|
||||
"By default we handle the AsyncPlayerPreLoginEvent which makes the plugin faster",
|
||||
"but it is incompatible with any permission plugin not included in our compatibility list.",
|
||||
"If you have issues with permission checks on player join please disable this option."
|
||||
})
|
||||
public static final Property<Boolean> USE_ASYNC_PRE_LOGIN_EVENT =
|
||||
newProperty("settings.useAsyncPreLoginEvent", true);
|
||||
|
||||
@Comment("The name of the server, used in some placeholders.")
|
||||
public static final Property<String> SERVER_NAME = newProperty("settings.serverName", "Your Minecraft Server");
|
||||
|
||||
|
@ -41,6 +41,7 @@ error:
|
||||
unexpected_error: '&4An unexpected error occurred, please contact an administrator!'
|
||||
kick_for_vip: '&3A VIP player has joined the server when it was full!'
|
||||
logged_in: '&cYou''re already logged in!'
|
||||
kick_unresolved_hostname: '&cAn error occurred: unresolved player hostname!'
|
||||
|
||||
# AntiBot
|
||||
antibot:
|
||||
|
@ -1,6 +1,5 @@
|
||||
package fr.xephi.authme.listener;
|
||||
|
||||
import fr.xephi.authme.ReflectionTestUtils;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Projectile;
|
||||
@ -200,8 +199,6 @@ public class EntityListenerTest {
|
||||
@Test
|
||||
public void shouldHandleOldShooterMethod() {
|
||||
// given
|
||||
ReflectionTestUtils.setField(listener, "shooterIsLivingEntity", true);
|
||||
ReflectionTestUtils.setField(listener, "getShooter", null);
|
||||
Projectile projectile = mock(Projectile.class);
|
||||
Player shooter = mock(Player.class);
|
||||
given(projectile.getShooter()).willReturn(shooter);
|
||||
|
@ -1,8 +1,8 @@
|
||||
package fr.xephi.authme.listener;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import fr.xephi.authme.ClassCollector;
|
||||
import fr.xephi.authme.TestHelper;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
@ -27,13 +27,6 @@ public final class ListenerConsistencyTest {
|
||||
|
||||
private static List<Class<? extends Listener>> classes;
|
||||
|
||||
private static final Set<String> CANCELED_EXCEPTIONS = Sets.newHashSet(
|
||||
"PlayerListener#onPlayerJoin", "PlayerListener#onPlayerLogin",
|
||||
"PlayerListener#onPlayerQuit", "ServerListener#onPluginDisable",
|
||||
"ServerListener#onServerPing", "ServerListener#onPluginEnable",
|
||||
"PlayerListener#onJoinMessage", "PlayerListener#onAsyncPlayerPreLoginEvent",
|
||||
"PlayerListener19Spigot#onPlayerSpawn");
|
||||
|
||||
@BeforeClass
|
||||
public static void collectListenerClasses() {
|
||||
ClassCollector collector = new ClassCollector(TestHelper.SOURCES_FOLDER, TestHelper.PROJECT_ROOT + "listener");
|
||||
@ -84,7 +77,7 @@ public final class ListenerConsistencyTest {
|
||||
Method[] methods = listenerClass.getDeclaredMethods();
|
||||
for (Method method : methods) {
|
||||
if (isTestableMethod(method) && method.isAnnotationPresent(EventHandler.class)) {
|
||||
if (CANCELED_EXCEPTIONS.contains(clazz + "#" + method.getName())) {
|
||||
if (!method.getParameterTypes()[0].isAssignableFrom(Cancellable.class)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -374,27 +374,27 @@ public class OnJoinVerifierTest {
|
||||
@Test
|
||||
public void shouldAllowUser() throws FailedVerificationException {
|
||||
// given
|
||||
JoiningPlayer joiningPlayer = JoiningPlayer.fromName("Bobby");
|
||||
String name = "Bobby";
|
||||
boolean isAuthAvailable = false;
|
||||
given(permissionsManager.hasPermission(joiningPlayer, PlayerStatePermission.BYPASS_ANTIBOT)).willReturn(false);
|
||||
given(permissionsManager.hasPermissionOffline(name, PlayerStatePermission.BYPASS_ANTIBOT)).willReturn(false);
|
||||
given(antiBotService.shouldKick()).willReturn(false);
|
||||
|
||||
// when
|
||||
onJoinVerifier.checkAntibot(joiningPlayer, isAuthAvailable);
|
||||
onJoinVerifier.checkAntibot(name, isAuthAvailable);
|
||||
|
||||
// then
|
||||
verify(permissionsManager).hasPermission(joiningPlayer, PlayerStatePermission.BYPASS_ANTIBOT);
|
||||
verify(permissionsManager).hasPermissionOffline(name, PlayerStatePermission.BYPASS_ANTIBOT);
|
||||
verify(antiBotService).shouldKick();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldAllowUserWithAuth() throws FailedVerificationException {
|
||||
// given
|
||||
JoiningPlayer joiningPlayer = JoiningPlayer.fromName("Lacey");
|
||||
String name = "Lacey";
|
||||
boolean isAuthAvailable = true;
|
||||
|
||||
// when
|
||||
onJoinVerifier.checkAntibot(joiningPlayer, isAuthAvailable);
|
||||
onJoinVerifier.checkAntibot(name, isAuthAvailable);
|
||||
|
||||
// then
|
||||
verifyZeroInteractions(permissionsManager, antiBotService);
|
||||
@ -403,32 +403,32 @@ public class OnJoinVerifierTest {
|
||||
@Test
|
||||
public void shouldAllowUserWithBypassPermission() throws FailedVerificationException {
|
||||
// given
|
||||
JoiningPlayer joiningPlayer = JoiningPlayer.fromName("Steward");
|
||||
String name = "Steward";
|
||||
boolean isAuthAvailable = false;
|
||||
given(permissionsManager.hasPermission(joiningPlayer, PlayerStatePermission.BYPASS_ANTIBOT)).willReturn(true);
|
||||
given(permissionsManager.hasPermissionOffline(name, PlayerStatePermission.BYPASS_ANTIBOT)).willReturn(true);
|
||||
|
||||
// when
|
||||
onJoinVerifier.checkAntibot(joiningPlayer, isAuthAvailable);
|
||||
onJoinVerifier.checkAntibot(name, isAuthAvailable);
|
||||
|
||||
// then
|
||||
verify(permissionsManager).hasPermission(joiningPlayer, PlayerStatePermission.BYPASS_ANTIBOT);
|
||||
verify(permissionsManager).hasPermissionOffline(name, PlayerStatePermission.BYPASS_ANTIBOT);
|
||||
verifyZeroInteractions(antiBotService);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldKickUserForFailedAntibotCheck() throws FailedVerificationException {
|
||||
public void shouldKickUserForFailedAntibotCheck() {
|
||||
// given
|
||||
JoiningPlayer joiningPlayer = JoiningPlayer.fromName("D3");
|
||||
String name = "D3";
|
||||
boolean isAuthAvailable = false;
|
||||
given(permissionsManager.hasPermission(joiningPlayer, PlayerStatePermission.BYPASS_ANTIBOT)).willReturn(false);
|
||||
given(permissionsManager.hasPermissionOffline(name, PlayerStatePermission.BYPASS_ANTIBOT)).willReturn(false);
|
||||
given(antiBotService.shouldKick()).willReturn(true);
|
||||
|
||||
// when / then
|
||||
try {
|
||||
onJoinVerifier.checkAntibot(joiningPlayer, isAuthAvailable);
|
||||
onJoinVerifier.checkAntibot(name, isAuthAvailable);
|
||||
fail("Expected exception to be thrown");
|
||||
} catch (FailedVerificationException e) {
|
||||
verify(permissionsManager).hasPermission(joiningPlayer, PlayerStatePermission.BYPASS_ANTIBOT);
|
||||
verify(permissionsManager).hasPermissionOffline(name, PlayerStatePermission.BYPASS_ANTIBOT);
|
||||
verify(antiBotService).shouldKick();
|
||||
}
|
||||
|
||||
@ -439,18 +439,18 @@ public class OnJoinVerifierTest {
|
||||
*/
|
||||
@Test
|
||||
public void shouldNotCheckCountry() throws FailedVerificationException {
|
||||
JoiningPlayer joiningPlayer = JoiningPlayer.fromName("david");
|
||||
String name = "david";
|
||||
String ip = "127.0.0.1";
|
||||
|
||||
// protection setting disabled
|
||||
given(settings.getProperty(ProtectionSettings.ENABLE_PROTECTION)).willReturn(false);
|
||||
given(settings.getProperty(ProtectionSettings.ENABLE_PROTECTION_REGISTERED)).willReturn(true);
|
||||
onJoinVerifier.checkPlayerCountry(joiningPlayer, ip, false);
|
||||
onJoinVerifier.checkPlayerCountry(name, ip, false);
|
||||
verifyZeroInteractions(validationService);
|
||||
|
||||
// protection for registered players disabled
|
||||
given(settings.getProperty(ProtectionSettings.ENABLE_PROTECTION_REGISTERED)).willReturn(false);
|
||||
onJoinVerifier.checkPlayerCountry(joiningPlayer, ip, true);
|
||||
onJoinVerifier.checkPlayerCountry(name, ip, true);
|
||||
verifyZeroInteractions(validationService);
|
||||
}
|
||||
|
||||
@ -458,12 +458,12 @@ public class OnJoinVerifierTest {
|
||||
public void shouldCheckAndAcceptUnregisteredPlayerCountry() throws FailedVerificationException {
|
||||
// given
|
||||
String ip = "192.168.0.1";
|
||||
JoiningPlayer joiningPlayer = JoiningPlayer.fromName("lucas");
|
||||
String name = "lucas";
|
||||
given(settings.getProperty(ProtectionSettings.ENABLE_PROTECTION)).willReturn(true);
|
||||
given(validationService.isCountryAdmitted(ip)).willReturn(true);
|
||||
|
||||
// when
|
||||
onJoinVerifier.checkPlayerCountry(joiningPlayer, ip, false);
|
||||
onJoinVerifier.checkPlayerCountry(name, ip, false);
|
||||
|
||||
// then
|
||||
verify(validationService).isCountryAdmitted(ip);
|
||||
@ -473,13 +473,13 @@ public class OnJoinVerifierTest {
|
||||
public void shouldCheckAndAcceptRegisteredPlayerCountry() throws FailedVerificationException {
|
||||
// given
|
||||
String ip = "192.168.10.24";
|
||||
JoiningPlayer joiningPlayer = JoiningPlayer.fromName("gabriel");
|
||||
String name = "gabriel";
|
||||
given(settings.getProperty(ProtectionSettings.ENABLE_PROTECTION)).willReturn(true);
|
||||
given(settings.getProperty(ProtectionSettings.ENABLE_PROTECTION_REGISTERED)).willReturn(true);
|
||||
given(validationService.isCountryAdmitted(ip)).willReturn(true);
|
||||
|
||||
// when
|
||||
onJoinVerifier.checkPlayerCountry(joiningPlayer, ip, true);
|
||||
onJoinVerifier.checkPlayerCountry(name, ip, true);
|
||||
|
||||
// then
|
||||
verify(validationService).isCountryAdmitted(ip);
|
||||
@ -489,7 +489,7 @@ public class OnJoinVerifierTest {
|
||||
public void shouldThrowForBannedCountry() throws FailedVerificationException {
|
||||
// given
|
||||
String ip = "192.168.40.0";
|
||||
JoiningPlayer joiningPlayer = JoiningPlayer.fromName("bob");
|
||||
String name = "bob";
|
||||
given(settings.getProperty(ProtectionSettings.ENABLE_PROTECTION)).willReturn(true);
|
||||
given(validationService.isCountryAdmitted(ip)).willReturn(false);
|
||||
|
||||
@ -497,7 +497,7 @@ public class OnJoinVerifierTest {
|
||||
expectValidationExceptionWith(MessageKey.COUNTRY_BANNED_ERROR);
|
||||
|
||||
// when
|
||||
onJoinVerifier.checkPlayerCountry(joiningPlayer, ip, false);
|
||||
onJoinVerifier.checkPlayerCountry(name, ip, false);
|
||||
}
|
||||
|
||||
private void expectValidationExceptionWith(MessageKey messageKey, String... args) {
|
||||
|
@ -1,6 +1,5 @@
|
||||
package fr.xephi.authme.listener;
|
||||
|
||||
import fr.xephi.authme.TestHelper;
|
||||
import fr.xephi.authme.data.QuickCommandsProtectionManager;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
@ -29,6 +28,7 @@ import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.inventory.InventoryOpenEvent;
|
||||
import org.bukkit.event.player.AsyncPlayerChatEvent;
|
||||
import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
|
||||
import org.bukkit.event.player.PlayerBedEnterEvent;
|
||||
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
||||
import org.bukkit.event.player.PlayerDropItemEvent;
|
||||
@ -38,12 +38,14 @@ import org.bukkit.event.player.PlayerInteractAtEntityEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEntityEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.event.player.PlayerItemConsumeEvent;
|
||||
import org.bukkit.event.player.PlayerItemHeldEvent;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerKickEvent;
|
||||
import org.bukkit.event.player.PlayerLoginEvent;
|
||||
import org.bukkit.event.player.PlayerMoveEvent;
|
||||
import org.bukkit.event.player.PlayerPickupItemEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.event.player.PlayerRespawnEvent;
|
||||
import org.bukkit.event.player.PlayerShearEntityEvent;
|
||||
import org.bukkit.inventory.InventoryView;
|
||||
import org.junit.Test;
|
||||
@ -58,6 +60,7 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import static com.google.common.collect.Sets.newHashSet;
|
||||
import static fr.xephi.authme.listener.EventCancelVerifier.withServiceMock;
|
||||
@ -71,7 +74,6 @@ import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.atLeast;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
@ -188,7 +190,8 @@ public class PlayerListenerTest {
|
||||
.check(listener::onPlayerConsumeItem, PlayerItemConsumeEvent.class)
|
||||
.check(listener::onPlayerInteract, PlayerInteractEvent.class)
|
||||
.check(listener::onPlayerPickupItem, PlayerPickupItemEvent.class)
|
||||
.check(listener::onPlayerInteractEntity, PlayerInteractEntityEvent.class);
|
||||
.check(listener::onPlayerInteractEntity, PlayerInteractEntityEvent.class)
|
||||
.check(listener::onPlayerHeldItem, PlayerItemHeldEvent.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -536,6 +539,98 @@ public class PlayerListenerTest {
|
||||
verifyNoModifyingCalls(event);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldIgnorePlayerRespawnWithNoTeleport() {
|
||||
// given
|
||||
Player player = mock(Player.class);
|
||||
Location respawnLocation = mock(Location.class);
|
||||
PlayerRespawnEvent event = spy(new PlayerRespawnEvent(player, respawnLocation, false));
|
||||
given(settings.getProperty(RestrictionSettings.NO_TELEPORT)).willReturn(true);
|
||||
|
||||
// when
|
||||
listener.onPlayerRespawn(event);
|
||||
|
||||
// then
|
||||
verifyZeroInteractions(listenerService);
|
||||
verify(event, never()).setRespawnLocation(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldIgnorePlayerRespawn() {
|
||||
// given
|
||||
Player player = mock(Player.class);
|
||||
Location respawnLocation = mock(Location.class);
|
||||
PlayerRespawnEvent event = spy(new PlayerRespawnEvent(player, respawnLocation, false));
|
||||
given(settings.getProperty(RestrictionSettings.NO_TELEPORT)).willReturn(false);
|
||||
given(listenerService.shouldCancelEvent(event)).willReturn(false);
|
||||
|
||||
// when
|
||||
listener.onPlayerRespawn(event);
|
||||
|
||||
// then
|
||||
verifyZeroInteractions(spawnLoader);
|
||||
verify(event, never()).setRespawnLocation(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldHandlePlayerRespawn() {
|
||||
// given
|
||||
Player player = mock(Player.class);
|
||||
Location originalLocation = mock(Location.class);
|
||||
Location newLocation = mock(Location.class);
|
||||
World world = mock(World.class);
|
||||
given(newLocation.getWorld()).willReturn(world);
|
||||
PlayerRespawnEvent event = spy(new PlayerRespawnEvent(player, originalLocation, false));
|
||||
given(settings.getProperty(RestrictionSettings.NO_TELEPORT)).willReturn(false);
|
||||
given(listenerService.shouldCancelEvent(event)).willReturn(true);
|
||||
given(spawnLoader.getSpawnLocation(player)).willReturn(newLocation);
|
||||
|
||||
// when
|
||||
listener.onPlayerRespawn(event);
|
||||
|
||||
// then
|
||||
verify(spawnLoader).getSpawnLocation(player);
|
||||
verify(event).setRespawnLocation(newLocation);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldIgnorePlayerRespawnUnloadedWorld() {
|
||||
// given
|
||||
Player player = mock(Player.class);
|
||||
Location originalLocation = mock(Location.class);
|
||||
Location newLocation = mock(Location.class);
|
||||
given(newLocation.getWorld()).willReturn(null);
|
||||
PlayerRespawnEvent event = spy(new PlayerRespawnEvent(player, originalLocation, false));
|
||||
given(settings.getProperty(RestrictionSettings.NO_TELEPORT)).willReturn(false);
|
||||
given(listenerService.shouldCancelEvent(event)).willReturn(true);
|
||||
given(spawnLoader.getSpawnLocation(player)).willReturn(newLocation);
|
||||
|
||||
// when
|
||||
listener.onPlayerRespawn(event);
|
||||
|
||||
// then
|
||||
verify(spawnLoader).getSpawnLocation(player);
|
||||
verify(event, never()).setRespawnLocation(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldHandlePlayerRespawnNoChanges() {
|
||||
// given
|
||||
Player player = mock(Player.class);
|
||||
Location originalLocation = mock(Location.class);
|
||||
PlayerRespawnEvent event = spy(new PlayerRespawnEvent(player, originalLocation, false));
|
||||
given(settings.getProperty(RestrictionSettings.NO_TELEPORT)).willReturn(false);
|
||||
given(listenerService.shouldCancelEvent(event)).willReturn(true);
|
||||
given(spawnLoader.getSpawnLocation(player)).willReturn(null);
|
||||
|
||||
// when
|
||||
listener.onPlayerRespawn(event);
|
||||
|
||||
// then
|
||||
verify(spawnLoader).getSpawnLocation(player);
|
||||
verify(event, never()).setRespawnLocation(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldHandlePlayerJoining() {
|
||||
// given
|
||||
@ -606,60 +701,113 @@ public class PlayerListenerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldPerformAllJoinVerificationsSuccessfully() throws FailedVerificationException {
|
||||
public void shouldPerformAllJoinVerificationsSuccessfullyPreLoginLowest() throws FailedVerificationException {
|
||||
// given
|
||||
String name = "someone";
|
||||
UUID uniqueId = UUID.fromString("753493c9-33ba-4a4a-bf61-1bce9d3c9a71");
|
||||
String ip = "12.34.56.78";
|
||||
|
||||
AsyncPlayerPreLoginEvent preLoginEvent = spy(new AsyncPlayerPreLoginEvent(name, mockAddrWithIp(ip), uniqueId));
|
||||
given(validationService.isUnrestricted(name)).willReturn(false);
|
||||
|
||||
// when
|
||||
listener.onAsyncPlayerPreLoginEventLowest(preLoginEvent);
|
||||
|
||||
// then
|
||||
verify(validationService).isUnrestricted(name);
|
||||
verify(onJoinVerifier).checkSingleSession(name);
|
||||
verify(onJoinVerifier).checkIsValidName(name);
|
||||
verifyZeroInteractions(dataSource);
|
||||
verifyNoModifyingCalls(preLoginEvent);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldKickPreLoginLowestUnresolvedHostname() throws FailedVerificationException {
|
||||
// given
|
||||
String name = "someone";
|
||||
UUID uniqueId = UUID.fromString("753493c9-33ba-4a4a-bf61-1bce9d3c9a71");
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
AsyncPlayerPreLoginEvent preLoginEvent = spy(new AsyncPlayerPreLoginEvent(name, null, uniqueId));
|
||||
given(messages.retrieveSingle(name, MessageKey.KICK_UNRESOLVED_HOSTNAME)).willReturn("Unresolved hostname");
|
||||
|
||||
// when
|
||||
listener.onAsyncPlayerPreLoginEventLowest(preLoginEvent);
|
||||
|
||||
// then
|
||||
verify(preLoginEvent).disallow(AsyncPlayerPreLoginEvent.Result.KICK_OTHER, "Unresolved hostname");
|
||||
verifyNoMoreInteractions(onJoinVerifier);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldPerformAllJoinVerificationsSuccessfullyPreLoginHighest() throws FailedVerificationException {
|
||||
// given
|
||||
String name = "someone";
|
||||
UUID uniqueId = UUID.fromString("753493c9-33ba-4a4a-bf61-1bce9d3c9a71");
|
||||
String ip = "12.34.56.78";
|
||||
|
||||
AsyncPlayerPreLoginEvent preLoginEvent = spy(new AsyncPlayerPreLoginEvent(name, mockAddrWithIp(ip), uniqueId));
|
||||
given(validationService.isUnrestricted(name)).willReturn(false);
|
||||
PlayerAuth auth = PlayerAuth.builder().name(name).build();
|
||||
given(dataSource.getAuth(name)).willReturn(auth);
|
||||
|
||||
// when
|
||||
listener.onAsyncPlayerPreLoginEventHighest(preLoginEvent);
|
||||
|
||||
// then
|
||||
verify(validationService).isUnrestricted(name);
|
||||
verify(onJoinVerifier).checkKickNonRegistered(true);
|
||||
verify(onJoinVerifier).checkAntibot(name, true);
|
||||
verify(onJoinVerifier).checkNameCasing(name, auth);
|
||||
verify(onJoinVerifier).checkPlayerCountry(name, ip, true);
|
||||
verifyNoModifyingCalls(preLoginEvent);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldPerformAllJoinVerificationsSuccessfullyLogin() {
|
||||
// given
|
||||
String name = "someone";
|
||||
Player player = mockPlayerWithName(name);
|
||||
String ip = "12.34.56.78";
|
||||
|
||||
PlayerLoginEvent event = spy(new PlayerLoginEvent(player, "", mockAddrWithIp(ip)));
|
||||
PlayerLoginEvent loginEvent = spy(new PlayerLoginEvent(player, "", mockAddrWithIp(ip)));
|
||||
given(validationService.isUnrestricted(name)).willReturn(false);
|
||||
given(onJoinVerifier.refusePlayerForFullServer(event)).willReturn(false);
|
||||
PlayerAuth auth = PlayerAuth.builder().name(name).build();
|
||||
given(dataSource.getAuth(name)).willReturn(auth);
|
||||
given(onJoinVerifier.refusePlayerForFullServer(loginEvent)).willReturn(false);
|
||||
|
||||
// when
|
||||
listener.onPlayerLogin(event);
|
||||
listener.onPlayerLogin(loginEvent);
|
||||
|
||||
// then
|
||||
verify(validationService).isUnrestricted(name);
|
||||
verify(onJoinVerifier).refusePlayerForFullServer(event);
|
||||
verify(onJoinVerifier).checkSingleSession(name);
|
||||
verify(onJoinVerifier).checkIsValidName(name);
|
||||
verify(onJoinVerifier).checkAntibot(any(JoiningPlayer.class), eq(true));
|
||||
verify(onJoinVerifier).checkKickNonRegistered(true);
|
||||
verify(onJoinVerifier).checkNameCasing(name, auth);
|
||||
verify(onJoinVerifier).checkPlayerCountry(any(JoiningPlayer.class), eq(ip), eq(true));
|
||||
verifyNoModifyingCalls(event);
|
||||
verify(onJoinVerifier).refusePlayerForFullServer(loginEvent);
|
||||
verifyZeroInteractions(dataSource);
|
||||
verifyNoModifyingCalls(loginEvent);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldAbortPlayerJoinForInvalidName() throws FailedVerificationException {
|
||||
// given
|
||||
String name = "inval!dName";
|
||||
Player player = mockPlayerWithName(name);
|
||||
TestHelper.mockPlayerIp(player, "33.32.33.33");
|
||||
PlayerLoginEvent event = spy(new PlayerLoginEvent(player, "", player.getAddress().getAddress()));
|
||||
UUID uniqueId = UUID.fromString("753493c9-33ba-4a4a-bf61-1bce9d3c9a71");
|
||||
InetAddress ip = mockAddrWithIp("33.32.33.33");
|
||||
AsyncPlayerPreLoginEvent event = spy(new AsyncPlayerPreLoginEvent(name, ip, uniqueId));
|
||||
given(validationService.isUnrestricted(name)).willReturn(false);
|
||||
given(onJoinVerifier.refusePlayerForFullServer(event)).willReturn(false);
|
||||
FailedVerificationException exception = new FailedVerificationException(
|
||||
MessageKey.INVALID_NAME_CHARACTERS, "[a-z]");
|
||||
doThrow(exception).when(onJoinVerifier).checkIsValidName(name);
|
||||
String message = "Invalid characters!";
|
||||
given(messages.retrieveSingle(player, exception.getReason(), exception.getArgs())).willReturn(message);
|
||||
given(messages.retrieveSingle(name, exception.getReason(), exception.getArgs())).willReturn(message);
|
||||
|
||||
// when
|
||||
listener.onPlayerLogin(event);
|
||||
listener.onAsyncPlayerPreLoginEventLowest(event);
|
||||
|
||||
// then
|
||||
verify(validationService).isUnrestricted(name);
|
||||
verify(onJoinVerifier).refusePlayerForFullServer(event);
|
||||
verify(onJoinVerifier).checkSingleSession(name);
|
||||
verify(onJoinVerifier).checkIsValidName(name);
|
||||
// Check that we don't talk with the data source before performing checks that don't require it
|
||||
verifyZeroInteractions(dataSource);
|
||||
verify(event).setKickMessage(message);
|
||||
verify(event).setResult(PlayerLoginEvent.Result.KICK_OTHER);
|
||||
verify(event).setLoginResult(AsyncPlayerPreLoginEvent.Result.KICK_OTHER);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -950,6 +1098,13 @@ public class PlayerListenerTest {
|
||||
verifyNoMoreInteractions(event);
|
||||
}
|
||||
|
||||
private static void verifyNoModifyingCalls(AsyncPlayerPreLoginEvent event) {
|
||||
verify(event, atLeast(0)).getLoginResult();
|
||||
verify(event, atLeast(0)).getAddress();
|
||||
verify(event, atLeast(0)).getName();
|
||||
verifyNoMoreInteractions(event);
|
||||
}
|
||||
|
||||
private static InetAddress mockAddrWithIp(String ip) {
|
||||
InetAddress addr = mock(InetAddress.class);
|
||||
given(addr.getHostAddress()).willReturn(ip);
|
||||
|
@ -81,19 +81,6 @@ public class ServerListenerTest {
|
||||
checkDisableHandling("UnknownPlugin", () -> verifyZeroInteractions(pluginHookService, spawnLoader));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldHandlePluginWithNullName() {
|
||||
PluginEnableEvent enableEvent = mock(PluginEnableEvent.class);
|
||||
given(enableEvent.getPlugin()).willReturn(null);
|
||||
serverListener.onPluginEnable(enableEvent);
|
||||
verifyNoMoreInteractionsAndReset();
|
||||
|
||||
PluginDisableEvent disableEvent = mock(PluginDisableEvent.class);
|
||||
given(disableEvent.getPlugin()).willReturn(null);
|
||||
serverListener.onPluginDisable(disableEvent);
|
||||
verifyNoMoreInteractionsAndReset();
|
||||
}
|
||||
|
||||
private void checkEnableHandling(String pluginName, Runnable verifier) {
|
||||
PluginEnableEvent event = mockEventWithPluginName(PluginEnableEvent.class, pluginName);
|
||||
serverListener.onPluginEnable(event);
|
||||
|
@ -1,6 +1,5 @@
|
||||
package fr.xephi.authme.permission;
|
||||
|
||||
import fr.xephi.authme.listener.JoiningPlayer;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
@ -13,13 +12,8 @@ import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* Test for {@link PermissionsManager}.
|
||||
@ -154,26 +148,4 @@ public class PermissionsManagerTest {
|
||||
// then
|
||||
assertThat(result, equalTo(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldHandleJoiningPlayerPermissionChecksWithProperMethod() {
|
||||
// given
|
||||
Player player = mock(Player.class);
|
||||
JoiningPlayer fromPlayer = JoiningPlayer.fromPlayerObject(player);
|
||||
JoiningPlayer fromName = JoiningPlayer.fromName("Chris");
|
||||
|
||||
PermissionsManager permManagerSpy = spy(permissionsManager);
|
||||
given(permManagerSpy.hasPermission(any(Player.class), eq(PlayerPermission.LOGIN))).willReturn(true);
|
||||
given(permManagerSpy.hasPermissionOffline(anyString(), eq(PlayerPermission.UNREGISTER))).willReturn(true);
|
||||
|
||||
// when
|
||||
boolean resultFromPlayer = permManagerSpy.hasPermission(fromPlayer, PlayerPermission.LOGIN);
|
||||
boolean resultFromName = permManagerSpy.hasPermission(fromName, PlayerPermission.UNREGISTER);
|
||||
|
||||
// then
|
||||
assertThat(resultFromPlayer, equalTo(true));
|
||||
assertThat(resultFromName, equalTo(true));
|
||||
verify(permManagerSpy).hasPermission(player, PlayerPermission.LOGIN);
|
||||
verify(permManagerSpy).hasPermissionOffline(fromName.getName(), PlayerPermission.UNREGISTER);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user