Merge branch 'master' of https://github.com/AuthMe-Team/AuthMeReloaded into 437-add-email
This commit is contained in:
@@ -3,6 +3,9 @@ package fr.xephi.authme.command;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import fr.xephi.authme.AuthMe;
|
||||
import fr.xephi.authme.command.help.HelpProvider;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import fr.xephi.authme.util.StringUtils;
|
||||
@@ -13,6 +16,12 @@ import fr.xephi.authme.util.StringUtils;
|
||||
*/
|
||||
public class CommandHandler {
|
||||
|
||||
/**
|
||||
* The threshold for suggesting a similar command. If the difference is below this value, we will
|
||||
* ask the player whether he meant the similar command.
|
||||
*/
|
||||
private static final double SUGGEST_COMMAND_THRESHOLD = 0.75;
|
||||
|
||||
private final CommandService commandService;
|
||||
|
||||
/**
|
||||
@@ -40,14 +49,32 @@ public class CommandHandler {
|
||||
parts.add(0, bukkitCommandLabel);
|
||||
|
||||
FoundCommandResult result = commandService.mapPartsToCommand(sender, parts);
|
||||
if (FoundResultStatus.SUCCESS.equals(result.getResultStatus())) {
|
||||
executeCommand(sender, result);
|
||||
} else {
|
||||
commandService.outputMappingError(sender, result);
|
||||
}
|
||||
handleCommandResult(sender, result);
|
||||
return !FoundResultStatus.MISSING_BASE_COMMAND.equals(result.getResultStatus());
|
||||
}
|
||||
|
||||
private void handleCommandResult(CommandSender sender, FoundCommandResult result) {
|
||||
switch (result.getResultStatus()) {
|
||||
case SUCCESS:
|
||||
executeCommand(sender, result);
|
||||
break;
|
||||
case MISSING_BASE_COMMAND:
|
||||
sender.sendMessage(ChatColor.DARK_RED + "Failed to parse " + AuthMe.getPluginName() + " command!");
|
||||
break;
|
||||
case INCORRECT_ARGUMENTS:
|
||||
sendImproperArgumentsMessage(sender, result);
|
||||
break;
|
||||
case UNKNOWN_LABEL:
|
||||
sendUnknownCommandMessage(sender, result);
|
||||
break;
|
||||
case NO_PERMISSION:
|
||||
sendPermissionDeniedError(sender);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unknown result status '" + result.getResultStatus() + "'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the command for the given command sender.
|
||||
*
|
||||
@@ -76,6 +103,46 @@ public class CommandHandler {
|
||||
return cleanArguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show an "unknown command" message to the user and suggest an existing command if its similarity is within
|
||||
* the defined threshold.
|
||||
*
|
||||
* @param sender The command sender
|
||||
* @param result The command that was found during the mapping process
|
||||
*/
|
||||
private static void sendUnknownCommandMessage(CommandSender sender, FoundCommandResult result) {
|
||||
sender.sendMessage(ChatColor.DARK_RED + "Unknown command!");
|
||||
|
||||
// Show a command suggestion if available and the difference isn't too big
|
||||
if (result.getDifference() <= SUGGEST_COMMAND_THRESHOLD && result.getCommandDescription() != null) {
|
||||
sender.sendMessage(ChatColor.YELLOW + "Did you mean " + ChatColor.GOLD
|
||||
+ CommandUtils.constructCommandPath(result.getCommandDescription()) + ChatColor.YELLOW + "?");
|
||||
}
|
||||
|
||||
sender.sendMessage(ChatColor.YELLOW + "Use the command " + ChatColor.GOLD + "/" + result.getLabels().get(0)
|
||||
+ " help" + ChatColor.YELLOW + " to view help.");
|
||||
}
|
||||
|
||||
private void sendImproperArgumentsMessage(CommandSender sender, FoundCommandResult result) {
|
||||
CommandDescription command = result.getCommandDescription();
|
||||
if (!commandService.getPermissionsManager().hasPermission(sender, command)) {
|
||||
sendPermissionDeniedError(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
// Show the command argument help
|
||||
sender.sendMessage(ChatColor.DARK_RED + "Incorrect command arguments!");
|
||||
commandService.outputHelp(sender, result, HelpProvider.SHOW_ARGUMENTS);
|
||||
|
||||
List<String> labels = result.getLabels();
|
||||
String childLabel = labels.size() >= 2 ? labels.get(1) : "";
|
||||
sender.sendMessage(ChatColor.GOLD + "Detailed help: " + ChatColor.WHITE
|
||||
+ "/" + labels.get(0) + " help " + childLabel);
|
||||
}
|
||||
|
||||
// TODO ljacqu 20151212: Remove me once I am a MessageKey
|
||||
private static void sendPermissionDeniedError(CommandSender sender) {
|
||||
sender.sendMessage(ChatColor.DARK_RED + "You don't have permission to use this command!");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
package fr.xephi.authme.command;
|
||||
|
||||
import fr.xephi.authme.AuthMe;
|
||||
import fr.xephi.authme.command.executable.HelpCommand;
|
||||
import fr.xephi.authme.command.help.HelpProvider;
|
||||
import fr.xephi.authme.output.Messages;
|
||||
import fr.xephi.authme.permission.PermissionsManager;
|
||||
import fr.xephi.authme.util.CollectionUtils;
|
||||
import fr.xephi.authme.util.StringUtils;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -19,101 +17,24 @@ import static fr.xephi.authme.command.FoundResultStatus.MISSING_BASE_COMMAND;
|
||||
import static fr.xephi.authme.command.FoundResultStatus.UNKNOWN_LABEL;
|
||||
|
||||
/**
|
||||
* The AuthMe command handler, responsible for mapping incoming command parts to the correct {@link CommandDescription}
|
||||
* or to display help messages for erroneous invocations (unknown command, no permission, etc.).
|
||||
* The AuthMe command handler, responsible for mapping incoming
|
||||
* command parts to the correct {@link CommandDescription}.
|
||||
*/
|
||||
public class CommandMapper {
|
||||
|
||||
/**
|
||||
* The threshold for suggesting a similar command. If the difference is below this value, we will
|
||||
* ask the player whether he meant the similar command.
|
||||
*/
|
||||
private static final double SUGGEST_COMMAND_THRESHOLD = 0.75;
|
||||
|
||||
/**
|
||||
* The class of the help command, to which the base label should also be passed in the arguments.
|
||||
*/
|
||||
private static final Class<? extends ExecutableCommand> HELP_COMMAND_CLASS = HelpCommand.class;
|
||||
|
||||
private final Set<CommandDescription> baseCommands;
|
||||
private final Messages messages;
|
||||
private final PermissionsManager permissionsManager;
|
||||
private final HelpProvider helpProvider;
|
||||
|
||||
public CommandMapper(Set<CommandDescription> baseCommands, Messages messages,
|
||||
PermissionsManager permissionsManager, HelpProvider helpProvider) {
|
||||
public CommandMapper(Set<CommandDescription> baseCommands, PermissionsManager permissionsManager) {
|
||||
this.baseCommands = baseCommands;
|
||||
this.messages = messages;
|
||||
this.permissionsManager = permissionsManager;
|
||||
this.helpProvider = helpProvider;
|
||||
}
|
||||
|
||||
public void outputStandardError(CommandSender sender, FoundCommandResult result) {
|
||||
switch (result.getResultStatus()) {
|
||||
case SUCCESS:
|
||||
// Successful mapping, so no error to output
|
||||
break;
|
||||
case MISSING_BASE_COMMAND:
|
||||
sender.sendMessage(ChatColor.DARK_RED + "Failed to parse " + AuthMe.getPluginName() + " command!");
|
||||
break;
|
||||
case INCORRECT_ARGUMENTS:
|
||||
sendImproperArgumentsMessage(sender, result);
|
||||
break;
|
||||
case UNKNOWN_LABEL:
|
||||
sendUnknownCommandMessage(sender, result);
|
||||
break;
|
||||
case NO_PERMISSION:
|
||||
sendPermissionDeniedError(sender);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unknown result status '" + result.getResultStatus() + "'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show an "unknown command" message to the user and suggest an existing command if its similarity is within
|
||||
* the defined threshold.
|
||||
*
|
||||
* @param sender The command sender
|
||||
* @param result The command that was found during the mapping process
|
||||
*/
|
||||
private static void sendUnknownCommandMessage(CommandSender sender, FoundCommandResult result) {
|
||||
sender.sendMessage(ChatColor.DARK_RED + "Unknown command!");
|
||||
|
||||
// Show a command suggestion if available and the difference isn't too big
|
||||
if (result.getDifference() <= SUGGEST_COMMAND_THRESHOLD && result.getCommandDescription() != null) {
|
||||
sender.sendMessage(ChatColor.YELLOW + "Did you mean " + ChatColor.GOLD
|
||||
+ CommandUtils.constructCommandPath(result.getCommandDescription()) + ChatColor.YELLOW + "?");
|
||||
}
|
||||
|
||||
sender.sendMessage(ChatColor.YELLOW + "Use the command " + ChatColor.GOLD + "/" + result.getLabels().get(0)
|
||||
+ " help" + ChatColor.YELLOW + " to view help.");
|
||||
}
|
||||
|
||||
private void sendImproperArgumentsMessage(CommandSender sender, FoundCommandResult result) {
|
||||
CommandDescription command = result.getCommandDescription();
|
||||
if (!permissionsManager.hasPermission(sender, command)) {
|
||||
sendPermissionDeniedError(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
// Show the command argument help
|
||||
sender.sendMessage(ChatColor.DARK_RED + "Incorrect command arguments!");
|
||||
List<String> lines = helpProvider.printHelp(sender, result, HelpProvider.SHOW_ARGUMENTS);
|
||||
for (String line : lines) {
|
||||
sender.sendMessage(line);
|
||||
}
|
||||
|
||||
List<String> labels = result.getLabels();
|
||||
String childLabel = labels.size() >= 2 ? labels.get(1) : "";
|
||||
sender.sendMessage(ChatColor.GOLD + "Detailed help: " + ChatColor.WHITE
|
||||
+ "/" + labels.get(0) + " help " + childLabel);
|
||||
}
|
||||
|
||||
// TODO ljacqu 20151212: Remove me once I am a MessageKey
|
||||
private static void sendPermissionDeniedError(CommandSender sender) {
|
||||
sender.sendMessage(ChatColor.DARK_RED + "You don't have permission to use this command!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Map incoming command parts to a command. This processes all parts and distinguishes the labels from arguments.
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
package fr.xephi.authme.command;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import fr.xephi.authme.AuthMe;
|
||||
import fr.xephi.authme.command.help.HelpProvider;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
@@ -12,6 +8,11 @@ import fr.xephi.authme.output.Messages;
|
||||
import fr.xephi.authme.permission.PermissionsManager;
|
||||
import fr.xephi.authme.process.Management;
|
||||
import fr.xephi.authme.security.PasswordSecurity;
|
||||
import fr.xephi.authme.settings.custom.NewSetting;
|
||||
import fr.xephi.authme.settings.domain.Property;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Service for implementations of {@link ExecutableCommand} to execute some common tasks.
|
||||
@@ -24,6 +25,8 @@ public class CommandService {
|
||||
private final HelpProvider helpProvider;
|
||||
private final CommandMapper commandMapper;
|
||||
private final PasswordSecurity passwordSecurity;
|
||||
private final PermissionsManager permissionsManager;
|
||||
private final NewSetting settings;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@@ -33,14 +36,19 @@ public class CommandService {
|
||||
* @param helpProvider Help provider
|
||||
* @param messages Messages instance
|
||||
* @param passwordSecurity The Password Security instance
|
||||
* @param permissionsManager The permissions manager
|
||||
* @param settings The settings manager
|
||||
*/
|
||||
public CommandService(AuthMe authMe, CommandMapper commandMapper, HelpProvider helpProvider, Messages messages,
|
||||
PasswordSecurity passwordSecurity) {
|
||||
PasswordSecurity passwordSecurity, PermissionsManager permissionsManager,
|
||||
NewSetting settings) {
|
||||
this.authMe = authMe;
|
||||
this.messages = messages;
|
||||
this.helpProvider = helpProvider;
|
||||
this.commandMapper = commandMapper;
|
||||
this.passwordSecurity = passwordSecurity;
|
||||
this.permissionsManager = permissionsManager;
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -75,17 +83,6 @@ public class CommandService {
|
||||
return commandMapper.mapPartsToCommand(sender, commandParts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the standard error message for the status in the provided {@link FoundCommandResult} object.
|
||||
* Does not output anything for successful mappings.
|
||||
*
|
||||
* @param sender The sender to output the error to
|
||||
* @param result The mapping result to process
|
||||
*/
|
||||
public void outputMappingError(CommandSender sender, FoundCommandResult result) {
|
||||
commandMapper.outputStandardError(sender, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the given task asynchronously with the Bukkit scheduler.
|
||||
*
|
||||
@@ -142,8 +139,7 @@ public class CommandService {
|
||||
* @return the permissions manager
|
||||
*/
|
||||
public PermissionsManager getPermissionsManager() {
|
||||
// TODO ljacqu 20151226: Might be nicer to pass the perm manager via constructor
|
||||
return authMe.getPermissionsManager();
|
||||
return permissionsManager;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -156,4 +152,15 @@ public class CommandService {
|
||||
return messages.retrieve(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the given property's value.
|
||||
*
|
||||
* @param property The property to retrieve
|
||||
* @param <T> The type of the property
|
||||
* @return The property's value
|
||||
*/
|
||||
public <T> T getProperty(Property<T> property) {
|
||||
return settings.getProperty(property);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+6
-5
@@ -8,7 +8,8 @@ import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.output.MessageKey;
|
||||
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.custom.RestrictionSettings;
|
||||
import fr.xephi.authme.settings.custom.SecuritySettings;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.util.List;
|
||||
@@ -27,7 +28,7 @@ public class ChangePasswordAdminCommand implements ExecutableCommand {
|
||||
|
||||
// Validate the password
|
||||
String playerPassLowerCase = playerPass.toLowerCase();
|
||||
if (!playerPassLowerCase.matches(Settings.getPassRegex)) {
|
||||
if (!playerPassLowerCase.matches(commandService.getProperty(RestrictionSettings.ALLOWED_PASSWORD_REGEX))) {
|
||||
commandService.send(sender, MessageKey.PASSWORD_MATCH_ERROR);
|
||||
return;
|
||||
}
|
||||
@@ -35,12 +36,12 @@ public class ChangePasswordAdminCommand implements ExecutableCommand {
|
||||
commandService.send(sender, MessageKey.PASSWORD_IS_USERNAME_ERROR);
|
||||
return;
|
||||
}
|
||||
if (playerPassLowerCase.length() < Settings.getPasswordMinLen
|
||||
|| playerPassLowerCase.length() > Settings.passwordMaxLength) {
|
||||
if (playerPassLowerCase.length() < commandService.getProperty(SecuritySettings.MIN_PASSWORD_LENGTH)
|
||||
|| playerPassLowerCase.length() > commandService.getProperty(SecuritySettings.MAX_PASSWORD_LENGTH)) {
|
||||
commandService.send(sender, MessageKey.INVALID_PASSWORD_LENGTH);
|
||||
return;
|
||||
}
|
||||
if (!Settings.unsafePasswords.isEmpty() && Settings.unsafePasswords.contains(playerPassLowerCase)) {
|
||||
if (commandService.getProperty(SecuritySettings.UNSAFE_PASSWORDS).contains(playerPassLowerCase)) {
|
||||
commandService.send(sender, MessageKey.PASSWORD_UNSAFE_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.output.MessageKey;
|
||||
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.custom.SecuritySettings;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
@@ -35,8 +36,8 @@ public class RegisterAdminCommand implements ExecutableCommand {
|
||||
commandService.send(sender, MessageKey.PASSWORD_IS_USERNAME_ERROR);
|
||||
return;
|
||||
}
|
||||
if (playerPassLowerCase.length() < Settings.getPasswordMinLen
|
||||
|| playerPassLowerCase.length() > Settings.passwordMaxLength) {
|
||||
if (playerPassLowerCase.length() < commandService.getProperty(SecuritySettings.MIN_PASSWORD_LENGTH)
|
||||
|| playerPassLowerCase.length() > commandService.getProperty(SecuritySettings.MAX_PASSWORD_LENGTH)) {
|
||||
commandService.send(sender, MessageKey.INVALID_PASSWORD_LENGTH);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import fr.xephi.authme.command.CommandService;
|
||||
import fr.xephi.authme.command.PlayerCommand;
|
||||
import fr.xephi.authme.output.MessageKey;
|
||||
import fr.xephi.authme.security.RandomString;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.custom.SecuritySettings;
|
||||
import fr.xephi.authme.util.Wrapper;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@@ -28,20 +28,20 @@ public class CaptchaCommand extends PlayerCommand {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Settings.useCaptcha) {
|
||||
if (!commandService.getProperty(SecuritySettings.USE_CAPTCHA)) {
|
||||
commandService.send(player, MessageKey.USAGE_LOGIN);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!plugin.cap.containsKey(playerNameLowerCase)) {
|
||||
commandService.send(player, MessageKey.USAGE_LOGIN);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Settings.useCaptcha && !captcha.equals(plugin.cap.get(playerNameLowerCase))) {
|
||||
if (!captcha.equals(plugin.cap.get(playerNameLowerCase))) {
|
||||
plugin.cap.remove(playerNameLowerCase);
|
||||
String randStr = RandomString.generate(Settings.captchaLength);
|
||||
int captchaLength = commandService.getProperty(SecuritySettings.CAPTCHA_LENGTH);
|
||||
String randStr = RandomString.generate(captchaLength);
|
||||
plugin.cap.put(playerNameLowerCase, randStr);
|
||||
commandService.send(player, MessageKey.CAPTCHA_WRONG_ERROR, plugin.cap.get(playerNameLowerCase));
|
||||
return;
|
||||
|
||||
+7
-5
@@ -5,7 +5,8 @@ import fr.xephi.authme.cache.auth.PlayerCache;
|
||||
import fr.xephi.authme.command.CommandService;
|
||||
import fr.xephi.authme.command.PlayerCommand;
|
||||
import fr.xephi.authme.output.MessageKey;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.custom.RestrictionSettings;
|
||||
import fr.xephi.authme.settings.custom.SecuritySettings;
|
||||
import fr.xephi.authme.task.ChangePasswordTask;
|
||||
import fr.xephi.authme.util.Wrapper;
|
||||
import org.bukkit.entity.Player;
|
||||
@@ -32,7 +33,7 @@ public class ChangePasswordCommand extends PlayerCommand {
|
||||
|
||||
// Make sure the password is allowed
|
||||
String playerPassLowerCase = newPassword.toLowerCase();
|
||||
if (!playerPassLowerCase.matches(Settings.getPassRegex)) {
|
||||
if (!playerPassLowerCase.matches(commandService.getProperty(RestrictionSettings.ALLOWED_PASSWORD_REGEX))) {
|
||||
commandService.send(player, MessageKey.PASSWORD_MATCH_ERROR);
|
||||
return;
|
||||
}
|
||||
@@ -40,17 +41,18 @@ public class ChangePasswordCommand extends PlayerCommand {
|
||||
commandService.send(player, MessageKey.PASSWORD_IS_USERNAME_ERROR);
|
||||
return;
|
||||
}
|
||||
if (playerPassLowerCase.length() < Settings.getPasswordMinLen
|
||||
|| playerPassLowerCase.length() > Settings.passwordMaxLength) {
|
||||
if (playerPassLowerCase.length() < commandService.getProperty(SecuritySettings.MIN_PASSWORD_LENGTH)
|
||||
|| playerPassLowerCase.length() > commandService.getProperty(SecuritySettings.MAX_PASSWORD_LENGTH)) {
|
||||
commandService.send(player, MessageKey.INVALID_PASSWORD_LENGTH);
|
||||
return;
|
||||
}
|
||||
if (!Settings.unsafePasswords.isEmpty() && Settings.unsafePasswords.contains(playerPassLowerCase)) {
|
||||
if (commandService.getProperty(SecuritySettings.UNSAFE_PASSWORDS).contains(playerPassLowerCase)) {
|
||||
commandService.send(player, MessageKey.PASSWORD_UNSAFE_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
AuthMe plugin = AuthMe.getInstance();
|
||||
// TODO ljacqu 20160117: Call async task via Management
|
||||
commandService.runTaskAsynchronously(new ChangePasswordTask(plugin, player, oldPassword, newPassword));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +43,6 @@ public class RegisterCommand extends PlayerCommand {
|
||||
|
||||
@Override
|
||||
public String getAlternativeCommand() {
|
||||
return "authme register <playername> <password>";
|
||||
return "/authme register <playername> <password>";
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user