Remove all files
This commit is contained in:
@@ -1,64 +0,0 @@
|
||||
package fr.xephi.authme.command.executable;
|
||||
|
||||
import fr.xephi.authme.command.CommandMapper;
|
||||
import fr.xephi.authme.command.CommandUtils;
|
||||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.command.FoundCommandResult;
|
||||
import fr.xephi.authme.command.FoundResultStatus;
|
||||
import fr.xephi.authme.command.help.HelpProvider;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
import static fr.xephi.authme.command.FoundResultStatus.MISSING_BASE_COMMAND;
|
||||
import static fr.xephi.authme.command.FoundResultStatus.UNKNOWN_LABEL;
|
||||
import static fr.xephi.authme.command.help.HelpProvider.ALL_OPTIONS;
|
||||
import static fr.xephi.authme.command.help.HelpProvider.SHOW_ALTERNATIVES;
|
||||
import static fr.xephi.authme.command.help.HelpProvider.SHOW_CHILDREN;
|
||||
import static fr.xephi.authme.command.help.HelpProvider.SHOW_COMMAND;
|
||||
import static fr.xephi.authme.command.help.HelpProvider.SHOW_DESCRIPTION;
|
||||
|
||||
/**
|
||||
* Displays help information to a user.
|
||||
*/
|
||||
public class HelpCommand implements ExecutableCommand {
|
||||
|
||||
@Inject
|
||||
private CommandMapper commandMapper;
|
||||
|
||||
@Inject
|
||||
private HelpProvider helpProvider;
|
||||
|
||||
|
||||
// Convention: arguments is not the actual invoked arguments but the command that was invoked,
|
||||
// e.g. "/authme help register" would typically be arguments = [register], but here we pass [authme, register]
|
||||
@Override
|
||||
public void executeCommand(CommandSender sender, List<String> arguments) {
|
||||
FoundCommandResult result = commandMapper.mapPartsToCommand(sender, arguments);
|
||||
|
||||
FoundResultStatus resultStatus = result.getResultStatus();
|
||||
if (MISSING_BASE_COMMAND.equals(resultStatus)) {
|
||||
sender.sendMessage(ChatColor.DARK_RED + "Could not get base command");
|
||||
return;
|
||||
} else if (UNKNOWN_LABEL.equals(resultStatus)) {
|
||||
if (result.getCommandDescription() == null) {
|
||||
sender.sendMessage(ChatColor.DARK_RED + "Unknown command");
|
||||
return;
|
||||
} else {
|
||||
sender.sendMessage(ChatColor.GOLD + "Assuming " + ChatColor.WHITE
|
||||
+ CommandUtils.constructCommandPath(result.getCommandDescription()));
|
||||
}
|
||||
}
|
||||
|
||||
int mappedCommandLevel = result.getCommandDescription().getLabelCount();
|
||||
if (mappedCommandLevel == 1) {
|
||||
helpProvider.outputHelp(sender, result,
|
||||
SHOW_COMMAND | SHOW_DESCRIPTION | SHOW_CHILDREN | SHOW_ALTERNATIVES);
|
||||
} else {
|
||||
helpProvider.outputHelp(sender, result, ALL_OPTIONS);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.authme;
|
||||
|
||||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Shows all accounts registered by the same IP address for the given player name or IP address.
|
||||
*/
|
||||
public class AccountsCommand implements ExecutableCommand {
|
||||
|
||||
@Inject
|
||||
private DataSource dataSource;
|
||||
|
||||
@Inject
|
||||
private BukkitService bukkitService;
|
||||
|
||||
@Inject
|
||||
private CommonService commonService;
|
||||
|
||||
@Override
|
||||
public void executeCommand(final CommandSender sender, List<String> arguments) {
|
||||
// TODO #1366: last IP vs. registration IP?
|
||||
final String playerName = arguments.isEmpty() ? sender.getName() : arguments.get(0);
|
||||
|
||||
// Assumption: a player name cannot contain '.'
|
||||
if (playerName.contains(".")) {
|
||||
bukkitService.runTaskAsynchronously(() -> {
|
||||
List<String> accountList = dataSource.getAllAuthsByIp(playerName);
|
||||
if (accountList.isEmpty()) {
|
||||
sender.sendMessage("[AuthMe] This IP does not exist in the database.");
|
||||
} else if (accountList.size() == 1) {
|
||||
sender.sendMessage("[AuthMe] " + playerName + " is a single account player");
|
||||
} else {
|
||||
outputAccountsList(sender, playerName, accountList);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
bukkitService.runTaskAsynchronously(() -> {
|
||||
PlayerAuth auth = dataSource.getAuth(playerName.toLowerCase(Locale.ROOT));
|
||||
if (auth == null) {
|
||||
commonService.send(sender, MessageKey.UNKNOWN_USER);
|
||||
return;
|
||||
} else if (auth.getLastIp() == null) {
|
||||
sender.sendMessage("No known last IP address for player");
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> accountList = dataSource.getAllAuthsByIp(auth.getLastIp());
|
||||
if (accountList.isEmpty()) {
|
||||
commonService.send(sender, MessageKey.UNKNOWN_USER);
|
||||
} else if (accountList.size() == 1) {
|
||||
sender.sendMessage("[AuthMe] " + playerName + " is a single account player");
|
||||
} else {
|
||||
outputAccountsList(sender, playerName, accountList);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static void outputAccountsList(CommandSender sender, String playerName, List<String> accountList) {
|
||||
sender.sendMessage("[AuthMe] " + playerName + " has " + accountList.size() + " accounts.");
|
||||
String message = "[AuthMe] " + String.join(", ", accountList) + ".";
|
||||
sender.sendMessage(message);
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.authme;
|
||||
|
||||
import fr.xephi.authme.AuthMe;
|
||||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* AuthMe base command; shows the version and some command pointers.
|
||||
*/
|
||||
public class AuthMeCommand implements ExecutableCommand {
|
||||
|
||||
@Override
|
||||
public void executeCommand(CommandSender sender, List<String> arguments) {
|
||||
sender.sendMessage(ChatColor.GREEN + "This server is running " + AuthMe.getPluginName() + " v"
|
||||
+ AuthMe.getPluginVersion() + " b" + AuthMe.getPluginBuildNumber()+ "! " + ChatColor.RED + "<3");
|
||||
sender.sendMessage(ChatColor.YELLOW + "Use the command " + ChatColor.GOLD + "/authme help" + ChatColor.YELLOW
|
||||
+ " to view help.");
|
||||
sender.sendMessage(ChatColor.YELLOW + "Use the command " + ChatColor.GOLD + "/authme about" + ChatColor.YELLOW
|
||||
+ " to view about.");
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.authme;
|
||||
|
||||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.service.BackupService;
|
||||
import fr.xephi.authme.service.BackupService.BackupCause;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Command to perform a backup.
|
||||
*/
|
||||
public class BackupCommand implements ExecutableCommand {
|
||||
|
||||
@Inject
|
||||
private BackupService backupService;
|
||||
|
||||
@Override
|
||||
public void executeCommand(CommandSender sender, List<String> arguments) {
|
||||
backupService.doBackup(BackupCause.COMMAND, sender);
|
||||
}
|
||||
}
|
||||
-41
@@ -1,41 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.authme;
|
||||
|
||||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.process.Management;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.service.ValidationService;
|
||||
import fr.xephi.authme.service.ValidationService.ValidationResult;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Admin command for changing a player's password.
|
||||
*/
|
||||
public class ChangePasswordAdminCommand implements ExecutableCommand {
|
||||
|
||||
@Inject
|
||||
private ValidationService validationService;
|
||||
|
||||
@Inject
|
||||
private CommonService commonService;
|
||||
|
||||
@Inject
|
||||
private Management management;
|
||||
|
||||
@Override
|
||||
public void executeCommand(CommandSender sender, List<String> arguments) {
|
||||
// Get the player and password
|
||||
final String playerName = arguments.get(0);
|
||||
final String playerPass = arguments.get(1);
|
||||
|
||||
// Validate the password
|
||||
ValidationResult validationResult = validationService.validatePassword(playerPass, playerName);
|
||||
if (validationResult.hasError()) {
|
||||
commonService.send(sender, validationResult.getMessageKey(), validationResult.getArgs());
|
||||
} else {
|
||||
management.performPasswordChangeAsAdmin(sender, playerName, playerPass);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.authme;
|
||||
|
||||
import ch.jalu.injector.factory.Factory;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.datasource.converter.Converter;
|
||||
import fr.xephi.authme.datasource.converter.CrazyLoginConverter;
|
||||
import fr.xephi.authme.datasource.converter.LoginSecurityConverter;
|
||||
import fr.xephi.authme.datasource.converter.MySqlToSqlite;
|
||||
import fr.xephi.authme.datasource.converter.RakamakConverter;
|
||||
import fr.xephi.authme.datasource.converter.RoyalAuthConverter;
|
||||
import fr.xephi.authme.datasource.converter.SqliteToSql;
|
||||
import fr.xephi.authme.datasource.converter.VAuthConverter;
|
||||
import fr.xephi.authme.datasource.converter.XAuthConverter;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Converter command: launches conversion based on its parameters.
|
||||
*/
|
||||
public class ConverterCommand implements ExecutableCommand {
|
||||
|
||||
@VisibleForTesting
|
||||
static final Map<String, Class<? extends Converter>> CONVERTERS = getConverters();
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(ConverterCommand.class);
|
||||
|
||||
@Inject
|
||||
private CommonService commonService;
|
||||
|
||||
@Inject
|
||||
private BukkitService bukkitService;
|
||||
|
||||
@Inject
|
||||
private Factory<Converter> converterFactory;
|
||||
|
||||
@Override
|
||||
public void executeCommand(CommandSender sender, List<String> arguments) {
|
||||
Class<? extends Converter> converterClass = getConverterClassFromArgs(arguments);
|
||||
if (converterClass == null) {
|
||||
sender.sendMessage("Converters: " + String.join(", ", CONVERTERS.keySet()));
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the proper converter instance
|
||||
final Converter converter = converterFactory.newInstance(converterClass);
|
||||
|
||||
// Run the convert job
|
||||
bukkitService.runTaskAsynchronously(() -> {
|
||||
try {
|
||||
converter.execute(sender);
|
||||
} catch (Exception e) {
|
||||
commonService.send(sender, MessageKey.ERROR);
|
||||
logger.logException("Error during conversion:", e);
|
||||
}
|
||||
});
|
||||
|
||||
// Show a status message
|
||||
sender.sendMessage("[AuthMe] Successfully started " + arguments.get(0));
|
||||
}
|
||||
|
||||
private static Class<? extends Converter> getConverterClassFromArgs(List<String> arguments) {
|
||||
return arguments.isEmpty()
|
||||
? null
|
||||
: CONVERTERS.get(arguments.get(0).toLowerCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes a map with all available converters.
|
||||
*
|
||||
* @return map with all available converters
|
||||
*/
|
||||
private static Map<String, Class<? extends Converter>> getConverters() {
|
||||
return ImmutableSortedMap.<String, Class<? extends Converter>>naturalOrder()
|
||||
.put("xauth", XAuthConverter.class)
|
||||
.put("crazylogin", CrazyLoginConverter.class)
|
||||
.put("rakamak", RakamakConverter.class)
|
||||
.put("royalauth", RoyalAuthConverter.class)
|
||||
.put("vauth", VAuthConverter.class)
|
||||
.put("sqlitetosql", SqliteToSql.class)
|
||||
.put("mysqltosqlite", MySqlToSqlite.class)
|
||||
.put("loginsecurity", LoginSecurityConverter.class)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.authme;
|
||||
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.command.PlayerCommand;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.SpawnLoader;
|
||||
import fr.xephi.authme.settings.properties.SecuritySettings;
|
||||
import fr.xephi.authme.util.TeleportUtils;
|
||||
import org.bukkit.entity.Player;
|
||||
import fr.xephi.authme.AuthMe;
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Teleports the player to the first spawn.
|
||||
*/
|
||||
public class FirstSpawnCommand extends PlayerCommand {
|
||||
@Inject
|
||||
private Settings settings;
|
||||
@Inject
|
||||
private SpawnLoader spawnLoader;
|
||||
@Override
|
||||
public void runCommand(Player player, List<String> arguments) {
|
||||
if (spawnLoader.getFirstSpawn() == null) {
|
||||
player.sendMessage("[AuthMe] First spawn has failed, please try to define the first spawn");
|
||||
} else {
|
||||
//String name= player.getName();
|
||||
if(AuthMe.SATEnabled) {
|
||||
TeleportUtils.teleport(player, spawnLoader.getFirstSpawn());
|
||||
} else {
|
||||
player.teleport(spawnLoader.getFirstSpawn());
|
||||
}
|
||||
//player.teleport(spawnLoader.getFirstSpawn());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.authme;
|
||||
|
||||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.permission.PermissionsManager;
|
||||
import fr.xephi.authme.process.Management;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
import static fr.xephi.authme.permission.PlayerPermission.CAN_LOGIN_BE_FORCED;
|
||||
|
||||
/**
|
||||
* Forces the login of a player, i.e. logs the player in without the need of a (correct) password.
|
||||
*/
|
||||
public class ForceLoginCommand implements ExecutableCommand {
|
||||
|
||||
@Inject
|
||||
private PermissionsManager permissionsManager;
|
||||
|
||||
@Inject
|
||||
private Management management;
|
||||
|
||||
@Inject
|
||||
private BukkitService bukkitService;
|
||||
|
||||
@Override
|
||||
public void executeCommand(CommandSender sender, List<String> arguments) {
|
||||
// Get the player query
|
||||
String playerName = arguments.isEmpty() ? sender.getName() : arguments.get(0);
|
||||
|
||||
Player player = bukkitService.getPlayerExact(playerName);
|
||||
if (player == null || !player.isOnline()) {
|
||||
sender.sendMessage("Player needs to be online!");
|
||||
} else if (!permissionsManager.hasPermission(player, CAN_LOGIN_BE_FORCED)) {
|
||||
sender.sendMessage("You cannot force login the player " + playerName + "!");
|
||||
} else {
|
||||
management.forceLogin(player);
|
||||
sender.sendMessage("Force login for " + playerName + " performed!");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.authme;
|
||||
|
||||
import ch.jalu.datasourcecolumns.data.DataSourceValue;
|
||||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Returns a player's email.
|
||||
*/
|
||||
public class GetEmailCommand implements ExecutableCommand {
|
||||
|
||||
@Inject
|
||||
private DataSource dataSource;
|
||||
|
||||
@Inject
|
||||
private CommonService commonService;
|
||||
|
||||
@Override
|
||||
public void executeCommand(CommandSender sender, List<String> arguments) {
|
||||
String playerName = arguments.isEmpty() ? sender.getName() : arguments.get(0);
|
||||
|
||||
DataSourceValue<String> email = dataSource.getEmail(playerName);
|
||||
if (email.rowExists()) {
|
||||
sender.sendMessage("[AuthMe] " + playerName + "'s email: " + email.getValue());
|
||||
} else {
|
||||
commonService.send(sender, MessageKey.UNKNOWN_USER);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.authme;
|
||||
|
||||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.util.PlayerUtils;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
public class GetIpCommand implements ExecutableCommand {
|
||||
|
||||
@Inject
|
||||
private BukkitService bukkitService;
|
||||
|
||||
@Inject
|
||||
private DataSource dataSource;
|
||||
|
||||
@Override
|
||||
public void executeCommand(CommandSender sender, List<String> arguments) {
|
||||
String playerName = arguments.get(0);
|
||||
Player player = bukkitService.getPlayerExact(playerName);
|
||||
PlayerAuth auth = dataSource.getAuth(playerName);
|
||||
|
||||
if (player != null) {
|
||||
sender.sendMessage("Current IP of " + player.getName() + " is " + PlayerUtils.getPlayerIp(player)
|
||||
+ ":" + player.getAddress().getPort());
|
||||
}
|
||||
|
||||
if (auth == null) {
|
||||
String displayName = player == null ? playerName : player.getName();
|
||||
sender.sendMessage(displayName + " is not registered in the database");
|
||||
} else {
|
||||
sender.sendMessage("Database: last IP: " + auth.getLastIp() + ", registration IP: "
|
||||
+ auth.getRegistrationIp());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.authme;
|
||||
|
||||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Returns the last login date of the given user.
|
||||
*/
|
||||
public class LastLoginCommand implements ExecutableCommand {
|
||||
|
||||
@Inject
|
||||
private DataSource dataSource;
|
||||
|
||||
@Inject
|
||||
private CommonService commonService;
|
||||
|
||||
@Override
|
||||
public void executeCommand(CommandSender sender, List<String> arguments) {
|
||||
// Get the player
|
||||
String playerName = arguments.isEmpty() ? sender.getName() : arguments.get(0);
|
||||
|
||||
PlayerAuth auth = dataSource.getAuth(playerName);
|
||||
if (auth == null) {
|
||||
commonService.send(sender, MessageKey.UNKNOWN_USER);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the last login date
|
||||
final Long lastLogin = auth.getLastLogin();
|
||||
final String lastLoginDate = lastLogin == null ? "never" : new Date(lastLogin).toString();
|
||||
|
||||
// Show the player status
|
||||
sender.sendMessage("[AuthMe] " + playerName + " last login: " + lastLoginDate);
|
||||
if (lastLogin != null) {
|
||||
sender.sendMessage("[AuthMe] The player " + playerName + " last logged in "
|
||||
+ createLastLoginIntervalMessage(lastLogin) + " ago");
|
||||
}
|
||||
sender.sendMessage("[AuthMe] Last player's IP: " + auth.getLastIp());
|
||||
}
|
||||
|
||||
private static String createLastLoginIntervalMessage(long lastLogin) {
|
||||
final long diff = System.currentTimeMillis() - lastLogin;
|
||||
return (int) (diff / 86400000) + " days "
|
||||
+ (int) (diff / 3600000 % 24) + " hours "
|
||||
+ (int) (diff / 60000 % 60) + " mins "
|
||||
+ (int) (diff / 1000 % 60) + " secs";
|
||||
}
|
||||
}
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.authme;
|
||||
|
||||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.task.purge.PurgeService;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Command for purging data of banned players. Depending on the settings
|
||||
* it purges (deletes) data from third-party plugins as well.
|
||||
*/
|
||||
public class PurgeBannedPlayersCommand implements ExecutableCommand {
|
||||
|
||||
@Inject
|
||||
private PurgeService purgeService;
|
||||
|
||||
@Inject
|
||||
private BukkitService bukkitService;
|
||||
|
||||
@Override
|
||||
public void executeCommand(CommandSender sender, List<String> arguments) {
|
||||
// Get the list of banned players
|
||||
Set<OfflinePlayer> bannedPlayers = bukkitService.getBannedPlayers();
|
||||
Set<String> namedBanned = new HashSet<>(bannedPlayers.size());
|
||||
for (OfflinePlayer offlinePlayer : bannedPlayers) {
|
||||
namedBanned.add(offlinePlayer.getName().toLowerCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
purgeService.purgePlayers(sender, namedBanned, bannedPlayers.toArray(new OfflinePlayer[bannedPlayers.size()]));
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.authme;
|
||||
|
||||
import com.google.common.primitives.Ints;
|
||||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.task.purge.PurgeService;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Command for purging the data of players which have not been online for a given number
|
||||
* of days. Depending on the settings, this removes player data in third-party plugins as well.
|
||||
*/
|
||||
public class PurgeCommand implements ExecutableCommand {
|
||||
|
||||
private static final int MINIMUM_LAST_SEEN_DAYS = 30;
|
||||
|
||||
@Inject
|
||||
private PurgeService purgeService;
|
||||
|
||||
@Override
|
||||
public void executeCommand(CommandSender sender, List<String> arguments) {
|
||||
// Get the days parameter
|
||||
String daysStr = arguments.get(0);
|
||||
|
||||
// Convert the days string to an integer value, and make sure it's valid
|
||||
Integer days = Ints.tryParse(daysStr);
|
||||
if (days == null) {
|
||||
sender.sendMessage(ChatColor.RED + "The value you've entered is invalid!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate the value
|
||||
if (days < MINIMUM_LAST_SEEN_DAYS) {
|
||||
sender.sendMessage(ChatColor.RED + "You can only purge data older than "
|
||||
+ MINIMUM_LAST_SEEN_DAYS + " days");
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a calender instance to determine the date
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.add(Calendar.DATE, -days);
|
||||
long until = calendar.getTimeInMillis();
|
||||
|
||||
// Run the purge
|
||||
purgeService.runPurge(sender, until);
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.authme;
|
||||
|
||||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Removes the stored last position of a user or of all.
|
||||
*/
|
||||
public class PurgeLastPositionCommand implements ExecutableCommand {
|
||||
|
||||
@Inject
|
||||
private DataSource dataSource;
|
||||
|
||||
@Inject
|
||||
private CommonService commonService;
|
||||
|
||||
@Override
|
||||
public void executeCommand(CommandSender sender, List<String> arguments) {
|
||||
String playerName = arguments.isEmpty() ? sender.getName() : arguments.get(0);
|
||||
|
||||
if ("*".equals(playerName)) {
|
||||
for (PlayerAuth auth : dataSource.getAllAuths()) {
|
||||
resetLastPosition(auth);
|
||||
dataSource.updateQuitLoc(auth);
|
||||
// TODO: send an update when a messaging service will be implemented (QUITLOC)
|
||||
}
|
||||
sender.sendMessage("All players last position locations are now reset");
|
||||
} else {
|
||||
// Get the user auth and make sure the user exists
|
||||
PlayerAuth auth = dataSource.getAuth(playerName);
|
||||
if (auth == null) {
|
||||
commonService.send(sender, MessageKey.UNKNOWN_USER);
|
||||
return;
|
||||
}
|
||||
|
||||
resetLastPosition(auth);
|
||||
dataSource.updateQuitLoc(auth);
|
||||
// TODO: send an update when a messaging service will be implemented (QUITLOC)
|
||||
sender.sendMessage(playerName + "'s last position location is now reset");
|
||||
}
|
||||
}
|
||||
|
||||
private static void resetLastPosition(PlayerAuth auth) {
|
||||
auth.setQuitLocX(0d);
|
||||
auth.setQuitLocY(0d);
|
||||
auth.setQuitLocZ(0d);
|
||||
auth.setWorld("world");
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.authme;
|
||||
|
||||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.task.purge.PurgeExecutor;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import static java.util.Collections.singletonList;
|
||||
|
||||
/**
|
||||
* Command to purge a player.
|
||||
*/
|
||||
public class PurgePlayerCommand implements ExecutableCommand {
|
||||
|
||||
@Inject
|
||||
private PurgeExecutor purgeExecutor;
|
||||
|
||||
@Inject
|
||||
private BukkitService bukkitService;
|
||||
|
||||
@Inject
|
||||
private DataSource dataSource;
|
||||
|
||||
@Override
|
||||
public void executeCommand(CommandSender sender, List<String> arguments) {
|
||||
String option = arguments.size() > 1 ? arguments.get(1) : null;
|
||||
bukkitService.runTaskAsynchronously(
|
||||
() -> executeCommand(sender, arguments.get(0), option));
|
||||
}
|
||||
|
||||
private void executeCommand(CommandSender sender, String name, String option) {
|
||||
if ("force".equals(option) || !dataSource.isAuthAvailable(name)) {
|
||||
OfflinePlayer offlinePlayer = bukkitService.getOfflinePlayer(name);
|
||||
purgeExecutor.executePurge(singletonList(offlinePlayer), singletonList(name.toLowerCase(Locale.ROOT)));
|
||||
sender.sendMessage("Purged data for player " + name);
|
||||
} else {
|
||||
sender.sendMessage("This player is still registered! Are you sure you want to proceed? "
|
||||
+ "Use '/authme purgeplayer " + name + " force' to run the command anyway");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.authme;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
|
||||
import static java.time.Instant.ofEpochMilli;
|
||||
|
||||
/**
|
||||
* Command showing the most recent logged in players.
|
||||
*/
|
||||
public class RecentPlayersCommand implements ExecutableCommand {
|
||||
|
||||
/** DateTime formatter, producing Strings such as "10:42 AM, 11 Jul". */
|
||||
private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("hh:mm a, dd MMM");
|
||||
|
||||
@Inject
|
||||
private DataSource dataSource;
|
||||
|
||||
@Override
|
||||
public void executeCommand(CommandSender sender, List<String> arguments) {
|
||||
List<PlayerAuth> recentPlayers = dataSource.getRecentlyLoggedInPlayers();
|
||||
|
||||
sender.sendMessage(ChatColor.BLUE + "[AuthMe] Recently logged in players");
|
||||
for (PlayerAuth auth : recentPlayers) {
|
||||
sender.sendMessage(formatPlayerMessage(auth));
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
ZoneId getZoneId() {
|
||||
return ZoneId.systemDefault();
|
||||
}
|
||||
|
||||
private String formatPlayerMessage(PlayerAuth auth) {
|
||||
String lastLoginText;
|
||||
if (auth.getLastLogin() == null) {
|
||||
lastLoginText = "never";
|
||||
} else {
|
||||
LocalDateTime lastLogin = LocalDateTime.ofInstant(ofEpochMilli(auth.getLastLogin()), getZoneId());
|
||||
lastLoginText = DATE_FORMAT.format(lastLogin);
|
||||
}
|
||||
|
||||
return "- " + auth.getRealName() + " (" + lastLoginText + " with IP " + auth.getLastIp() + ")";
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.authme;
|
||||
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
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.service.ValidationService.ValidationResult;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Admin command to register a user.
|
||||
*/
|
||||
public class RegisterAdminCommand implements ExecutableCommand {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(RegisterAdminCommand.class);
|
||||
|
||||
@Inject
|
||||
private PasswordSecurity passwordSecurity;
|
||||
|
||||
@Inject
|
||||
private CommonService commonService;
|
||||
|
||||
@Inject
|
||||
private DataSource dataSource;
|
||||
|
||||
@Inject
|
||||
private BukkitService bukkitService;
|
||||
|
||||
@Inject
|
||||
private ValidationService validationService;
|
||||
|
||||
@Override
|
||||
public void executeCommand(final CommandSender sender, List<String> arguments) {
|
||||
// Get the player name and password
|
||||
final String playerName = arguments.get(0);
|
||||
final String playerPass = arguments.get(1);
|
||||
final String playerNameLowerCase = playerName.toLowerCase(Locale.ROOT);
|
||||
|
||||
// Command logic
|
||||
ValidationResult passwordValidation = validationService.validatePassword(playerPass, playerName);
|
||||
if (passwordValidation.hasError()) {
|
||||
commonService.send(sender, passwordValidation.getMessageKey(), passwordValidation.getArgs());
|
||||
return;
|
||||
}
|
||||
|
||||
bukkitService.runTaskOptionallyAsync(() -> {
|
||||
if (dataSource.isAuthAvailable(playerNameLowerCase)) {
|
||||
commonService.send(sender, MessageKey.NAME_ALREADY_REGISTERED);
|
||||
return;
|
||||
}
|
||||
HashedPassword hashedPassword = passwordSecurity.computeHash(playerPass, playerNameLowerCase);
|
||||
PlayerAuth auth = PlayerAuth.builder()
|
||||
.name(playerNameLowerCase)
|
||||
.realName(playerName)
|
||||
.password(hashedPassword)
|
||||
.registrationDate(System.currentTimeMillis())
|
||||
.build();
|
||||
|
||||
if (!dataSource.saveAuth(auth)) {
|
||||
commonService.send(sender, MessageKey.ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
commonService.send(sender, MessageKey.REGISTER_SUCCESS);
|
||||
logger.info(sender.getName() + " registered " + playerName);
|
||||
final Player player = bukkitService.getPlayerExact(playerName);
|
||||
if (player != null) {
|
||||
bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(() ->
|
||||
player.kickPlayer(commonService.retrieveSingleMessage(player, MessageKey.KICK_FOR_ADMIN_REGISTER)));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.authme;
|
||||
|
||||
import ch.jalu.injector.factory.SingletonStore;
|
||||
import fr.xephi.authme.AuthMe;
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.initialization.Reloadable;
|
||||
import fr.xephi.authme.initialization.SettingsDependent;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.SettingsWarner;
|
||||
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
||||
import fr.xephi.authme.util.Utils;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The reload command.
|
||||
*/
|
||||
public class ReloadCommand implements ExecutableCommand {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(ReloadCommand.class);
|
||||
|
||||
@Inject
|
||||
private AuthMe plugin;
|
||||
|
||||
@Inject
|
||||
private Settings settings;
|
||||
|
||||
@Inject
|
||||
private DataSource dataSource;
|
||||
|
||||
@Inject
|
||||
private CommonService commonService;
|
||||
|
||||
@Inject
|
||||
private SettingsWarner settingsWarner;
|
||||
|
||||
@Inject
|
||||
private SingletonStore<Reloadable> reloadableStore;
|
||||
|
||||
@Inject
|
||||
private SingletonStore<SettingsDependent> settingsDependentStore;
|
||||
|
||||
@Override
|
||||
public void executeCommand(CommandSender sender, List<String> arguments) {
|
||||
try {
|
||||
settings.reload();
|
||||
ConsoleLoggerFactory.reloadSettings(settings);
|
||||
settingsWarner.logWarningsForMisconfigurations();
|
||||
|
||||
// We do not change database type for consistency issues, but we'll output a note in the logs
|
||||
if (!settings.getProperty(DatabaseSettings.BACKEND).equals(dataSource.getType())) {
|
||||
Utils.logAndSendMessage(sender, "Note: cannot change database type during /authme reload");
|
||||
}
|
||||
performReloadOnServices();
|
||||
commonService.send(sender, MessageKey.CONFIG_RELOAD_SUCCESS);
|
||||
} catch (Exception e) {
|
||||
sender.sendMessage("Error occurred during reload of AuthMe: aborting");
|
||||
logger.logException("Aborting! Encountered exception during reload of AuthMe:", e);
|
||||
plugin.stopOrUnload();
|
||||
}
|
||||
}
|
||||
|
||||
private void performReloadOnServices() {
|
||||
reloadableStore.retrieveAllOfType()
|
||||
.forEach(r -> r.reload());
|
||||
|
||||
settingsDependentStore.retrieveAllOfType()
|
||||
.forEach(s -> s.reload(settings));
|
||||
}
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.authme;
|
||||
|
||||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
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.service.BukkitService;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.service.ValidationService;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Admin command for setting an email to an account.
|
||||
*/
|
||||
public class SetEmailCommand implements ExecutableCommand {
|
||||
|
||||
@Inject
|
||||
private DataSource dataSource;
|
||||
|
||||
@Inject
|
||||
private CommonService commonService;
|
||||
|
||||
@Inject
|
||||
private PlayerCache playerCache;
|
||||
|
||||
@Inject
|
||||
private BukkitService bukkitService;
|
||||
|
||||
@Inject
|
||||
private ValidationService validationService;
|
||||
|
||||
@Override
|
||||
public void executeCommand(final CommandSender sender, List<String> arguments) {
|
||||
// Get the player name and email address
|
||||
final String playerName = arguments.get(0);
|
||||
final String playerEmail = arguments.get(1);
|
||||
|
||||
// Validate the email address
|
||||
if (!validationService.validateEmail(playerEmail)) {
|
||||
commonService.send(sender, MessageKey.INVALID_EMAIL);
|
||||
return;
|
||||
}
|
||||
|
||||
bukkitService.runTaskOptionallyAsync(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Validate the user
|
||||
PlayerAuth auth = dataSource.getAuth(playerName);
|
||||
if (auth == null) {
|
||||
commonService.send(sender, MessageKey.UNKNOWN_USER);
|
||||
return;
|
||||
} else if (!validationService.isEmailFreeForRegistration(playerEmail, sender)) {
|
||||
commonService.send(sender, MessageKey.EMAIL_ALREADY_USED_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the email address
|
||||
auth.setEmail(playerEmail);
|
||||
if (!dataSource.updateEmail(auth)) {
|
||||
commonService.send(sender, MessageKey.ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
// Update the player cache
|
||||
if (playerCache.getAuth(playerName) != null) {
|
||||
playerCache.updatePlayer(auth);
|
||||
}
|
||||
|
||||
// Show a status message
|
||||
commonService.send(sender, MessageKey.EMAIL_CHANGED_SUCCESS);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.authme;
|
||||
|
||||
import fr.xephi.authme.command.PlayerCommand;
|
||||
import fr.xephi.authme.settings.SpawnLoader;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
public class SetFirstSpawnCommand extends PlayerCommand {
|
||||
|
||||
@Inject
|
||||
private SpawnLoader spawnLoader;
|
||||
|
||||
@Override
|
||||
public void runCommand(Player player, List<String> arguments) {
|
||||
if (spawnLoader.setFirstSpawn(player.getLocation())) {
|
||||
player.sendMessage("[AuthMe] Correctly defined new first spawn point");
|
||||
} else {
|
||||
player.sendMessage("[AuthMe] SetFirstSpawn has failed, please retry");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.authme;
|
||||
|
||||
import fr.xephi.authme.command.PlayerCommand;
|
||||
import fr.xephi.authme.settings.SpawnLoader;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
public class SetSpawnCommand extends PlayerCommand {
|
||||
|
||||
@Inject
|
||||
private SpawnLoader spawnLoader;
|
||||
|
||||
@Override
|
||||
public void runCommand(Player player, List<String> arguments) {
|
||||
if (spawnLoader.setSpawn(player.getLocation())) {
|
||||
player.sendMessage("[AuthMe] Correctly defined new spawn point");
|
||||
} else {
|
||||
player.sendMessage("[AuthMe] SetSpawn has failed, please retry");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.authme;
|
||||
|
||||
import fr.xephi.authme.command.PlayerCommand;
|
||||
import fr.xephi.authme.settings.SpawnLoader;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
public class SpawnCommand extends PlayerCommand {
|
||||
|
||||
@Inject
|
||||
private SpawnLoader spawnLoader;
|
||||
|
||||
@Override
|
||||
public void runCommand(Player player, List<String> arguments) {
|
||||
if (spawnLoader.getSpawn() == null) {
|
||||
player.sendMessage("[AuthMe] Spawn has failed, please try to define the spawn");
|
||||
} else {
|
||||
player.teleport(spawnLoader.getSpawn());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.authme;
|
||||
|
||||
import fr.xephi.authme.command.CommandMapper;
|
||||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.command.FoundCommandResult;
|
||||
import fr.xephi.authme.command.help.HelpProvider;
|
||||
import fr.xephi.authme.service.AntiBotService;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Display or change the status of the antibot mod.
|
||||
*/
|
||||
public class SwitchAntiBotCommand implements ExecutableCommand {
|
||||
|
||||
@Inject
|
||||
private AntiBotService antiBotService;
|
||||
|
||||
@Inject
|
||||
private CommandMapper commandMapper;
|
||||
|
||||
@Inject
|
||||
private HelpProvider helpProvider;
|
||||
|
||||
@Override
|
||||
public void executeCommand(final CommandSender sender, List<String> arguments) {
|
||||
if (arguments.isEmpty()) {
|
||||
sender.sendMessage("[AuthMe] AntiBot status: " + antiBotService.getAntiBotStatus().name());
|
||||
return;
|
||||
}
|
||||
|
||||
String newState = arguments.get(0);
|
||||
|
||||
// Enable or disable the mod
|
||||
if ("ON".equalsIgnoreCase(newState)) {
|
||||
antiBotService.overrideAntiBotStatus(true);
|
||||
sender.sendMessage("[AuthMe] AntiBot Manual Override: enabled!");
|
||||
} else if ("OFF".equalsIgnoreCase(newState)) {
|
||||
antiBotService.overrideAntiBotStatus(false);
|
||||
sender.sendMessage("[AuthMe] AntiBot Manual Override: disabled!");
|
||||
} else {
|
||||
sender.sendMessage(ChatColor.DARK_RED + "Invalid AntiBot mode!");
|
||||
FoundCommandResult result = commandMapper.mapPartsToCommand(sender, Arrays.asList("authme", "antibot"));
|
||||
helpProvider.outputHelp(sender, result, HelpProvider.SHOW_ARGUMENTS);
|
||||
sender.sendMessage(ChatColor.GOLD + "Detailed help: " + ChatColor.WHITE + "/authme help antibot");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.authme;
|
||||
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.message.Messages;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Command to disable two-factor authentication for a user.
|
||||
*/
|
||||
public class TotpDisableAdminCommand implements ExecutableCommand {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(TotpDisableAdminCommand.class);
|
||||
|
||||
@Inject
|
||||
private DataSource dataSource;
|
||||
|
||||
@Inject
|
||||
private Messages messages;
|
||||
|
||||
@Inject
|
||||
private BukkitService bukkitService;
|
||||
|
||||
@Override
|
||||
public void executeCommand(CommandSender sender, List<String> arguments) {
|
||||
String player = arguments.get(0);
|
||||
|
||||
PlayerAuth auth = dataSource.getAuth(player);
|
||||
if (auth == null) {
|
||||
messages.send(sender, MessageKey.UNKNOWN_USER);
|
||||
} else if (auth.getTotpKey() == null) {
|
||||
sender.sendMessage(ChatColor.RED + "Player '" + player + "' does not have two-factor auth enabled");
|
||||
} else {
|
||||
removeTotpKey(sender, player);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeTotpKey(CommandSender sender, String player) {
|
||||
if (dataSource.removeTotpKey(player)) {
|
||||
sender.sendMessage("Disabled two-factor authentication successfully for '" + player + "'");
|
||||
logger.info(sender.getName() + " disable two-factor authentication for '" + player + "'");
|
||||
|
||||
Player onlinePlayer = bukkitService.getPlayerExact(player);
|
||||
if (onlinePlayer != null) {
|
||||
messages.send(onlinePlayer, MessageKey.TWO_FACTOR_REMOVED_SUCCESS);
|
||||
}
|
||||
} else {
|
||||
messages.send(sender, MessageKey.ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.authme;
|
||||
|
||||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.message.Messages;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Command to see whether a user has enabled two-factor authentication.
|
||||
*/
|
||||
public class TotpViewStatusCommand implements ExecutableCommand {
|
||||
|
||||
@Inject
|
||||
private DataSource dataSource;
|
||||
|
||||
@Inject
|
||||
private Messages messages;
|
||||
|
||||
@Override
|
||||
public void executeCommand(CommandSender sender, List<String> arguments) {
|
||||
String player = arguments.get(0);
|
||||
|
||||
PlayerAuth auth = dataSource.getAuth(player);
|
||||
if (auth == null) {
|
||||
messages.send(sender, MessageKey.UNKNOWN_USER);
|
||||
} else if (auth.getTotpKey() == null) {
|
||||
sender.sendMessage(ChatColor.RED + "Player '" + player + "' does NOT have two-factor auth enabled");
|
||||
} else {
|
||||
sender.sendMessage(ChatColor.DARK_GREEN + "Player '" + player + "' has enabled two-factor authentication");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.authme;
|
||||
|
||||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.process.Management;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Admin command to unregister a player.
|
||||
*/
|
||||
public class UnregisterAdminCommand implements ExecutableCommand {
|
||||
|
||||
@Inject
|
||||
private DataSource dataSource;
|
||||
|
||||
@Inject
|
||||
private CommonService commonService;
|
||||
|
||||
@Inject
|
||||
private BukkitService bukkitService;
|
||||
|
||||
@Inject
|
||||
private Management management;
|
||||
|
||||
UnregisterAdminCommand() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeCommand(final CommandSender sender, List<String> arguments) {
|
||||
String playerName = arguments.get(0);
|
||||
|
||||
// Make sure the user exists
|
||||
if (!dataSource.isAuthAvailable(playerName)) {
|
||||
commonService.send(sender, MessageKey.UNKNOWN_USER);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the player from the server and perform unregister
|
||||
Player target = bukkitService.getPlayerExact(playerName);
|
||||
management.performUnregisterByAdmin(sender, playerName, target);
|
||||
}
|
||||
}
|
||||
-39
@@ -1,39 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.authme;
|
||||
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.command.help.HelpMessagesService;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.service.HelpTranslationGenerator;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Messages command, updates the user's help messages file with any missing files
|
||||
* from the provided file in the JAR.
|
||||
*/
|
||||
public class UpdateHelpMessagesCommand implements ExecutableCommand {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(UpdateHelpMessagesCommand.class);
|
||||
|
||||
@Inject
|
||||
private HelpTranslationGenerator helpTranslationGenerator;
|
||||
@Inject
|
||||
private HelpMessagesService helpMessagesService;
|
||||
|
||||
@Override
|
||||
public void executeCommand(CommandSender sender, List<String> arguments) {
|
||||
try {
|
||||
File updatedFile = helpTranslationGenerator.updateHelpFile();
|
||||
sender.sendMessage("Successfully updated the help file '" + updatedFile.getName() + "'");
|
||||
helpMessagesService.reloadMessagesFile();
|
||||
} catch (IOException e) {
|
||||
sender.sendMessage("Could not update help file: " + e.getMessage());
|
||||
logger.logException("Could not update help file:", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.authme;
|
||||
|
||||
import fr.xephi.authme.AuthMe;
|
||||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
public class VersionCommand implements ExecutableCommand {
|
||||
|
||||
@Inject
|
||||
private BukkitService bukkitService;
|
||||
|
||||
@Override
|
||||
public void executeCommand(CommandSender sender, List<String> arguments) {
|
||||
// Show some version info
|
||||
sender.sendMessage(ChatColor.GOLD + "==========[ " + AuthMe.getPluginName() + " ABOUT ]==========");
|
||||
sender.sendMessage(ChatColor.GOLD + "Version: " + ChatColor.WHITE + AuthMe.getPluginName()
|
||||
+ " v" + AuthMe.getPluginVersion() + ChatColor.GRAY + " (build: " + AuthMe.getPluginBuildNumber() + ")");
|
||||
sender.sendMessage(ChatColor.GOLD + "Authors:");
|
||||
Collection<Player> onlinePlayers = bukkitService.getOnlinePlayers();
|
||||
printDeveloper(sender, "Gabriele C.", "sgdc3", "Project manager, Contributor", onlinePlayers);
|
||||
printDeveloper(sender, "Lucas J.", "ljacqu", "Main Developer", onlinePlayers);
|
||||
printDeveloper(sender, "games647", "games647", "Developer", onlinePlayers);
|
||||
printDeveloper(sender, "Hex3l", "Hex3l", "Developer", onlinePlayers);
|
||||
printDeveloper(sender, "krusic22", "krusic22", "Support", onlinePlayers);
|
||||
sender.sendMessage(ChatColor.GOLD + "Retired authors:");
|
||||
printDeveloper(sender, "Alexandre Vanhecke", "xephi59", "Original Author", onlinePlayers);
|
||||
printDeveloper(sender, "Gnat008", "gnat008", "Developer, Retired", onlinePlayers);
|
||||
printDeveloper(sender, "DNx5", "DNx5", "Developer, Retired", onlinePlayers);
|
||||
printDeveloper(sender, "Tim Visee", "timvisee", "Developer, Retired", onlinePlayers);
|
||||
sender.sendMessage(ChatColor.GOLD + "Website: " + ChatColor.WHITE
|
||||
+ "https://github.com/AuthMe/AuthMeReloaded");
|
||||
sender.sendMessage(ChatColor.GOLD + "License: " + ChatColor.WHITE + "GNU GPL v3.0"
|
||||
+ ChatColor.GRAY + ChatColor.ITALIC + " (See LICENSE file)");
|
||||
sender.sendMessage(ChatColor.GOLD + "Copyright: " + ChatColor.WHITE
|
||||
+ "Copyright (c) AuthMe-Team " + new SimpleDateFormat("yyyy").format(new Date())
|
||||
+ ". Released under GPL v3 License.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a developer with proper styling.
|
||||
*
|
||||
* @param sender The command sender
|
||||
* @param name The display name of the developer
|
||||
* @param minecraftName The Minecraft username of the developer, if available
|
||||
* @param function The function of the developer
|
||||
* @param onlinePlayers The list of online players
|
||||
*/
|
||||
private static void printDeveloper(CommandSender sender, String name, String minecraftName, String function,
|
||||
Collection<Player> onlinePlayers) {
|
||||
// Print the name
|
||||
StringBuilder msg = new StringBuilder();
|
||||
msg.append(" ")
|
||||
.append(ChatColor.WHITE)
|
||||
.append(name);
|
||||
|
||||
// Append the Minecraft name
|
||||
msg.append(ChatColor.GRAY).append(" // ").append(ChatColor.WHITE).append(minecraftName);
|
||||
msg.append(ChatColor.GRAY).append(ChatColor.ITALIC).append(" (").append(function).append(")");
|
||||
|
||||
// Show the online status
|
||||
if (isPlayerOnline(minecraftName, onlinePlayers)) {
|
||||
msg.append(ChatColor.GREEN).append(ChatColor.ITALIC).append(" (In-Game)");
|
||||
}
|
||||
|
||||
// Print the message
|
||||
sender.sendMessage(msg.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a player is online.
|
||||
*
|
||||
* @param minecraftName The Minecraft player name
|
||||
* @param onlinePlayers List of online players
|
||||
*
|
||||
* @return True if the player is online, false otherwise
|
||||
*/
|
||||
private static boolean isPlayerOnline(String minecraftName, Collection<Player> onlinePlayers) {
|
||||
for (Player player : onlinePlayers) {
|
||||
if (player.getName().equalsIgnoreCase(minecraftName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.authme.debug;
|
||||
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.permission.DebugSectionPermissions;
|
||||
import fr.xephi.authme.permission.PermissionNode;
|
||||
import fr.xephi.authme.service.GeoIpService;
|
||||
import fr.xephi.authme.service.ValidationService;
|
||||
import fr.xephi.authme.settings.properties.ProtectionSettings;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Shows the GeoIP information as returned by the geoIpService.
|
||||
*/
|
||||
class CountryLookup implements DebugSection {
|
||||
|
||||
private static final Pattern IS_IP_ADDR = Pattern.compile("(\\d{1,3}\\.){3}\\d{1,3}");
|
||||
|
||||
@Inject
|
||||
private GeoIpService geoIpService;
|
||||
|
||||
@Inject
|
||||
private DataSource dataSource;
|
||||
|
||||
@Inject
|
||||
private ValidationService validationService;
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "cty";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Check country protection / country data";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender sender, List<String> arguments) {
|
||||
sender.sendMessage(ChatColor.BLUE + "AuthMe country lookup");
|
||||
if (arguments.isEmpty()) {
|
||||
sender.sendMessage("Check player: /authme debug cty Bobby");
|
||||
sender.sendMessage("Check IP address: /authme debug cty 127.123.45.67");
|
||||
return;
|
||||
}
|
||||
|
||||
String argument = arguments.get(0);
|
||||
if (IS_IP_ADDR.matcher(argument).matches()) {
|
||||
outputInfoForIpAddr(sender, argument);
|
||||
} else {
|
||||
outputInfoForPlayer(sender, argument);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionNode getRequiredPermission() {
|
||||
return DebugSectionPermissions.COUNTRY_LOOKUP;
|
||||
}
|
||||
|
||||
private void outputInfoForIpAddr(CommandSender sender, String ipAddr) {
|
||||
sender.sendMessage("IP '" + ipAddr + "' maps to country '" + geoIpService.getCountryCode(ipAddr)
|
||||
+ "' (" + geoIpService.getCountryName(ipAddr) + ")");
|
||||
if (validationService.isCountryAdmitted(ipAddr)) {
|
||||
sender.sendMessage(ChatColor.DARK_GREEN + "This IP address' country is not blocked");
|
||||
} else {
|
||||
sender.sendMessage(ChatColor.DARK_RED + "This IP address' country is blocked from the server");
|
||||
}
|
||||
sender.sendMessage("Note: if " + ProtectionSettings.ENABLE_PROTECTION + " is false no country is blocked");
|
||||
}
|
||||
|
||||
// TODO #1366: Extend with registration IP?
|
||||
private void outputInfoForPlayer(CommandSender sender, String name) {
|
||||
PlayerAuth auth = dataSource.getAuth(name);
|
||||
if (auth == null) {
|
||||
sender.sendMessage("No player with name '" + name + "'");
|
||||
} else if (auth.getLastIp() == null) {
|
||||
sender.sendMessage("No last IP address known for '" + name + "'");
|
||||
} else {
|
||||
sender.sendMessage("Player '" + name + "' has IP address " + auth.getLastIp());
|
||||
outputInfoForIpAddr(sender, auth.getLastIp());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.authme.debug;
|
||||
|
||||
import ch.jalu.injector.factory.SingletonStore;
|
||||
import fr.xephi.authme.data.auth.PlayerCache;
|
||||
import fr.xephi.authme.data.limbo.LimboService;
|
||||
import fr.xephi.authme.datasource.CacheDataSource;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.initialization.HasCleanup;
|
||||
import fr.xephi.authme.initialization.Reloadable;
|
||||
import fr.xephi.authme.initialization.SettingsDependent;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.permission.DebugSectionPermissions;
|
||||
import fr.xephi.authme.permission.PermissionNode;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static fr.xephi.authme.command.executable.authme.debug.DebugSectionUtils.applyToLimboPlayersMap;
|
||||
|
||||
/**
|
||||
* Fetches various statistics, particularly regarding in-memory data that is stored.
|
||||
*/
|
||||
class DataStatistics implements DebugSection {
|
||||
|
||||
@Inject
|
||||
private PlayerCache playerCache;
|
||||
|
||||
@Inject
|
||||
private LimboService limboService;
|
||||
|
||||
@Inject
|
||||
private DataSource dataSource;
|
||||
|
||||
@Inject
|
||||
private SingletonStore<Object> singletonStore;
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "stats";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Outputs general data statistics";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender sender, List<String> arguments) {
|
||||
sender.sendMessage(ChatColor.BLUE + "AuthMe statistics");
|
||||
sender.sendMessage("LimboPlayers in memory: " + applyToLimboPlayersMap(limboService, Map::size));
|
||||
sender.sendMessage("PlayerCache size: " + playerCache.getLogged() + " (= logged in players)");
|
||||
|
||||
outputDatabaseStats(sender);
|
||||
outputInjectorStats(sender);
|
||||
sender.sendMessage("Total logger instances: " + ConsoleLoggerFactory.getTotalLoggers());
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionNode getRequiredPermission() {
|
||||
return DebugSectionPermissions.DATA_STATISTICS;
|
||||
}
|
||||
|
||||
private void outputDatabaseStats(CommandSender sender) {
|
||||
sender.sendMessage("Total players in DB: " + dataSource.getAccountsRegistered());
|
||||
if (dataSource instanceof CacheDataSource) {
|
||||
CacheDataSource cacheDataSource = (CacheDataSource) this.dataSource;
|
||||
sender.sendMessage("Cached PlayerAuth objects: " + cacheDataSource.getCachedAuths().size());
|
||||
}
|
||||
}
|
||||
|
||||
private void outputInjectorStats(CommandSender sender) {
|
||||
sender.sendMessage("Singleton Java classes: " + singletonStore.retrieveAllOfType().size());
|
||||
sender.sendMessage(String.format("(Reloadable: %d / SettingsDependent: %d / HasCleanup: %d)",
|
||||
singletonStore.retrieveAllOfType(Reloadable.class).size(),
|
||||
singletonStore.retrieveAllOfType(SettingsDependent.class).size(),
|
||||
singletonStore.retrieveAllOfType(HasCleanup.class).size()));
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.authme.debug;
|
||||
|
||||
import ch.jalu.injector.factory.Factory;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.permission.PermissionsManager;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
* Debug command main.
|
||||
*/
|
||||
public class DebugCommand implements ExecutableCommand {
|
||||
|
||||
private static final Set<Class<? extends DebugSection>> SECTION_CLASSES = ImmutableSet.of(
|
||||
PermissionGroups.class, DataStatistics.class, CountryLookup.class, PlayerAuthViewer.class, InputValidator.class,
|
||||
LimboPlayerViewer.class, CountryLookup.class, HasPermissionChecker.class, TestEmailSender.class,
|
||||
SpawnLocationViewer.class, MySqlDefaultChanger.class);
|
||||
|
||||
@Inject
|
||||
private Factory<DebugSection> debugSectionFactory;
|
||||
|
||||
@Inject
|
||||
private PermissionsManager permissionsManager;
|
||||
|
||||
private Map<String, DebugSection> sections;
|
||||
|
||||
@Override
|
||||
public void executeCommand(CommandSender sender, List<String> arguments) {
|
||||
DebugSection debugSection = findDebugSection(arguments);
|
||||
if (debugSection == null) {
|
||||
sendAvailableSections(sender);
|
||||
} else {
|
||||
executeSection(debugSection, sender, arguments);
|
||||
}
|
||||
}
|
||||
|
||||
private DebugSection findDebugSection(List<String> arguments) {
|
||||
if (arguments.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return getSections().get(arguments.get(0).toLowerCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
private void sendAvailableSections(CommandSender sender) {
|
||||
sender.sendMessage(ChatColor.BLUE + "AuthMe debug utils");
|
||||
sender.sendMessage("Sections available to you:");
|
||||
long availableSections = getSections().values().stream()
|
||||
.filter(section -> permissionsManager.hasPermission(sender, section.getRequiredPermission()))
|
||||
.peek(e -> sender.sendMessage("- " + e.getName() + ": " + e.getDescription()))
|
||||
.count();
|
||||
|
||||
if (availableSections == 0) {
|
||||
sender.sendMessage(ChatColor.RED + "You don't have permission to view any debug section");
|
||||
}
|
||||
}
|
||||
|
||||
private void executeSection(DebugSection section, CommandSender sender, List<String> arguments) {
|
||||
if (permissionsManager.hasPermission(sender, section.getRequiredPermission())) {
|
||||
section.execute(sender, arguments.subList(1, arguments.size()));
|
||||
} else {
|
||||
sender.sendMessage(ChatColor.RED + "You don't have permission for this section. See /authme debug");
|
||||
}
|
||||
}
|
||||
|
||||
// Lazy getter
|
||||
private Map<String, DebugSection> getSections() {
|
||||
if (sections == null) {
|
||||
Map<String, DebugSection> sections = new TreeMap<>();
|
||||
for (Class<? extends DebugSection> sectionClass : SECTION_CLASSES) {
|
||||
DebugSection section = debugSectionFactory.newInstance(sectionClass);
|
||||
sections.put(section.getName(), section);
|
||||
}
|
||||
this.sections = sections;
|
||||
}
|
||||
return sections;
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.authme.debug;
|
||||
|
||||
import fr.xephi.authme.permission.PermissionNode;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A debug section: "child" command of the debug command.
|
||||
*/
|
||||
interface DebugSection {
|
||||
|
||||
/**
|
||||
* @return the name to get to this child command
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* @return short description of the child command
|
||||
*/
|
||||
String getDescription();
|
||||
|
||||
/**
|
||||
* Executes the debug child command.
|
||||
*
|
||||
* @param sender the sender executing the command
|
||||
* @param arguments the arguments, without the label of the child command
|
||||
*/
|
||||
void execute(CommandSender sender, List<String> arguments);
|
||||
|
||||
/**
|
||||
* @return permission required to run this section
|
||||
*/
|
||||
PermissionNode getRequiredPermission();
|
||||
|
||||
}
|
||||
@@ -1,130 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.authme.debug;
|
||||
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.data.limbo.LimboService;
|
||||
import fr.xephi.authme.datasource.CacheDataSource;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import org.bukkit.Location;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.math.RoundingMode;
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.DecimalFormatSymbols;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Utilities used within the DebugSection implementations.
|
||||
*/
|
||||
final class DebugSectionUtils {
|
||||
|
||||
private static ConsoleLogger logger = ConsoleLoggerFactory.get(DebugSectionUtils.class);
|
||||
private static Field limboEntriesField;
|
||||
|
||||
private DebugSectionUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the given location in a human readable way. Null-safe.
|
||||
*
|
||||
* @param location the location to format
|
||||
* @return the formatted location
|
||||
*/
|
||||
static String formatLocation(Location location) {
|
||||
if (location == null) {
|
||||
return "null";
|
||||
}
|
||||
|
||||
String worldName = location.getWorld() == null ? "null" : location.getWorld().getName();
|
||||
return formatLocation(location.getX(), location.getY(), location.getZ(), worldName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the given location in a human readable way.
|
||||
*
|
||||
* @param x the x coordinate
|
||||
* @param y the y coordinate
|
||||
* @param z the z coordinate
|
||||
* @param world the world name
|
||||
* @return the formatted location
|
||||
*/
|
||||
static String formatLocation(double x, double y, double z, String world) {
|
||||
return "(" + round(x) + ", " + round(y) + ", " + round(z) + ") in '" + world + "'";
|
||||
}
|
||||
|
||||
/**
|
||||
* Rounds the given number to two decimals.
|
||||
*
|
||||
* @param number the number to round
|
||||
* @return the rounded number
|
||||
*/
|
||||
private static String round(double number) {
|
||||
DecimalFormat df = new DecimalFormat("#.##");
|
||||
df.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.US));
|
||||
df.setRoundingMode(RoundingMode.HALF_UP);
|
||||
return df.format(number);
|
||||
}
|
||||
|
||||
private static Field getLimboPlayerEntriesField() {
|
||||
if (limboEntriesField == null) {
|
||||
try {
|
||||
Field field = LimboService.class.getDeclaredField("entries");
|
||||
field.setAccessible(true);
|
||||
limboEntriesField = field;
|
||||
} catch (Exception e) {
|
||||
logger.logException("Could not retrieve LimboService entries field:", e);
|
||||
}
|
||||
}
|
||||
return limboEntriesField;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the given function to the map in LimboService containing the LimboPlayers.
|
||||
* As we don't want to expose this information in non-debug settings, this is done with reflection.
|
||||
* Exceptions are generously caught and {@code null} is returned on failure.
|
||||
*
|
||||
* @param limboService the limbo service instance to get the map from
|
||||
* @param function the function to apply to the map
|
||||
* @param <U> the result type of the function
|
||||
*
|
||||
* @return the value of the function applied to the map, or null upon error
|
||||
*/
|
||||
static <U> U applyToLimboPlayersMap(LimboService limboService, Function<Map, U> function) {
|
||||
Field limboPlayerEntriesField = getLimboPlayerEntriesField();
|
||||
if (limboPlayerEntriesField != null) {
|
||||
try {
|
||||
return function.apply((Map) limboEntriesField.get(limboService));
|
||||
} catch (Exception e) {
|
||||
logger.logException("Could not retrieve LimboService values:", e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static <T> T castToTypeOrNull(Object object, Class<T> clazz) {
|
||||
return clazz.isInstance(object) ? clazz.cast(object) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unwraps the "cache data source" and returns the underlying source. Returns the
|
||||
* same as the input argument otherwise.
|
||||
*
|
||||
* @param dataSource the data source to unwrap if applicable
|
||||
* @return the non-cache data source
|
||||
*/
|
||||
static DataSource unwrapSourceFromCacheDataSource(DataSource dataSource) {
|
||||
if (dataSource instanceof CacheDataSource) {
|
||||
try {
|
||||
Field source = CacheDataSource.class.getDeclaredField("source");
|
||||
source.setAccessible(true);
|
||||
return (DataSource) source.get(dataSource);
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
logger.logException("Could not get source of CacheDataSource:", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return dataSource;
|
||||
}
|
||||
}
|
||||
-138
@@ -1,138 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.authme.debug;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import fr.xephi.authme.permission.AdminPermission;
|
||||
import fr.xephi.authme.permission.DebugSectionPermissions;
|
||||
import fr.xephi.authme.permission.DefaultPermission;
|
||||
import fr.xephi.authme.permission.PermissionNode;
|
||||
import fr.xephi.authme.permission.PermissionsManager;
|
||||
import fr.xephi.authme.permission.PlayerPermission;
|
||||
import fr.xephi.authme.permission.PlayerStatePermission;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
/**
|
||||
* Checks if a player has a given permission, as checked by AuthMe.
|
||||
*/
|
||||
class HasPermissionChecker implements DebugSection {
|
||||
|
||||
static final List<Class<? extends PermissionNode>> PERMISSION_NODE_CLASSES = ImmutableList.of(
|
||||
AdminPermission.class, PlayerPermission.class, PlayerStatePermission.class, DebugSectionPermissions.class);
|
||||
|
||||
@Inject
|
||||
private PermissionsManager permissionsManager;
|
||||
|
||||
@Inject
|
||||
private BukkitService bukkitService;
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "perm";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Checks if a player has a given permission";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender sender, List<String> arguments) {
|
||||
sender.sendMessage(ChatColor.BLUE + "AuthMe permission check");
|
||||
if (arguments.size() < 2) {
|
||||
sender.sendMessage("Check if a player has permission:");
|
||||
sender.sendMessage("Example: /authme debug perm bobby my.perm.node");
|
||||
sender.sendMessage("Permission system type used: " + permissionsManager.getPermissionSystem());
|
||||
return;
|
||||
}
|
||||
|
||||
final String playerName = arguments.get(0);
|
||||
final String permissionNode = arguments.get(1);
|
||||
|
||||
Player player = bukkitService.getPlayerExact(playerName);
|
||||
if (player == null) {
|
||||
OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(playerName);
|
||||
if (offlinePlayer == null) {
|
||||
sender.sendMessage(ChatColor.DARK_RED + "Player '" + playerName + "' does not exist");
|
||||
} else {
|
||||
sender.sendMessage("Player '" + playerName + "' not online; checking with offline player");
|
||||
performPermissionCheck(offlinePlayer, permissionNode, permissionsManager::hasPermissionOffline, sender);
|
||||
}
|
||||
} else {
|
||||
performPermissionCheck(player, permissionNode, permissionsManager::hasPermission, sender);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionNode getRequiredPermission() {
|
||||
return DebugSectionPermissions.HAS_PERMISSION_CHECK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a permission check and informs the given sender of the result. {@code permissionChecker} is the
|
||||
* permission check to perform with the given {@code node} and the {@code player}.
|
||||
*
|
||||
* @param player the player to check a permission for
|
||||
* @param node the node of the permission to check
|
||||
* @param permissionChecker permission checking function
|
||||
* @param sender the sender to inform of the result
|
||||
* @param <P> the player type
|
||||
*/
|
||||
private static <P extends OfflinePlayer> void performPermissionCheck(
|
||||
P player, String node, BiFunction<P, PermissionNode, Boolean> permissionChecker, CommandSender sender) {
|
||||
|
||||
PermissionNode permNode = getPermissionNode(sender, node);
|
||||
if (permissionChecker.apply(player, permNode)) {
|
||||
sender.sendMessage(ChatColor.DARK_GREEN + "Success: player '" + player.getName()
|
||||
+ "' has permission '" + node + "'");
|
||||
} else {
|
||||
sender.sendMessage(ChatColor.DARK_RED + "Check failed: player '" + player.getName()
|
||||
+ "' does NOT have permission '" + node + "'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Based on the given permission node (String), tries to find the according AuthMe {@link PermissionNode}
|
||||
* instance, or creates a new one if not available.
|
||||
*
|
||||
* @param sender the sender (used to inform him if no AuthMe PermissionNode can be matched)
|
||||
* @param node the node to search for
|
||||
* @return the node as {@link PermissionNode} object
|
||||
*/
|
||||
private static PermissionNode getPermissionNode(CommandSender sender, String node) {
|
||||
Optional<? extends PermissionNode> permNode = PERMISSION_NODE_CLASSES.stream()
|
||||
.map(Class::getEnumConstants)
|
||||
.flatMap(Arrays::stream)
|
||||
.filter(perm -> perm.getNode().equals(node))
|
||||
.findFirst();
|
||||
if (permNode.isPresent()) {
|
||||
return permNode.get();
|
||||
} else {
|
||||
sender.sendMessage("Did not detect AuthMe permission; using default permission = DENIED");
|
||||
return createPermNode(node);
|
||||
}
|
||||
}
|
||||
|
||||
private static PermissionNode createPermNode(String node) {
|
||||
return new PermissionNode() {
|
||||
@Override
|
||||
public String getNode() {
|
||||
return node;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultPermission getDefaultPermission() {
|
||||
return DefaultPermission.NOT_ALLOWED;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,124 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.authme.debug;
|
||||
|
||||
import fr.xephi.authme.listener.FailedVerificationException;
|
||||
import fr.xephi.authme.listener.OnJoinVerifier;
|
||||
import fr.xephi.authme.message.Messages;
|
||||
import fr.xephi.authme.permission.DebugSectionPermissions;
|
||||
import fr.xephi.authme.permission.PermissionNode;
|
||||
import fr.xephi.authme.service.ValidationService;
|
||||
import fr.xephi.authme.service.ValidationService.ValidationResult;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static fr.xephi.authme.command.executable.authme.debug.InputValidator.ValidationObject.MAIL;
|
||||
import static fr.xephi.authme.command.executable.authme.debug.InputValidator.ValidationObject.NAME;
|
||||
import static fr.xephi.authme.command.executable.authme.debug.InputValidator.ValidationObject.PASS;
|
||||
|
||||
/**
|
||||
* Checks if a sample username, email or password is valid according to the AuthMe settings.
|
||||
*/
|
||||
class InputValidator implements DebugSection {
|
||||
|
||||
@Inject
|
||||
private ValidationService validationService;
|
||||
|
||||
@Inject
|
||||
private Messages messages;
|
||||
|
||||
@Inject
|
||||
private OnJoinVerifier onJoinVerifier;
|
||||
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "valid";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Checks if your config.yml allows a password / email";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender sender, List<String> arguments) {
|
||||
if (arguments.size() < 2 || !ValidationObject.matchesAny(arguments.get(0))) {
|
||||
displayUsageHint(sender);
|
||||
|
||||
} else if (PASS.matches(arguments.get(0))) {
|
||||
validatePassword(sender, arguments.get(1));
|
||||
|
||||
} else if (MAIL.matches(arguments.get(0))) {
|
||||
validateEmail(sender, arguments.get(1));
|
||||
|
||||
} else if (NAME.matches(arguments.get(0))) {
|
||||
validateUsername(sender, arguments.get(1));
|
||||
|
||||
} else {
|
||||
throw new IllegalStateException("Unexpected validation object with arg[0] = '" + arguments.get(0) + "'");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionNode getRequiredPermission() {
|
||||
return DebugSectionPermissions.INPUT_VALIDATOR;
|
||||
}
|
||||
|
||||
private void displayUsageHint(CommandSender sender) {
|
||||
sender.sendMessage(ChatColor.BLUE + "Validation tests");
|
||||
sender.sendMessage("You can define forbidden emails and passwords in your config.yml."
|
||||
+ " You can test your settings with this command.");
|
||||
final String command = ChatColor.GOLD + "/authme debug valid";
|
||||
sender.sendMessage(" Use " + command + " pass <pass>" + ChatColor.RESET + " to check a password");
|
||||
sender.sendMessage(" Use " + command + " mail <mail>" + ChatColor.RESET + " to check an email");
|
||||
sender.sendMessage(" Use " + command + " name <name>" + ChatColor.RESET + " to check a username");
|
||||
}
|
||||
|
||||
private void validatePassword(CommandSender sender, String password) {
|
||||
ValidationResult validationResult = validationService.validatePassword(password, "");
|
||||
sender.sendMessage(ChatColor.BLUE + "Validation of password '" + password + "'");
|
||||
if (validationResult.hasError()) {
|
||||
messages.send(sender, validationResult.getMessageKey(), validationResult.getArgs());
|
||||
} else {
|
||||
sender.sendMessage(ChatColor.DARK_GREEN + "Valid password!");
|
||||
}
|
||||
}
|
||||
|
||||
private void validateEmail(CommandSender sender, String email) {
|
||||
boolean isValidEmail = validationService.validateEmail(email);
|
||||
sender.sendMessage(ChatColor.BLUE + "Validation of email '" + email + "'");
|
||||
if (isValidEmail) {
|
||||
sender.sendMessage(ChatColor.DARK_GREEN + "Valid email!");
|
||||
} else {
|
||||
sender.sendMessage(ChatColor.DARK_RED + "Email is not valid!");
|
||||
}
|
||||
}
|
||||
|
||||
private void validateUsername(CommandSender sender, String username) {
|
||||
sender.sendMessage(ChatColor.BLUE + "Validation of username '" + username + "'");
|
||||
try {
|
||||
onJoinVerifier.checkIsValidName(username);
|
||||
sender.sendMessage("Valid username!");
|
||||
} catch (FailedVerificationException failedVerificationEx) {
|
||||
messages.send(sender, failedVerificationEx.getReason(), failedVerificationEx.getArgs());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
enum ValidationObject {
|
||||
|
||||
PASS, MAIL, NAME;
|
||||
|
||||
static boolean matchesAny(String arg) {
|
||||
return Arrays.stream(values()).anyMatch(vo -> vo.matches(arg));
|
||||
}
|
||||
|
||||
boolean matches(String arg) {
|
||||
return name().equalsIgnoreCase(arg);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,143 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.authme.debug;
|
||||
|
||||
import fr.xephi.authme.data.limbo.LimboPlayer;
|
||||
import fr.xephi.authme.data.limbo.LimboService;
|
||||
import fr.xephi.authme.data.limbo.persistence.LimboPersistence;
|
||||
import fr.xephi.authme.permission.DebugSectionPermissions;
|
||||
import fr.xephi.authme.permission.PermissionNode;
|
||||
import fr.xephi.authme.permission.PermissionsManager;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static fr.xephi.authme.command.executable.authme.debug.DebugSectionUtils.applyToLimboPlayersMap;
|
||||
import static fr.xephi.authme.command.executable.authme.debug.DebugSectionUtils.formatLocation;
|
||||
|
||||
/**
|
||||
* Shows the data stored in LimboPlayers and the equivalent properties on online players.
|
||||
*/
|
||||
class LimboPlayerViewer implements DebugSection {
|
||||
|
||||
@Inject
|
||||
private LimboService limboService;
|
||||
|
||||
@Inject
|
||||
private LimboPersistence limboPersistence;
|
||||
|
||||
@Inject
|
||||
private BukkitService bukkitService;
|
||||
|
||||
@Inject
|
||||
private PermissionsManager permissionsManager;
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "limbo";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "View LimboPlayers and player's \"limbo stats\"";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender sender, List<String> arguments) {
|
||||
if (arguments.isEmpty()) {
|
||||
sender.sendMessage(ChatColor.BLUE + "AuthMe limbo viewer");
|
||||
sender.sendMessage("/authme debug limbo <player>: show a player's limbo info");
|
||||
sender.sendMessage("Available limbo records: " + applyToLimboPlayersMap(limboService, Map::keySet));
|
||||
return;
|
||||
}
|
||||
|
||||
LimboPlayer memoryLimbo = limboService.getLimboPlayer(arguments.get(0));
|
||||
Player player = bukkitService.getPlayerExact(arguments.get(0));
|
||||
LimboPlayer diskLimbo = player != null ? limboPersistence.getLimboPlayer(player) : null;
|
||||
if (memoryLimbo == null && player == null) {
|
||||
sender.sendMessage(ChatColor.BLUE + "No AuthMe limbo data");
|
||||
sender.sendMessage("No limbo data and no player online with name '" + arguments.get(0) + "'");
|
||||
return;
|
||||
}
|
||||
|
||||
sender.sendMessage(ChatColor.BLUE + "Player / limbo / disk limbo info for '" + arguments.get(0) + "'");
|
||||
new InfoDisplayer(sender, player, memoryLimbo, diskLimbo)
|
||||
.sendEntry("Is op", Player::isOp, LimboPlayer::isOperator)
|
||||
.sendEntry("Walk speed", Player::getWalkSpeed, LimboPlayer::getWalkSpeed)
|
||||
.sendEntry("Can fly", Player::getAllowFlight, LimboPlayer::isCanFly)
|
||||
.sendEntry("Fly speed", Player::getFlySpeed, LimboPlayer::getFlySpeed)
|
||||
.sendEntry("Location", p -> formatLocation(p.getLocation()), l -> formatLocation(l.getLocation()))
|
||||
.sendEntry("Prim. group",
|
||||
p -> permissionsManager.hasGroupSupport() ? permissionsManager.getPrimaryGroup(p) : "N/A",
|
||||
LimboPlayer::getGroups);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionNode getRequiredPermission() {
|
||||
return DebugSectionPermissions.LIMBO_PLAYER_VIEWER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the info for the given LimboPlayer and Player to the provided CommandSender.
|
||||
*/
|
||||
private static final class InfoDisplayer {
|
||||
private final CommandSender sender;
|
||||
private final Optional<Player> player;
|
||||
private final Optional<LimboPlayer> memoryLimbo;
|
||||
private final Optional<LimboPlayer> diskLimbo;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param sender command sender to send the information to
|
||||
* @param player the player to get data from
|
||||
* @param memoryLimbo the limbo player to get data from
|
||||
*/
|
||||
InfoDisplayer(CommandSender sender, Player player, LimboPlayer memoryLimbo, LimboPlayer diskLimbo) {
|
||||
this.sender = sender;
|
||||
this.player = Optional.ofNullable(player);
|
||||
this.memoryLimbo = Optional.ofNullable(memoryLimbo);
|
||||
this.diskLimbo = Optional.ofNullable(diskLimbo);
|
||||
|
||||
if (memoryLimbo == null) {
|
||||
sender.sendMessage("Note: no Limbo information available");
|
||||
}
|
||||
if (player == null) {
|
||||
sender.sendMessage("Note: player is not online");
|
||||
} else if (diskLimbo == null) {
|
||||
sender.sendMessage("Note: no Limbo on disk available");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a piece of information to the command sender.
|
||||
*
|
||||
* @param title the designation of the piece of information
|
||||
* @param playerGetter getter for data retrieval on Player
|
||||
* @param limboGetter getter for data retrieval on the LimboPlayer
|
||||
* @param <T> the data type
|
||||
* @return this instance (for chaining)
|
||||
*/
|
||||
<T> InfoDisplayer sendEntry(String title,
|
||||
Function<Player, T> playerGetter,
|
||||
Function<LimboPlayer, T> limboGetter) {
|
||||
sender.sendMessage(
|
||||
title + ": "
|
||||
+ getData(player, playerGetter)
|
||||
+ " / "
|
||||
+ getData(memoryLimbo, limboGetter)
|
||||
+ " / "
|
||||
+ getData(diskLimbo, limboGetter));
|
||||
return this;
|
||||
}
|
||||
|
||||
static <E, T> String getData(Optional<E> entity, Function<E, T> getter) {
|
||||
return entity.map(getter).map(String::valueOf).orElse(" -- ");
|
||||
}
|
||||
}
|
||||
}
|
||||
-327
@@ -1,327 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.authme.debug;
|
||||
|
||||
import ch.jalu.configme.properties.Property;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.datasource.MySQL;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.permission.DebugSectionPermissions;
|
||||
import fr.xephi.authme.permission.PermissionNode;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.inject.Inject;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static fr.xephi.authme.command.executable.authme.debug.DebugSectionUtils.castToTypeOrNull;
|
||||
import static fr.xephi.authme.command.executable.authme.debug.DebugSectionUtils.unwrapSourceFromCacheDataSource;
|
||||
import static fr.xephi.authme.data.auth.PlayerAuth.DB_EMAIL_DEFAULT;
|
||||
import static fr.xephi.authme.data.auth.PlayerAuth.DB_LAST_IP_DEFAULT;
|
||||
import static fr.xephi.authme.data.auth.PlayerAuth.DB_LAST_LOGIN_DEFAULT;
|
||||
import static fr.xephi.authme.datasource.SqlDataSourceUtils.getColumnDefaultValue;
|
||||
import static fr.xephi.authme.datasource.SqlDataSourceUtils.isNotNullColumn;
|
||||
import static java.lang.String.format;
|
||||
|
||||
/**
|
||||
* Convenience command to add or remove the default value of a column and its nullable status
|
||||
* in the MySQL data source.
|
||||
*/
|
||||
class MySqlDefaultChanger implements DebugSection {
|
||||
|
||||
private static final String NOT_NULL_SUFFIX = ChatColor.DARK_AQUA + "@" + ChatColor.RESET;
|
||||
private static final String DEFAULT_VALUE_SUFFIX = ChatColor.GOLD + "#" + ChatColor.RESET;
|
||||
|
||||
private ConsoleLogger logger = ConsoleLoggerFactory.get(MySqlDefaultChanger.class);
|
||||
|
||||
@Inject
|
||||
private Settings settings;
|
||||
|
||||
@Inject
|
||||
private DataSource dataSource;
|
||||
|
||||
private MySQL mySql;
|
||||
|
||||
@PostConstruct
|
||||
void setMySqlField() {
|
||||
this.mySql = castToTypeOrNull(unwrapSourceFromCacheDataSource(this.dataSource), MySQL.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "mysqldef";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Add or remove the default value of MySQL columns";
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionNode getRequiredPermission() {
|
||||
return DebugSectionPermissions.MYSQL_DEFAULT_CHANGER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender sender, List<String> arguments) {
|
||||
if (mySql == null) {
|
||||
sender.sendMessage("Defaults can be changed for the MySQL data source only.");
|
||||
return;
|
||||
}
|
||||
|
||||
Operation operation = matchToEnum(arguments, 0, Operation.class);
|
||||
Columns column = matchToEnum(arguments, 1, Columns.class);
|
||||
if (operation == Operation.DETAILS) {
|
||||
showColumnDetails(sender);
|
||||
} else if (operation == null || column == null) {
|
||||
displayUsageHints(sender);
|
||||
} else {
|
||||
sender.sendMessage(ChatColor.BLUE + "[AuthMe] MySQL change '" + column + "'");
|
||||
try (Connection con = getConnection(mySql)) {
|
||||
switch (operation) {
|
||||
case ADD:
|
||||
changeColumnToNotNullWithDefault(sender, column, con);
|
||||
break;
|
||||
case REMOVE:
|
||||
removeNotNullAndDefault(sender, column, con);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unknown operation '" + operation + "'");
|
||||
}
|
||||
} catch (SQLException | IllegalStateException e) {
|
||||
logger.logException("Failed to perform MySQL default altering operation:", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a default value to the column definition and adds a {@code NOT NULL} constraint for
|
||||
* the specified column.
|
||||
*
|
||||
* @param sender the command sender initiation the action
|
||||
* @param column the column to modify
|
||||
* @param con connection to the database
|
||||
* @throws SQLException .
|
||||
*/
|
||||
private void changeColumnToNotNullWithDefault(CommandSender sender, Columns column,
|
||||
Connection con) throws SQLException {
|
||||
final String tableName = settings.getProperty(DatabaseSettings.MYSQL_TABLE);
|
||||
final String columnName = settings.getProperty(column.getColumnNameProperty());
|
||||
|
||||
// Replace NULLs with future default value
|
||||
String sql = format("UPDATE %s SET %s = ? WHERE %s IS NULL;", tableName, columnName, columnName);
|
||||
int updatedRows;
|
||||
try (PreparedStatement pst = con.prepareStatement(sql)) {
|
||||
pst.setObject(1, column.getDefaultValue());
|
||||
updatedRows = pst.executeUpdate();
|
||||
}
|
||||
sender.sendMessage("Replaced NULLs with default value ('" + column.getDefaultValue()
|
||||
+ "'), modifying " + updatedRows + " entries");
|
||||
|
||||
// Change column definition to NOT NULL version
|
||||
try (Statement st = con.createStatement()) {
|
||||
st.execute(format("ALTER TABLE %s MODIFY %s %s", tableName, columnName, column.getNotNullDefinition()));
|
||||
sender.sendMessage("Changed column '" + columnName + "' to have NOT NULL constraint");
|
||||
}
|
||||
|
||||
// Log success message
|
||||
logger.info("Changed MySQL column '" + columnName + "' to be NOT NULL, as initiated by '"
|
||||
+ sender.getName() + "'");
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the {@code NOT NULL} constraint of a column definition and replaces rows with the
|
||||
* default value to {@code NULL}.
|
||||
*
|
||||
* @param sender the command sender initiation the action
|
||||
* @param column the column to modify
|
||||
* @param con connection to the database
|
||||
* @throws SQLException .
|
||||
*/
|
||||
private void removeNotNullAndDefault(CommandSender sender, Columns column, Connection con) throws SQLException {
|
||||
final String tableName = settings.getProperty(DatabaseSettings.MYSQL_TABLE);
|
||||
final String columnName = settings.getProperty(column.getColumnNameProperty());
|
||||
|
||||
// Change column definition to nullable version
|
||||
try (Statement st = con.createStatement()) {
|
||||
st.execute(format("ALTER TABLE %s MODIFY %s %s", tableName, columnName, column.getNullableDefinition()));
|
||||
sender.sendMessage("Changed column '" + columnName + "' to allow nulls");
|
||||
}
|
||||
|
||||
// Replace old default value with NULL
|
||||
String sql = format("UPDATE %s SET %s = NULL WHERE %s = ?;", tableName, columnName, columnName);
|
||||
int updatedRows;
|
||||
try (PreparedStatement pst = con.prepareStatement(sql)) {
|
||||
pst.setObject(1, column.getDefaultValue());
|
||||
updatedRows = pst.executeUpdate();
|
||||
}
|
||||
sender.sendMessage("Replaced default value ('" + column.getDefaultValue()
|
||||
+ "') to be NULL, modifying " + updatedRows + " entries");
|
||||
|
||||
// Log success message
|
||||
logger.info("Changed MySQL column '" + columnName + "' to allow NULL, as initiated by '"
|
||||
+ sender.getName() + "'");
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs the current definitions of all {@link Columns} which can be migrated.
|
||||
*
|
||||
* @param sender command sender to output the data to
|
||||
*/
|
||||
private void showColumnDetails(CommandSender sender) {
|
||||
sender.sendMessage(ChatColor.BLUE + "MySQL column details");
|
||||
final String tableName = settings.getProperty(DatabaseSettings.MYSQL_TABLE);
|
||||
try (Connection con = getConnection(mySql)) {
|
||||
final DatabaseMetaData metaData = con.getMetaData();
|
||||
for (Columns col : Columns.values()) {
|
||||
String columnName = settings.getProperty(col.getColumnNameProperty());
|
||||
String isNullText = isNotNullColumn(metaData, tableName, columnName) ? "NOT NULL" : "nullable";
|
||||
Object defaultValue = getColumnDefaultValue(metaData, tableName, columnName);
|
||||
String defaultText = defaultValue == null ? "no default" : "default: '" + defaultValue + "'";
|
||||
sender.sendMessage(formatColumnWithMetadata(col, metaData, tableName)
|
||||
+ " (" + columnName + "): " + isNullText + ", " + defaultText);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
logger.logException("Failed while showing column details:", e);
|
||||
sender.sendMessage("Failed while showing column details. See log for info");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays sample commands and the list of columns that can be changed.
|
||||
*
|
||||
* @param sender the sender issuing the command
|
||||
*/
|
||||
private void displayUsageHints(CommandSender sender) {
|
||||
sender.sendMessage(ChatColor.BLUE + "MySQL column changer");
|
||||
sender.sendMessage("Adds or removes a NOT NULL constraint for a column.");
|
||||
sender.sendMessage("Examples: add a NOT NULL constraint with");
|
||||
sender.sendMessage(" /authme debug mysqldef add <column>");
|
||||
sender.sendMessage("Remove one with /authme debug mysqldef remove <column>");
|
||||
|
||||
sender.sendMessage("Available columns: " + constructColumnListWithMetadata());
|
||||
sender.sendMessage(" " + NOT_NULL_SUFFIX + ": not-null, " + DEFAULT_VALUE_SUFFIX
|
||||
+ ": has default. See /authme debug mysqldef details");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list of {@link Columns} we can toggle with suffixes indicating their NOT NULL and default value status
|
||||
*/
|
||||
private String constructColumnListWithMetadata() {
|
||||
try (Connection con = getConnection(mySql)) {
|
||||
final DatabaseMetaData metaData = con.getMetaData();
|
||||
final String tableName = settings.getProperty(DatabaseSettings.MYSQL_TABLE);
|
||||
|
||||
List<String> formattedColumns = new ArrayList<>(Columns.values().length);
|
||||
for (Columns col : Columns.values()) {
|
||||
formattedColumns.add(formatColumnWithMetadata(col, metaData, tableName));
|
||||
}
|
||||
return String.join(ChatColor.RESET + ", ", formattedColumns);
|
||||
} catch (SQLException e) {
|
||||
logger.logException("Failed to construct column list:", e);
|
||||
return ChatColor.RED + "An error occurred! Please see the console for details.";
|
||||
}
|
||||
}
|
||||
|
||||
private String formatColumnWithMetadata(Columns column, DatabaseMetaData metaData,
|
||||
String tableName) throws SQLException {
|
||||
String columnName = settings.getProperty(column.getColumnNameProperty());
|
||||
boolean isNotNull = isNotNullColumn(metaData, tableName, columnName);
|
||||
boolean hasDefaultValue = getColumnDefaultValue(metaData, tableName, columnName) != null;
|
||||
return column.name()
|
||||
+ (isNotNull ? NOT_NULL_SUFFIX : "")
|
||||
+ (hasDefaultValue ? DEFAULT_VALUE_SUFFIX : "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Connection object from the MySQL data source.
|
||||
*
|
||||
* @param mySql the MySQL data source to get the connection from
|
||||
* @return the connection
|
||||
*/
|
||||
@VisibleForTesting
|
||||
Connection getConnection(MySQL mySql) {
|
||||
try {
|
||||
Method method = MySQL.class.getDeclaredMethod("getConnection");
|
||||
method.setAccessible(true);
|
||||
return (Connection) method.invoke(mySql);
|
||||
} catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
|
||||
throw new IllegalStateException("Could not get MySQL connection", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static <E extends Enum<E>> E matchToEnum(List<String> arguments, int index, Class<E> clazz) {
|
||||
if (arguments.size() <= index) {
|
||||
return null;
|
||||
}
|
||||
String str = arguments.get(index);
|
||||
return Arrays.stream(clazz.getEnumConstants())
|
||||
.filter(e -> e.name().equalsIgnoreCase(str))
|
||||
.findFirst().orElse(null);
|
||||
}
|
||||
|
||||
private enum Operation {
|
||||
ADD, REMOVE, DETAILS
|
||||
}
|
||||
|
||||
/** MySQL columns which can be toggled between being NOT NULL and allowing NULL values. */
|
||||
enum Columns {
|
||||
|
||||
LASTLOGIN(DatabaseSettings.MYSQL_COL_LASTLOGIN,
|
||||
"BIGINT", "BIGINT NOT NULL DEFAULT 0", DB_LAST_LOGIN_DEFAULT),
|
||||
|
||||
LASTIP(DatabaseSettings.MYSQL_COL_LAST_IP,
|
||||
"VARCHAR(40) CHARACTER SET ascii COLLATE ascii_bin",
|
||||
"VARCHAR(40) CHARACTER SET ascii COLLATE ascii_bin NOT NULL DEFAULT '127.0.0.1'",
|
||||
DB_LAST_IP_DEFAULT),
|
||||
|
||||
EMAIL(DatabaseSettings.MYSQL_COL_EMAIL,
|
||||
"VARCHAR(255)", "VARCHAR(255) NOT NULL DEFAULT 'your@email.com'", DB_EMAIL_DEFAULT);
|
||||
|
||||
private final Property<String> columnNameProperty;
|
||||
private final String nullableDefinition;
|
||||
private final String notNullDefinition;
|
||||
private final Object defaultValue;
|
||||
|
||||
Columns(Property<String> columnNameProperty, String nullableDefinition,
|
||||
String notNullDefinition, Object defaultValue) {
|
||||
this.columnNameProperty = columnNameProperty;
|
||||
this.nullableDefinition = nullableDefinition;
|
||||
this.notNullDefinition = notNullDefinition;
|
||||
this.defaultValue = defaultValue;
|
||||
}
|
||||
|
||||
/** @return property defining the column name in the database */
|
||||
Property<String> getColumnNameProperty() {
|
||||
return columnNameProperty;
|
||||
}
|
||||
|
||||
/** @return SQL definition of the column allowing NULL values */
|
||||
String getNullableDefinition() {
|
||||
return nullableDefinition;
|
||||
}
|
||||
|
||||
/** @return SQL definition of the column with a NOT NULL constraint */
|
||||
String getNotNullDefinition() {
|
||||
return notNullDefinition;
|
||||
}
|
||||
|
||||
/** @return the default value used in {@link #notNullDefinition} */
|
||||
Object getDefaultValue() {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.authme.debug;
|
||||
|
||||
import fr.xephi.authme.data.limbo.UserGroup;
|
||||
import fr.xephi.authme.permission.DebugSectionPermissions;
|
||||
import fr.xephi.authme.permission.PermissionNode;
|
||||
import fr.xephi.authme.permission.PermissionsManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
/**
|
||||
* Outputs the permission groups of a player.
|
||||
*/
|
||||
class PermissionGroups implements DebugSection {
|
||||
|
||||
@Inject
|
||||
private PermissionsManager permissionsManager;
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "groups";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Show permission groups a player belongs to";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender sender, List<String> arguments) {
|
||||
sender.sendMessage(ChatColor.BLUE + "AuthMe permission groups");
|
||||
String name = arguments.isEmpty() ? sender.getName() : arguments.get(0);
|
||||
Player player = Bukkit.getPlayer(name);
|
||||
if (player == null) {
|
||||
sender.sendMessage("Player " + name + " could not be found");
|
||||
} else {
|
||||
List<String> groupNames = permissionsManager.getGroups(player).stream()
|
||||
.map(UserGroup::getGroupName)
|
||||
.collect(toList());
|
||||
|
||||
sender.sendMessage("Player " + name + " has permission groups: " + String.join(", ", groupNames));
|
||||
sender.sendMessage("Primary group is: " + permissionsManager.getGroups(player));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionNode getRequiredPermission() {
|
||||
return DebugSectionPermissions.PERM_GROUPS;
|
||||
}
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.authme.debug;
|
||||
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.permission.DebugSectionPermissions;
|
||||
import fr.xephi.authme.permission.PermissionNode;
|
||||
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||
import fr.xephi.authme.util.StringUtils;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
|
||||
import static fr.xephi.authme.command.executable.authme.debug.DebugSectionUtils.formatLocation;
|
||||
|
||||
/**
|
||||
* Allows to view the data of a PlayerAuth in the database.
|
||||
*/
|
||||
class PlayerAuthViewer implements DebugSection {
|
||||
|
||||
@Inject
|
||||
private DataSource dataSource;
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "db";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "View player's data in the database";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender sender, List<String> arguments) {
|
||||
if (arguments.isEmpty()) {
|
||||
sender.sendMessage(ChatColor.BLUE + "AuthMe database viewer");
|
||||
sender.sendMessage("Enter player name to view his data in the database.");
|
||||
sender.sendMessage("Example: /authme debug db Bobby");
|
||||
return;
|
||||
}
|
||||
|
||||
PlayerAuth auth = dataSource.getAuth(arguments.get(0));
|
||||
if (auth == null) {
|
||||
sender.sendMessage(ChatColor.BLUE + "AuthMe database viewer");
|
||||
sender.sendMessage("No record exists for '" + arguments.get(0) + "'");
|
||||
} else {
|
||||
displayAuthToSender(auth, sender);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionNode getRequiredPermission() {
|
||||
return DebugSectionPermissions.PLAYER_AUTH_VIEWER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs the PlayerAuth information to the given sender.
|
||||
*
|
||||
* @param auth the PlayerAuth to display
|
||||
* @param sender the sender to send the messages to
|
||||
*/
|
||||
private void displayAuthToSender(PlayerAuth auth, CommandSender sender) {
|
||||
sender.sendMessage(ChatColor.BLUE + "[AuthMe] Player " + auth.getNickname() + " / " + auth.getRealName());
|
||||
sender.sendMessage("Email: " + auth.getEmail() + ". IP: " + auth.getLastIp() + ". Group: " + auth.getGroupId());
|
||||
sender.sendMessage("Quit location: "
|
||||
+ formatLocation(auth.getQuitLocX(), auth.getQuitLocY(), auth.getQuitLocZ(), auth.getWorld()));
|
||||
sender.sendMessage("Last login: " + formatDate(auth.getLastLogin()));
|
||||
sender.sendMessage("Registration: " + formatDate(auth.getRegistrationDate())
|
||||
+ " with IP " + auth.getRegistrationIp());
|
||||
|
||||
HashedPassword hashedPass = auth.getPassword();
|
||||
sender.sendMessage("Hash / salt (partial): '" + safeSubstring(hashedPass.getHash(), 6)
|
||||
+ "' / '" + safeSubstring(hashedPass.getSalt(), 4) + "'");
|
||||
sender.sendMessage("TOTP code (partial): '" + safeSubstring(auth.getTotpKey(), 3) + "'");
|
||||
}
|
||||
|
||||
/**
|
||||
* Fail-safe substring method. Guarantees not to show the entire String.
|
||||
*
|
||||
* @param str the string to transform
|
||||
* @param length number of characters to show from the start of the String
|
||||
* @return the first <code>length</code> characters of the string, or half of the string if it is shorter,
|
||||
* or empty string if the string is null or empty
|
||||
*/
|
||||
private static String safeSubstring(String str, int length) {
|
||||
if (StringUtils.isBlank(str)) {
|
||||
return "";
|
||||
} else if (str.length() < length) {
|
||||
return str.substring(0, str.length() / 2) + "...";
|
||||
} else {
|
||||
return str.substring(0, length) + "...";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the given timestamp to a human readable date.
|
||||
*
|
||||
* @param timestamp the timestamp to format (nullable)
|
||||
* @return the formatted timestamp
|
||||
*/
|
||||
private static String formatDate(Long timestamp) {
|
||||
if (timestamp == null) {
|
||||
return "Not available (null)";
|
||||
} else if (timestamp == 0) {
|
||||
return "Not available (0)";
|
||||
} else {
|
||||
LocalDateTime date = LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneId.systemDefault());
|
||||
return DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(date);
|
||||
}
|
||||
}
|
||||
}
|
||||
-87
@@ -1,87 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.authme.debug;
|
||||
|
||||
import fr.xephi.authme.permission.DebugSectionPermissions;
|
||||
import fr.xephi.authme.permission.PermissionNode;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.SpawnLoader;
|
||||
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
import static fr.xephi.authme.command.executable.authme.debug.DebugSectionUtils.formatLocation;
|
||||
|
||||
/**
|
||||
* Shows the spawn location that AuthMe is configured to use.
|
||||
*/
|
||||
class SpawnLocationViewer implements DebugSection {
|
||||
|
||||
@Inject
|
||||
private SpawnLoader spawnLoader;
|
||||
|
||||
@Inject
|
||||
private Settings settings;
|
||||
|
||||
@Inject
|
||||
private BukkitService bukkitService;
|
||||
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "spawn";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Shows the spawn location that AuthMe will use";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender sender, List<String> arguments) {
|
||||
sender.sendMessage(ChatColor.BLUE + "AuthMe spawn location viewer");
|
||||
if (arguments.isEmpty()) {
|
||||
showGeneralInfo(sender);
|
||||
} else if ("?".equals(arguments.get(0))) {
|
||||
showHelp(sender);
|
||||
} else {
|
||||
showPlayerSpawn(sender, arguments.get(0));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionNode getRequiredPermission() {
|
||||
return DebugSectionPermissions.SPAWN_LOCATION;
|
||||
}
|
||||
|
||||
private void showGeneralInfo(CommandSender sender) {
|
||||
sender.sendMessage("Spawn priority: "
|
||||
+ String.join(", ", settings.getProperty(RestrictionSettings.SPAWN_PRIORITY)));
|
||||
sender.sendMessage("AuthMe spawn location: " + formatLocation(spawnLoader.getSpawn()));
|
||||
sender.sendMessage("AuthMe first spawn location: " + formatLocation(spawnLoader.getFirstSpawn()));
|
||||
sender.sendMessage("AuthMe (first)spawn are only used depending on the configured priority!");
|
||||
sender.sendMessage("Use '/authme debug spawn ?' for further help");
|
||||
}
|
||||
|
||||
private void showHelp(CommandSender sender) {
|
||||
sender.sendMessage("Use /authme spawn and /authme firstspawn to teleport to the spawns.");
|
||||
sender.sendMessage("/authme set(first)spawn sets the (first) spawn to your current location.");
|
||||
sender.sendMessage("Use /authme debug spawn <player> to view where a player would be teleported to.");
|
||||
sender.sendMessage("Read more at https://github.com/AuthMe/AuthMeReloaded/wiki/Spawn-Handling");
|
||||
}
|
||||
|
||||
private void showPlayerSpawn(CommandSender sender, String playerName) {
|
||||
Player player = bukkitService.getPlayerExact(playerName);
|
||||
if (player == null) {
|
||||
sender.sendMessage("Player '" + playerName + "' is not online!");
|
||||
} else {
|
||||
Location spawn = spawnLoader.getSpawnLocation(player);
|
||||
sender.sendMessage("Player '" + playerName + "' has spawn location: " + formatLocation(spawn));
|
||||
sender.sendMessage("Note: this check excludes the AuthMe firstspawn.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.authme.debug;
|
||||
|
||||
import ch.jalu.datasourcecolumns.data.DataSourceValue;
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.mail.SendMailSsl;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.permission.DebugSectionPermissions;
|
||||
import fr.xephi.authme.permission.PermissionNode;
|
||||
import fr.xephi.authme.util.StringUtils;
|
||||
import fr.xephi.authme.util.Utils;
|
||||
import org.apache.commons.mail.EmailException;
|
||||
import org.apache.commons.mail.HtmlEmail;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Sends out a test email.
|
||||
*/
|
||||
class TestEmailSender implements DebugSection {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(TestEmailSender.class);
|
||||
|
||||
@Inject
|
||||
private DataSource dataSource;
|
||||
|
||||
@Inject
|
||||
private SendMailSsl sendMailSsl;
|
||||
|
||||
@Inject
|
||||
private Server server;
|
||||
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "mail";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Sends out a test email";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender sender, List<String> arguments) {
|
||||
sender.sendMessage(ChatColor.BLUE + "AuthMe test email sender");
|
||||
if (!sendMailSsl.hasAllInformation()) {
|
||||
sender.sendMessage(ChatColor.RED + "You haven't set all required configurations in config.yml "
|
||||
+ "for sending emails. Please check your config.yml");
|
||||
return;
|
||||
}
|
||||
|
||||
String email = getEmail(sender, arguments);
|
||||
|
||||
// getEmail() takes care of informing the sender of the error if email == null
|
||||
if (email != null) {
|
||||
boolean sendMail = sendTestEmail(email);
|
||||
if (sendMail) {
|
||||
sender.sendMessage("Test email sent to " + email + " with success");
|
||||
} else {
|
||||
sender.sendMessage(ChatColor.RED + "Failed to send test mail to " + email + "; please check your logs");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionNode getRequiredPermission() {
|
||||
return DebugSectionPermissions.TEST_EMAIL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the email address to use based on the sender and the arguments. If the arguments are empty,
|
||||
* we attempt to retrieve the email from the sender. If there is an argument, we verify that it is
|
||||
* an email address.
|
||||
* {@code null} is returned if no email address could be found. This method informs the sender of
|
||||
* the specific error in such cases.
|
||||
*
|
||||
* @param sender the command sender
|
||||
* @param arguments the provided arguments
|
||||
* @return the email to use, or null if none found
|
||||
*/
|
||||
private String getEmail(CommandSender sender, List<String> arguments) {
|
||||
if (arguments.isEmpty()) {
|
||||
DataSourceValue<String> emailResult = dataSource.getEmail(sender.getName());
|
||||
if (!emailResult.rowExists()) {
|
||||
sender.sendMessage(ChatColor.RED + "Please provide an email address, "
|
||||
+ "e.g. /authme debug mail test@example.com");
|
||||
return null;
|
||||
}
|
||||
final String email = emailResult.getValue();
|
||||
if (Utils.isEmailEmpty(email)) {
|
||||
sender.sendMessage(ChatColor.RED + "No email set for your account!"
|
||||
+ " Please use /authme debug mail <email>");
|
||||
return null;
|
||||
}
|
||||
return email;
|
||||
} else {
|
||||
String email = arguments.get(0);
|
||||
if (StringUtils.isInsideString('@', email)) {
|
||||
return email;
|
||||
}
|
||||
sender.sendMessage(ChatColor.RED + "Invalid email! Usage: /authme debug mail test@example.com");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean sendTestEmail(String email) {
|
||||
HtmlEmail htmlEmail;
|
||||
try {
|
||||
htmlEmail = sendMailSsl.initializeMail(email);
|
||||
} catch (EmailException e) {
|
||||
logger.logException("Failed to create email for sample email:", e);
|
||||
return false;
|
||||
}
|
||||
|
||||
htmlEmail.setSubject("AuthMe test email");
|
||||
String message = "Hello there!<br />This is a sample email sent to you from a Minecraft server ("
|
||||
+ server.getName() + ") via /authme debug mail. If you're seeing this, sending emails should be fine.";
|
||||
return sendMailSsl.sendEmail(message, htmlEmail);
|
||||
}
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.captcha;
|
||||
|
||||
import fr.xephi.authme.command.PlayerCommand;
|
||||
import fr.xephi.authme.data.auth.PlayerCache;
|
||||
import fr.xephi.authme.data.captcha.LoginCaptchaManager;
|
||||
import fr.xephi.authme.data.captcha.RegistrationCaptchaManager;
|
||||
import fr.xephi.authme.data.limbo.LimboMessageType;
|
||||
import fr.xephi.authme.data.limbo.LimboService;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Captcha command, allowing a player to solve a captcha.
|
||||
*/
|
||||
public class CaptchaCommand extends PlayerCommand {
|
||||
|
||||
@Inject
|
||||
private PlayerCache playerCache;
|
||||
|
||||
@Inject
|
||||
private LoginCaptchaManager loginCaptchaManager;
|
||||
|
||||
@Inject
|
||||
private RegistrationCaptchaManager registrationCaptchaManager;
|
||||
|
||||
@Inject
|
||||
private CommonService commonService;
|
||||
|
||||
@Inject
|
||||
private LimboService limboService;
|
||||
|
||||
@Inject
|
||||
private DataSource dataSource;
|
||||
|
||||
@Override
|
||||
public void runCommand(Player player, List<String> arguments) {
|
||||
final String name = player.getName();
|
||||
|
||||
if (playerCache.isAuthenticated(name)) {
|
||||
// No captcha is relevant if the player is logged in
|
||||
commonService.send(player, MessageKey.ALREADY_LOGGED_IN_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (loginCaptchaManager.isCaptchaRequired(name)) {
|
||||
checkLoginCaptcha(player, arguments.get(0));
|
||||
} else {
|
||||
final boolean isPlayerRegistered = dataSource.isAuthAvailable(name);
|
||||
if (!isPlayerRegistered && registrationCaptchaManager.isCaptchaRequired(name)) {
|
||||
checkRegisterCaptcha(player, arguments.get(0));
|
||||
} else {
|
||||
MessageKey errorMessage = isPlayerRegistered ? MessageKey.USAGE_LOGIN : MessageKey.USAGE_REGISTER;
|
||||
commonService.send(player, errorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkLoginCaptcha(Player player, String captchaCode) {
|
||||
final boolean isCorrectCode = loginCaptchaManager.checkCode(player, captchaCode);
|
||||
if (isCorrectCode) {
|
||||
commonService.send(player, MessageKey.CAPTCHA_SUCCESS);
|
||||
commonService.send(player, MessageKey.LOGIN_MESSAGE);
|
||||
limboService.unmuteMessageTask(player);
|
||||
} else {
|
||||
String newCode = loginCaptchaManager.getCaptchaCodeOrGenerateNew(player.getName());
|
||||
commonService.send(player, MessageKey.CAPTCHA_WRONG_ERROR, newCode);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkRegisterCaptcha(Player player, String captchaCode) {
|
||||
final boolean isCorrectCode = registrationCaptchaManager.checkCode(player, captchaCode);
|
||||
if (isCorrectCode) {
|
||||
commonService.send(player, MessageKey.REGISTER_CAPTCHA_SUCCESS);
|
||||
commonService.send(player, MessageKey.REGISTER_MESSAGE);
|
||||
} else {
|
||||
String newCode = registrationCaptchaManager.getCaptchaCodeOrGenerateNew(player.getName());
|
||||
commonService.send(player, MessageKey.CAPTCHA_WRONG_ERROR, newCode);
|
||||
}
|
||||
limboService.resetMessageTask(player, LimboMessageType.REGISTER);
|
||||
}
|
||||
}
|
||||
-74
@@ -1,74 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.changepassword;
|
||||
|
||||
import fr.xephi.authme.command.PlayerCommand;
|
||||
import fr.xephi.authme.data.VerificationCodeManager;
|
||||
import fr.xephi.authme.data.auth.PlayerCache;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.process.Management;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.service.ValidationService;
|
||||
import fr.xephi.authme.service.ValidationService.ValidationResult;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* The command for a player to change his password with.
|
||||
*/
|
||||
public class ChangePasswordCommand extends PlayerCommand {
|
||||
|
||||
@Inject
|
||||
private CommonService commonService;
|
||||
|
||||
@Inject
|
||||
private PlayerCache playerCache;
|
||||
|
||||
@Inject
|
||||
private ValidationService validationService;
|
||||
|
||||
@Inject
|
||||
private Management management;
|
||||
|
||||
@Inject
|
||||
private VerificationCodeManager codeManager;
|
||||
|
||||
@Override
|
||||
public void runCommand(Player player, List<String> arguments) {
|
||||
String name = player.getName().toLowerCase(Locale.ROOT);
|
||||
|
||||
if (!playerCache.isAuthenticated(name)) {
|
||||
commonService.send(player, MessageKey.NOT_LOGGED_IN);
|
||||
return;
|
||||
}
|
||||
// Check if the user has been verified or not
|
||||
if (codeManager.isVerificationRequired(player)) {
|
||||
codeManager.codeExistOrGenerateNew(name);
|
||||
commonService.send(player, MessageKey.VERIFICATION_CODE_REQUIRED);
|
||||
return;
|
||||
}
|
||||
|
||||
String oldPassword = arguments.get(0);
|
||||
String newPassword = arguments.get(1);
|
||||
|
||||
// Make sure the password is allowed
|
||||
ValidationResult passwordValidation = validationService.validatePassword(newPassword, name);
|
||||
if (passwordValidation.hasError()) {
|
||||
commonService.send(player, passwordValidation.getMessageKey(), passwordValidation.getArgs());
|
||||
return;
|
||||
}
|
||||
|
||||
management.performPasswordChange(player, oldPassword, newPassword);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getAlternativeCommand() {
|
||||
return "/authme password <playername> <password>";
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageKey getArgumentsMismatchMessage() {
|
||||
return MessageKey.USAGE_CHANGE_PASSWORD;
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.email;
|
||||
|
||||
import fr.xephi.authme.command.PlayerCommand;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.process.Management;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Command for setting an email to an account.
|
||||
*/
|
||||
public class AddEmailCommand extends PlayerCommand {
|
||||
|
||||
@Inject
|
||||
private Management management;
|
||||
|
||||
@Inject
|
||||
private CommonService commonService;
|
||||
|
||||
@Override
|
||||
public void runCommand(Player player, List<String> arguments) {
|
||||
String email = arguments.get(0);
|
||||
String emailConfirmation = arguments.get(1);
|
||||
|
||||
if (email.equals(emailConfirmation)) {
|
||||
// Closer inspection of the mail address handled by the async task
|
||||
management.performAddEmail(player, email);
|
||||
} else {
|
||||
commonService.send(player, MessageKey.CONFIRM_EMAIL_MESSAGE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageKey getArgumentsMismatchMessage() {
|
||||
return MessageKey.USAGE_ADD_EMAIL;
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.email;
|
||||
|
||||
import fr.xephi.authme.command.PlayerCommand;
|
||||
import fr.xephi.authme.data.VerificationCodeManager;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.process.Management;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Change email command.
|
||||
*/
|
||||
public class ChangeEmailCommand extends PlayerCommand {
|
||||
|
||||
@Inject
|
||||
private Management management;
|
||||
|
||||
@Inject
|
||||
private CommonService commonService;
|
||||
|
||||
@Inject
|
||||
private VerificationCodeManager codeManager;
|
||||
|
||||
@Override
|
||||
public void runCommand(Player player, List<String> arguments) {
|
||||
final String playerName = player.getName();
|
||||
// Check if the user has been verified or not
|
||||
if (codeManager.isVerificationRequired(player)) {
|
||||
codeManager.codeExistOrGenerateNew(playerName);
|
||||
commonService.send(player, MessageKey.VERIFICATION_CODE_REQUIRED);
|
||||
return;
|
||||
}
|
||||
|
||||
String playerMailOld = arguments.get(0);
|
||||
String playerMailNew = arguments.get(1);
|
||||
management.performChangeEmail(player, playerMailOld, playerMailNew);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageKey getArgumentsMismatchMessage() {
|
||||
return MessageKey.USAGE_CHANGE_EMAIL;
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.email;
|
||||
|
||||
import fr.xephi.authme.command.CommandMapper;
|
||||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.command.FoundCommandResult;
|
||||
import fr.xephi.authme.command.help.HelpProvider;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Base command for /email, showing information about the child commands.
|
||||
*/
|
||||
public class EmailBaseCommand implements ExecutableCommand {
|
||||
|
||||
@Inject
|
||||
private CommandMapper commandMapper;
|
||||
|
||||
@Inject
|
||||
private HelpProvider helpProvider;
|
||||
|
||||
@Override
|
||||
public void executeCommand(CommandSender sender, List<String> arguments) {
|
||||
FoundCommandResult result = commandMapper.mapPartsToCommand(sender, Collections.singletonList("email"));
|
||||
helpProvider.outputHelp(sender, result, HelpProvider.SHOW_CHILDREN);
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.email;
|
||||
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.command.PlayerCommand;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.security.PasswordSecurity;
|
||||
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.service.PasswordRecoveryService;
|
||||
import fr.xephi.authme.service.ValidationService;
|
||||
import fr.xephi.authme.service.ValidationService.ValidationResult;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Command for changing password following successful recovery.
|
||||
*/
|
||||
public class EmailSetPasswordCommand extends PlayerCommand {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(EmailSetPasswordCommand.class);
|
||||
|
||||
@Inject
|
||||
private DataSource dataSource;
|
||||
|
||||
@Inject
|
||||
private CommonService commonService;
|
||||
|
||||
@Inject
|
||||
private PasswordRecoveryService recoveryService;
|
||||
|
||||
@Inject
|
||||
private PasswordSecurity passwordSecurity;
|
||||
|
||||
@Inject
|
||||
private ValidationService validationService;
|
||||
|
||||
@Override
|
||||
protected void runCommand(Player player, List<String> arguments) {
|
||||
if (recoveryService.canChangePassword(player)) {
|
||||
String name = player.getName();
|
||||
String password = arguments.get(0);
|
||||
|
||||
ValidationResult result = validationService.validatePassword(password, name);
|
||||
if (!result.hasError()) {
|
||||
HashedPassword hashedPassword = passwordSecurity.computeHash(password, name);
|
||||
dataSource.updatePassword(name, hashedPassword);
|
||||
recoveryService.removeFromSuccessfulRecovery(player);
|
||||
logger.info("Player '" + name + "' has changed their password from recovery");
|
||||
commonService.send(player, MessageKey.PASSWORD_CHANGED_SUCCESS);
|
||||
} else {
|
||||
commonService.send(player, result.getMessageKey(), result.getArgs());
|
||||
}
|
||||
} else {
|
||||
commonService.send(player, MessageKey.CHANGE_PASSWORD_EXPIRED);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.email;
|
||||
|
||||
import fr.xephi.authme.command.PlayerCommand;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.service.PasswordRecoveryService;
|
||||
import fr.xephi.authme.service.RecoveryCodeService;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Command for submitting email recovery code.
|
||||
*/
|
||||
public class ProcessCodeCommand extends PlayerCommand {
|
||||
|
||||
@Inject
|
||||
private CommonService commonService;
|
||||
|
||||
@Inject
|
||||
private RecoveryCodeService codeService;
|
||||
|
||||
@Inject
|
||||
private PasswordRecoveryService recoveryService;
|
||||
|
||||
@Override
|
||||
protected void runCommand(Player player, List<String> arguments) {
|
||||
String name = player.getName();
|
||||
String code = arguments.get(0);
|
||||
|
||||
if (codeService.hasTriesLeft(name)) {
|
||||
if (codeService.isCodeValid(name, code)) {
|
||||
commonService.send(player, MessageKey.RECOVERY_CODE_CORRECT);
|
||||
recoveryService.addSuccessfulRecovery(player);
|
||||
codeService.removeCode(name);
|
||||
} else {
|
||||
commonService.send(player, MessageKey.INCORRECT_RECOVERY_CODE,
|
||||
Integer.toString(codeService.getTriesLeft(name)));
|
||||
}
|
||||
} else {
|
||||
codeService.removeCode(name);
|
||||
commonService.send(player, MessageKey.RECOVERY_TRIES_EXCEEDED);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.email;
|
||||
|
||||
import ch.jalu.datasourcecolumns.data.DataSourceValue;
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.command.PlayerCommand;
|
||||
import fr.xephi.authme.data.auth.PlayerCache;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.mail.EmailService;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.service.PasswordRecoveryService;
|
||||
import fr.xephi.authme.service.RecoveryCodeService;
|
||||
import fr.xephi.authme.util.Utils;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Command for password recovery by email.
|
||||
*/
|
||||
public class RecoverEmailCommand extends PlayerCommand {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(RecoverEmailCommand.class);
|
||||
|
||||
@Inject
|
||||
private CommonService commonService;
|
||||
|
||||
@Inject
|
||||
private DataSource dataSource;
|
||||
|
||||
@Inject
|
||||
private PlayerCache playerCache;
|
||||
|
||||
@Inject
|
||||
private EmailService emailService;
|
||||
|
||||
@Inject
|
||||
private PasswordRecoveryService recoveryService;
|
||||
|
||||
@Inject
|
||||
private RecoveryCodeService recoveryCodeService;
|
||||
|
||||
@Inject
|
||||
private BukkitService bukkitService;
|
||||
|
||||
@Override
|
||||
protected void runCommand(Player player, List<String> arguments) {
|
||||
final String playerMail = arguments.get(0);
|
||||
final String playerName = player.getName();
|
||||
|
||||
if (!emailService.hasAllInformation()) {
|
||||
logger.warning("Mail API is not set");
|
||||
commonService.send(player, MessageKey.INCOMPLETE_EMAIL_SETTINGS);
|
||||
return;
|
||||
}
|
||||
if (playerCache.isAuthenticated(playerName)) {
|
||||
commonService.send(player, MessageKey.ALREADY_LOGGED_IN_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
DataSourceValue<String> emailResult = dataSource.getEmail(playerName);
|
||||
if (!emailResult.rowExists()) {
|
||||
commonService.send(player, MessageKey.USAGE_REGISTER);
|
||||
return;
|
||||
}
|
||||
|
||||
final String email = emailResult.getValue();
|
||||
if (Utils.isEmailEmpty(email) || !email.equalsIgnoreCase(playerMail)) {
|
||||
commonService.send(player, MessageKey.INVALID_EMAIL);
|
||||
return;
|
||||
}
|
||||
|
||||
bukkitService.runTaskAsynchronously(() -> {
|
||||
if (recoveryCodeService.isRecoveryCodeNeeded()) {
|
||||
// Recovery code is needed; generate and send one
|
||||
recoveryService.createAndSendRecoveryCode(player, email);
|
||||
} else {
|
||||
// Code not needed, just send them a new password
|
||||
recoveryService.generateAndSendNewPassword(player, email);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageKey getArgumentsMismatchMessage() {
|
||||
return MessageKey.USAGE_RECOVER_EMAIL;
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.email;
|
||||
|
||||
import fr.xephi.authme.command.PlayerCommand;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.data.auth.PlayerCache;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.settings.properties.SecuritySettings;
|
||||
import fr.xephi.authme.util.Utils;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Show email command.
|
||||
*/
|
||||
public class ShowEmailCommand extends PlayerCommand {
|
||||
|
||||
@Inject
|
||||
private CommonService commonService;
|
||||
|
||||
@Inject
|
||||
private PlayerCache playerCache;
|
||||
|
||||
@Override
|
||||
public void runCommand(Player player, List<String> arguments) {
|
||||
PlayerAuth auth = playerCache.getAuth(player.getName());
|
||||
if (auth != null && !Utils.isEmailEmpty(auth.getEmail())) {
|
||||
if (commonService.getProperty(SecuritySettings.USE_EMAIL_MASKING)){
|
||||
commonService.send(player, MessageKey.EMAIL_SHOW, emailMask(auth.getEmail()));
|
||||
} else {
|
||||
commonService.send(player, MessageKey.EMAIL_SHOW, auth.getEmail());
|
||||
}
|
||||
} else {
|
||||
commonService.send(player, MessageKey.SHOW_NO_EMAIL);
|
||||
}
|
||||
}
|
||||
|
||||
private String emailMask(String email){
|
||||
String[] frag = email.split("@"); //Split id and domain
|
||||
int sid = frag[0].length() / 3 + 1; //Define the id view (required length >= 1)
|
||||
int sdomain = frag[1].length() / 3; //Define the domain view (required length >= 0)
|
||||
String id = frag[0].substring(0, sid) + "***"; //Build the id
|
||||
String domain = "***" + frag[1].substring(sdomain); //Build the domain
|
||||
return id + "@" + domain;
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.login;
|
||||
|
||||
import fr.xephi.authme.command.PlayerCommand;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.process.Management;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Login command.
|
||||
*/
|
||||
public class LoginCommand extends PlayerCommand {
|
||||
|
||||
@Inject
|
||||
private Management management;
|
||||
|
||||
@Override
|
||||
public void runCommand(Player player, List<String> arguments) {
|
||||
String password = arguments.get(0);
|
||||
management.performLogin(player, password);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageKey getArgumentsMismatchMessage() {
|
||||
return MessageKey.USAGE_LOGIN;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getAlternativeCommand() {
|
||||
return "/authme forcelogin <player>";
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.logout;
|
||||
|
||||
import fr.xephi.authme.command.PlayerCommand;
|
||||
import fr.xephi.authme.process.Management;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Logout command.
|
||||
*/
|
||||
public class LogoutCommand extends PlayerCommand {
|
||||
|
||||
@Inject
|
||||
private Management management;
|
||||
|
||||
@Override
|
||||
public void runCommand(Player player, List<String> arguments) {
|
||||
management.performLogout(player);
|
||||
}
|
||||
}
|
||||
@@ -1,225 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.register;
|
||||
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.command.PlayerCommand;
|
||||
import fr.xephi.authme.data.captcha.RegistrationCaptchaManager;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.mail.EmailService;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.process.Management;
|
||||
import fr.xephi.authme.process.register.RegisterSecondaryArgument;
|
||||
import fr.xephi.authme.process.register.RegistrationType;
|
||||
import fr.xephi.authme.process.register.executors.EmailRegisterParams;
|
||||
import fr.xephi.authme.process.register.executors.PasswordRegisterParams;
|
||||
import fr.xephi.authme.process.register.executors.RegistrationMethod;
|
||||
import fr.xephi.authme.process.register.executors.TwoFactorRegisterParams;
|
||||
import fr.xephi.authme.security.HashAlgorithm;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.service.ValidationService;
|
||||
import fr.xephi.authme.settings.properties.EmailSettings;
|
||||
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
||||
import fr.xephi.authme.settings.properties.SecuritySettings;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
import static fr.xephi.authme.process.register.RegisterSecondaryArgument.CONFIRMATION;
|
||||
import static fr.xephi.authme.process.register.RegisterSecondaryArgument.EMAIL_MANDATORY;
|
||||
import static fr.xephi.authme.process.register.RegisterSecondaryArgument.EMAIL_OPTIONAL;
|
||||
import static fr.xephi.authme.process.register.RegisterSecondaryArgument.NONE;
|
||||
import static fr.xephi.authme.settings.properties.RegistrationSettings.REGISTER_SECOND_ARGUMENT;
|
||||
|
||||
/**
|
||||
* Command for /register.
|
||||
*/
|
||||
public class RegisterCommand extends PlayerCommand {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(RegisterCommand.class);
|
||||
|
||||
@Inject
|
||||
private Management management;
|
||||
|
||||
@Inject
|
||||
private CommonService commonService;
|
||||
|
||||
@Inject
|
||||
private DataSource dataSource;
|
||||
|
||||
@Inject
|
||||
private EmailService emailService;
|
||||
|
||||
@Inject
|
||||
private ValidationService validationService;
|
||||
|
||||
@Inject
|
||||
private RegistrationCaptchaManager registrationCaptchaManager;
|
||||
|
||||
@Override
|
||||
public void runCommand(Player player, List<String> arguments) {
|
||||
if (!isCaptchaFulfilled(player)) {
|
||||
return; // isCaptchaFulfilled handles informing the player on failure
|
||||
}
|
||||
|
||||
if (commonService.getProperty(SecuritySettings.PASSWORD_HASH) == HashAlgorithm.TWO_FACTOR) {
|
||||
//for two factor auth we don't need to check the usage
|
||||
management.performRegister(RegistrationMethod.TWO_FACTOR_REGISTRATION,
|
||||
TwoFactorRegisterParams.of(player));
|
||||
return;
|
||||
} else if (arguments.size() < 1) {
|
||||
commonService.send(player, MessageKey.USAGE_REGISTER);
|
||||
return;
|
||||
}
|
||||
|
||||
RegistrationType registrationType = commonService.getProperty(RegistrationSettings.REGISTRATION_TYPE);
|
||||
if (registrationType == RegistrationType.PASSWORD) {
|
||||
handlePasswordRegistration(player, arguments);
|
||||
} else if (registrationType == RegistrationType.EMAIL) {
|
||||
handleEmailRegistration(player, arguments);
|
||||
} else {
|
||||
throw new IllegalStateException("Unknown registration type '" + registrationType + "'");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getAlternativeCommand() {
|
||||
return "/authme register <playername> <password>";
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageKey getArgumentsMismatchMessage() {
|
||||
return MessageKey.USAGE_REGISTER;
|
||||
}
|
||||
|
||||
private boolean isCaptchaFulfilled(Player player) {
|
||||
if (registrationCaptchaManager.isCaptchaRequired(player.getName())) {
|
||||
String code = registrationCaptchaManager.getCaptchaCodeOrGenerateNew(player.getName());
|
||||
commonService.send(player, MessageKey.CAPTCHA_FOR_REGISTRATION_REQUIRED, code);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void handlePasswordRegistration(Player player, List<String> arguments) {
|
||||
if (isSecondArgValidForPasswordRegistration(player, arguments)) {
|
||||
final String password = arguments.get(0);
|
||||
final String email = getEmailIfAvailable(arguments);
|
||||
|
||||
management.performRegister(RegistrationMethod.PASSWORD_REGISTRATION,
|
||||
PasswordRegisterParams.of(player, password, email));
|
||||
}
|
||||
}
|
||||
|
||||
private String getEmailIfAvailable(List<String> arguments) {
|
||||
if (arguments.size() >= 2) {
|
||||
RegisterSecondaryArgument secondArgType = commonService.getProperty(REGISTER_SECOND_ARGUMENT);
|
||||
if (secondArgType == EMAIL_MANDATORY || secondArgType == EMAIL_OPTIONAL) {
|
||||
return arguments.get(1);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that the second argument is valid (based on the configuration)
|
||||
* to perform a password registration. The player is informed if the check
|
||||
* is unsuccessful.
|
||||
*
|
||||
* @param player the player to register
|
||||
* @param arguments the provided arguments
|
||||
* @return true if valid, false otherwise
|
||||
*/
|
||||
private boolean isSecondArgValidForPasswordRegistration(Player player, List<String> arguments) {
|
||||
RegisterSecondaryArgument secondArgType = commonService.getProperty(REGISTER_SECOND_ARGUMENT);
|
||||
// cases where args.size < 2
|
||||
if (secondArgType == NONE || secondArgType == EMAIL_OPTIONAL && arguments.size() < 2) {
|
||||
return true;
|
||||
} else if (arguments.size() < 2) {
|
||||
commonService.send(player, MessageKey.USAGE_REGISTER);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (secondArgType == CONFIRMATION) {
|
||||
if (arguments.get(0).equals(arguments.get(1))) {
|
||||
return true;
|
||||
} else {
|
||||
commonService.send(player, MessageKey.PASSWORD_MATCH_ERROR);
|
||||
return false;
|
||||
}
|
||||
} else if (secondArgType == EMAIL_MANDATORY || secondArgType == EMAIL_OPTIONAL) {
|
||||
if (validationService.validateEmail(arguments.get(1))) {
|
||||
return true;
|
||||
} else {
|
||||
commonService.send(player, MessageKey.INVALID_EMAIL);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
throw new IllegalStateException("Unknown secondary argument type '" + secondArgType + "'");
|
||||
}
|
||||
}
|
||||
|
||||
private void handleEmailRegistration(Player player, List<String> arguments) {
|
||||
if (!emailService.hasAllInformation()) {
|
||||
commonService.send(player, MessageKey.INCOMPLETE_EMAIL_SETTINGS);
|
||||
logger.warning("Cannot register player '" + player.getName() + "': no email or password is set "
|
||||
+ "to send emails from. Please adjust your config at " + EmailSettings.MAIL_ACCOUNT.getPath());
|
||||
return;
|
||||
}
|
||||
|
||||
final String email = arguments.get(0);
|
||||
if (!validationService.validateEmail(email)) {
|
||||
commonService.send(player, MessageKey.INVALID_EMAIL);
|
||||
} else if (isSecondArgValidForEmailRegistration(player, arguments)) {
|
||||
management.performRegister(RegistrationMethod.EMAIL_REGISTRATION,
|
||||
EmailRegisterParams.of(player, email));
|
||||
Timer timer = new Timer();
|
||||
timer.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (dataSource.getAuth(player.getName()) != null) {
|
||||
if (dataSource.getAuth(player.getName()).getLastLogin() == null) {
|
||||
management.performUnregisterByAdmin(null, player.getName(), player);
|
||||
timer.cancel();
|
||||
}
|
||||
} else {
|
||||
timer.cancel();
|
||||
}
|
||||
}
|
||||
}, 600000);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that the second argument is valid (based on the configuration)
|
||||
* to perform an email registration. The player is informed if the check
|
||||
* is unsuccessful.
|
||||
*
|
||||
* @param player the player to register
|
||||
* @param arguments the provided arguments
|
||||
* @return true if valid, false otherwise
|
||||
*/
|
||||
private boolean isSecondArgValidForEmailRegistration(Player player, List<String> arguments) {
|
||||
RegisterSecondaryArgument secondArgType = commonService.getProperty(REGISTER_SECOND_ARGUMENT);
|
||||
// cases where args.size < 2
|
||||
if (secondArgType == NONE || secondArgType == EMAIL_OPTIONAL && arguments.size() < 2) {
|
||||
return true;
|
||||
} else if (arguments.size() < 2) {
|
||||
commonService.send(player, MessageKey.USAGE_REGISTER);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (secondArgType == EMAIL_OPTIONAL || secondArgType == EMAIL_MANDATORY || secondArgType == CONFIRMATION) {
|
||||
if (arguments.get(0).equals(arguments.get(1))) {
|
||||
return true;
|
||||
} else {
|
||||
commonService.send(player, MessageKey.USAGE_REGISTER);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
throw new IllegalStateException("Unknown secondary argument type '" + secondArgType + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.totp;
|
||||
|
||||
import fr.xephi.authme.command.PlayerCommand;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.data.auth.PlayerCache;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.message.Messages;
|
||||
import fr.xephi.authme.security.totp.GenerateTotpService;
|
||||
import fr.xephi.authme.security.totp.TotpAuthenticator.TotpGenerationResult;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Command for a player to enable TOTP.
|
||||
*/
|
||||
public class AddTotpCommand extends PlayerCommand {
|
||||
|
||||
@Inject
|
||||
private GenerateTotpService generateTotpService;
|
||||
|
||||
@Inject
|
||||
private PlayerCache playerCache;
|
||||
|
||||
@Inject
|
||||
private Messages messages;
|
||||
|
||||
@Override
|
||||
protected void runCommand(Player player, List<String> arguments) {
|
||||
PlayerAuth auth = playerCache.getAuth(player.getName());
|
||||
if (auth == null) {
|
||||
messages.send(player, MessageKey.NOT_LOGGED_IN);
|
||||
} else if (auth.getTotpKey() == null) {
|
||||
TotpGenerationResult createdTotpInfo = generateTotpService.generateTotpKey(player);
|
||||
messages.send(player, MessageKey.TWO_FACTOR_CREATE,
|
||||
createdTotpInfo.getTotpKey(), createdTotpInfo.getAuthenticatorQrCodeUrl());
|
||||
messages.send(player, MessageKey.TWO_FACTOR_CREATE_CONFIRMATION_REQUIRED);
|
||||
} else {
|
||||
messages.send(player, MessageKey.TWO_FACTOR_ALREADY_ENABLED);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.totp;
|
||||
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.command.PlayerCommand;
|
||||
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.message.Messages;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.security.totp.GenerateTotpService;
|
||||
import fr.xephi.authme.security.totp.TotpAuthenticator.TotpGenerationResult;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Command to enable TOTP by supplying the proper code as confirmation.
|
||||
*/
|
||||
public class ConfirmTotpCommand extends PlayerCommand {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(ConfirmTotpCommand.class);
|
||||
|
||||
@Inject
|
||||
private GenerateTotpService generateTotpService;
|
||||
|
||||
@Inject
|
||||
private PlayerCache playerCache;
|
||||
|
||||
@Inject
|
||||
private DataSource dataSource;
|
||||
|
||||
@Inject
|
||||
private Messages messages;
|
||||
|
||||
@Override
|
||||
protected void runCommand(Player player, List<String> arguments) {
|
||||
PlayerAuth auth = playerCache.getAuth(player.getName());
|
||||
if (auth == null) {
|
||||
messages.send(player, MessageKey.NOT_LOGGED_IN);
|
||||
} else if (auth.getTotpKey() != null) {
|
||||
messages.send(player, MessageKey.TWO_FACTOR_ALREADY_ENABLED);
|
||||
} else {
|
||||
verifyTotpCodeConfirmation(player, auth, arguments.get(0));
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyTotpCodeConfirmation(Player player, PlayerAuth auth, String inputTotpCode) {
|
||||
final TotpGenerationResult totpDetails = generateTotpService.getGeneratedTotpKey(player);
|
||||
if (totpDetails == null) {
|
||||
messages.send(player, MessageKey.TWO_FACTOR_ENABLE_ERROR_NO_CODE);
|
||||
} else {
|
||||
boolean isCodeValid = generateTotpService.isTotpCodeCorrectForGeneratedTotpKey(player, inputTotpCode);
|
||||
if (isCodeValid) {
|
||||
generateTotpService.removeGenerateTotpKey(player);
|
||||
insertTotpKeyIntoDatabase(player, auth, totpDetails);
|
||||
} else {
|
||||
messages.send(player, MessageKey.TWO_FACTOR_ENABLE_ERROR_WRONG_CODE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void insertTotpKeyIntoDatabase(Player player, PlayerAuth auth, TotpGenerationResult totpDetails) {
|
||||
if (dataSource.setTotpKey(player.getName(), totpDetails.getTotpKey())) {
|
||||
messages.send(player, MessageKey.TWO_FACTOR_ENABLE_SUCCESS);
|
||||
auth.setTotpKey(totpDetails.getTotpKey());
|
||||
playerCache.updatePlayer(auth);
|
||||
logger.info("Player '" + player.getName() + "' has successfully added a TOTP key to their account");
|
||||
} else {
|
||||
messages.send(player, MessageKey.ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.totp;
|
||||
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.command.PlayerCommand;
|
||||
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.message.Messages;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.security.totp.TotpAuthenticator;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Command for a player to remove 2FA authentication.
|
||||
*/
|
||||
public class RemoveTotpCommand extends PlayerCommand {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(RemoveTotpCommand.class);
|
||||
|
||||
@Inject
|
||||
private DataSource dataSource;
|
||||
|
||||
@Inject
|
||||
private PlayerCache playerCache;
|
||||
|
||||
@Inject
|
||||
private TotpAuthenticator totpAuthenticator;
|
||||
|
||||
@Inject
|
||||
private Messages messages;
|
||||
|
||||
@Override
|
||||
protected void runCommand(Player player, List<String> arguments) {
|
||||
PlayerAuth auth = playerCache.getAuth(player.getName());
|
||||
if (auth == null) {
|
||||
messages.send(player, MessageKey.NOT_LOGGED_IN);
|
||||
} else if (auth.getTotpKey() == null) {
|
||||
messages.send(player, MessageKey.TWO_FACTOR_NOT_ENABLED_ERROR);
|
||||
} else {
|
||||
if (totpAuthenticator.checkCode(auth, arguments.get(0))) {
|
||||
removeTotpKeyFromDatabase(player, auth);
|
||||
} else {
|
||||
messages.send(player, MessageKey.TWO_FACTOR_INVALID_CODE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void removeTotpKeyFromDatabase(Player player, PlayerAuth auth) {
|
||||
if (dataSource.removeTotpKey(auth.getNickname())) {
|
||||
auth.setTotpKey(null);
|
||||
playerCache.updatePlayer(auth);
|
||||
messages.send(player, MessageKey.TWO_FACTOR_REMOVED_SUCCESS);
|
||||
logger.info("Player '" + player.getName() + "' removed their TOTP key");
|
||||
} else {
|
||||
messages.send(player, MessageKey.ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.totp;
|
||||
|
||||
import fr.xephi.authme.command.CommandMapper;
|
||||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.command.FoundCommandResult;
|
||||
import fr.xephi.authme.command.help.HelpProvider;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Base command for /totp.
|
||||
*/
|
||||
public class TotpBaseCommand implements ExecutableCommand {
|
||||
|
||||
@Inject
|
||||
private CommandMapper commandMapper;
|
||||
|
||||
@Inject
|
||||
private HelpProvider helpProvider;
|
||||
|
||||
@Override
|
||||
public void executeCommand(CommandSender sender, List<String> arguments) {
|
||||
FoundCommandResult result = commandMapper.mapPartsToCommand(sender, Collections.singletonList("totp"));
|
||||
helpProvider.outputHelp(sender, result, HelpProvider.SHOW_CHILDREN);
|
||||
}
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.totp;
|
||||
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.command.PlayerCommand;
|
||||
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.LimboPlayerState;
|
||||
import fr.xephi.authme.data.limbo.LimboService;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.message.Messages;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.process.login.AsynchronousLogin;
|
||||
import fr.xephi.authme.security.totp.TotpAuthenticator;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* TOTP code command for processing the 2FA code during the login process.
|
||||
*/
|
||||
public class TotpCodeCommand extends PlayerCommand {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(TotpCodeCommand.class);
|
||||
|
||||
@Inject
|
||||
private LimboService limboService;
|
||||
|
||||
@Inject
|
||||
private PlayerCache playerCache;
|
||||
|
||||
@Inject
|
||||
private Messages messages;
|
||||
|
||||
@Inject
|
||||
private TotpAuthenticator totpAuthenticator;
|
||||
|
||||
@Inject
|
||||
private DataSource dataSource;
|
||||
|
||||
@Inject
|
||||
private AsynchronousLogin asynchronousLogin;
|
||||
|
||||
@Override
|
||||
protected void runCommand(Player player, List<String> arguments) {
|
||||
if (playerCache.isAuthenticated(player.getName())) {
|
||||
messages.send(player, MessageKey.ALREADY_LOGGED_IN_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
PlayerAuth auth = dataSource.getAuth(player.getName());
|
||||
if (auth == null) {
|
||||
messages.send(player, MessageKey.REGISTER_MESSAGE);
|
||||
return;
|
||||
}
|
||||
|
||||
LimboPlayer limbo = limboService.getLimboPlayer(player.getName());
|
||||
if (limbo != null && limbo.getState() == LimboPlayerState.TOTP_REQUIRED) {
|
||||
processCode(player, auth, arguments.get(0));
|
||||
} else {
|
||||
logger.debug(() -> "Aborting TOTP check for player '" + player.getName()
|
||||
+ "'. Invalid limbo state: " + (limbo == null ? "no limbo" : limbo.getState()));
|
||||
messages.send(player, MessageKey.LOGIN_MESSAGE);
|
||||
}
|
||||
}
|
||||
|
||||
private void processCode(Player player, PlayerAuth auth, String inputCode) {
|
||||
boolean isCodeValid = totpAuthenticator.checkCode(auth, inputCode);
|
||||
if (isCodeValid) {
|
||||
logger.debug("Successfully checked TOTP code for `{0}`", player.getName());
|
||||
asynchronousLogin.performLogin(player, auth);
|
||||
} else {
|
||||
logger.debug("Input TOTP code was invalid for player `{0}`", player.getName());
|
||||
messages.send(player, MessageKey.TWO_FACTOR_INVALID_CODE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.unregister;
|
||||
|
||||
import fr.xephi.authme.command.PlayerCommand;
|
||||
import fr.xephi.authme.data.VerificationCodeManager;
|
||||
import fr.xephi.authme.data.auth.PlayerCache;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.process.Management;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Command for a player to unregister himself.
|
||||
*/
|
||||
public class UnregisterCommand extends PlayerCommand {
|
||||
|
||||
@Inject
|
||||
private Management management;
|
||||
|
||||
@Inject
|
||||
private CommonService commonService;
|
||||
|
||||
@Inject
|
||||
private PlayerCache playerCache;
|
||||
|
||||
@Inject
|
||||
private VerificationCodeManager codeManager;
|
||||
|
||||
@Override
|
||||
public void runCommand(Player player, List<String> arguments) {
|
||||
String playerPass = arguments.get(0);
|
||||
String playerName = player.getName();
|
||||
|
||||
// Make sure the player is authenticated
|
||||
if (!playerCache.isAuthenticated(playerName)) {
|
||||
commonService.send(player, MessageKey.NOT_LOGGED_IN);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the user has been verified or not
|
||||
if (codeManager.isVerificationRequired(player)) {
|
||||
codeManager.codeExistOrGenerateNew(playerName);
|
||||
commonService.send(player, MessageKey.VERIFICATION_CODE_REQUIRED);
|
||||
return;
|
||||
}
|
||||
|
||||
// Unregister the player
|
||||
management.performUnregister(player, playerPass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageKey getArgumentsMismatchMessage() {
|
||||
return MessageKey.USAGE_UNREGISTER;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getAlternativeCommand() {
|
||||
return "/authme unregister <player>";
|
||||
}
|
||||
}
|
||||
-61
@@ -1,61 +0,0 @@
|
||||
package fr.xephi.authme.command.executable.verification;
|
||||
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.command.PlayerCommand;
|
||||
import fr.xephi.authme.data.VerificationCodeManager;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Used to complete the email verification process.
|
||||
*/
|
||||
public class VerificationCommand extends PlayerCommand {
|
||||
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(VerificationCommand.class);
|
||||
|
||||
@Inject
|
||||
private CommonService commonService;
|
||||
|
||||
@Inject
|
||||
private VerificationCodeManager codeManager;
|
||||
|
||||
@Override
|
||||
public void runCommand(Player player, List<String> arguments) {
|
||||
final String playerName = player.getName();
|
||||
|
||||
if (!codeManager.canSendMail()) {
|
||||
logger.warning("Mail API is not set");
|
||||
commonService.send(player, MessageKey.INCOMPLETE_EMAIL_SETTINGS);
|
||||
return;
|
||||
}
|
||||
|
||||
if (codeManager.isVerificationRequired(player)) {
|
||||
if (codeManager.isCodeRequired(playerName)) {
|
||||
if (codeManager.checkCode(playerName, arguments.get(0))) {
|
||||
commonService.send(player, MessageKey.VERIFICATION_CODE_VERIFIED);
|
||||
} else {
|
||||
commonService.send(player, MessageKey.INCORRECT_VERIFICATION_CODE);
|
||||
}
|
||||
} else {
|
||||
commonService.send(player, MessageKey.VERIFICATION_CODE_EXPIRED);
|
||||
}
|
||||
} else {
|
||||
if (codeManager.hasEmail(playerName)) {
|
||||
commonService.send(player, MessageKey.VERIFICATION_CODE_ALREADY_VERIFIED);
|
||||
} else {
|
||||
commonService.send(player, MessageKey.VERIFICATION_CODE_EMAIL_NEEDED);
|
||||
commonService.send(player, MessageKey.ADD_EMAIL_MESSAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageKey getArgumentsMismatchMessage() {
|
||||
return MessageKey.USAGE_VERIFICATION_CODE;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user