mirror of
https://github.com/AuthMe/AuthMeReloaded.git
synced 2024-11-30 06:03:36 +01:00
#830 Initialize login process with more specific methods (with password vs. force login)
This commit is contained in:
parent
532dbd5921
commit
8d64c0e5bf
@ -157,7 +157,7 @@ public class API {
|
|||||||
* @param player The player to log in
|
* @param player The player to log in
|
||||||
*/
|
*/
|
||||||
public static void forceLogin(Player player) {
|
public static void forceLogin(Player player) {
|
||||||
management.performLogin(player, "dontneed", true);
|
management.forceLogin(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AuthMe getPlugin() {
|
public AuthMe getPlugin() {
|
||||||
|
@ -179,7 +179,7 @@ public class NewAPI {
|
|||||||
* @param player The player to log in
|
* @param player The player to log in
|
||||||
*/
|
*/
|
||||||
public void forceLogin(Player player) {
|
public void forceLogin(Player player) {
|
||||||
management.performLogin(player, "dontneed", true);
|
management.forceLogin(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -37,7 +37,7 @@ public class ForceLoginCommand implements ExecutableCommand {
|
|||||||
} else if (!permissionsManager.hasPermission(player, CAN_LOGIN_BE_FORCED)) {
|
} else if (!permissionsManager.hasPermission(player, CAN_LOGIN_BE_FORCED)) {
|
||||||
sender.sendMessage("You cannot force login the player " + playerName + "!");
|
sender.sendMessage("You cannot force login the player " + playerName + "!");
|
||||||
} else {
|
} else {
|
||||||
management.performLogin(player, "dontneed", true);
|
management.forceLogin(player);
|
||||||
sender.sendMessage("Force login for " + playerName + " performed!");
|
sender.sendMessage("Force login for " + playerName + " performed!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,6 @@ public class LoginCommand extends PlayerCommand {
|
|||||||
@Override
|
@Override
|
||||||
public void runCommand(Player player, List<String> arguments) {
|
public void runCommand(Player player, List<String> arguments) {
|
||||||
final String password = arguments.get(0);
|
final String password = arguments.get(0);
|
||||||
management.performLogin(player, password, false);
|
management.performLogin(player, password);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,8 +47,12 @@ public class Management {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void performLogin(Player player, String password, boolean forceLogin) {
|
public void performLogin(Player player, String password) {
|
||||||
runTask(() -> asynchronousLogin.login(player, password, forceLogin));
|
runTask(() -> asynchronousLogin.login(player, password));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void forceLogin(Player player) {
|
||||||
|
runTask(() -> asynchronousLogin.forceLogin(player));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void performLogout(Player player) {
|
public void performLogout(Player player) {
|
||||||
|
@ -140,7 +140,7 @@ public class AsynchronousJoin implements AsynchronousProcess {
|
|||||||
playerCache.removePlayer(name);
|
playerCache.removePlayer(name);
|
||||||
if (auth != null && auth.getIp().equals(ip)) {
|
if (auth != null && auth.getIp().equals(ip)) {
|
||||||
service.send(player, MessageKey.SESSION_RECONNECTION);
|
service.send(player, MessageKey.SESSION_RECONNECTION);
|
||||||
bukkitService.runTaskOptionallyAsync(() -> asynchronousLogin.login(player, "dontneed", true));
|
bukkitService.runTaskOptionallyAsync(() -> asynchronousLogin.forceLogin(player));
|
||||||
return;
|
return;
|
||||||
} else if (service.getProperty(PluginSettings.SESSIONS_EXPIRE_ON_IP_CHANGE)) {
|
} else if (service.getProperty(PluginSettings.SESSIONS_EXPIRE_ON_IP_CHANGE)) {
|
||||||
service.send(player, MessageKey.SESSION_EXPIRED);
|
service.send(player, MessageKey.SESSION_EXPIRED);
|
||||||
@ -239,12 +239,8 @@ public class AsynchronousJoin implements AsynchronousProcess {
|
|||||||
&& !"localhost".equalsIgnoreCase(ip)
|
&& !"localhost".equalsIgnoreCase(ip)
|
||||||
&& countOnlinePlayersByIp(ip) > service.getProperty(RestrictionSettings.MAX_JOIN_PER_IP)) {
|
&& countOnlinePlayersByIp(ip) > service.getProperty(RestrictionSettings.MAX_JOIN_PER_IP)) {
|
||||||
|
|
||||||
bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(new Runnable() {
|
bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(
|
||||||
@Override
|
() -> player.kickPlayer(service.retrieveSingleMessage(MessageKey.SAME_IP_ONLINE)));
|
||||||
public void run() {
|
|
||||||
player.kickPlayer(service.retrieveSingleMessage(MessageKey.SAME_IP_ONLINE));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package fr.xephi.authme.process.login;
|
package fr.xephi.authme.process.login;
|
||||||
|
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import fr.xephi.authme.ConsoleLogger;
|
import fr.xephi.authme.ConsoleLogger;
|
||||||
import fr.xephi.authme.cache.CaptchaManager;
|
import fr.xephi.authme.cache.CaptchaManager;
|
||||||
import fr.xephi.authme.cache.TempbanManager;
|
import fr.xephi.authme.cache.TempbanManager;
|
||||||
@ -35,11 +36,12 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Asynchronous task for a player login.
|
||||||
*/
|
*/
|
||||||
public class AsynchronousLogin implements AsynchronousProcess {
|
public class AsynchronousLogin implements AsynchronousProcess {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private DataSource database;
|
private DataSource dataSource;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private ProcessService service;
|
private ProcessService service;
|
||||||
@ -71,23 +73,50 @@ public class AsynchronousLogin implements AsynchronousProcess {
|
|||||||
@Inject
|
@Inject
|
||||||
private PlayerDataTaskManager playerDataTaskManager;
|
private PlayerDataTaskManager playerDataTaskManager;
|
||||||
|
|
||||||
AsynchronousLogin() { }
|
AsynchronousLogin() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes a player's login request.
|
||||||
|
*
|
||||||
|
* @param player the player to log in
|
||||||
|
* @param password the password to log in with
|
||||||
|
*/
|
||||||
|
public void login(Player player, String password) {
|
||||||
|
PlayerAuth auth = getPlayerAuth(player);
|
||||||
|
if (auth != null && checkPlayerInfo(player, auth, password)) {
|
||||||
|
performLogin(player, auth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs a player in without requiring a password.
|
||||||
|
*
|
||||||
|
* @param player the player to log in
|
||||||
|
*/
|
||||||
|
public void forceLogin(Player player) {
|
||||||
|
PlayerAuth auth = getPlayerAuth(player);
|
||||||
|
if (auth != null) {
|
||||||
|
performLogin(player, auth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks the precondition for authentication (like user known) and returns
|
* Checks the precondition for authentication (like user known) and returns
|
||||||
* the playerAuth-State
|
* the player's {@link PlayerAuth} object.
|
||||||
*
|
*
|
||||||
* @return PlayerAuth
|
* @return the PlayerAuth object, or {@code null} if the player doesn't exist or may not log in
|
||||||
|
* (e.g. because he is already logged in)
|
||||||
*/
|
*/
|
||||||
private PlayerAuth preAuth(Player player) {
|
private PlayerAuth getPlayerAuth(Player player) {
|
||||||
final String name = player.getName().toLowerCase();
|
final String name = player.getName().toLowerCase();
|
||||||
if (playerCache.isAuthenticated(name)) {
|
if (playerCache.isAuthenticated(name)) {
|
||||||
service.send(player, MessageKey.ALREADY_LOGGED_IN_ERROR);
|
service.send(player, MessageKey.ALREADY_LOGGED_IN_ERROR);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayerAuth pAuth = database.getAuth(name);
|
PlayerAuth auth = dataSource.getAuth(name);
|
||||||
if (pAuth == null) {
|
if (auth == null) {
|
||||||
service.send(player, MessageKey.USER_NOT_REGISTERED);
|
service.send(player, MessageKey.USER_NOT_REGISTERED);
|
||||||
// Recreate the message task to immediately send the message again as response
|
// Recreate the message task to immediately send the message again as response
|
||||||
// and to make sure we send the right register message (password vs. email registration)
|
// and to make sure we send the right register message (password vs. email registration)
|
||||||
@ -96,19 +125,15 @@ public class AsynchronousLogin implements AsynchronousProcess {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!service.getProperty(DatabaseSettings.MYSQL_COL_GROUP).isEmpty()
|
if (!service.getProperty(DatabaseSettings.MYSQL_COL_GROUP).isEmpty()
|
||||||
&& pAuth.getGroupId() == service.getProperty(HooksSettings.NON_ACTIVATED_USERS_GROUP)) {
|
&& auth.getGroupId() == service.getProperty(HooksSettings.NON_ACTIVATED_USERS_GROUP)) {
|
||||||
service.send(player, MessageKey.ACCOUNT_NOT_ACTIVATED);
|
service.send(player, MessageKey.ACCOUNT_NOT_ACTIVATED);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
final String ip = Utils.getPlayerIp(player);
|
final String ip = Utils.getPlayerIp(player);
|
||||||
if (service.getProperty(RestrictionSettings.MAX_LOGIN_PER_IP) > 0
|
if (hasReachedMaxLoggedInPlayersForIp(player, ip)) {
|
||||||
&& !permissionsManager.hasPermission(player, PlayerStatePermission.ALLOW_MULTIPLE_ACCOUNTS)
|
service.send(player, MessageKey.ALREADY_LOGGED_IN_ERROR);
|
||||||
&& !"127.0.0.1".equalsIgnoreCase(ip) && !"localhost".equalsIgnoreCase(ip)) {
|
return null;
|
||||||
if (isLoggedIp(name, ip)) {
|
|
||||||
service.send(player, MessageKey.ALREADY_LOGGED_IN_ERROR);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isAsync = service.getProperty(PluginSettings.USE_ASYNC_TASKS);
|
boolean isAsync = service.getProperty(PluginSettings.USE_ASYNC_TASKS);
|
||||||
@ -117,52 +142,90 @@ public class AsynchronousLogin implements AsynchronousProcess {
|
|||||||
if (!event.canLogin()) {
|
if (!event.canLogin()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return pAuth;
|
return auth;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void login(final Player player, String password, boolean forceLogin) {
|
/**
|
||||||
PlayerAuth pAuth = preAuth(player);
|
* Checks various conditions for regular player login (not used in force login).
|
||||||
if (pAuth == null) {
|
*
|
||||||
return;
|
* @param player the player requesting to log in
|
||||||
}
|
* @param auth the PlayerAuth object of the player
|
||||||
|
* @param password the password supplied by the player
|
||||||
|
* @return true if the password matches and all other conditions are met (e.g. no captcha required),
|
||||||
|
* false otherwise
|
||||||
|
*/
|
||||||
|
private boolean checkPlayerInfo(Player player, PlayerAuth auth, String password) {
|
||||||
final String name = player.getName().toLowerCase();
|
final String name = player.getName().toLowerCase();
|
||||||
|
|
||||||
// If Captcha is required send a message to the player and deny to login
|
// If captcha is required send a message to the player and deny to log in
|
||||||
if (captchaManager.isCaptchaRequired(name)) {
|
if (captchaManager.isCaptchaRequired(name)) {
|
||||||
service.send(player, MessageKey.USAGE_CAPTCHA, captchaManager.getCaptchaCodeOrGenerateNew(name));
|
service.send(player, MessageKey.USAGE_CAPTCHA, captchaManager.getCaptchaCodeOrGenerateNew(name));
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
final String ip = Utils.getPlayerIp(player);
|
final String ip = Utils.getPlayerIp(player);
|
||||||
|
|
||||||
// Increase the counts here before knowing the result of the login.
|
// Increase the counts here before knowing the result of the login.
|
||||||
// If the login is successful, we clear the captcha count for the player.
|
|
||||||
captchaManager.increaseCount(name);
|
captchaManager.increaseCount(name);
|
||||||
tempbanManager.increaseCount(ip, name);
|
tempbanManager.increaseCount(ip, name);
|
||||||
|
|
||||||
String email = pAuth.getEmail();
|
if (passwordSecurity.comparePassword(password, auth.getPassword(), player.getName())) {
|
||||||
boolean passwordVerified = forceLogin || passwordSecurity.comparePassword(
|
return true;
|
||||||
password, pAuth.getPassword(), player.getName());
|
} else {
|
||||||
if (passwordVerified && player.isOnline()) {
|
handleWrongPassword(player, ip);
|
||||||
PlayerAuth auth = PlayerAuth.builder()
|
return false;
|
||||||
.name(name)
|
}
|
||||||
.realName(player.getName())
|
}
|
||||||
.ip(ip)
|
|
||||||
.email(email)
|
|
||||||
.password(pAuth.getPassword())
|
|
||||||
.build();
|
|
||||||
database.updateSession(auth);
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles a login with wrong password.
|
||||||
|
*
|
||||||
|
* @param player the player who attempted to log in
|
||||||
|
* @param ip the ip address of the player
|
||||||
|
*/
|
||||||
|
private void handleWrongPassword(Player player, String ip) {
|
||||||
|
ConsoleLogger.fine(player.getName() + " used the wrong password");
|
||||||
|
if (tempbanManager.shouldTempban(ip)) {
|
||||||
|
tempbanManager.tempbanPlayer(player);
|
||||||
|
} else if (service.getProperty(RestrictionSettings.KICK_ON_WRONG_PASSWORD)) {
|
||||||
|
bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(
|
||||||
|
() -> player.kickPlayer(service.retrieveSingleMessage(MessageKey.WRONG_PASSWORD)));
|
||||||
|
} else {
|
||||||
|
service.send(player, MessageKey.WRONG_PASSWORD);
|
||||||
|
|
||||||
|
// If the authentication fails check if Captcha is required and send a message to the player
|
||||||
|
if (captchaManager.isCaptchaRequired(player.getName())) {
|
||||||
|
service.send(player, MessageKey.USAGE_CAPTCHA,
|
||||||
|
captchaManager.getCaptchaCodeOrGenerateNew(player.getName()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the player to the logged in state.
|
||||||
|
*
|
||||||
|
* @param player the player to log in
|
||||||
|
* @param auth the associated PlayerAuth object
|
||||||
|
*/
|
||||||
|
private void performLogin(Player player, PlayerAuth auth) {
|
||||||
|
if (player.isOnline()) {
|
||||||
|
// Update auth to reflect this new login
|
||||||
|
final String ip = Utils.getPlayerIp(player);
|
||||||
|
auth.setRealName(player.getName());
|
||||||
|
auth.setLastLogin(System.currentTimeMillis());
|
||||||
|
auth.setIp(ip);
|
||||||
|
dataSource.updateSession(auth);
|
||||||
|
|
||||||
|
// Successful login, so reset the captcha & temp ban count
|
||||||
|
final String name = player.getName();
|
||||||
captchaManager.resetCounts(name);
|
captchaManager.resetCounts(name);
|
||||||
tempbanManager.resetCount(ip, name);
|
tempbanManager.resetCount(ip, name);
|
||||||
player.setNoDamageTicks(0);
|
player.setNoDamageTicks(0);
|
||||||
|
|
||||||
if (!forceLogin)
|
service.send(player, MessageKey.LOGIN_SUCCESS);
|
||||||
service.send(player, MessageKey.LOGIN_SUCCESS);
|
|
||||||
|
|
||||||
displayOtherAccounts(auth, player);
|
displayOtherAccounts(auth, player);
|
||||||
|
|
||||||
|
final String email = auth.getEmail();
|
||||||
if (service.getProperty(EmailSettings.RECALL_PLAYERS)
|
if (service.getProperty(EmailSettings.RECALL_PLAYERS)
|
||||||
&& (StringUtils.isEmpty(email) || "your@email.com".equalsIgnoreCase(email))) {
|
&& (StringUtils.isEmpty(email) || "your@email.com".equalsIgnoreCase(email))) {
|
||||||
service.send(player, MessageKey.ADD_EMAIL_MESSAGE);
|
service.send(player, MessageKey.ADD_EMAIL_MESSAGE);
|
||||||
@ -172,7 +235,7 @@ public class AsynchronousLogin implements AsynchronousProcess {
|
|||||||
|
|
||||||
// makes player isLoggedin via API
|
// makes player isLoggedin via API
|
||||||
playerCache.addPlayer(auth);
|
playerCache.addPlayer(auth);
|
||||||
database.setLogged(name);
|
dataSource.setLogged(name);
|
||||||
|
|
||||||
// As the scheduling executes the Task most likely after the current
|
// As the scheduling executes the Task most likely after the current
|
||||||
// task, we schedule it in the end
|
// task, we schedule it in the end
|
||||||
@ -183,23 +246,8 @@ public class AsynchronousLogin implements AsynchronousProcess {
|
|||||||
playerData.clearTasks();
|
playerData.clearTasks();
|
||||||
}
|
}
|
||||||
syncProcessManager.processSyncPlayerLogin(player);
|
syncProcessManager.processSyncPlayerLogin(player);
|
||||||
} else if (player.isOnline()) {
|
|
||||||
ConsoleLogger.fine(player.getName() + " used the wrong password");
|
|
||||||
if (service.getProperty(RestrictionSettings.KICK_ON_WRONG_PASSWORD)) {
|
|
||||||
bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(
|
|
||||||
() -> player.kickPlayer(service.retrieveSingleMessage(MessageKey.WRONG_PASSWORD)));
|
|
||||||
} else if (tempbanManager.shouldTempban(ip)) {
|
|
||||||
tempbanManager.tempbanPlayer(player);
|
|
||||||
} else {
|
|
||||||
service.send(player, MessageKey.WRONG_PASSWORD);
|
|
||||||
|
|
||||||
// If the authentication fails check if Captcha is required and send a message to the player
|
|
||||||
if (captchaManager.isCaptchaRequired(name)) {
|
|
||||||
service.send(player, MessageKey.USAGE_CAPTCHA, captchaManager.getCaptchaCodeOrGenerateNew(name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
ConsoleLogger.warning("Player " + name + " wasn't online during login process, aborted... ");
|
ConsoleLogger.warning("Player '" + player.getName() + "' wasn't online during login process, aborted...");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,7 +256,7 @@ public class AsynchronousLogin implements AsynchronousProcess {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> auths = database.getAllAuthsByIp(auth.getIp());
|
List<String> auths = dataSource.getAllAuthsByIp(auth.getIp());
|
||||||
if (auths.size() <= 1) {
|
if (auths.size() <= 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -217,13 +265,13 @@ public class AsynchronousLogin implements AsynchronousProcess {
|
|||||||
for (String currentName : auths) {
|
for (String currentName : auths) {
|
||||||
Player currentPlayer = bukkitService.getPlayerExact(currentName);
|
Player currentPlayer = bukkitService.getPlayerExact(currentName);
|
||||||
if (currentPlayer != null && currentPlayer.isOnline()) {
|
if (currentPlayer != null && currentPlayer.isOnline()) {
|
||||||
formattedNames.add(ChatColor.GREEN + currentName);
|
formattedNames.add(ChatColor.GREEN + currentPlayer.getName() + ChatColor.GRAY);
|
||||||
} else {
|
} else {
|
||||||
formattedNames.add(currentName);
|
formattedNames.add(currentName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String message = ChatColor.GRAY + StringUtils.join(ChatColor.GRAY + ", ", formattedNames) + ".";
|
String message = ChatColor.GRAY + String.join(", ", formattedNames) + ".";
|
||||||
|
|
||||||
ConsoleLogger.fine("The user " + player.getName() + " has " + auths.size() + " accounts:");
|
ConsoleLogger.fine("The user " + player.getName() + " has " + auths.size() + " accounts:");
|
||||||
ConsoleLogger.fine(message);
|
ConsoleLogger.fine(message);
|
||||||
@ -241,12 +289,31 @@ public class AsynchronousLogin implements AsynchronousProcess {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isLoggedIp(String name, String ip) {
|
/**
|
||||||
|
* Checks whether the maximum threshold of logged in player per IP address has been reached
|
||||||
|
* for the given player and IP address.
|
||||||
|
*
|
||||||
|
* @param player the player to process
|
||||||
|
* @param ip the associated ip address
|
||||||
|
* @return true if the threshold has been reached, false otherwise
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
boolean hasReachedMaxLoggedInPlayersForIp(Player player, String ip) {
|
||||||
|
// Do not perform the check if player has multiple accounts permission or if IP is localhost
|
||||||
|
if (service.getProperty(RestrictionSettings.MAX_LOGIN_PER_IP) <= 0
|
||||||
|
|| permissionsManager.hasPermission(player, PlayerStatePermission.ALLOW_MULTIPLE_ACCOUNTS)
|
||||||
|
|| "127.0.0.1".equalsIgnoreCase(ip)
|
||||||
|
|| "localhost".equalsIgnoreCase(ip)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count logged in players with same IP address
|
||||||
|
final String name = player.getName();
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (Player player : bukkitService.getOnlinePlayers()) {
|
for (Player onlinePlayer : bukkitService.getOnlinePlayers()) {
|
||||||
if (ip.equalsIgnoreCase(Utils.getPlayerIp(player))
|
if (ip.equalsIgnoreCase(Utils.getPlayerIp(onlinePlayer))
|
||||||
&& database.isLogged(player.getName().toLowerCase())
|
&& !onlinePlayer.getName().equals(name)
|
||||||
&& !player.getName().equalsIgnoreCase(name)) {
|
&& dataSource.isLogged(onlinePlayer.getName().toLowerCase())) {
|
||||||
++count;
|
++count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -171,10 +171,9 @@ public class AsyncRegister implements AsynchronousProcess {
|
|||||||
|
|
||||||
if (!service.getProperty(RegistrationSettings.FORCE_LOGIN_AFTER_REGISTER) && autoLogin) {
|
if (!service.getProperty(RegistrationSettings.FORCE_LOGIN_AFTER_REGISTER) && autoLogin) {
|
||||||
if (service.getProperty(PluginSettings.USE_ASYNC_TASKS)) {
|
if (service.getProperty(PluginSettings.USE_ASYNC_TASKS)) {
|
||||||
bukkitService.runTaskAsynchronously(() -> asynchronousLogin.login(player, "dontneed", true));
|
bukkitService.runTaskAsynchronously(() -> asynchronousLogin.forceLogin(player));
|
||||||
} else {
|
} else {
|
||||||
bukkitService.scheduleSyncDelayedTask(
|
bukkitService.scheduleSyncDelayedTask(() -> asynchronousLogin.forceLogin(player), SYNC_LOGIN_DELAY);
|
||||||
() -> asynchronousLogin.login(player, "dontneed", true), SYNC_LOGIN_DELAY);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
syncProcessManager.processSyncPasswordRegister(player);
|
syncProcessManager.processSyncPasswordRegister(player);
|
||||||
|
@ -3,7 +3,6 @@ package fr.xephi.authme.util;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utils class for collections.
|
* Utils class for collections.
|
||||||
@ -60,15 +59,4 @@ public final class CollectionUtils {
|
|||||||
public static boolean isEmpty(Collection<?> coll) {
|
public static boolean isEmpty(Collection<?> coll) {
|
||||||
return coll == null || coll.isEmpty();
|
return coll == null || coll.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> List<T> filterCommonStart(List<T> list1, List<T> list2) {
|
|
||||||
List<T> commonStart = new ArrayList<>();
|
|
||||||
int minSize = Math.min(list1.size(), list2.size());
|
|
||||||
int i = 0;
|
|
||||||
while (i < minSize && Objects.equals(list1.get(i), list2.get(i))) {
|
|
||||||
commonStart.add(list1.get(i));
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
return commonStart;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -17,9 +17,7 @@ import java.util.Collections;
|
|||||||
import static org.hamcrest.Matchers.containsString;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
import static org.hamcrest.Matchers.equalTo;
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
import static org.mockito.BDDMockito.given;
|
import static org.mockito.BDDMockito.given;
|
||||||
import static org.mockito.Matchers.anyString;
|
|
||||||
import static org.mockito.Matchers.argThat;
|
import static org.mockito.Matchers.argThat;
|
||||||
import static org.mockito.Matchers.eq;
|
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||||
@ -107,7 +105,7 @@ public class ForceLoginCommandTest {
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
verify(bukkitService).getPlayerExact(playerName);
|
verify(bukkitService).getPlayerExact(playerName);
|
||||||
verify(management).performLogin(eq(player), anyString(), eq(true));
|
verify(management).forceLogin(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -125,7 +123,7 @@ public class ForceLoginCommandTest {
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
verify(bukkitService).getPlayerExact(senderName);
|
verify(bukkitService).getPlayerExact(senderName);
|
||||||
verify(management).performLogin(eq(player), anyString(), eq(true));
|
verify(management).forceLogin(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Player mockPlayer(boolean isOnline, String name) {
|
private static Player mockPlayer(boolean isOnline, String name) {
|
||||||
|
@ -55,7 +55,7 @@ public class LoginCommandTest {
|
|||||||
command.executeCommand(sender, Collections.singletonList("password"));
|
command.executeCommand(sender, Collections.singletonList("password"));
|
||||||
|
|
||||||
// then
|
// then
|
||||||
verify(management).performLogin(eq(sender), eq("password"), eq(false));
|
verify(management).performLogin(eq(sender), eq("password"));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,280 @@
|
|||||||
|
package fr.xephi.authme.process.login;
|
||||||
|
|
||||||
|
import fr.xephi.authme.TestHelper;
|
||||||
|
import fr.xephi.authme.cache.auth.PlayerAuth;
|
||||||
|
import fr.xephi.authme.cache.auth.PlayerCache;
|
||||||
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
|
import fr.xephi.authme.events.AuthMeAsyncPreLoginEvent;
|
||||||
|
import fr.xephi.authme.output.MessageKey;
|
||||||
|
import fr.xephi.authme.permission.PermissionsManager;
|
||||||
|
import fr.xephi.authme.permission.PlayerStatePermission;
|
||||||
|
import fr.xephi.authme.process.ProcessService;
|
||||||
|
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
||||||
|
import fr.xephi.authme.settings.properties.HooksSettings;
|
||||||
|
import fr.xephi.authme.settings.properties.PluginSettings;
|
||||||
|
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
||||||
|
import fr.xephi.authme.task.PlayerDataTaskManager;
|
||||||
|
import fr.xephi.authme.util.BukkitService;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.InjectMocks;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.Spy;
|
||||||
|
import org.mockito.invocation.InvocationOnMock;
|
||||||
|
import org.mockito.runners.MockitoJUnitRunner;
|
||||||
|
import org.mockito.stubbing.Answer;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
import static org.mockito.BDDMockito.given;
|
||||||
|
import static org.mockito.Matchers.any;
|
||||||
|
import static org.mockito.Matchers.anyString;
|
||||||
|
import static org.mockito.Mockito.doAnswer;
|
||||||
|
import static org.mockito.Mockito.doReturn;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||||
|
import static org.mockito.internal.verification.VerificationModeFactory.only;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for {@link AsynchronousLogin}.
|
||||||
|
*/
|
||||||
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
|
public class AsynchronousLoginTest {
|
||||||
|
|
||||||
|
@InjectMocks
|
||||||
|
@Spy
|
||||||
|
private AsynchronousLogin asynchronousLogin;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private DataSource dataSource;
|
||||||
|
@Mock
|
||||||
|
private PlayerCache playerCache;
|
||||||
|
@Mock
|
||||||
|
private ProcessService processService;
|
||||||
|
@Mock
|
||||||
|
private PlayerDataTaskManager playerDataTaskManager;
|
||||||
|
@Mock
|
||||||
|
private BukkitService bukkitService;
|
||||||
|
@Mock
|
||||||
|
private PermissionsManager permissionsManager;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void initLogger() {
|
||||||
|
TestHelper.setupLogger();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldNotForceLoginAlreadyLoggedInPlayer() {
|
||||||
|
// given
|
||||||
|
String name = "bobby";
|
||||||
|
Player player = mockPlayer(name);
|
||||||
|
given(playerCache.isAuthenticated(name)).willReturn(true);
|
||||||
|
|
||||||
|
// when
|
||||||
|
asynchronousLogin.forceLogin(player);
|
||||||
|
|
||||||
|
// then
|
||||||
|
verify(playerCache, only()).isAuthenticated(name);
|
||||||
|
verify(processService).send(player, MessageKey.ALREADY_LOGGED_IN_ERROR);
|
||||||
|
verifyZeroInteractions(dataSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldNotForceLoginNonExistentUser() {
|
||||||
|
// given
|
||||||
|
String name = "oscar";
|
||||||
|
Player player = mockPlayer(name);
|
||||||
|
given(playerCache.isAuthenticated(name)).willReturn(false);
|
||||||
|
given(dataSource.getAuth(name)).willReturn(null);
|
||||||
|
|
||||||
|
// when
|
||||||
|
asynchronousLogin.forceLogin(player);
|
||||||
|
|
||||||
|
// then
|
||||||
|
verify(playerCache, only()).isAuthenticated(name);
|
||||||
|
verify(processService).send(player, MessageKey.USER_NOT_REGISTERED);
|
||||||
|
verify(dataSource, only()).getAuth(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldNotForceLoginInactiveUser() {
|
||||||
|
// given
|
||||||
|
String name = "oscar";
|
||||||
|
Player player = mockPlayer(name);
|
||||||
|
given(playerCache.isAuthenticated(name)).willReturn(false);
|
||||||
|
int groupId = 13;
|
||||||
|
PlayerAuth auth = PlayerAuth.builder().name(name).groupId(groupId).build();
|
||||||
|
given(dataSource.getAuth(name)).willReturn(auth);
|
||||||
|
given(processService.getProperty(DatabaseSettings.MYSQL_COL_GROUP)).willReturn("group");
|
||||||
|
given(processService.getProperty(HooksSettings.NON_ACTIVATED_USERS_GROUP)).willReturn(groupId);
|
||||||
|
|
||||||
|
// when
|
||||||
|
asynchronousLogin.forceLogin(player);
|
||||||
|
|
||||||
|
// then
|
||||||
|
verify(playerCache, only()).isAuthenticated(name);
|
||||||
|
verify(processService).send(player, MessageKey.ACCOUNT_NOT_ACTIVATED);
|
||||||
|
verify(dataSource, only()).getAuth(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldNotForceLoginUserWithAlreadyOnlineIp() {
|
||||||
|
// given
|
||||||
|
String name = "oscar";
|
||||||
|
String ip = "127.0.12.245";
|
||||||
|
Player player = mockPlayer(name);
|
||||||
|
TestHelper.mockPlayerIp(player, ip);
|
||||||
|
given(playerCache.isAuthenticated(name)).willReturn(false);
|
||||||
|
PlayerAuth auth = PlayerAuth.builder().name(name).build();
|
||||||
|
given(dataSource.getAuth(name)).willReturn(auth);
|
||||||
|
given(processService.getProperty(DatabaseSettings.MYSQL_COL_GROUP)).willReturn("");
|
||||||
|
doReturn(true).when(asynchronousLogin).hasReachedMaxLoggedInPlayersForIp(any(Player.class), anyString());
|
||||||
|
|
||||||
|
// when
|
||||||
|
asynchronousLogin.forceLogin(player);
|
||||||
|
|
||||||
|
// then
|
||||||
|
verify(playerCache, only()).isAuthenticated(name);
|
||||||
|
verify(processService).send(player, MessageKey.ALREADY_LOGGED_IN_ERROR);
|
||||||
|
verify(dataSource, only()).getAuth(name);
|
||||||
|
verify(asynchronousLogin).hasReachedMaxLoggedInPlayersForIp(player, ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldNotForceLoginForCanceledEvent() {
|
||||||
|
// given
|
||||||
|
String name = "oscar";
|
||||||
|
String ip = "127.0.12.245";
|
||||||
|
Player player = mockPlayer(name);
|
||||||
|
TestHelper.mockPlayerIp(player, ip);
|
||||||
|
given(playerCache.isAuthenticated(name)).willReturn(false);
|
||||||
|
PlayerAuth auth = PlayerAuth.builder().name(name).build();
|
||||||
|
given(dataSource.getAuth(name)).willReturn(auth);
|
||||||
|
given(processService.getProperty(DatabaseSettings.MYSQL_COL_GROUP)).willReturn("");
|
||||||
|
given(processService.getProperty(PluginSettings.USE_ASYNC_TASKS)).willReturn(true);
|
||||||
|
doReturn(false).when(asynchronousLogin).hasReachedMaxLoggedInPlayersForIp(any(Player.class), anyString());
|
||||||
|
doAnswer(new Answer<Void>() {
|
||||||
|
@Override
|
||||||
|
public Void answer(InvocationOnMock invocation) throws Throwable {
|
||||||
|
invocation.getArgumentAt(0, AuthMeAsyncPreLoginEvent.class).setCanLogin(false);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}).when(bukkitService).callEvent(any(AuthMeAsyncPreLoginEvent.class));
|
||||||
|
|
||||||
|
// when
|
||||||
|
asynchronousLogin.forceLogin(player);
|
||||||
|
|
||||||
|
// then
|
||||||
|
verify(playerCache, only()).isAuthenticated(name);
|
||||||
|
verify(dataSource, only()).getAuth(name);
|
||||||
|
verify(asynchronousLogin).hasReachedMaxLoggedInPlayersForIp(player, ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldPassMaxLoginPerIpCheck() {
|
||||||
|
// given
|
||||||
|
Player player = mockPlayer("Carl");
|
||||||
|
given(processService.getProperty(RestrictionSettings.MAX_LOGIN_PER_IP)).willReturn(2);
|
||||||
|
given(permissionsManager.hasPermission(player, PlayerStatePermission.ALLOW_MULTIPLE_ACCOUNTS)).willReturn(false);
|
||||||
|
mockOnlinePlayersInBukkitService();
|
||||||
|
|
||||||
|
// when
|
||||||
|
boolean result = asynchronousLogin.hasReachedMaxLoggedInPlayersForIp(player, "127.0.0.4");
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(result, equalTo(false));
|
||||||
|
verify(permissionsManager).hasPermission(player, PlayerStatePermission.ALLOW_MULTIPLE_ACCOUNTS);
|
||||||
|
verify(bukkitService).getOnlinePlayers();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldSkipIpCheckForZeroThreshold() {
|
||||||
|
// given
|
||||||
|
Player player = mockPlayer("Fiona");
|
||||||
|
given(processService.getProperty(RestrictionSettings.MAX_LOGIN_PER_IP)).willReturn(0);
|
||||||
|
|
||||||
|
// when
|
||||||
|
boolean result = asynchronousLogin.hasReachedMaxLoggedInPlayersForIp(player, "192.168.0.1");
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(result, equalTo(false));
|
||||||
|
verifyZeroInteractions(bukkitService);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldSkipIpCheckForPlayerWithMultipleAccountsPermission() {
|
||||||
|
// given
|
||||||
|
Player player = mockPlayer("Frank");
|
||||||
|
given(processService.getProperty(RestrictionSettings.MAX_LOGIN_PER_IP)).willReturn(1);
|
||||||
|
given(permissionsManager.hasPermission(player, PlayerStatePermission.ALLOW_MULTIPLE_ACCOUNTS)).willReturn(true);
|
||||||
|
|
||||||
|
// when
|
||||||
|
boolean result = asynchronousLogin.hasReachedMaxLoggedInPlayersForIp(player, "127.0.0.4");
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(result, equalTo(false));
|
||||||
|
verify(permissionsManager).hasPermission(player, PlayerStatePermission.ALLOW_MULTIPLE_ACCOUNTS);
|
||||||
|
verifyZeroInteractions(bukkitService);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldFailIpCheckForIpWithTooManyPlayersOnline() {
|
||||||
|
// given
|
||||||
|
Player player = mockPlayer("Ian");
|
||||||
|
given(processService.getProperty(RestrictionSettings.MAX_LOGIN_PER_IP)).willReturn(2);
|
||||||
|
given(permissionsManager.hasPermission(player, PlayerStatePermission.ALLOW_MULTIPLE_ACCOUNTS)).willReturn(false);
|
||||||
|
mockOnlinePlayersInBukkitService();
|
||||||
|
|
||||||
|
// when
|
||||||
|
boolean result = asynchronousLogin.hasReachedMaxLoggedInPlayersForIp(player, "192.168.0.1");
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(result, equalTo(true));
|
||||||
|
verify(permissionsManager).hasPermission(player, PlayerStatePermission.ALLOW_MULTIPLE_ACCOUNTS);
|
||||||
|
verify(bukkitService).getOnlinePlayers();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Player mockPlayer(String name) {
|
||||||
|
Player player = mock(Player.class);
|
||||||
|
given(player.getName()).willReturn(name);
|
||||||
|
return player;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private void mockOnlinePlayersInBukkitService() {
|
||||||
|
// 127.0.0.4: albania (online), brazil (offline)
|
||||||
|
Player playerA = mockPlayer("albania");
|
||||||
|
TestHelper.mockPlayerIp(playerA, "127.0.0.4");
|
||||||
|
given(dataSource.isLogged(playerA.getName())).willReturn(true);
|
||||||
|
Player playerB = mockPlayer("brazil");
|
||||||
|
TestHelper.mockPlayerIp(playerB, "127.0.0.4");
|
||||||
|
given(dataSource.isLogged(playerB.getName())).willReturn(false);
|
||||||
|
|
||||||
|
// 192.168.0.1: congo (online), denmark (offline), ecuador (online)
|
||||||
|
Player playerC = mockPlayer("congo");
|
||||||
|
TestHelper.mockPlayerIp(playerC, "192.168.0.1");
|
||||||
|
given(dataSource.isLogged(playerC.getName())).willReturn(true);
|
||||||
|
Player playerD = mockPlayer("denmark");
|
||||||
|
TestHelper.mockPlayerIp(playerD, "192.168.0.1");
|
||||||
|
given(dataSource.isLogged(playerD.getName())).willReturn(false);
|
||||||
|
Player playerE = mockPlayer("ecuador");
|
||||||
|
TestHelper.mockPlayerIp(playerE, "192.168.0.1");
|
||||||
|
given(dataSource.isLogged(playerE.getName())).willReturn(true);
|
||||||
|
|
||||||
|
// 192.168.0.0: france (offline)
|
||||||
|
Player playerF = mockPlayer("france");
|
||||||
|
TestHelper.mockPlayerIp(playerF, "192.168.0.0");
|
||||||
|
given(dataSource.isLogged(playerF.getName())).willReturn(false);
|
||||||
|
|
||||||
|
Collection onlinePlayers = Arrays.asList(playerA, playerB, playerC, playerD, playerE, playerF);
|
||||||
|
given(bukkitService.getOnlinePlayers()).willReturn(onlinePlayers);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user