Del all files
This commit is contained in:
@@ -1,10 +0,0 @@
|
||||
package fr.xephi.authme.process;
|
||||
|
||||
/**
|
||||
* Marker interface for asynchronous AuthMe processes.
|
||||
* <p>
|
||||
* These processes handle intensive (I/O or otherwise) actions and are
|
||||
* therefore scheduled to run asynchronously.
|
||||
*/
|
||||
public interface AsynchronousProcess {
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
package fr.xephi.authme.process;
|
||||
|
||||
import fr.xephi.authme.process.changepassword.AsyncChangePassword;
|
||||
import fr.xephi.authme.process.email.AsyncAddEmail;
|
||||
import fr.xephi.authme.process.email.AsyncChangeEmail;
|
||||
import fr.xephi.authme.process.join.AsynchronousJoin;
|
||||
import fr.xephi.authme.process.login.AsynchronousLogin;
|
||||
import fr.xephi.authme.process.logout.AsynchronousLogout;
|
||||
import fr.xephi.authme.process.quit.AsynchronousQuit;
|
||||
import fr.xephi.authme.process.register.AsyncRegister;
|
||||
import fr.xephi.authme.process.register.executors.RegistrationMethod;
|
||||
import fr.xephi.authme.process.register.executors.RegistrationParameters;
|
||||
import fr.xephi.authme.process.unregister.AsynchronousUnregister;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* Performs auth actions, e.g. when a player joins, registers or wants to change his password.
|
||||
*/
|
||||
public class Management {
|
||||
|
||||
@Inject
|
||||
private BukkitService bukkitService;
|
||||
|
||||
// Processes
|
||||
@Inject
|
||||
private AsyncAddEmail asyncAddEmail;
|
||||
@Inject
|
||||
private AsyncChangeEmail asyncChangeEmail;
|
||||
@Inject
|
||||
private AsynchronousLogout asynchronousLogout;
|
||||
@Inject
|
||||
private AsynchronousQuit asynchronousQuit;
|
||||
@Inject
|
||||
private AsynchronousJoin asynchronousJoin;
|
||||
@Inject
|
||||
private AsyncRegister asyncRegister;
|
||||
@Inject
|
||||
private AsynchronousLogin asynchronousLogin;
|
||||
@Inject
|
||||
private AsynchronousUnregister asynchronousUnregister;
|
||||
@Inject
|
||||
private AsyncChangePassword asyncChangePassword;
|
||||
|
||||
Management() {
|
||||
}
|
||||
|
||||
|
||||
public void performLogin(Player player, String password) {
|
||||
runTask(() -> asynchronousLogin.login(player, password));
|
||||
}
|
||||
|
||||
public void forceLogin(Player player) {
|
||||
runTask(() -> asynchronousLogin.forceLogin(player,0));
|
||||
}
|
||||
|
||||
public void forceLogin(Player player, boolean quiet) {
|
||||
runTask(() -> asynchronousLogin.forceLogin(player, quiet));
|
||||
}
|
||||
|
||||
public void performLogout(Player player) {
|
||||
runTask(() -> asynchronousLogout.logout(player));
|
||||
}
|
||||
|
||||
public <P extends RegistrationParameters> void performRegister(RegistrationMethod<P> variant, P parameters) {
|
||||
runTask(() -> asyncRegister.register(variant, parameters));
|
||||
}
|
||||
|
||||
public void performUnregister(Player player, String password) {
|
||||
runTask(() -> asynchronousUnregister.unregister(player, password));
|
||||
}
|
||||
|
||||
public void performUnregisterByAdmin(CommandSender initiator, String name, Player player) {
|
||||
runTask(() -> asynchronousUnregister.adminUnregister(initiator, name, player));
|
||||
}
|
||||
|
||||
public void performJoin(Player player) {
|
||||
runTask(() -> asynchronousJoin.processJoin(player));
|
||||
}
|
||||
|
||||
public void performQuit(Player player) {
|
||||
runTask(() -> asynchronousQuit.processQuit(player));
|
||||
}
|
||||
|
||||
public void performAddEmail(Player player, String newEmail) {
|
||||
runTask(() -> asyncAddEmail.addEmail(player, newEmail));
|
||||
}
|
||||
|
||||
public void performChangeEmail(Player player, String oldEmail, String newEmail) {
|
||||
runTask(() -> asyncChangeEmail.changeEmail(player, oldEmail, newEmail));
|
||||
}
|
||||
|
||||
public void performPasswordChange(Player player, String oldPassword, String newPassword) {
|
||||
runTask(() -> asyncChangePassword.changePassword(player, oldPassword, newPassword));
|
||||
}
|
||||
|
||||
public void performPasswordChangeAsAdmin(CommandSender sender, String playerName, String newPassword) {
|
||||
runTask(() -> asyncChangePassword.changePasswordAsAdmin(sender, playerName, newPassword));
|
||||
}
|
||||
|
||||
private void runTask(Runnable runnable) {
|
||||
bukkitService.runTaskOptionallyAsync(runnable);
|
||||
}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
package fr.xephi.authme.process;
|
||||
|
||||
import fr.xephi.authme.process.login.ProcessSyncPlayerLogin;
|
||||
import fr.xephi.authme.process.logout.ProcessSyncPlayerLogout;
|
||||
import fr.xephi.authme.process.quit.ProcessSyncPlayerQuit;
|
||||
import fr.xephi.authme.process.register.ProcessSyncEmailRegister;
|
||||
import fr.xephi.authme.process.register.ProcessSyncPasswordRegister;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Manager for scheduling synchronous processes internally from the asynchronous processes.
|
||||
* These synchronous processes are a continuation of the associated async processes; they only
|
||||
* contain certain tasks which may only be run synchronously (most interactions with Bukkit).
|
||||
* These synchronous tasks should never be called aside from the asynchronous processes.
|
||||
*
|
||||
* @see Management
|
||||
*/
|
||||
public class SyncProcessManager {
|
||||
|
||||
@Inject
|
||||
private BukkitService bukkitService;
|
||||
|
||||
@Inject
|
||||
private ProcessSyncEmailRegister processSyncEmailRegister;
|
||||
@Inject
|
||||
private ProcessSyncPasswordRegister processSyncPasswordRegister;
|
||||
@Inject
|
||||
private ProcessSyncPlayerLogin processSyncPlayerLogin;
|
||||
@Inject
|
||||
private ProcessSyncPlayerLogout processSyncPlayerLogout;
|
||||
@Inject
|
||||
private ProcessSyncPlayerQuit processSyncPlayerQuit;
|
||||
|
||||
|
||||
public void processSyncEmailRegister(Player player) {
|
||||
runTask(() -> processSyncEmailRegister.processEmailRegister(player));
|
||||
}
|
||||
|
||||
public void processSyncPasswordRegister(Player player) {
|
||||
runTask(() -> processSyncPasswordRegister.processPasswordRegister(player));
|
||||
}
|
||||
|
||||
public void processSyncPlayerLogout(Player player) {
|
||||
runTask(() -> processSyncPlayerLogout.processSyncLogout(player));
|
||||
}
|
||||
|
||||
public void processSyncPlayerLogin(Player player, boolean isFirstLogin, List<String> authsWithSameIp) {
|
||||
runTask(() -> processSyncPlayerLogin.processPlayerLogin(player, isFirstLogin, authsWithSameIp));
|
||||
}
|
||||
|
||||
public void processSyncPlayerQuit(Player player, boolean wasLoggedIn) {
|
||||
runTask(() -> processSyncPlayerQuit.processSyncQuit(player, wasLoggedIn));
|
||||
}
|
||||
|
||||
private void runTask(Runnable runnable) {
|
||||
bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(runnable);
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package fr.xephi.authme.process;
|
||||
|
||||
/**
|
||||
* Marker interface for synchronous processes.
|
||||
* <p>
|
||||
* Such processes are scheduled by {@link AsynchronousProcess asynchronous tasks} to perform tasks
|
||||
* which are required to be executed synchronously (e.g. interactions with the Bukkit API).
|
||||
*/
|
||||
public interface SynchronousProcess {
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
package fr.xephi.authme.process.changepassword;
|
||||
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.data.auth.PlayerCache;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.process.AsynchronousProcess;
|
||||
import fr.xephi.authme.security.PasswordSecurity;
|
||||
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Locale;
|
||||
|
||||
public class AsyncChangePassword implements AsynchronousProcess {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(AsyncChangePassword.class);
|
||||
|
||||
@Inject
|
||||
private DataSource dataSource;
|
||||
|
||||
@Inject
|
||||
private CommonService commonService;
|
||||
|
||||
@Inject
|
||||
private PasswordSecurity passwordSecurity;
|
||||
|
||||
@Inject
|
||||
private PlayerCache playerCache;
|
||||
|
||||
AsyncChangePassword() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Change password for an online player
|
||||
*
|
||||
* @param player the player
|
||||
* @param oldPassword the old password used by the player
|
||||
* @param newPassword the new password chosen by the player
|
||||
*/
|
||||
public void changePassword(Player player, String oldPassword, String newPassword) {
|
||||
String name = player.getName().toLowerCase(Locale.ROOT);
|
||||
PlayerAuth auth = playerCache.getAuth(name);
|
||||
if (passwordSecurity.comparePassword(oldPassword, auth.getPassword(), player.getName())) {
|
||||
HashedPassword hashedPassword = passwordSecurity.computeHash(newPassword, name);
|
||||
auth.setPassword(hashedPassword);
|
||||
|
||||
if (!dataSource.updatePassword(auth)) {
|
||||
commonService.send(player, MessageKey.ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: send an update when a messaging service will be implemented (PASSWORD_CHANGED)
|
||||
|
||||
playerCache.updatePlayer(auth);
|
||||
commonService.send(player, MessageKey.PASSWORD_CHANGED_SUCCESS);
|
||||
logger.info(player.getName() + " changed his password");
|
||||
} else {
|
||||
commonService.send(player, MessageKey.WRONG_PASSWORD);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Change a user's password as an administrator, without asking for the previous one
|
||||
*
|
||||
* @param sender who is performing the operation, null if called by other plugins
|
||||
* @param playerName the player name
|
||||
* @param newPassword the new password chosen for the player
|
||||
*/
|
||||
public void changePasswordAsAdmin(CommandSender sender, String playerName, String newPassword) {
|
||||
String lowerCaseName = playerName.toLowerCase(Locale.ROOT);
|
||||
if (!(playerCache.isAuthenticated(lowerCaseName) || dataSource.isAuthAvailable(lowerCaseName))) {
|
||||
if (sender == null) {
|
||||
logger.warning("Tried to change password for user " + lowerCaseName + " but it doesn't exist!");
|
||||
} else {
|
||||
commonService.send(sender, MessageKey.UNKNOWN_USER);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
HashedPassword hashedPassword = passwordSecurity.computeHash(newPassword, lowerCaseName);
|
||||
if (dataSource.updatePassword(lowerCaseName, hashedPassword)) {
|
||||
// TODO: send an update when a messaging service will be implemented (PASSWORD_CHANGED)
|
||||
|
||||
if (sender != null) {
|
||||
commonService.send(sender, MessageKey.PASSWORD_CHANGED_SUCCESS);
|
||||
logger.info(sender.getName() + " changed password of " + lowerCaseName);
|
||||
} else {
|
||||
logger.info("Changed password of " + lowerCaseName);
|
||||
}
|
||||
} else {
|
||||
if (sender != null) {
|
||||
commonService.send(sender, MessageKey.ERROR);
|
||||
}
|
||||
logger.warning("An error occurred while changing password for user " + lowerCaseName + "!");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
package fr.xephi.authme.process.email;
|
||||
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.data.auth.PlayerCache;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.events.EmailChangedEvent;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.process.AsynchronousProcess;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.service.ValidationService;
|
||||
import fr.xephi.authme.util.Utils;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Async task to add an email to an account.
|
||||
*/
|
||||
public class AsyncAddEmail implements AsynchronousProcess {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(AsyncAddEmail.class);
|
||||
|
||||
@Inject
|
||||
private CommonService service;
|
||||
|
||||
@Inject
|
||||
private DataSource dataSource;
|
||||
|
||||
@Inject
|
||||
private PlayerCache playerCache;
|
||||
|
||||
@Inject
|
||||
private ValidationService validationService;
|
||||
|
||||
@Inject
|
||||
private BukkitService bukkitService;
|
||||
|
||||
AsyncAddEmail() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the request to add the given email to the player's account.
|
||||
*
|
||||
* @param player the player to add the email to
|
||||
* @param email the email to add
|
||||
*/
|
||||
public void addEmail(Player player, String email) {
|
||||
String playerName = player.getName().toLowerCase(Locale.ROOT);
|
||||
|
||||
if (playerCache.isAuthenticated(playerName)) {
|
||||
PlayerAuth auth = playerCache.getAuth(playerName);
|
||||
String currentEmail = auth.getEmail();
|
||||
|
||||
if (!Utils.isEmailEmpty(currentEmail)) {
|
||||
service.send(player, MessageKey.USAGE_CHANGE_EMAIL);
|
||||
} else if (!validationService.validateEmail(email)) {
|
||||
service.send(player, MessageKey.INVALID_EMAIL);
|
||||
} else if (!validationService.isEmailFreeForRegistration(email, player)) {
|
||||
service.send(player, MessageKey.EMAIL_ALREADY_USED_ERROR);
|
||||
} else {
|
||||
EmailChangedEvent event = bukkitService.createAndCallEvent(isAsync
|
||||
-> new EmailChangedEvent(player, null, email, isAsync));
|
||||
if (event.isCancelled()) {
|
||||
logger.info("Could not add email to player '" + player + "' – event was cancelled");
|
||||
service.send(player, MessageKey.EMAIL_ADD_NOT_ALLOWED);
|
||||
return;
|
||||
}
|
||||
auth.setEmail(email);
|
||||
if (dataSource.updateEmail(auth)) {
|
||||
playerCache.updatePlayer(auth);
|
||||
// TODO: send an update when a messaging service will be implemented (ADD_MAIL)
|
||||
service.send(player, MessageKey.EMAIL_ADDED_SUCCESS);
|
||||
} else {
|
||||
logger.warning("Could not save email for player '" + player + "'");
|
||||
service.send(player, MessageKey.ERROR);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sendUnloggedMessage(player);
|
||||
}
|
||||
}
|
||||
|
||||
private void sendUnloggedMessage(Player player) {
|
||||
if (dataSource.isAuthAvailable(player.getName())) {
|
||||
service.send(player, MessageKey.LOGIN_MESSAGE);
|
||||
} else {
|
||||
service.send(player, MessageKey.REGISTER_MESSAGE);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
package fr.xephi.authme.process.email;
|
||||
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.data.auth.PlayerCache;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.events.EmailChangedEvent;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.process.AsynchronousProcess;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.service.ValidationService;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Async task for changing the email.
|
||||
*/
|
||||
public class AsyncChangeEmail implements AsynchronousProcess {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(AsyncChangeEmail.class);
|
||||
|
||||
@Inject
|
||||
private CommonService service;
|
||||
|
||||
@Inject
|
||||
private PlayerCache playerCache;
|
||||
|
||||
@Inject
|
||||
private DataSource dataSource;
|
||||
|
||||
@Inject
|
||||
private ValidationService validationService;
|
||||
|
||||
@Inject
|
||||
private BukkitService bukkitService;
|
||||
|
||||
AsyncChangeEmail() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the request to change the player's email address.
|
||||
*
|
||||
* @param player the player to change the email for
|
||||
* @param oldEmail provided old email
|
||||
* @param newEmail provided new email
|
||||
*/
|
||||
public void changeEmail(Player player, String oldEmail, String newEmail) {
|
||||
String playerName = player.getName().toLowerCase(Locale.ROOT);
|
||||
if (playerCache.isAuthenticated(playerName)) {
|
||||
PlayerAuth auth = playerCache.getAuth(playerName);
|
||||
String currentEmail = auth.getEmail();
|
||||
|
||||
if (currentEmail == null) {
|
||||
service.send(player, MessageKey.USAGE_ADD_EMAIL);
|
||||
} else if (newEmail == null || !validationService.validateEmail(newEmail)) {
|
||||
service.send(player, MessageKey.INVALID_NEW_EMAIL);
|
||||
} else if (!oldEmail.equalsIgnoreCase(currentEmail)) {
|
||||
service.send(player, MessageKey.INVALID_OLD_EMAIL);
|
||||
} else if (!validationService.isEmailFreeForRegistration(newEmail, player)) {
|
||||
service.send(player, MessageKey.EMAIL_ALREADY_USED_ERROR);
|
||||
} else {
|
||||
saveNewEmail(auth, player, oldEmail, newEmail);
|
||||
}
|
||||
} else {
|
||||
outputUnloggedMessage(player);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the new email value into the database and informs services.
|
||||
*
|
||||
* @param auth the player auth object
|
||||
* @param player the player object
|
||||
* @param oldEmail the old email value
|
||||
* @param newEmail the new email value
|
||||
*/
|
||||
private void saveNewEmail(PlayerAuth auth, Player player, String oldEmail, String newEmail) {
|
||||
EmailChangedEvent event = bukkitService.createAndCallEvent(isAsync
|
||||
-> new EmailChangedEvent(player, oldEmail, newEmail, isAsync));
|
||||
if (event.isCancelled()) {
|
||||
logger.info("Could not change email for player '" + player + "' – event was cancelled");
|
||||
service.send(player, MessageKey.EMAIL_CHANGE_NOT_ALLOWED);
|
||||
return;
|
||||
}
|
||||
|
||||
auth.setEmail(newEmail);
|
||||
if (dataSource.updateEmail(auth)) {
|
||||
playerCache.updatePlayer(auth);
|
||||
// TODO: send an update when a messaging service will be implemented (CHANGE_MAIL)
|
||||
service.send(player, MessageKey.EMAIL_CHANGED_SUCCESS);
|
||||
} else {
|
||||
service.send(player, MessageKey.ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
private void outputUnloggedMessage(Player player) {
|
||||
if (dataSource.isAuthAvailable(player.getName())) {
|
||||
service.send(player, MessageKey.LOGIN_MESSAGE);
|
||||
} else {
|
||||
service.send(player, MessageKey.REGISTER_MESSAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,228 +0,0 @@
|
||||
package fr.xephi.authme.process.join;
|
||||
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.data.ProxySessionManager;
|
||||
import fr.xephi.authme.data.limbo.LimboService;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.events.ProtectInventoryEvent;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.permission.PlayerStatePermission;
|
||||
import fr.xephi.authme.process.AsynchronousProcess;
|
||||
import fr.xephi.authme.process.login.AsynchronousLogin;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.service.PluginHookService;
|
||||
import fr.xephi.authme.service.SessionService;
|
||||
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.commandconfig.CommandManager;
|
||||
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.InternetProtocolUtils;
|
||||
import fr.xephi.authme.util.PlayerUtils;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Locale;
|
||||
|
||||
import static fr.xephi.authme.service.BukkitService.TICKS_PER_SECOND;
|
||||
import static fr.xephi.authme.settings.properties.RestrictionSettings.PROTECT_INVENTORY_BEFORE_LOGIN;
|
||||
|
||||
/**
|
||||
* Asynchronous process for when a player joins.
|
||||
*/
|
||||
public class AsynchronousJoin implements AsynchronousProcess {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(AsynchronousJoin.class);
|
||||
|
||||
@Inject
|
||||
private Server server;
|
||||
|
||||
@Inject
|
||||
private DataSource database;
|
||||
|
||||
@Inject
|
||||
private CommonService service;
|
||||
|
||||
@Inject
|
||||
private LimboService limboService;
|
||||
|
||||
@Inject
|
||||
private PluginHookService pluginHookService;
|
||||
|
||||
@Inject
|
||||
private BukkitService bukkitService;
|
||||
|
||||
@Inject
|
||||
private AsynchronousLogin asynchronousLogin;
|
||||
|
||||
@Inject
|
||||
private CommandManager commandManager;
|
||||
|
||||
@Inject
|
||||
private ValidationService validationService;
|
||||
|
||||
@Inject
|
||||
private SessionService sessionService;
|
||||
|
||||
@Inject
|
||||
private BungeeSender bungeeSender;
|
||||
|
||||
@Inject
|
||||
private ProxySessionManager proxySessionManager;
|
||||
|
||||
AsynchronousJoin() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the given player that has just joined.
|
||||
*
|
||||
* @param player the player to process
|
||||
*/
|
||||
public void processJoin(Player player) {
|
||||
String name = player.getName().toLowerCase(Locale.ROOT);
|
||||
String ip = PlayerUtils.getPlayerIp(player);
|
||||
|
||||
if (!validationService.fulfillsNameRestrictions(player)) {
|
||||
handlePlayerWithUnmetNameRestriction(player, ip);
|
||||
return;
|
||||
}
|
||||
|
||||
if (service.getProperty(RestrictionSettings.UNRESTRICTED_NAMES).contains(name)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (service.getProperty(RestrictionSettings.FORCE_SURVIVAL_MODE)
|
||||
&& player.getGameMode() != GameMode.SURVIVAL
|
||||
&& !service.hasPermission(player, PlayerStatePermission.BYPASS_FORCE_SURVIVAL)) {
|
||||
bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(() -> player.setGameMode(GameMode.SURVIVAL));
|
||||
}
|
||||
|
||||
if (service.getProperty(HooksSettings.DISABLE_SOCIAL_SPY)) {
|
||||
pluginHookService.setEssentialsSocialSpyStatus(player, false);
|
||||
}
|
||||
|
||||
if (!validatePlayerCountForIp(player, ip)) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean isAuthAvailable = database.isAuthAvailable(name);
|
||||
|
||||
if (isAuthAvailable) {
|
||||
// Protect inventory
|
||||
if (service.getProperty(PROTECT_INVENTORY_BEFORE_LOGIN)) {
|
||||
ProtectInventoryEvent ev = bukkitService.createAndCallEvent(
|
||||
isAsync -> new ProtectInventoryEvent(player, isAsync));
|
||||
if (ev.isCancelled()) {
|
||||
player.updateInventory();
|
||||
logger.fine("ProtectInventoryEvent has been cancelled for " + player.getName() + "...");
|
||||
}
|
||||
}
|
||||
|
||||
// Session logic
|
||||
if (sessionService.canResumeSession(player)) {
|
||||
// Run commands
|
||||
bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(
|
||||
() -> commandManager.runCommandsOnSessionLogin(player));
|
||||
bukkitService.runTaskOptionallyAsync(() -> asynchronousLogin.forceLogin(player,service.getProperty(PluginSettings.HIDE_SESSIONS_LOGIN) ? 1 : 0));
|
||||
return;
|
||||
} else if (proxySessionManager.shouldResumeSession(name)) {
|
||||
// Run commands
|
||||
bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(
|
||||
() -> commandManager.runCommandsOnSessionLogin(player));
|
||||
bukkitService.runTaskOptionallyAsync(() -> asynchronousLogin.forceLogin(player,service.getProperty(PluginSettings.HIDE_SESSIONS_LOGIN) ? 1 : 0));
|
||||
logger.info("The user " + player.getName() + " has been automatically logged in, "
|
||||
+ "as present in autologin queue.");
|
||||
return;
|
||||
}
|
||||
} else if (!service.getProperty(RegistrationSettings.FORCE)) {
|
||||
|
||||
// Skip if registration is optional
|
||||
|
||||
if (bungeeSender.isEnabled()) {
|
||||
// As described at https://www.spigotmc.org/wiki/bukkit-bungee-plugin-messaging-channel/
|
||||
// "Keep in mind that you can't send plugin messages directly after a player joins."
|
||||
bukkitService.scheduleSyncDelayedTask(() ->
|
||||
bungeeSender.sendAuthMeBungeecordMessage(player, MessageType.LOGIN), 5L);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
processJoinSync(player, isAuthAvailable);
|
||||
}
|
||||
|
||||
private void handlePlayerWithUnmetNameRestriction(Player player, String ip) {
|
||||
bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(() -> {
|
||||
player.kickPlayer(service.retrieveSingleMessage(player, MessageKey.NOT_OWNER_ERROR));
|
||||
if (service.getProperty(RestrictionSettings.BAN_UNKNOWN_IP)) {
|
||||
server.banIP(ip);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs various operations in sync mode for an unauthenticated player (such as blindness effect and
|
||||
* limbo player creation).
|
||||
*
|
||||
* @param player the player to process
|
||||
* @param isAuthAvailable true if the player is registered, false otherwise
|
||||
*/
|
||||
private void processJoinSync(Player player, boolean isAuthAvailable) {
|
||||
int registrationTimeout = service.getProperty(RestrictionSettings.TIMEOUT) * TICKS_PER_SECOND;
|
||||
|
||||
bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(() -> {
|
||||
limboService.createLimboPlayer(player, isAuthAvailable);
|
||||
|
||||
player.setNoDamageTicks(registrationTimeout);
|
||||
if (pluginHookService.isEssentialsAvailable() && service.getProperty(HooksSettings.USE_ESSENTIALS_MOTD)) {
|
||||
player.performCommand("motd");
|
||||
}
|
||||
if (service.getProperty(RegistrationSettings.APPLY_BLIND_EFFECT)) {
|
||||
// Allow infinite blindness effect
|
||||
int blindTimeOut = (registrationTimeout <= 0) ? 99999 : registrationTimeout;
|
||||
player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, blindTimeOut, 2));
|
||||
}
|
||||
commandManager.runCommandsOnJoin(player);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the maximum number of accounts has been exceeded for the given IP address (according to
|
||||
* settings and permissions). If this is the case, the player is kicked.
|
||||
*
|
||||
* @param player the player to verify
|
||||
* @param ip the ip address of the player
|
||||
*
|
||||
* @return true if the verification is OK (no infraction), false if player has been kicked
|
||||
*/
|
||||
private boolean validatePlayerCountForIp(Player player, String ip) {
|
||||
if (service.getProperty(RestrictionSettings.MAX_JOIN_PER_IP) > 0
|
||||
&& !service.hasPermission(player, PlayerStatePermission.ALLOW_MULTIPLE_ACCOUNTS)
|
||||
&& !InternetProtocolUtils.isLoopbackAddress(ip)
|
||||
&& countOnlinePlayersByIp(ip) > service.getProperty(RestrictionSettings.MAX_JOIN_PER_IP)) {
|
||||
|
||||
bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(
|
||||
() -> player.kickPlayer(service.retrieveSingleMessage(player, MessageKey.SAME_IP_ONLINE)));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private int countOnlinePlayersByIp(String ip) {
|
||||
int count = 0;
|
||||
for (Player player : bukkitService.getOnlinePlayers()) {
|
||||
if (ip.equalsIgnoreCase(PlayerUtils.getPlayerIp(player))) {
|
||||
++count;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
||||
@@ -1,390 +0,0 @@
|
||||
package fr.xephi.authme.process.login;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.data.TempbanManager;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.data.auth.PlayerCache;
|
||||
import fr.xephi.authme.data.captcha.LoginCaptchaManager;
|
||||
import fr.xephi.authme.data.limbo.LimboMessageType;
|
||||
import fr.xephi.authme.data.limbo.LimboPlayerState;
|
||||
import fr.xephi.authme.data.limbo.LimboService;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.events.AuthMeAsyncPreLoginEvent;
|
||||
import fr.xephi.authme.events.FailedLoginEvent;
|
||||
import fr.xephi.authme.mail.EmailService;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.permission.AdminPermission;
|
||||
import fr.xephi.authme.permission.PlayerPermission;
|
||||
import fr.xephi.authme.permission.PlayerStatePermission;
|
||||
import fr.xephi.authme.process.AsynchronousProcess;
|
||||
import fr.xephi.authme.process.SyncProcessManager;
|
||||
import fr.xephi.authme.security.PasswordSecurity;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.service.SessionService;
|
||||
import fr.xephi.authme.service.bungeecord.BungeeSender;
|
||||
import fr.xephi.authme.service.bungeecord.MessageType;
|
||||
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
||||
import fr.xephi.authme.settings.properties.EmailSettings;
|
||||
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.util.InternetProtocolUtils;
|
||||
import fr.xephi.authme.util.PlayerUtils;
|
||||
import fr.xephi.authme.util.Utils;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Asynchronous task for a player login.
|
||||
*/
|
||||
public class AsynchronousLogin implements AsynchronousProcess {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(AsynchronousLogin.class);
|
||||
|
||||
@Inject
|
||||
private DataSource dataSource;
|
||||
|
||||
@Inject
|
||||
private CommonService service;
|
||||
|
||||
@Inject
|
||||
private PlayerCache playerCache;
|
||||
|
||||
@Inject
|
||||
private SyncProcessManager syncProcessManager;
|
||||
|
||||
@Inject
|
||||
private BukkitService bukkitService;
|
||||
|
||||
@Inject
|
||||
private PasswordSecurity passwordSecurity;
|
||||
|
||||
@Inject
|
||||
private LoginCaptchaManager loginCaptchaManager;
|
||||
|
||||
@Inject
|
||||
private TempbanManager tempbanManager;
|
||||
|
||||
@Inject
|
||||
private LimboService limboService;
|
||||
|
||||
@Inject
|
||||
private EmailService emailService;
|
||||
|
||||
@Inject
|
||||
private SessionService sessionService;
|
||||
|
||||
@Inject
|
||||
private BungeeSender bungeeSender;
|
||||
|
||||
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)) {
|
||||
if (auth.getTotpKey() != null) {
|
||||
limboService.resetMessageTask(player, LimboMessageType.TOTP_CODE);
|
||||
limboService.getLimboPlayer(player.getName()).setState(LimboPlayerState.TOTP_REQUIRED);
|
||||
// TODO #1141: Check if we should check limbo state before processing password
|
||||
} else {
|
||||
performLogin(player, auth, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a player in without requiring a password.
|
||||
*
|
||||
* @param player the player to log in
|
||||
*/
|
||||
public void forceLogin(Player player,int quiet) {
|
||||
PlayerAuth auth = getPlayerAuth(player);
|
||||
if (auth != null) {
|
||||
performLogin(player, auth, quiet == 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a player in without requiring a password.
|
||||
*
|
||||
* @param player the player to log in
|
||||
* @param quiet if true no messages will be sent
|
||||
*/
|
||||
public void forceLogin(Player player, boolean quiet) {
|
||||
PlayerAuth auth = getPlayerAuth(player, quiet);
|
||||
if (auth != null) {
|
||||
performLogin(player, auth, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the precondition for authentication (like user known) and returns
|
||||
* the player's {@link PlayerAuth} object.
|
||||
*
|
||||
* @param player the player to check
|
||||
* @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 getPlayerAuth(Player player) {
|
||||
return getPlayerAuth(player, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the precondition for authentication (like user known) and returns
|
||||
* the player's {@link PlayerAuth} object.
|
||||
*
|
||||
* @param player the player to check
|
||||
* @param quiet don't send messages
|
||||
* @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 getPlayerAuth(Player player, boolean quiet) {
|
||||
String name = player.getName().toLowerCase(Locale.ROOT);
|
||||
if (playerCache.isAuthenticated(name)) {
|
||||
if (!quiet) {
|
||||
service.send(player, MessageKey.ALREADY_LOGGED_IN_ERROR);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
PlayerAuth auth = dataSource.getAuth(name);
|
||||
if (auth == null) {
|
||||
if (!quiet) {
|
||||
service.send(player, MessageKey.UNKNOWN_USER);
|
||||
}
|
||||
// Recreate the message task to immediately send the message again as response
|
||||
limboService.resetMessageTask(player, LimboMessageType.REGISTER);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!service.getProperty(DatabaseSettings.MYSQL_COL_GROUP).isEmpty()
|
||||
&& auth.getGroupId() == service.getProperty(HooksSettings.NON_ACTIVATED_USERS_GROUP)) {
|
||||
if (!quiet) {
|
||||
service.send(player, MessageKey.ACCOUNT_NOT_ACTIVATED);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
String ip = PlayerUtils.getPlayerIp(player);
|
||||
if (hasReachedMaxLoggedInPlayersForIp(player, ip)) {
|
||||
if (!quiet) {
|
||||
service.send(player, MessageKey.ALREADY_LOGGED_IN_ERROR);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
boolean isAsync = service.getProperty(PluginSettings.USE_ASYNC_TASKS);
|
||||
AuthMeAsyncPreLoginEvent event = new AuthMeAsyncPreLoginEvent(player, isAsync);
|
||||
bukkitService.callEvent(event);
|
||||
if (!event.canLogin()) {
|
||||
return null;
|
||||
}
|
||||
return auth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks various conditions for regular player login (not used in force login).
|
||||
*
|
||||
* @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) {
|
||||
String name = player.getName().toLowerCase(Locale.ROOT);
|
||||
|
||||
// If captcha is required send a message to the player and deny to log in
|
||||
if (loginCaptchaManager.isCaptchaRequired(name)) {
|
||||
service.send(player, MessageKey.USAGE_CAPTCHA, loginCaptchaManager.getCaptchaCodeOrGenerateNew(name));
|
||||
return false;
|
||||
}
|
||||
|
||||
String ip = PlayerUtils.getPlayerIp(player);
|
||||
|
||||
// Increase the counts here before knowing the result of the login.
|
||||
loginCaptchaManager.increaseLoginFailureCount(name);
|
||||
tempbanManager.increaseCount(ip, name);
|
||||
|
||||
if (passwordSecurity.comparePassword(password, auth.getPassword(), player.getName())) {
|
||||
return true;
|
||||
} else {
|
||||
handleWrongPassword(player, auth, ip);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a login with wrong password.
|
||||
*
|
||||
* @param player the player who attempted to log in
|
||||
* @param auth the PlayerAuth object of the player
|
||||
* @param ip the ip address of the player
|
||||
*/
|
||||
private void handleWrongPassword(Player player, PlayerAuth auth, String ip) {
|
||||
logger.fine(player.getName() + " used the wrong password");
|
||||
|
||||
bukkitService.createAndCallEvent(isAsync -> new FailedLoginEvent(player, isAsync));
|
||||
if (tempbanManager.shouldTempban(ip)) {
|
||||
tempbanManager.tempbanPlayer(player);
|
||||
} else if (service.getProperty(RestrictionSettings.KICK_ON_WRONG_PASSWORD)) {
|
||||
bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(
|
||||
() -> player.kickPlayer(service.retrieveSingleMessage(player, 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 (loginCaptchaManager.isCaptchaRequired(player.getName())) {
|
||||
limboService.muteMessageTask(player);
|
||||
service.send(player, MessageKey.USAGE_CAPTCHA,
|
||||
loginCaptchaManager.getCaptchaCodeOrGenerateNew(player.getName()));
|
||||
} else if (emailService.hasAllInformation() && !Utils.isEmailEmpty(auth.getEmail())) {
|
||||
service.send(player, MessageKey.FORGOT_PASSWORD_MESSAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the player to the logged in state.
|
||||
*
|
||||
* @param player the player to log in
|
||||
* @param auth the associated PlayerAuth object
|
||||
*/
|
||||
public void performLogin(Player player, PlayerAuth auth, boolean quiet) {
|
||||
if (player.isOnline()) {
|
||||
boolean isFirstLogin = (auth.getLastLogin() == null);
|
||||
|
||||
// Update auth to reflect this new login
|
||||
String ip = PlayerUtils.getPlayerIp(player);
|
||||
auth.setRealName(player.getName());
|
||||
auth.setLastLogin(System.currentTimeMillis());
|
||||
auth.setLastIp(ip);
|
||||
dataSource.updateSession(auth);
|
||||
|
||||
// TODO: send an update when a messaging service will be implemented (SESSION)
|
||||
|
||||
// Successful login, so reset the captcha & temp ban count
|
||||
String name = player.getName();
|
||||
loginCaptchaManager.resetLoginFailureCount(name);
|
||||
tempbanManager.resetCount(ip, name);
|
||||
player.setNoDamageTicks(0);
|
||||
|
||||
if (!quiet) {service.send(player, MessageKey.LOGIN_SUCCESS);}
|
||||
|
||||
// Other auths
|
||||
List<String> auths = dataSource.getAllAuthsByIp(auth.getLastIp());
|
||||
displayOtherAccounts(auths, player);
|
||||
|
||||
String email = auth.getEmail();
|
||||
if (service.getProperty(EmailSettings.RECALL_PLAYERS) && Utils.isEmailEmpty(email)) {
|
||||
service.send(player, MessageKey.ADD_EMAIL_MESSAGE);
|
||||
}
|
||||
|
||||
logger.fine(player.getName() + " logged in " + ip);
|
||||
|
||||
// makes player loggedin
|
||||
playerCache.updatePlayer(auth);
|
||||
dataSource.setLogged(name);
|
||||
sessionService.grantSession(name);
|
||||
|
||||
if (bungeeSender.isEnabled()) {
|
||||
// As described at https://www.spigotmc.org/wiki/bukkit-bungee-plugin-messaging-channel/
|
||||
// "Keep in mind that you can't send plugin messages directly after a player joins."
|
||||
bukkitService.scheduleSyncDelayedTask(() ->
|
||||
bungeeSender.sendAuthMeBungeecordMessage(player, MessageType.LOGIN), 5L);
|
||||
}
|
||||
|
||||
// As the scheduling executes the Task most likely after the current
|
||||
// task, we schedule it in the end
|
||||
// so that we can be sure, and have not to care if it might be
|
||||
// processed in other order.
|
||||
syncProcessManager.processSyncPlayerLogin(player, isFirstLogin, auths);
|
||||
} else {
|
||||
logger.warning("Player '" + player.getName() + "' wasn't online during login process, aborted...");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends info about the other accounts owned by the given player to the configured users.
|
||||
*
|
||||
* @param auths the names of the accounts also owned by the player
|
||||
* @param player the player
|
||||
*/
|
||||
private void displayOtherAccounts(List<String> auths, Player player) {
|
||||
if (!service.getProperty(RestrictionSettings.DISPLAY_OTHER_ACCOUNTS) || auths.size() <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> formattedNames = new ArrayList<>(auths.size());
|
||||
for (String currentName : auths) {
|
||||
Player currentPlayer = bukkitService.getPlayerExact(currentName);
|
||||
if (currentPlayer != null && currentPlayer.isOnline()) {
|
||||
formattedNames.add(ChatColor.GREEN + currentPlayer.getName() + ChatColor.GRAY);
|
||||
} else {
|
||||
formattedNames.add(currentName);
|
||||
}
|
||||
}
|
||||
|
||||
String message = ChatColor.GRAY + String.join(", ", formattedNames) + ".";
|
||||
|
||||
logger.fine("The user " + player.getName() + " has " + auths.size() + " accounts:");
|
||||
logger.fine(message);
|
||||
|
||||
for (Player onlinePlayer : bukkitService.getOnlinePlayers()) {
|
||||
if (onlinePlayer.getName().equalsIgnoreCase(player.getName())
|
||||
&& service.hasPermission(onlinePlayer, PlayerPermission.SEE_OWN_ACCOUNTS)) {
|
||||
service.send(onlinePlayer, MessageKey.ACCOUNTS_OWNED_SELF, Integer.toString(auths.size()));
|
||||
onlinePlayer.sendMessage(message);
|
||||
} else if (service.hasPermission(onlinePlayer, AdminPermission.SEE_OTHER_ACCOUNTS)) {
|
||||
service.send(onlinePlayer, MessageKey.ACCOUNTS_OWNED_OTHER,
|
||||
player.getName(), Integer.toString(auths.size()));
|
||||
onlinePlayer.sendMessage(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|| service.hasPermission(player, PlayerStatePermission.ALLOW_MULTIPLE_ACCOUNTS)
|
||||
|| InternetProtocolUtils.isLoopbackAddress(ip)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Count logged in players with same IP address
|
||||
String name = player.getName();
|
||||
int count = 0;
|
||||
for (Player onlinePlayer : bukkitService.getOnlinePlayers()) {
|
||||
if (ip.equalsIgnoreCase(PlayerUtils.getPlayerIp(onlinePlayer))
|
||||
&& !onlinePlayer.getName().equals(name)
|
||||
&& dataSource.isLogged(onlinePlayer.getName().toLowerCase(Locale.ROOT))) {
|
||||
++count;
|
||||
}
|
||||
}
|
||||
return count >= service.getProperty(RestrictionSettings.MAX_LOGIN_PER_IP);
|
||||
}
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
package fr.xephi.authme.process.login;
|
||||
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.data.auth.PlayerCache;
|
||||
import fr.xephi.authme.data.limbo.LimboPlayer;
|
||||
import fr.xephi.authme.data.limbo.LimboService;
|
||||
import fr.xephi.authme.events.LoginEvent;
|
||||
import fr.xephi.authme.events.RestoreInventoryEvent;
|
||||
import fr.xephi.authme.permission.PermissionsManager;
|
||||
import fr.xephi.authme.permission.PlayerStatePermission;
|
||||
import fr.xephi.authme.process.SynchronousProcess;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.service.JoinMessageService;
|
||||
import fr.xephi.authme.service.TeleportationService;
|
||||
import fr.xephi.authme.service.bungeecord.BungeeSender;
|
||||
import fr.xephi.authme.settings.commandconfig.CommandManager;
|
||||
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import static fr.xephi.authme.settings.properties.RestrictionSettings.PROTECT_INVENTORY_BEFORE_LOGIN;
|
||||
|
||||
public class ProcessSyncPlayerLogin implements SynchronousProcess {
|
||||
|
||||
@Inject
|
||||
private BungeeSender bungeeSender;
|
||||
|
||||
@Inject
|
||||
private LimboService limboService;
|
||||
|
||||
@Inject
|
||||
private BukkitService bukkitService;
|
||||
|
||||
@Inject
|
||||
private TeleportationService teleportationService;
|
||||
|
||||
@Inject
|
||||
private PlayerCache playerCache;
|
||||
|
||||
@Inject
|
||||
private CommandManager commandManager;
|
||||
|
||||
@Inject
|
||||
private CommonService commonService;
|
||||
|
||||
@Inject
|
||||
private JoinMessageService joinMessageService;
|
||||
|
||||
@Inject
|
||||
private PermissionsManager permissionsManager;
|
||||
|
||||
ProcessSyncPlayerLogin() {
|
||||
}
|
||||
|
||||
private void restoreInventory(Player player) {
|
||||
RestoreInventoryEvent event = new RestoreInventoryEvent(player);
|
||||
bukkitService.callEvent(event);
|
||||
if (!event.isCancelled()) {
|
||||
player.updateInventory();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs operations in sync mode for a player that has just logged in.
|
||||
*
|
||||
* @param player the player that was logged in
|
||||
* @param isFirstLogin true if this is the first time the player logged in
|
||||
* @param authsWithSameIp registered names with the same IP address as the player's
|
||||
*/
|
||||
public void processPlayerLogin(Player player, boolean isFirstLogin, List<String> authsWithSameIp) {
|
||||
final String name = player.getName().toLowerCase(Locale.ROOT);
|
||||
final LimboPlayer limbo = limboService.getLimboPlayer(name);
|
||||
|
||||
// Limbo contains the State of the Player before /login
|
||||
if (limbo != null) {
|
||||
limboService.restoreData(player);
|
||||
}
|
||||
|
||||
if (commonService.getProperty(PROTECT_INVENTORY_BEFORE_LOGIN)) {
|
||||
restoreInventory(player);
|
||||
}
|
||||
|
||||
final PlayerAuth auth = playerCache.getAuth(name);
|
||||
teleportationService.teleportOnLogin(player, auth, limbo);
|
||||
|
||||
// We can now display the join message (if delayed)
|
||||
joinMessageService.sendMessage(name);
|
||||
|
||||
if (commonService.getProperty(RegistrationSettings.APPLY_BLIND_EFFECT)) {
|
||||
player.removePotionEffect(PotionEffectType.BLINDNESS);
|
||||
}
|
||||
|
||||
// The Login event now fires (as intended) after everything is processed
|
||||
bukkitService.callEvent(new LoginEvent(player));
|
||||
|
||||
// Login is now finished; we can force all commands
|
||||
if (isFirstLogin) {
|
||||
commandManager.runCommandsOnFirstLogin(player, authsWithSameIp);
|
||||
}
|
||||
commandManager.runCommandsOnLogin(player, authsWithSameIp);
|
||||
|
||||
if (!permissionsManager.hasPermission(player, PlayerStatePermission.BYPASS_BUNGEE_SEND)) {
|
||||
// Send Bungee stuff. The service will check if it is enabled or not.
|
||||
bungeeSender.connectPlayerOnLogin(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
package fr.xephi.authme.process.logout;
|
||||
|
||||
import fr.xephi.authme.data.VerificationCodeManager;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.data.auth.PlayerCache;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.process.AsynchronousProcess;
|
||||
import fr.xephi.authme.process.SyncProcessManager;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.service.SessionService;
|
||||
import fr.xephi.authme.service.bungeecord.BungeeSender;
|
||||
import fr.xephi.authme.service.bungeecord.MessageType;
|
||||
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Async task when a player wants to log out.
|
||||
*/
|
||||
public class AsynchronousLogout implements AsynchronousProcess {
|
||||
|
||||
@Inject
|
||||
private DataSource database;
|
||||
|
||||
@Inject
|
||||
private CommonService service;
|
||||
|
||||
@Inject
|
||||
private PlayerCache playerCache;
|
||||
|
||||
@Inject
|
||||
private VerificationCodeManager codeManager;
|
||||
|
||||
@Inject
|
||||
private SyncProcessManager syncProcessManager;
|
||||
|
||||
@Inject
|
||||
private SessionService sessionService;
|
||||
|
||||
@Inject
|
||||
private BungeeSender bungeeSender;
|
||||
|
||||
AsynchronousLogout() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a player's request to log out.
|
||||
*
|
||||
* @param player the player wanting to log out
|
||||
*/
|
||||
public void logout(Player player) {
|
||||
String name = player.getName().toLowerCase(Locale.ROOT);
|
||||
if (!playerCache.isAuthenticated(name)) {
|
||||
service.send(player, MessageKey.NOT_LOGGED_IN);
|
||||
return;
|
||||
}
|
||||
|
||||
PlayerAuth auth = playerCache.getAuth(name);
|
||||
database.updateSession(auth);
|
||||
// TODO: send an update when a messaging service will be implemented (SESSION)
|
||||
if (service.getProperty(RestrictionSettings.SAVE_QUIT_LOCATION)) {
|
||||
auth.setQuitLocation(player.getLocation());
|
||||
database.updateQuitLoc(auth);
|
||||
// TODO: send an update when a messaging service will be implemented (QUITLOC)
|
||||
}
|
||||
|
||||
playerCache.removePlayer(name);
|
||||
codeManager.unverify(name);
|
||||
database.setUnlogged(name);
|
||||
sessionService.revokeSession(name);
|
||||
bungeeSender.sendAuthMeBungeecordMessage(player, MessageType.LOGOUT);
|
||||
syncProcessManager.processSyncPlayerLogout(player);
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
package fr.xephi.authme.process.logout;
|
||||
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.data.limbo.LimboService;
|
||||
import fr.xephi.authme.events.LogoutEvent;
|
||||
import fr.xephi.authme.listener.protocollib.ProtocolLibService;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.process.SynchronousProcess;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.service.TeleportationService;
|
||||
import fr.xephi.authme.settings.commandconfig.CommandManager;
|
||||
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
||||
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static fr.xephi.authme.service.BukkitService.TICKS_PER_SECOND;
|
||||
|
||||
|
||||
public class ProcessSyncPlayerLogout implements SynchronousProcess {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(ProcessSyncPlayerLogout.class);
|
||||
|
||||
@Inject
|
||||
private CommonService service;
|
||||
|
||||
@Inject
|
||||
private BukkitService bukkitService;
|
||||
|
||||
@Inject
|
||||
private ProtocolLibService protocolLibService;
|
||||
|
||||
@Inject
|
||||
private LimboService limboService;
|
||||
|
||||
@Inject
|
||||
private TeleportationService teleportationService;
|
||||
|
||||
@Inject
|
||||
private CommandManager commandManager;
|
||||
|
||||
ProcessSyncPlayerLogout() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a player which has been logged out.
|
||||
*
|
||||
* @param player the player logging out
|
||||
*/
|
||||
public void processSyncLogout(Player player) {
|
||||
if (service.getProperty(RestrictionSettings.PROTECT_INVENTORY_BEFORE_LOGIN)) {
|
||||
protocolLibService.sendBlankInventoryPacket(player);
|
||||
}
|
||||
|
||||
applyLogoutEffect(player);
|
||||
commandManager.runCommandsOnLogout(player);
|
||||
|
||||
// Player is now logout... Time to fire event !
|
||||
bukkitService.callEvent(new LogoutEvent(player));
|
||||
|
||||
service.send(player, MessageKey.LOGOUT_SUCCESS);
|
||||
logger.info(player.getName() + " logged out");
|
||||
}
|
||||
|
||||
private void applyLogoutEffect(Player player) {
|
||||
// dismount player
|
||||
player.leaveVehicle();
|
||||
teleportationService.teleportOnJoin(player);
|
||||
|
||||
// Apply Blindness effect
|
||||
if (service.getProperty(RegistrationSettings.APPLY_BLIND_EFFECT)) {
|
||||
int timeout = service.getProperty(RestrictionSettings.TIMEOUT) * TICKS_PER_SECOND;
|
||||
player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, timeout, 2));
|
||||
}
|
||||
|
||||
// Set player's data to unauthenticated
|
||||
limboService.createLimboPlayer(player, true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
package fr.xephi.authme.process.quit;
|
||||
|
||||
import fr.xephi.authme.AuthMe;
|
||||
import fr.xephi.authme.data.VerificationCodeManager;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.data.auth.PlayerCache;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.process.AsynchronousProcess;
|
||||
import fr.xephi.authme.process.SyncProcessManager;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.service.SessionService;
|
||||
import fr.xephi.authme.service.ValidationService;
|
||||
import fr.xephi.authme.settings.SpawnLoader;
|
||||
import fr.xephi.authme.settings.properties.PluginSettings;
|
||||
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
||||
import fr.xephi.authme.util.PlayerUtils;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Async process called when a player quits the server.
|
||||
*/
|
||||
public class AsynchronousQuit implements AsynchronousProcess {
|
||||
|
||||
@Inject
|
||||
private AuthMe plugin;
|
||||
|
||||
@Inject
|
||||
private DataSource database;
|
||||
|
||||
@Inject
|
||||
private CommonService service;
|
||||
|
||||
@Inject
|
||||
private PlayerCache playerCache;
|
||||
|
||||
@Inject
|
||||
private SyncProcessManager syncProcessManager;
|
||||
|
||||
@Inject
|
||||
private SpawnLoader spawnLoader;
|
||||
|
||||
@Inject
|
||||
private ValidationService validationService;
|
||||
|
||||
@Inject
|
||||
private VerificationCodeManager codeManager;
|
||||
|
||||
@Inject
|
||||
private SessionService sessionService;
|
||||
|
||||
AsynchronousQuit() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes that the given player has quit the server.
|
||||
*
|
||||
* @param player the player who left
|
||||
*/
|
||||
public void processQuit(Player player) {
|
||||
if (player == null || validationService.isUnrestricted(player.getName())) {
|
||||
return;
|
||||
}
|
||||
String name = player.getName().toLowerCase(Locale.ROOT);
|
||||
boolean wasLoggedIn = playerCache.isAuthenticated(name);
|
||||
|
||||
if (wasLoggedIn) {
|
||||
if (service.getProperty(RestrictionSettings.SAVE_QUIT_LOCATION)) {
|
||||
Location loc = spawnLoader.getPlayerLocationOrSpawn(player);
|
||||
PlayerAuth auth = PlayerAuth.builder()
|
||||
.name(name).location(loc)
|
||||
.realName(player.getName()).build();
|
||||
database.updateQuitLoc(auth);
|
||||
}
|
||||
|
||||
String ip = PlayerUtils.getPlayerIp(player);
|
||||
PlayerAuth auth = PlayerAuth.builder()
|
||||
.name(name)
|
||||
.realName(player.getName())
|
||||
.lastIp(ip)
|
||||
.lastLogin(System.currentTimeMillis())
|
||||
.build();
|
||||
database.updateSession(auth);
|
||||
|
||||
// TODO: send an update when a messaging service will be implemented (QUITLOC)
|
||||
}
|
||||
|
||||
//always unauthenticate the player - use session only for auto logins on the same ip
|
||||
playerCache.removePlayer(name);
|
||||
codeManager.unverify(name);
|
||||
|
||||
//always update the database when the player quit the game (if sessions are disabled)
|
||||
if (wasLoggedIn) {
|
||||
database.setUnlogged(name);
|
||||
if (!service.getProperty(PluginSettings.SESSIONS_ENABLED)) {
|
||||
sessionService.revokeSession(name);
|
||||
}
|
||||
}
|
||||
|
||||
if (plugin.isEnabled()) {
|
||||
syncProcessManager.processSyncPlayerQuit(player, wasLoggedIn);
|
||||
}
|
||||
|
||||
// remove player from cache
|
||||
database.invalidateCache(name);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package fr.xephi.authme.process.quit;
|
||||
|
||||
import fr.xephi.authme.data.limbo.LimboService;
|
||||
import fr.xephi.authme.process.SynchronousProcess;
|
||||
import fr.xephi.authme.settings.commandconfig.CommandManager;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
|
||||
public class ProcessSyncPlayerQuit implements SynchronousProcess {
|
||||
|
||||
@Inject
|
||||
private LimboService limboService;
|
||||
|
||||
@Inject
|
||||
private CommandManager commandManager;
|
||||
|
||||
/**
|
||||
* Processes a player having quit.
|
||||
*
|
||||
* @param player the player that left
|
||||
* @param wasLoggedIn true if the player was logged in when leaving, false otherwise
|
||||
*/
|
||||
public void processSyncQuit(Player player, boolean wasLoggedIn) {
|
||||
if (wasLoggedIn) {
|
||||
commandManager.runCommandsOnLogout(player);
|
||||
} else {
|
||||
limboService.restoreData(player);
|
||||
player.saveData(); // #1238: Speed is sometimes not restored properly
|
||||
}
|
||||
player.leaveVehicle();
|
||||
}
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
package fr.xephi.authme.process.register;
|
||||
|
||||
import ch.jalu.injector.factory.SingletonStore;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.data.auth.PlayerCache;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.events.AuthMeAsyncPreRegisterEvent;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.process.AsynchronousProcess;
|
||||
import fr.xephi.authme.process.register.executors.RegistrationExecutor;
|
||||
import fr.xephi.authme.process.register.executors.RegistrationMethod;
|
||||
import fr.xephi.authme.process.register.executors.RegistrationParameters;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
||||
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
||||
import fr.xephi.authme.util.InternetProtocolUtils;
|
||||
import fr.xephi.authme.util.PlayerUtils;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import static fr.xephi.authme.permission.PlayerStatePermission.ALLOW_MULTIPLE_ACCOUNTS;
|
||||
|
||||
/**
|
||||
* Asynchronous processing of a request for registration.
|
||||
*/
|
||||
public class AsyncRegister implements AsynchronousProcess {
|
||||
|
||||
@Inject
|
||||
private DataSource database;
|
||||
@Inject
|
||||
private PlayerCache playerCache;
|
||||
@Inject
|
||||
private BukkitService bukkitService;
|
||||
@Inject
|
||||
private CommonService service;
|
||||
@Inject
|
||||
private SingletonStore<RegistrationExecutor> registrationExecutorFactory;
|
||||
|
||||
AsyncRegister() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the registration process for the given player.
|
||||
*
|
||||
* @param variant the registration method
|
||||
* @param parameters the parameters
|
||||
* @param <P> parameters type
|
||||
*/
|
||||
public <P extends RegistrationParameters> void register(RegistrationMethod<P> variant, P parameters) {
|
||||
if (preRegisterCheck(variant, parameters.getPlayer())) {
|
||||
RegistrationExecutor<P> executor = registrationExecutorFactory.getSingleton(variant.getExecutorClass());
|
||||
if (executor.isRegistrationAdmitted(parameters)) {
|
||||
executeRegistration(parameters, executor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the player is able to register, in that case the {@link AuthMeAsyncPreRegisterEvent} is invoked.
|
||||
*
|
||||
* @param variant the registration type variant.
|
||||
* @param player the player which is trying to register.
|
||||
*
|
||||
* @return true if the checks are successful and the event hasn't marked the action as denied, false otherwise.
|
||||
*/
|
||||
private boolean preRegisterCheck(RegistrationMethod<?> variant, Player player) {
|
||||
String name = player.getName().toLowerCase(Locale.ROOT);
|
||||
if (playerCache.isAuthenticated(name)) {
|
||||
service.send(player, MessageKey.ALREADY_LOGGED_IN_ERROR);
|
||||
return false;
|
||||
} else if (!service.getProperty(RegistrationSettings.IS_ENABLED)) {
|
||||
service.send(player, MessageKey.REGISTRATION_DISABLED);
|
||||
return false;
|
||||
} else if (database.isAuthAvailable(name)) {
|
||||
service.send(player, MessageKey.NAME_ALREADY_REGISTERED);
|
||||
return false;
|
||||
}
|
||||
|
||||
AuthMeAsyncPreRegisterEvent event = bukkitService.createAndCallEvent(
|
||||
isAsync -> new AuthMeAsyncPreRegisterEvent(player, isAsync));
|
||||
if (!event.canRegister()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return variant == RegistrationMethod.API_REGISTRATION || isPlayerIpAllowedToRegister(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the registration.
|
||||
*
|
||||
* @param parameters the registration parameters
|
||||
* @param executor the executor to perform the registration process with
|
||||
* @param <P> registration params type
|
||||
*/
|
||||
private <P extends RegistrationParameters>
|
||||
void executeRegistration(P parameters, RegistrationExecutor<P> executor) {
|
||||
PlayerAuth auth = executor.buildPlayerAuth(parameters);
|
||||
if (database.saveAuth(auth)) {
|
||||
executor.executePostPersistAction(parameters);
|
||||
} else {
|
||||
service.send(parameters.getPlayer(), MessageKey.ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the registration threshold has been exceeded for the given player's IP address.
|
||||
*
|
||||
* @param player the player to check
|
||||
*
|
||||
* @return true if registration may take place, false otherwise (IP check failed)
|
||||
*/
|
||||
private boolean isPlayerIpAllowedToRegister(Player player) {
|
||||
int maxRegPerIp = service.getProperty(RestrictionSettings.MAX_REGISTRATION_PER_IP);
|
||||
String ip = PlayerUtils.getPlayerIp(player);
|
||||
if (maxRegPerIp > 0
|
||||
&& !InternetProtocolUtils.isLoopbackAddress(ip)
|
||||
&& !service.hasPermission(player, ALLOW_MULTIPLE_ACCOUNTS)) {
|
||||
List<String> otherAccounts = database.getAllAuthsByIp(ip);
|
||||
if (otherAccounts.size() >= maxRegPerIp) {
|
||||
service.send(player, MessageKey.MAX_REGISTER_EXCEEDED, Integer.toString(maxRegPerIp),
|
||||
Integer.toString(otherAccounts.size()), String.join(", ", otherAccounts));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
package fr.xephi.authme.process.register;
|
||||
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.data.limbo.LimboService;
|
||||
import fr.xephi.authme.events.RegisterEvent;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.process.SynchronousProcess;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.util.PlayerUtils;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* Performs synchronous tasks after a successful {@link RegistrationType#EMAIL email registration}.
|
||||
*/
|
||||
public class ProcessSyncEmailRegister implements SynchronousProcess {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(ProcessSyncEmailRegister.class);
|
||||
|
||||
@Inject
|
||||
private BukkitService bukkitService;
|
||||
|
||||
@Inject
|
||||
private CommonService service;
|
||||
|
||||
@Inject
|
||||
private LimboService limboService;
|
||||
|
||||
ProcessSyncEmailRegister() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs sync tasks for a player which has just registered by email.
|
||||
*
|
||||
* @param player the recently registered player
|
||||
*/
|
||||
public void processEmailRegister(Player player) {
|
||||
service.send(player, MessageKey.ACCOUNT_NOT_ACTIVATED);
|
||||
limboService.replaceTasksAfterRegistration(player);
|
||||
|
||||
bukkitService.callEvent(new RegisterEvent(player));
|
||||
logger.fine(player.getName() + " registered " + PlayerUtils.getPlayerIp(player));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
package fr.xephi.authme.process.register;
|
||||
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.data.limbo.LimboService;
|
||||
import fr.xephi.authme.events.RegisterEvent;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.process.SynchronousProcess;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.service.bungeecord.BungeeSender;
|
||||
import fr.xephi.authme.settings.commandconfig.CommandManager;
|
||||
import fr.xephi.authme.settings.properties.EmailSettings;
|
||||
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
||||
import fr.xephi.authme.util.PlayerUtils;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* Performs synchronous tasks after a successful {@link RegistrationType#PASSWORD password registration}.
|
||||
*/
|
||||
public class ProcessSyncPasswordRegister implements SynchronousProcess {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(ProcessSyncPasswordRegister.class);
|
||||
|
||||
@Inject
|
||||
private BungeeSender bungeeSender;
|
||||
|
||||
@Inject
|
||||
private CommonService service;
|
||||
|
||||
@Inject
|
||||
private LimboService limboService;
|
||||
|
||||
@Inject
|
||||
private CommandManager commandManager;
|
||||
|
||||
@Inject
|
||||
private BukkitService bukkitService;
|
||||
|
||||
ProcessSyncPasswordRegister() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Request that the player log in.
|
||||
*
|
||||
* @param player the player
|
||||
*/
|
||||
private void requestLogin(Player player) {
|
||||
limboService.replaceTasksAfterRegistration(player);
|
||||
|
||||
if (player.isInsideVehicle() && player.getVehicle() != null) {
|
||||
player.getVehicle().eject();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a player having registered with a password.
|
||||
*
|
||||
* @param player the newly registered player
|
||||
*/
|
||||
public void processPasswordRegister(Player player) {
|
||||
service.send(player, MessageKey.REGISTER_SUCCESS);
|
||||
|
||||
if (!service.getProperty(EmailSettings.MAIL_ACCOUNT).isEmpty()) {
|
||||
service.send(player, MessageKey.ADD_EMAIL_MESSAGE);
|
||||
}
|
||||
|
||||
bukkitService.callEvent(new RegisterEvent(player));
|
||||
logger.fine(player.getName() + " registered " + PlayerUtils.getPlayerIp(player));
|
||||
|
||||
// Kick Player after Registration is enabled, kick the player
|
||||
if (service.getProperty(RegistrationSettings.FORCE_KICK_AFTER_REGISTER)) {
|
||||
player.kickPlayer(service.retrieveSingleMessage(player, MessageKey.REGISTER_SUCCESS));
|
||||
return;
|
||||
}
|
||||
|
||||
// Register is now finished; we can force all commands
|
||||
commandManager.runCommandsOnRegister(player);
|
||||
|
||||
// Request login after registration
|
||||
if (service.getProperty(RegistrationSettings.FORCE_LOGIN_AFTER_REGISTER)) {
|
||||
requestLogin(player);
|
||||
return;
|
||||
}
|
||||
|
||||
// Send Bungee stuff. The service will check if it is enabled or not.
|
||||
bungeeSender.connectPlayerOnLogin(player);
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package fr.xephi.authme.process.register;
|
||||
|
||||
/**
|
||||
* Type of the second argument of the {@code /register} command.
|
||||
*/
|
||||
public enum RegisterSecondaryArgument {
|
||||
|
||||
/** No second argument. */
|
||||
NONE,
|
||||
|
||||
/** Confirmation of the first argument. */
|
||||
CONFIRMATION,
|
||||
|
||||
/** For password registration, mandatory secondary argument is email. */
|
||||
EMAIL_MANDATORY,
|
||||
|
||||
/** For password registration, optional secondary argument is email. */
|
||||
EMAIL_OPTIONAL
|
||||
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package fr.xephi.authme.process.register;
|
||||
|
||||
/**
|
||||
* Registration type.
|
||||
*/
|
||||
public enum RegistrationType {
|
||||
|
||||
/**
|
||||
* Password registration: account is registered with a password supplied by the player.
|
||||
*/
|
||||
PASSWORD,
|
||||
|
||||
/**
|
||||
* Email registration: account is registered with an email supplied by the player. A password
|
||||
* is generated and sent to the email address.
|
||||
*/
|
||||
EMAIL
|
||||
|
||||
}
|
||||
-99
@@ -1,99 +0,0 @@
|
||||
package fr.xephi.authme.process.register.executors;
|
||||
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.process.SyncProcessManager;
|
||||
import fr.xephi.authme.process.login.AsynchronousLogin;
|
||||
import fr.xephi.authme.security.PasswordSecurity;
|
||||
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.service.ValidationService;
|
||||
import fr.xephi.authme.settings.properties.PluginSettings;
|
||||
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* Registration executor for registration methods where the password
|
||||
* is supplied by the user.
|
||||
*
|
||||
* @param <P> the parameters type
|
||||
*/
|
||||
abstract class AbstractPasswordRegisterExecutor<P extends AbstractPasswordRegisterParams>
|
||||
implements RegistrationExecutor<P> {
|
||||
|
||||
/**
|
||||
* Number of ticks to wait before running the login action when it is run synchronously.
|
||||
* A small delay is necessary or the database won't return the newly saved PlayerAuth object
|
||||
* and the login process thinks the user is not registered.
|
||||
*/
|
||||
private static final int SYNC_LOGIN_DELAY = 5;
|
||||
|
||||
@Inject
|
||||
private ValidationService validationService;
|
||||
|
||||
@Inject
|
||||
private CommonService commonService;
|
||||
|
||||
@Inject
|
||||
private PasswordSecurity passwordSecurity;
|
||||
|
||||
@Inject
|
||||
private BukkitService bukkitService;
|
||||
|
||||
@Inject
|
||||
private SyncProcessManager syncProcessManager;
|
||||
|
||||
@Inject
|
||||
private AsynchronousLogin asynchronousLogin;
|
||||
|
||||
@Override
|
||||
public boolean isRegistrationAdmitted(P params) {
|
||||
ValidationService.ValidationResult passwordValidation = validationService.validatePassword(
|
||||
params.getPassword(), params.getPlayer().getName());
|
||||
if (passwordValidation.hasError()) {
|
||||
commonService.send(params.getPlayer(), passwordValidation.getMessageKey(), passwordValidation.getArgs());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlayerAuth buildPlayerAuth(P params) {
|
||||
HashedPassword hashedPassword = passwordSecurity.computeHash(params.getPassword(), params.getPlayerName());
|
||||
params.setHashedPassword(hashedPassword);
|
||||
return createPlayerAuthObject(params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the PlayerAuth object to store into the database, based on the registration parameters.
|
||||
*
|
||||
* @param params the parameters
|
||||
* @return the PlayerAuth representing the new account to register
|
||||
*/
|
||||
protected abstract PlayerAuth createPlayerAuthObject(P params);
|
||||
|
||||
/**
|
||||
* Returns whether the player should be automatically logged in after registration.
|
||||
*
|
||||
* @param params the registration parameters
|
||||
* @return true if the player should be logged in, false otherwise
|
||||
*/
|
||||
protected boolean performLoginAfterRegister(P params) {
|
||||
return !commonService.getProperty(RegistrationSettings.FORCE_LOGIN_AFTER_REGISTER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executePostPersistAction(P params) {
|
||||
final Player player = params.getPlayer();
|
||||
if (performLoginAfterRegister(params)) {
|
||||
if (commonService.getProperty(PluginSettings.USE_ASYNC_TASKS)) {
|
||||
bukkitService.runTaskAsynchronously(() -> asynchronousLogin.forceLogin(player,0));
|
||||
} else {
|
||||
bukkitService.scheduleSyncDelayedTask(() -> asynchronousLogin.forceLogin(player,0), SYNC_LOGIN_DELAY);
|
||||
}
|
||||
}
|
||||
syncProcessManager.processSyncPasswordRegister(player);
|
||||
}
|
||||
}
|
||||
-48
@@ -1,48 +0,0 @@
|
||||
package fr.xephi.authme.process.register.executors;
|
||||
|
||||
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/**
|
||||
* Common params type for implementors of {@link AbstractPasswordRegisterExecutor}.
|
||||
* Password must be supplied on creation and cannot be changed later on. The {@link HashedPassword}
|
||||
* is stored on the params object for later use.
|
||||
*/
|
||||
public abstract class AbstractPasswordRegisterParams extends RegistrationParameters {
|
||||
|
||||
private final String password;
|
||||
private HashedPassword hashedPassword;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param player the player to register
|
||||
* @param password the password to use
|
||||
*/
|
||||
public AbstractPasswordRegisterParams(Player player, String password) {
|
||||
super(player);
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor with no defined password. Use for registration methods which
|
||||
* have no implicit password (like two factor authentication).
|
||||
*
|
||||
* @param player the player to register
|
||||
*/
|
||||
public AbstractPasswordRegisterParams(Player player) {
|
||||
this(player, null);
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
void setHashedPassword(HashedPassword hashedPassword) {
|
||||
this.hashedPassword = hashedPassword;
|
||||
}
|
||||
|
||||
HashedPassword getHashedPassword() {
|
||||
return hashedPassword;
|
||||
}
|
||||
}
|
||||
-20
@@ -1,20 +0,0 @@
|
||||
package fr.xephi.authme.process.register.executors;
|
||||
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
|
||||
/**
|
||||
* Executor for password registration via API call.
|
||||
*/
|
||||
class ApiPasswordRegisterExecutor extends AbstractPasswordRegisterExecutor<ApiPasswordRegisterParams> {
|
||||
|
||||
@Override
|
||||
protected PlayerAuth createPlayerAuthObject(ApiPasswordRegisterParams params) {
|
||||
return PlayerAuthBuilderHelper
|
||||
.createPlayerAuth(params.getPlayer(), params.getHashedPassword(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean performLoginAfterRegister(ApiPasswordRegisterParams params) {
|
||||
return params.getLoginAfterRegister();
|
||||
}
|
||||
}
|
||||
-35
@@ -1,35 +0,0 @@
|
||||
package fr.xephi.authme.process.register.executors;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/**
|
||||
* Parameters for {@link ApiPasswordRegisterExecutor}.
|
||||
*/
|
||||
public class ApiPasswordRegisterParams extends PasswordRegisterParams {
|
||||
|
||||
private final boolean loginAfterRegister;
|
||||
|
||||
protected ApiPasswordRegisterParams(Player player, String password, boolean loginAfterRegister) {
|
||||
super(player, password, null);
|
||||
this.loginAfterRegister = loginAfterRegister;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a parameters object.
|
||||
*
|
||||
* @param player the player to register
|
||||
* @param password the password to register with
|
||||
* @param loginAfterRegister whether the player should be logged in after registration
|
||||
* @return params object with the given data
|
||||
*/
|
||||
public static ApiPasswordRegisterParams of(Player player, String password, boolean loginAfterRegister) {
|
||||
return new ApiPasswordRegisterParams(player, password, loginAfterRegister);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the player should be logged in after being registered, false otherwise
|
||||
*/
|
||||
public boolean getLoginAfterRegister() {
|
||||
return loginAfterRegister;
|
||||
}
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
package fr.xephi.authme.process.register.executors;
|
||||
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.mail.EmailService;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.process.SyncProcessManager;
|
||||
import fr.xephi.authme.security.PasswordSecurity;
|
||||
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.settings.properties.EmailSettings;
|
||||
import fr.xephi.authme.util.PlayerUtils;
|
||||
import fr.xephi.authme.util.RandomStringUtils;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
import static fr.xephi.authme.permission.PlayerStatePermission.ALLOW_MULTIPLE_ACCOUNTS;
|
||||
import static fr.xephi.authme.process.register.executors.PlayerAuthBuilderHelper.createPlayerAuth;
|
||||
import static fr.xephi.authme.settings.properties.EmailSettings.RECOVERY_PASSWORD_LENGTH;
|
||||
|
||||
/**
|
||||
* Executor for email registration: the player only provides his email address,
|
||||
* to which a generated password is sent.
|
||||
*/
|
||||
class EmailRegisterExecutor implements RegistrationExecutor<EmailRegisterParams> {
|
||||
|
||||
@Inject
|
||||
private DataSource dataSource;
|
||||
|
||||
@Inject
|
||||
private CommonService commonService;
|
||||
|
||||
@Inject
|
||||
private EmailService emailService;
|
||||
|
||||
@Inject
|
||||
private SyncProcessManager syncProcessManager;
|
||||
|
||||
@Inject
|
||||
private PasswordSecurity passwordSecurity;
|
||||
|
||||
@Override
|
||||
public boolean isRegistrationAdmitted(EmailRegisterParams params) {
|
||||
final int maxRegPerEmail = commonService.getProperty(EmailSettings.MAX_REG_PER_EMAIL);
|
||||
if (maxRegPerEmail > 0 && !commonService.hasPermission(params.getPlayer(), ALLOW_MULTIPLE_ACCOUNTS)) {
|
||||
int otherAccounts = dataSource.countAuthsByEmail(params.getEmail());
|
||||
if (otherAccounts >= maxRegPerEmail) {
|
||||
commonService.send(params.getPlayer(), MessageKey.MAX_REGISTER_EXCEEDED,
|
||||
Integer.toString(maxRegPerEmail), Integer.toString(otherAccounts), "@");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlayerAuth buildPlayerAuth(EmailRegisterParams params) {
|
||||
String password = RandomStringUtils.generate(commonService.getProperty(RECOVERY_PASSWORD_LENGTH));
|
||||
HashedPassword hashedPassword = passwordSecurity.computeHash(password, params.getPlayer().getName());
|
||||
params.setPassword(password);
|
||||
return createPlayerAuth(params.getPlayer(), hashedPassword, params.getEmail());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executePostPersistAction(EmailRegisterParams params) {
|
||||
Player player = params.getPlayer();
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy'年'MM'月'dd'日' HH:mm:ss");
|
||||
Date date = new Date(System.currentTimeMillis());
|
||||
boolean couldSendMail = emailService.sendNewPasswordMail(
|
||||
player.getName(), params.getEmail(), params.getPassword(), PlayerUtils.getPlayerIp(player), dateFormat.format(date));
|
||||
if (couldSendMail) {
|
||||
syncProcessManager.processSyncEmailRegister(player);
|
||||
} else {
|
||||
commonService.send(player, MessageKey.EMAIL_SEND_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
package fr.xephi.authme.process.register.executors;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/**
|
||||
* Parameters for email registration.
|
||||
*/
|
||||
public class EmailRegisterParams extends RegistrationParameters {
|
||||
|
||||
private final String email;
|
||||
private String password;
|
||||
|
||||
protected EmailRegisterParams(Player player, String email) {
|
||||
super(player);
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a params object for email registration.
|
||||
*
|
||||
* @param player the player to register
|
||||
* @param email the player's email
|
||||
* @return params object with the given data
|
||||
*/
|
||||
public static EmailRegisterParams of(Player player, String email) {
|
||||
return new EmailRegisterParams(player, email);
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the password generated for the player
|
||||
*/
|
||||
String getPassword() {
|
||||
return password;
|
||||
}
|
||||
}
|
||||
-17
@@ -1,17 +0,0 @@
|
||||
package fr.xephi.authme.process.register.executors;
|
||||
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
|
||||
import static fr.xephi.authme.process.register.executors.PlayerAuthBuilderHelper.createPlayerAuth;
|
||||
|
||||
/**
|
||||
* Registration executor for password registration.
|
||||
*/
|
||||
class PasswordRegisterExecutor extends AbstractPasswordRegisterExecutor<PasswordRegisterParams> {
|
||||
|
||||
@Override
|
||||
public PlayerAuth createPlayerAuthObject(PasswordRegisterParams params) {
|
||||
return createPlayerAuth(params.getPlayer(), params.getHashedPassword(), params.getEmail());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package fr.xephi.authme.process.register.executors;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/**
|
||||
* Parameters for registration with a given password, and optionally an email address.
|
||||
*/
|
||||
public class PasswordRegisterParams extends AbstractPasswordRegisterParams {
|
||||
|
||||
private final String email;
|
||||
|
||||
protected PasswordRegisterParams(Player player, String password, String email) {
|
||||
super(player, password);
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a params object.
|
||||
*
|
||||
* @param player the player to register
|
||||
* @param password the password to register with
|
||||
* @param email the email of the player (may be null)
|
||||
* @return params object with the given data
|
||||
*/
|
||||
public static PasswordRegisterParams of(Player player, String password, String email) {
|
||||
return new PasswordRegisterParams(player, password, email);
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package fr.xephi.authme.process.register.executors;
|
||||
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||
import fr.xephi.authme.util.PlayerUtils;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Helper for constructing PlayerAuth objects.
|
||||
*/
|
||||
final class PlayerAuthBuilderHelper {
|
||||
|
||||
private PlayerAuthBuilderHelper() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link PlayerAuth} object with the given data.
|
||||
*
|
||||
* @param player the player to create a PlayerAuth for
|
||||
* @param hashedPassword the hashed password
|
||||
* @param email the email address (nullable)
|
||||
* @return the generated PlayerAuth object
|
||||
*/
|
||||
static PlayerAuth createPlayerAuth(Player player, HashedPassword hashedPassword, String email) {
|
||||
return PlayerAuth.builder()
|
||||
.name(player.getName().toLowerCase(Locale.ROOT))
|
||||
.realName(player.getName())
|
||||
.password(hashedPassword)
|
||||
.email(email)
|
||||
.registrationIp(PlayerUtils.getPlayerIp(player))
|
||||
.registrationDate(System.currentTimeMillis())
|
||||
.uuid(player.getUniqueId())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
package fr.xephi.authme.process.register.executors;
|
||||
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
|
||||
/**
|
||||
* Performs the registration action.
|
||||
*
|
||||
* @param <P> the registration parameters type
|
||||
*/
|
||||
public interface RegistrationExecutor<P extends RegistrationParameters> {
|
||||
|
||||
/**
|
||||
* Returns whether the registration may take place. Use this method to execute
|
||||
* checks specific to the registration method.
|
||||
* <p>
|
||||
* If this method returns {@code false}, it is expected that the executor inform
|
||||
* the player about the error within this method call.
|
||||
*
|
||||
* @param params the parameters for the registration
|
||||
* @return true if registration may be performed, false otherwise
|
||||
*/
|
||||
boolean isRegistrationAdmitted(P params);
|
||||
|
||||
/**
|
||||
* Constructs the PlayerAuth object to persist into the database.
|
||||
*
|
||||
* @param params the parameters for the registration
|
||||
* @return the player auth to register in the data source
|
||||
*/
|
||||
PlayerAuth buildPlayerAuth(P params);
|
||||
|
||||
/**
|
||||
* Follow-up method called after the player auth could be added into the database.
|
||||
*
|
||||
* @param params the parameters for the registration
|
||||
*/
|
||||
void executePostPersistAction(P params);
|
||||
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package fr.xephi.authme.process.register.executors;
|
||||
|
||||
/**
|
||||
* Methods with which a player can be registered.
|
||||
* <p>
|
||||
* These constants each define a different way of registering a player and define the
|
||||
* {@link RegistrationParameters parameters} and {@link RegistrationExecutor executor}
|
||||
* classes which perform this registration method. This is essentially a <i>typed enum</i>
|
||||
* as passing a constant of this class along with a parameters object to a method can
|
||||
* be restricted to the correct parameters type.
|
||||
*
|
||||
* @param <P> the registration parameters type the method uses
|
||||
*/
|
||||
public final class RegistrationMethod<P extends RegistrationParameters> {
|
||||
|
||||
/**
|
||||
* Password registration.
|
||||
*/
|
||||
public static final RegistrationMethod<PasswordRegisterParams> PASSWORD_REGISTRATION =
|
||||
new RegistrationMethod<>(PasswordRegisterExecutor.class);
|
||||
|
||||
/**
|
||||
* Registration with two-factor authentication as login means.
|
||||
*/
|
||||
public static final RegistrationMethod<TwoFactorRegisterParams> TWO_FACTOR_REGISTRATION =
|
||||
new RegistrationMethod<>(TwoFactorRegisterExecutor.class);
|
||||
|
||||
/**
|
||||
* Email registration: an email address is provided, to which a generated password is sent.
|
||||
*/
|
||||
public static final RegistrationMethod<EmailRegisterParams> EMAIL_REGISTRATION =
|
||||
new RegistrationMethod<>(EmailRegisterExecutor.class);
|
||||
|
||||
/**
|
||||
* API registration: player and password are provided via an API method.
|
||||
*/
|
||||
public static final RegistrationMethod<ApiPasswordRegisterParams> API_REGISTRATION =
|
||||
new RegistrationMethod<>(ApiPasswordRegisterExecutor.class);
|
||||
|
||||
|
||||
private final Class<? extends RegistrationExecutor<P>> executorClass;
|
||||
|
||||
private RegistrationMethod(Class<? extends RegistrationExecutor<P>> executorClass) {
|
||||
this.executorClass = executorClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the executor class to perform the registration method
|
||||
*/
|
||||
public Class<? extends RegistrationExecutor<P>> getExecutorClass() {
|
||||
return executorClass;
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package fr.xephi.authme.process.register.executors;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/**
|
||||
* Parent of all registration parameters.
|
||||
*/
|
||||
public abstract class RegistrationParameters {
|
||||
|
||||
private final Player player;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param player the player to perform the registration for
|
||||
*/
|
||||
public RegistrationParameters(Player player) {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
public String getPlayerName() {
|
||||
return player.getName();
|
||||
}
|
||||
}
|
||||
-43
@@ -1,43 +0,0 @@
|
||||
package fr.xephi.authme.process.register.executors;
|
||||
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.security.crypts.TwoFactor;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static fr.xephi.authme.process.register.executors.PlayerAuthBuilderHelper.createPlayerAuth;
|
||||
|
||||
/**
|
||||
* Executor for two-factor registration.
|
||||
*/
|
||||
class TwoFactorRegisterExecutor extends AbstractPasswordRegisterExecutor<TwoFactorRegisterParams> {
|
||||
|
||||
@Inject
|
||||
private CommonService commonService;
|
||||
|
||||
@Override
|
||||
public boolean isRegistrationAdmitted(TwoFactorRegisterParams params) {
|
||||
// nothing to check
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PlayerAuth createPlayerAuthObject(TwoFactorRegisterParams params) {
|
||||
return createPlayerAuth(params.getPlayer(), params.getHashedPassword(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executePostPersistAction(TwoFactorRegisterParams params) {
|
||||
super.executePostPersistAction(params);
|
||||
|
||||
// Note ljacqu 20170317: This two-factor registration type is only invoked when the password hash is configured
|
||||
// to two-factor authentication. Therefore, the hashed password is the result of the TwoFactor EncryptionMethod
|
||||
// implementation (contains the TOTP secret).
|
||||
String hash = params.getHashedPassword().getHash();
|
||||
String qrCodeUrl = TwoFactor.getQrBarcodeUrl(params.getPlayerName(), Bukkit.getIp(), hash);
|
||||
commonService.send(params.getPlayer(), MessageKey.TWO_FACTOR_CREATE, hash, qrCodeUrl);
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package fr.xephi.authme.process.register.executors;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/**
|
||||
* Parameters for registration with two-factor authentication.
|
||||
*/
|
||||
public class TwoFactorRegisterParams extends AbstractPasswordRegisterParams {
|
||||
|
||||
protected TwoFactorRegisterParams(Player player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a parameters object.
|
||||
*
|
||||
* @param player the player to register
|
||||
* @return params object with the given player
|
||||
*/
|
||||
public static TwoFactorRegisterParams of(Player player) {
|
||||
return new TwoFactorRegisterParams(player);
|
||||
}
|
||||
}
|
||||
@@ -1,151 +0,0 @@
|
||||
package fr.xephi.authme.process.unregister;
|
||||
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
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.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.process.AsynchronousProcess;
|
||||
import fr.xephi.authme.security.PasswordSecurity;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.service.TeleportationService;
|
||||
import fr.xephi.authme.service.bungeecord.BungeeSender;
|
||||
import fr.xephi.authme.service.bungeecord.MessageType;
|
||||
import fr.xephi.authme.settings.commandconfig.CommandManager;
|
||||
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
||||
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static fr.xephi.authme.service.BukkitService.TICKS_PER_SECOND;
|
||||
|
||||
public class AsynchronousUnregister implements AsynchronousProcess {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(AsynchronousUnregister.class);
|
||||
|
||||
@Inject
|
||||
private DataSource dataSource;
|
||||
|
||||
@Inject
|
||||
private CommonService service;
|
||||
|
||||
@Inject
|
||||
private PasswordSecurity passwordSecurity;
|
||||
|
||||
@Inject
|
||||
private PlayerCache playerCache;
|
||||
|
||||
@Inject
|
||||
private BukkitService bukkitService;
|
||||
|
||||
@Inject
|
||||
private LimboService limboService;
|
||||
|
||||
@Inject
|
||||
private TeleportationService teleportationService;
|
||||
|
||||
@Inject
|
||||
private CommandManager commandManager;
|
||||
|
||||
@Inject
|
||||
private BungeeSender bungeeSender;
|
||||
|
||||
AsynchronousUnregister() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a player's request to unregister himself. Unregisters the player after
|
||||
* successful password check.
|
||||
*
|
||||
* @param player the player
|
||||
* @param password the input password to check before unregister
|
||||
*/
|
||||
public void unregister(Player player, String password) {
|
||||
String name = player.getName();
|
||||
PlayerAuth cachedAuth = playerCache.getAuth(name);
|
||||
if (passwordSecurity.comparePassword(password, cachedAuth.getPassword(), name)) {
|
||||
if (dataSource.removeAuth(name)) {
|
||||
performPostUnregisterActions(name, player);
|
||||
logger.info(name + " unregistered himself");
|
||||
bukkitService.createAndCallEvent(isAsync -> new UnregisterByPlayerEvent(player, isAsync));
|
||||
} else {
|
||||
service.send(player, MessageKey.ERROR);
|
||||
}
|
||||
} else {
|
||||
service.send(player, MessageKey.WRONG_PASSWORD);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters a player as administrator or console.
|
||||
*
|
||||
* @param initiator the initiator of this process (nullable)
|
||||
* @param name the name of the player
|
||||
* @param player the according Player object (nullable)
|
||||
*/
|
||||
// We need to have the name and the player separate because Player might be null in this case:
|
||||
// we might have some player in the database that has never been online on the server
|
||||
public void adminUnregister(CommandSender initiator, String name, Player player) {
|
||||
if (dataSource.removeAuth(name)) {
|
||||
performPostUnregisterActions(name, player);
|
||||
bukkitService.createAndCallEvent(isAsync -> new UnregisterByAdminEvent(player, name, isAsync, initiator));
|
||||
|
||||
if (initiator == null) {
|
||||
logger.info(name + " was unregistered");
|
||||
} else {
|
||||
logger.info(name + " was unregistered by " + initiator.getName());
|
||||
service.send(initiator, MessageKey.UNREGISTERED_SUCCESS);
|
||||
}
|
||||
} else if (initiator != null) {
|
||||
service.send(initiator, MessageKey.ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the post unregister actions. Makes the user status consistent.
|
||||
*
|
||||
* @param name the name of the player
|
||||
* @param player the according Player object (nullable)
|
||||
*/
|
||||
private void performPostUnregisterActions(String name, Player player) {
|
||||
if (player != null && playerCache.isAuthenticated(name)) {
|
||||
bungeeSender.sendAuthMeBungeecordMessage(player, MessageType.LOGOUT);
|
||||
}
|
||||
playerCache.removePlayer(name);
|
||||
|
||||
// TODO: send an update when a messaging service will be implemented (UNREGISTER)
|
||||
|
||||
if (player == null || !player.isOnline()) {
|
||||
return;
|
||||
}
|
||||
bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(() ->
|
||||
commandManager.runCommandsOnUnregister(player));
|
||||
|
||||
if (service.getProperty(RegistrationSettings.FORCE)) {
|
||||
teleportationService.teleportOnJoin(player);
|
||||
|
||||
bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(() -> {
|
||||
limboService.createLimboPlayer(player, false);
|
||||
applyBlindEffect(player);
|
||||
});
|
||||
}
|
||||
service.send(player, MessageKey.UNREGISTERED_SUCCESS);
|
||||
}
|
||||
|
||||
private void applyBlindEffect(Player player) {
|
||||
if (service.getProperty(RegistrationSettings.APPLY_BLIND_EFFECT)) {
|
||||
int timeout = service.getProperty(RestrictionSettings.TIMEOUT) * TICKS_PER_SECOND;
|
||||
player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, timeout, 2));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user