diff --git a/src/main/java/fr/xephi/authme/events/AbstractUnregisterEvent.java b/src/main/java/fr/xephi/authme/events/AbstractUnregisterEvent.java new file mode 100644 index 00000000..1ab96689 --- /dev/null +++ b/src/main/java/fr/xephi/authme/events/AbstractUnregisterEvent.java @@ -0,0 +1,32 @@ +package fr.xephi.authme.events; + +import org.bukkit.entity.Player; + +/** + * Event fired when a player has been unregistered. + */ +public abstract class AbstractUnregisterEvent extends CustomEvent { + + private final Player player; + + /** + * Constructor for a player that has unregistered himself. + * + * @param player the player + */ + public AbstractUnregisterEvent(Player player, boolean isAsync) { + super(isAsync); + this.player = player; + } + + /** + * Returns the player that has been unregistered. + *
+ * This may be {@code null}! Please refer to the implementations of this class for details. + * + * @return the unregistered player, or null + */ + public Player getPlayer() { + return player; + } +} diff --git a/src/main/java/fr/xephi/authme/events/UnregisterByAdminEvent.java b/src/main/java/fr/xephi/authme/events/UnregisterByAdminEvent.java new file mode 100644 index 00000000..f12e5116 --- /dev/null +++ b/src/main/java/fr/xephi/authme/events/UnregisterByAdminEvent.java @@ -0,0 +1,67 @@ +package fr.xephi.authme.events; + +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.event.HandlerList; + +/** + * Event fired after a player has been unregistered from an external source (by an admin or via the API). + *
+ * Note that only the {@code playerName} is guaranteed to be not {@code null} in any case. + *
+ * The {@code player} may be null if a name is supplied which has never been online on the server – + * due to migrations, data removal, etc. it is possible that a user exists in the database for which the + * server knows no {@link Player} object. + *
+ * If a player is unregistered via an API call, the {@code initiator} is null as the action has not been
+ * started by any {@link CommandSender}. Otherwise, the {@code initiator} is the user who performed the
+ * command to unregister the player name.
+ */
+public class UnregisterByAdminEvent extends AbstractUnregisterEvent {
+
+ private static final HandlerList handlers = new HandlerList();
+ private final String playerName;
+ private final CommandSender initiator;
+
+ /**
+ * Constructor.
+ *
+ * @param player the player (may be null - see class JavaDoc)
+ * @param playerName the name of the player that was unregistered
+ * @param isAsync whether or not the event is async
+ * @param initiator the initiator of the unregister process (may be null - see class JavaDoc)
+ */
+ public UnregisterByAdminEvent(Player player, String playerName, boolean isAsync, CommandSender initiator) {
+ super(player, isAsync);
+ this.playerName = playerName;
+ this.initiator = initiator;
+ }
+
+ /**
+ * @return the name of the player that was unregistered
+ */
+ public String getPlayerName() {
+ return playerName;
+ }
+
+ /**
+ * @return the user who requested to unregister the name, or null if not applicable
+ */
+ public CommandSender getInitiator() {
+ return initiator;
+ }
+
+ /**
+ * Return the list of handlers, equivalent to {@link #getHandlers()} and required by {@link org.bukkit.event.Event}.
+ *
+ * @return The list of handlers
+ */
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+}
diff --git a/src/main/java/fr/xephi/authme/events/UnregisterByPlayerEvent.java b/src/main/java/fr/xephi/authme/events/UnregisterByPlayerEvent.java
new file mode 100644
index 00000000..bd28c50e
--- /dev/null
+++ b/src/main/java/fr/xephi/authme/events/UnregisterByPlayerEvent.java
@@ -0,0 +1,35 @@
+package fr.xephi.authme.events;
+
+import org.bukkit.entity.Player;
+import org.bukkit.event.HandlerList;
+
+/**
+ * Event fired after a player has unregistered himself.
+ */
+public class UnregisterByPlayerEvent extends AbstractUnregisterEvent {
+
+ private static final HandlerList handlers = new HandlerList();
+
+ /**
+ * Constructor.
+ *
+ * @param player the player (never null)
+ */
+ public UnregisterByPlayerEvent(Player player, boolean isAsync) {
+ super(player, isAsync);
+ }
+
+ /**
+ * Return the list of handlers, equivalent to {@link #getHandlers()} and required by {@link org.bukkit.event.Event}.
+ *
+ * @return The list of handlers
+ */
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+}
diff --git a/src/main/java/fr/xephi/authme/process/unregister/AsynchronousUnregister.java b/src/main/java/fr/xephi/authme/process/unregister/AsynchronousUnregister.java
index eabd902e..f0332238 100644
--- a/src/main/java/fr/xephi/authme/process/unregister/AsynchronousUnregister.java
+++ b/src/main/java/fr/xephi/authme/process/unregister/AsynchronousUnregister.java
@@ -5,6 +5,8 @@ import fr.xephi.authme.data.auth.PlayerAuth;
import fr.xephi.authme.data.auth.PlayerCache;
import fr.xephi.authme.data.limbo.LimboService;
import fr.xephi.authme.datasource.DataSource;
+import fr.xephi.authme.events.UnregisterByAdminEvent;
+import fr.xephi.authme.events.UnregisterByPlayerEvent;
import fr.xephi.authme.message.MessageKey;
import fr.xephi.authme.permission.AuthGroupHandler;
import fr.xephi.authme.permission.AuthGroupType;
@@ -66,6 +68,7 @@ public class AsynchronousUnregister implements AsynchronousProcess {
if (dataSource.removeAuth(name)) {
performUnregister(name, player);
ConsoleLogger.info(name + " unregistered himself");
+ bukkitService.createAndCallEvent(isAsync -> new UnregisterByPlayerEvent(player, isAsync));
} else {
service.send(player, MessageKey.ERROR);
}
@@ -86,6 +89,8 @@ public class AsynchronousUnregister implements AsynchronousProcess {
public void adminUnregister(CommandSender initiator, String name, Player player) {
if (dataSource.removeAuth(name)) {
performUnregister(name, player);
+ bukkitService.createAndCallEvent(isAsync -> new UnregisterByAdminEvent(player, name, isAsync, initiator));
+
if (initiator == null) {
ConsoleLogger.info(name + " was unregistered");
} else {
diff --git a/src/test/java/fr/xephi/authme/process/unregister/AsynchronousUnregisterTest.java b/src/test/java/fr/xephi/authme/process/unregister/AsynchronousUnregisterTest.java
index 26433a45..9ff0faee 100644
--- a/src/test/java/fr/xephi/authme/process/unregister/AsynchronousUnregisterTest.java
+++ b/src/test/java/fr/xephi/authme/process/unregister/AsynchronousUnregisterTest.java
@@ -5,6 +5,7 @@ import fr.xephi.authme.data.auth.PlayerAuth;
import fr.xephi.authme.data.auth.PlayerCache;
import fr.xephi.authme.data.limbo.LimboService;
import fr.xephi.authme.datasource.DataSource;
+import fr.xephi.authme.events.AbstractUnregisterEvent;
import fr.xephi.authme.message.MessageKey;
import fr.xephi.authme.permission.AuthGroupHandler;
import fr.xephi.authme.permission.AuthGroupType;
@@ -19,10 +20,15 @@ import org.bukkit.entity.Player;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
+import java.util.function.Function;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.junit.Assert.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
@@ -81,7 +87,7 @@ public class AsynchronousUnregisterTest {
// then
verify(service).send(player, MessageKey.WRONG_PASSWORD);
verify(passwordSecurity).comparePassword(userPassword, password, name);
- verifyZeroInteractions(dataSource, limboService, authGroupHandler, teleportationService);
+ verifyZeroInteractions(dataSource, limboService, authGroupHandler, teleportationService, bukkitService);
verify(player, only()).getName();
}
@@ -112,6 +118,7 @@ public class AsynchronousUnregisterTest {
verify(teleportationService).teleportOnJoin(player);
verify(authGroupHandler).setGroup(player, AuthGroupType.UNREGISTERED);
verify(bukkitService).scheduleSyncTaskFromOptionallyAsyncTask(any(Runnable.class));
+ verifyCalledUnregisterEventFor(player);
}
@Test
@@ -141,6 +148,7 @@ public class AsynchronousUnregisterTest {
verify(teleportationService).teleportOnJoin(player);
verify(authGroupHandler).setGroup(player, AuthGroupType.UNREGISTERED);
verify(bukkitService).scheduleSyncTaskFromOptionallyAsyncTask(any(Runnable.class));
+ verifyCalledUnregisterEventFor(player);
}
@Test
@@ -169,6 +177,7 @@ public class AsynchronousUnregisterTest {
verify(authGroupHandler).setGroup(player, AuthGroupType.UNREGISTERED);
verifyZeroInteractions(teleportationService, limboService);
verify(bukkitService, never()).runTask(any(Runnable.class));
+ verifyCalledUnregisterEventFor(player);
}
@Test
@@ -218,6 +227,7 @@ public class AsynchronousUnregisterTest {
verify(dataSource).removeAuth(name);
verify(playerCache).removePlayer(name);
verifyZeroInteractions(teleportationService, authGroupHandler);
+ verifyCalledUnregisterEventFor(player);
}
// Initiator known and Player object available
@@ -242,6 +252,7 @@ public class AsynchronousUnregisterTest {
verify(teleportationService).teleportOnJoin(player);
verify(authGroupHandler).setGroup(player, AuthGroupType.UNREGISTERED);
verify(bukkitService).scheduleSyncTaskFromOptionallyAsyncTask(any(Runnable.class));
+ verifyCalledUnregisterEventFor(player);
}
@Test
@@ -257,6 +268,7 @@ public class AsynchronousUnregisterTest {
verify(dataSource).removeAuth(name);
verify(playerCache).removePlayer(name);
verifyZeroInteractions(authGroupHandler, teleportationService);
+ verifyCalledUnregisterEventFor(null);
}
@Test
@@ -272,6 +284,15 @@ public class AsynchronousUnregisterTest {
// then
verify(dataSource).removeAuth(name);
verify(service).send(initiator, MessageKey.ERROR);
- verifyZeroInteractions(playerCache, teleportationService, authGroupHandler);
+ verifyZeroInteractions(playerCache, teleportationService, authGroupHandler, bukkitService);
+ }
+
+ @SuppressWarnings("unchecked")
+ private void verifyCalledUnregisterEventFor(Player player) {
+ ArgumentCaptor