Merge remote-tracking branch 'origin/master'

This commit is contained in:
DNx5 2015-12-07 19:58:19 +07:00
commit a91ad46659
62 changed files with 1654 additions and 812 deletions

View File

@ -5,6 +5,8 @@
<value>
<option name="AUTODETECT_INDENTS" value="false" />
<option name="LINE_SEPARATOR" value="&#10;" />
<option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99" />
<option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99" />
<option name="JD_ADD_BLANK_AFTER_PARM_COMMENTS" value="true" />
<option name="JD_ADD_BLANK_AFTER_RETURN" value="true" />
<XML>

View File

@ -10,6 +10,7 @@ import fr.xephi.authme.cache.backup.JsonCache;
import fr.xephi.authme.cache.limbo.LimboCache;
import fr.xephi.authme.cache.limbo.LimboPlayer;
import fr.xephi.authme.command.CommandHandler;
import fr.xephi.authme.command.CommandInitializer;
import fr.xephi.authme.converter.Converter;
import fr.xephi.authme.converter.ForceFlatToSqlite;
import fr.xephi.authme.datasource.*;
@ -433,7 +434,7 @@ public class AuthMe extends JavaPlugin {
* Set up the command handler.
*/
private void setupCommandHandler() {
this.commandHandler = new CommandHandler();
this.commandHandler = new CommandHandler(CommandInitializer.getBaseCommands());
}
/**
@ -956,14 +957,14 @@ public class AuthMe extends JavaPlugin {
@Override
public boolean onCommand(CommandSender sender, Command cmd,
String commandLabel, String[] args) {
// Get the command handler, and make sure it's valid
// Make sure the command handler has been initialized
if (commandHandler == null) {
wrapper.getLogger().warning("AuthMe command handler is not available");
wrapper.getLogger().severe("AuthMe command handler is not available");
return false;
}
// Handle the command, return the result
return commandHandler.onCommand(sender, cmd, commandLabel, args);
// Handle the command
return commandHandler.processCommand(sender, commandLabel, args);
}
/**

View File

@ -2,7 +2,6 @@ package fr.xephi.authme;
import com.google.common.base.Throwables;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.util.StringUtils;
import fr.xephi.authme.util.Wrapper;
import java.io.IOException;
@ -17,8 +16,10 @@ import java.util.Date;
*/
public final class ConsoleLogger {
private static final String NEW_LINE = System.getProperty("line.separator");
private static final DateFormat DATE_FORMAT = new SimpleDateFormat("[MM-dd HH:mm:ss]");
private static Wrapper wrapper = Wrapper.getInstance();
private static final DateFormat df = new SimpleDateFormat("[MM-dd HH:mm:ss]");
private ConsoleLogger() {
// Service class
@ -57,11 +58,11 @@ public final class ConsoleLogger {
*/
private static void writeLog(String message) {
String dateTime;
synchronized (df) {
dateTime = df.format(new Date());
synchronized (DATE_FORMAT) {
dateTime = DATE_FORMAT.format(new Date());
}
try {
Files.write(Settings.LOG_FILE.toPath(), (dateTime + ": " + message + StringUtils.newline).getBytes(),
Files.write(Settings.LOG_FILE.toPath(), (dateTime + ": " + message + NEW_LINE).getBytes(),
StandardOpenOption.APPEND,
StandardOpenOption.CREATE);
} catch (IOException ignored) {
@ -77,6 +78,6 @@ public final class ConsoleLogger {
if (!Settings.useLogging) {
return;
}
writeLog("" + Throwables.getStackTraceAsString(ex));
writeLog(Throwables.getStackTraceAsString(ex));
}
}

View File

@ -5,8 +5,6 @@ package fr.xephi.authme.command;
*/
public class CommandArgumentDescription {
// TODO: Allow argument to consist of infinite parts. <label ...>
/**
* Argument label (one-word description of the argument).
*/

View File

@ -1,6 +1,8 @@
package fr.xephi.authme.command;
import fr.xephi.authme.permission.DefaultPermission;
import fr.xephi.authme.permission.PermissionNode;
import fr.xephi.authme.util.CollectionUtils;
import fr.xephi.authme.util.StringUtils;
import org.bukkit.command.CommandSender;
@ -25,7 +27,7 @@ public class CommandDescription {
* Defines the labels to execute the command. For example, if labels are "register" and "r" and the parent is
* the command for "/authme", then both "/authme register" and "/authme r" will be handled by this command.
*/
private List<String> labels = new ArrayList<>(); // TODO remove field initialization
private List<String> labels;
/**
* Command description.
*/
@ -49,11 +51,7 @@ public class CommandDescription {
/**
* The arguments the command takes.
*/
private List<CommandArgumentDescription> arguments = new ArrayList<>(); // TODO remove field initialization
/**
* Defines whether there is an argument maximum or not.
*/
private boolean noArgumentMaximum = false; // TODO remove field initialization
private List<CommandArgumentDescription> arguments;
/**
* Defines the command permissions.
*/
@ -70,57 +68,54 @@ public class CommandDescription {
*/
@Deprecated
public CommandDescription(ExecutableCommand executableCommand, List<String> labels, String description, String detailedDescription, CommandDescription parent) {
this(executableCommand, labels, description, detailedDescription, parent,
new ArrayList<CommandArgumentDescription>());
}
/**
* Constructor.
*
* @param executableCommand The executable command, or null.
* @param labels List of command labels.
* @param description Command description.
* @param detailedDescription Detailed comment description.
* @param parent Parent command.
* @param arguments Command arguments.
*/
@Deprecated
public CommandDescription(ExecutableCommand executableCommand, List<String> labels, String description, String detailedDescription, CommandDescription parent, List<CommandArgumentDescription> arguments) {
setExecutableCommand(executableCommand);
this.labels = labels;
this.description = description;
this.detailedDescription = detailedDescription;
setParent(parent);
this.arguments = arguments;
this.arguments = new ArrayList<>();
}
/**
* Private constructor. Use {@link CommandDescription#builder()} to create instances of this class.
* <p />
* Note for developers: Instances should be created with {@link CommandDescription#createInstance} to be properly
* registered in the command tree.
*/
private CommandDescription() {
}
/**
* Create an instance for internal use.
*
* @param executableCommand The executable command, or null.
* @param labels List of command labels.
* @param description Command description.
* @param detailedDescription Detailed comment description.
* @param executableCommand The executable command, or null.
* @param parent Parent command.
* @param arguments Command arguments.
* @param permissions The permissions required to execute this command.
*
* @return The created instance
* @see CommandDescription#builder()
*/
private CommandDescription(List<String> labels, String description, String detailedDescription,
ExecutableCommand executableCommand, CommandDescription parent,
List<CommandArgumentDescription> arguments, boolean noArgumentMaximum,
CommandPermissions permissions) {
this.labels = labels;
this.description = description;
this.detailedDescription = detailedDescription;
this.executableCommand = executableCommand;
this.parent = parent;
this.arguments = arguments;
this.noArgumentMaximum = noArgumentMaximum;
this.permissions = permissions;
private static CommandDescription createInstance(List<String> labels, String description,
String detailedDescription, ExecutableCommand executableCommand,
CommandDescription parent, List<CommandArgumentDescription> arguments,
CommandPermissions permissions) {
CommandDescription instance = new CommandDescription();
instance.labels = labels;
instance.description = description;
instance.detailedDescription = detailedDescription;
instance.executableCommand = executableCommand;
instance.parent = parent;
instance.arguments = arguments;
instance.permissions = permissions;
if (parent != null) {
// Passing `this` in constructor is not very nice; consider creating a "static create()" method instead
parent.addChild(this);
parent.addChild(instance);
}
return instance;
}
/**
@ -191,10 +186,6 @@ public class CommandDescription {
* @return True if the command reference is suitable to this command label, false otherwise.
*/
public boolean isSuitableLabel(CommandParts commandReference) {
// Make sure the command reference is valid
if (commandReference.getCount() <= 0)
return false;
// Get the parent count
//getParent() = getParent().getParentCount() + 1
String element = commandReference.get(getParentCount());
@ -220,8 +211,9 @@ public class CommandDescription {
List<String> referenceList = new ArrayList<>();
// Check whether this command has a parent, if so, add the absolute parent command
if (getParent() != null)
if (getParent() != null) {
referenceList.addAll(getParent().getCommandReference(reference).getList());
}
// Get the current label
referenceList.add(getLabel(reference));
@ -258,7 +250,8 @@ public class CommandDescription {
CommandParts reference = getCommandReference(other);
// Compare the two references, return the result
return reference.getDifference(new CommandParts(other.getRange(0, reference.getCount())), fullCompare);
return CommandUtils.getDifference(reference.getList(),
CollectionUtils.getRange(other.getList(), 0, reference.getList().size()), fullCompare);
}
/**
@ -279,15 +272,6 @@ public class CommandDescription {
this.executableCommand = executableCommand;
}
/**
* Check whether this command is executable, based on the assigned executable command.
*
* @return True if this command is executable.
*/
public boolean isExecutable() {
return this.executableCommand != null;
}
/**
* Execute the command, if possible.
*
@ -298,10 +282,6 @@ public class CommandDescription {
* @return True on success, false on failure.
*/
public boolean execute(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) {
// Make sure the command is executable
if (!isExecutable())
return false;
// Execute the command, return the result
return getExecutableCommand().executeCommand(sender, commandReference, commandArguments);
}
@ -453,10 +433,6 @@ public class CommandDescription {
return !getArguments().isEmpty();
}
public boolean hasMaximumArguments() {
return !noArgumentMaximum; // TODO ljacqu 20151130 Change variable name
}
/**
* Get the command description.
*
@ -492,13 +468,13 @@ public class CommandDescription {
return new FoundCommandResult(
this,
getCommandReference(queryReference),
new CommandParts(),
new CommandParts(new ArrayList<String>()),
queryReference);
}
// Get the new command reference and arguments
CommandParts newReference = new CommandParts(queryReference.getRange(0, getParentCount() + 1));
CommandParts newArguments = new CommandParts(queryReference.getRange(getParentCount() + 1));
CommandParts newReference = new CommandParts(CollectionUtils.getRange(queryReference.getList(), 0, getParentCount() + 1));
CommandParts newArguments = new CommandParts(CollectionUtils.getRange(queryReference.getList(), getParentCount() + 1));
// Handle the child's, if this command has any
if (getChildren().size() > 0) {
@ -580,16 +556,6 @@ public class CommandDescription {
return this.permissions;
}
/**
* Set the command permissions.
*
* @param permissionNode The permission node required.
* @param defaultPermission The default permission.
*/
public void setCommandPermissions(PermissionNode permissionNode, CommandPermissions.DefaultPermission defaultPermission) {
this.permissions = new CommandPermissions(permissionNode, defaultPermission);
}
public static CommandBuilder builder() {
return new CommandBuilder();
}
@ -604,7 +570,6 @@ public class CommandDescription {
private ExecutableCommand executableCommand;
private CommandDescription parent;
private List<CommandArgumentDescription> arguments = new ArrayList<>();
private boolean noArgumentMaximum;
private CommandPermissions permissions;
/**
@ -614,14 +579,13 @@ public class CommandDescription {
* @return The generated CommandDescription object
*/
public CommandDescription build() {
return new CommandDescription(
return createInstance(
getOrThrow(labels, "labels"),
firstNonNull(description, ""),
firstNonNull(detailedDescription, ""),
getOrThrow(executableCommand, "executableCommand"),
firstNonNull(parent, null),
arguments,
noArgumentMaximum,
firstNonNull(permissions, null)
);
}
@ -670,12 +634,7 @@ public class CommandDescription {
return this;
}
public CommandBuilder noArgumentMaximum(boolean noArgumentMaximum) {
this.noArgumentMaximum = noArgumentMaximum;
return this;
}
public CommandBuilder permissions(CommandPermissions.DefaultPermission defaultPermission,
public CommandBuilder permissions(DefaultPermission defaultPermission,
PermissionNode... permissionNodes) {
this.permissions = new CommandPermissions(asMutableList(permissionNodes), defaultPermission);
return this;

View File

@ -2,13 +2,14 @@ package fr.xephi.authme.command;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.command.help.HelpProvider;
import fr.xephi.authme.util.CollectionUtils;
import fr.xephi.authme.util.StringUtils;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
* The AuthMe command handler, responsible for mapping incoming commands to the correct {@link CommandDescription}
@ -28,104 +29,70 @@ public class CommandHandler {
*/
private static final double SUGGEST_COMMAND_THRESHOLD = 0.75;
private final Set<CommandDescription> commands;
/**
* Process a command.
* Create a command handler.
*
* @param commands The collection of available AuthMe commands
*/
public CommandHandler(Set<CommandDescription> commands) {
this.commands = commands;
}
/**
* Map a command that was invoked to the proper {@link CommandDescription} or return a useful error
* message upon failure.
*
* @param sender The command sender (Bukkit).
* @param bukkitCommand The command (Bukkit).
* @param bukkitCommandLabel The command label (Bukkit).
* @param bukkitArgs The command arguments (Bukkit).
*
* @return True if the command was executed, false otherwise.
*/
// TODO ljacqu 20151129: Rename onCommand() method to something not suggesting it is auto-invoked by an event
public boolean onCommand(CommandSender sender, Command bukkitCommand, String bukkitCommandLabel, String[] bukkitArgs) {
public boolean processCommand(CommandSender sender, String bukkitCommandLabel, String[] bukkitArgs) {
List<String> commandArgs = skipEmptyArguments(bukkitArgs);
// Add the Bukkit command label to the front so we get a list like [authme, register, pass, passConfirm]
commandArgs.add(0, bukkitCommandLabel);
// Make sure the command isn't empty (does this happen?)
CommandParts commandReference = new CommandParts(bukkitCommandLabel, commandArgs);
if (commandReference.getCount() == 0)
return false;
// TODO: remove commandParts
CommandParts commandReference = new CommandParts(commandArgs);
// Get a suitable command for this reference, and make sure it isn't null
FoundCommandResult result = findCommand(commandReference);
if (result == null) {
// TODO ljacqu 20151204: Log more information to the console (bukkitCommandLabel)
sender.sendMessage(ChatColor.DARK_RED + "Failed to parse " + AuthMe.getPluginName() + " command!");
return false;
}
// Get the base command
String baseCommand = commandReference.get(0);
String baseCommand = commandArgs.get(0);
// Make sure the difference between the command reference and the actual command isn't too big
final double commandDifference = result.getDifference();
if (commandDifference > ASSUME_COMMAND_THRESHOLD) {
// Show the unknown command warning
sender.sendMessage(ChatColor.DARK_RED + "Unknown command!");
if (commandDifference <= ASSUME_COMMAND_THRESHOLD) {
// Show a command suggestion if available and the difference isn't too big
if (commandDifference < SUGGEST_COMMAND_THRESHOLD)
if (result.getCommandDescription() != null)
sender.sendMessage(ChatColor.YELLOW + "Did you mean " + ChatColor.GOLD + "/" + result.getCommandDescription().getCommandReference(commandReference) + ChatColor.YELLOW + "?");
// Show a message when the command handler is assuming a command
if (commandDifference > 0) {
sendCommandAssumptionMessage(sender, result, commandReference);
}
// Show the help command
sender.sendMessage(ChatColor.YELLOW + "Use the command " + ChatColor.GOLD + "/" + baseCommand + " help" + ChatColor.YELLOW + " to view help.");
return true;
if (!result.hasPermission(sender)) {
sender.sendMessage(ChatColor.DARK_RED + "You don't have permission to use this command!");
} else if (!result.hasProperArguments()) {
sendImproperArgumentsMessage(sender, result, commandReference, baseCommand);
} else {
return result.executeCommand(sender);
}
} else {
sendUnknownCommandMessage(sender, commandDifference, result, baseCommand);
}
// Show a message when the command handler is assuming a command
if (commandDifference > 0) {
// Get the suggested command
CommandParts suggestedCommandParts = new CommandParts(result.getCommandDescription().getCommandReference(commandReference));
// Show the suggested command
sender.sendMessage(ChatColor.DARK_RED + "Unknown command, assuming " + ChatColor.GOLD + "/" + suggestedCommandParts +
ChatColor.DARK_RED + "!");
}
// Make sure the command is executable
if (!result.isExecutable()) {
// Get the command reference
CommandParts helpCommandReference = new CommandParts(result.getCommandReference().getRange(1));
// Show the unknown command warning
sender.sendMessage(ChatColor.DARK_RED + "Invalid command!");
// Show the help command
sender.sendMessage(ChatColor.YELLOW + "Use the command " + ChatColor.GOLD + "/" + baseCommand + " help " + helpCommandReference + ChatColor.YELLOW + " to view help.");
return true;
}
// Make sure the command sender has permission
if (!result.hasPermission(sender)) {
// Show the no permissions warning
sender.sendMessage(ChatColor.DARK_RED + "You don't have permission to use this command!");
return true;
}
// Make sure the command sender has permission
if (!result.hasProperArguments()) {
// Get the command and the suggested command reference
CommandParts suggestedCommandReference = new CommandParts(result.getCommandDescription().getCommandReference(commandReference));
CommandParts helpCommandReference = new CommandParts(suggestedCommandReference.getRange(1));
// Show the invalid arguments warning
sender.sendMessage(ChatColor.DARK_RED + "Incorrect command arguments!");
// Show the command argument help
HelpProvider.showHelp(sender, commandReference, suggestedCommandReference, true, false, true, false, false, false);
// Show the command to use for detailed help
sender.sendMessage(ChatColor.GOLD + "Detailed help: " + ChatColor.WHITE + "/" + baseCommand + " help " + helpCommandReference);
return true;
}
// Execute the command if it's suitable
return result.executeCommand(sender);
return true;
}
/**
* Skips all entries of the given array that are simply whitespace.
* Skip all entries of the given array that are simply whitespace.
*
* @param args The array to process
* @return List of the items that are not empty
@ -162,10 +129,7 @@ public class CommandHandler {
if (queryReference.getCount() <= 0)
return null;
// TODO ljacqu 20151129: If base commands are only used in here (or in the future CommandHandler after changes),
// it might make sense to make the CommandInitializer package-private and to return its result into this class
// instead of regularly fetching the list of base commands from the other class.
for (CommandDescription commandDescription : CommandInitializer.getBaseCommands()) {
for (CommandDescription commandDescription : commands) {
// Check whether there's a command description available for the
// current command
if (!commandDescription.isSuitableLabel(queryReference))
@ -186,7 +150,7 @@ public class CommandHandler {
*
* @return The command found, or null.
*/
public CommandDescription findCommand(List<String> commandParts) {
private CommandDescription findCommand(List<String> commandParts) {
// Make sure the command reference is valid
if (commandParts.isEmpty()) {
return null;
@ -211,10 +175,63 @@ public class CommandHandler {
return null;
}
for (CommandDescription command : commands) {
if (command.getLabels().contains(label)) {
if (command.getLabels().contains(label)) { // TODO ljacqu should be case-insensitive
return command;
}
}
return null;
}
/**
* Show an "unknown command" to the user and suggests an existing command if its similarity is within
* the defined threshold.
*
* @param sender The command sender
* @param commandDifference The difference between the invoked command and the existing one
* @param result The command that was found during the mapping process
* @param baseCommand The base command (TODO: This is probably already in FoundCommandResult)
*/
private static void sendUnknownCommandMessage(CommandSender sender, double commandDifference,
FoundCommandResult result, String baseCommand) {
CommandParts commandReference = result.getCommandReference();
sender.sendMessage(ChatColor.DARK_RED + "Unknown command!");
// Show a command suggestion if available and the difference isn't too big
if (commandDifference < SUGGEST_COMMAND_THRESHOLD && result.getCommandDescription() != null) {
sender.sendMessage(ChatColor.YELLOW + "Did you mean " + ChatColor.GOLD + "/"
+ result.getCommandDescription().getCommandReference(commandReference) + ChatColor.YELLOW + "?");
}
sender.sendMessage(ChatColor.YELLOW + "Use the command " + ChatColor.GOLD + "/" + baseCommand + " help"
+ ChatColor.YELLOW + " to view help.");
}
private static void sendImproperArgumentsMessage(CommandSender sender, FoundCommandResult result,
CommandParts commandReference, String baseCommand) {
// Get the command and the suggested command reference
List<String> suggestedCommandReference =
result.getCommandDescription().getCommandReference(commandReference).getList();
List<String> helpCommandReference = CollectionUtils.getRange(suggestedCommandReference, 1);
// Show the invalid arguments warning
sender.sendMessage(ChatColor.DARK_RED + "Incorrect command arguments!");
// Show the command argument help
HelpProvider.showHelp(sender, commandReference, new CommandParts(suggestedCommandReference),
true, false, true, false, false, false);
// Show the command to use for detailed help
sender.sendMessage(ChatColor.GOLD + "Detailed help: " + ChatColor.WHITE + "/" + baseCommand
+ " help " + CommandUtils.labelsToString(helpCommandReference));
}
private static void sendCommandAssumptionMessage(CommandSender sender, FoundCommandResult result,
CommandParts commandReference) {
List<String> assumedCommandParts =
result.getCommandDescription().getCommandReference(commandReference).getList();
sender.sendMessage(ChatColor.DARK_RED + "Unknown command, assuming " + ChatColor.GOLD + "/"
+ CommandUtils.labelsToString(assumedCommandParts) + ChatColor.DARK_RED + "!");
}
}

View File

@ -3,7 +3,7 @@ package fr.xephi.authme.command;
import fr.xephi.authme.command.executable.HelpCommand;
import fr.xephi.authme.command.executable.authme.AccountsCommand;
import fr.xephi.authme.command.executable.authme.AuthMeCommand;
import fr.xephi.authme.command.executable.authme.ChangePasswordCommand;
import fr.xephi.authme.command.executable.authme.ChangePasswordAdminCommand;
import fr.xephi.authme.command.executable.authme.FirstSpawnCommand;
import fr.xephi.authme.command.executable.authme.ForceLoginCommand;
import fr.xephi.authme.command.executable.authme.GetEmailCommand;
@ -12,45 +12,46 @@ import fr.xephi.authme.command.executable.authme.LastLoginCommand;
import fr.xephi.authme.command.executable.authme.PurgeBannedPlayersCommand;
import fr.xephi.authme.command.executable.authme.PurgeCommand;
import fr.xephi.authme.command.executable.authme.PurgeLastPositionCommand;
import fr.xephi.authme.command.executable.authme.RegisterCommand;
import fr.xephi.authme.command.executable.authme.RegisterAdminCommand;
import fr.xephi.authme.command.executable.authme.ReloadCommand;
import fr.xephi.authme.command.executable.authme.SetEmailCommand;
import fr.xephi.authme.command.executable.authme.SetFirstSpawnCommand;
import fr.xephi.authme.command.executable.authme.SetSpawnCommand;
import fr.xephi.authme.command.executable.authme.SpawnCommand;
import fr.xephi.authme.command.executable.authme.SwitchAntiBotCommand;
import fr.xephi.authme.command.executable.authme.UnregisterCommand;
import fr.xephi.authme.command.executable.authme.UnregisterAdminCommand;
import fr.xephi.authme.command.executable.authme.VersionCommand;
import fr.xephi.authme.command.executable.captcha.CaptchaCommand;
import fr.xephi.authme.command.executable.changepassword.ChangePasswordCommand;
import fr.xephi.authme.command.executable.converter.ConverterCommand;
import fr.xephi.authme.command.executable.email.AddEmailCommand;
import fr.xephi.authme.command.executable.email.ChangeEmailCommand;
import fr.xephi.authme.command.executable.email.RecoverEmailCommand;
import fr.xephi.authme.command.executable.login.LoginCommand;
import fr.xephi.authme.command.executable.logout.LogoutCommand;
import fr.xephi.authme.command.executable.register.RegisterCommand;
import fr.xephi.authme.command.executable.unregister.UnregisterCommand;
import fr.xephi.authme.permission.AdminPermission;
import fr.xephi.authme.permission.PlayerPermission;
import fr.xephi.authme.util.Wrapper;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.*;
import static fr.xephi.authme.command.CommandPermissions.DefaultPermission.ALLOWED;
import static fr.xephi.authme.command.CommandPermissions.DefaultPermission.OP_ONLY;
import static fr.xephi.authme.permission.DefaultPermission.ALLOWED;
import static fr.xephi.authme.permission.DefaultPermission.OP_ONLY;
/**
* Initializes all available AuthMe commands.
*/
public final class CommandInitializer {
private static List<CommandDescription> baseCommands;
private static Set<CommandDescription> baseCommands;
private CommandInitializer() {
// Helper class
}
public static List<CommandDescription> getBaseCommands() {
public static Set<CommandDescription> getBaseCommands() {
if (baseCommands == null) {
Wrapper.getInstance().getLogger().info("Initializing AuthMe commands");
initializeCommands();
@ -89,8 +90,8 @@ public final class CommandInitializer {
.detailedDescription("Register the specified player with the specified password.")
.withArgument("player", "Player name", false)
.withArgument("password", "Password", false)
.permissions(OP_ONLY, PlayerPermission.REGISTER)
.executableCommand(new RegisterCommand())
.permissions(OP_ONLY, AdminPermission.REGISTER)
.executableCommand(new RegisterAdminCommand())
.build();
// Register the unregister command
@ -100,8 +101,8 @@ public final class CommandInitializer {
.description("Unregister a player")
.detailedDescription("Unregister the specified player.")
.withArgument("player", "Player name", false)
.permissions(OP_ONLY, PlayerPermission.UNREGISTER)
.executableCommand(new UnregisterCommand())
.permissions(OP_ONLY, AdminPermission.UNREGISTER)
.executableCommand(new UnregisterAdminCommand())
.build();
// Register the forcelogin command
@ -124,7 +125,7 @@ public final class CommandInitializer {
.withArgument("player", "Player name", false)
.withArgument("pwd", "New password", false)
.permissions(OP_ONLY, AdminPermission.CHANGE_PASSWORD)
.executableCommand(new ChangePasswordCommand())
.executableCommand(new ChangePasswordAdminCommand())
.build();
// Register the last login command
@ -161,7 +162,7 @@ public final class CommandInitializer {
.build();
// Register the setemail command
CommandDescription setEmailCommand = CommandDescription.builder()
CommandDescription.builder()
.executableCommand(new SetEmailCommand())
.parent(AUTHME_BASE)
.labels("chgemail", "chgmail", "setemail", "setmail")
@ -173,96 +174,101 @@ public final class CommandInitializer {
.build();
// Register the getip command
CommandDescription getIpCommand = new CommandDescription(new GetIpCommand(), new ArrayList<String>() {
{
add("getip");
add("ip");
}
}, "Get player's IP", "Get the IP address of the specified online player.", AUTHME_BASE);
getIpCommand.setCommandPermissions(AdminPermission.GET_IP, OP_ONLY);
getIpCommand.addArgument(new CommandArgumentDescription("player", "Online player name", true));
CommandDescription.builder()
.executableCommand(new GetIpCommand())
.parent(AUTHME_BASE)
.labels("getip", "ip")
.description("Get player's IP")
.detailedDescription("Get the IP address of the specified online player.")
.permissions(OP_ONLY, AdminPermission.GET_IP)
.withArgument("player", "Player Name", false)
.build();
// Register the spawn command
CommandDescription spawnCommand = new CommandDescription(new SpawnCommand(), new ArrayList<String>() {
{
add("spawn");
add("home");
}
}, "Teleport to spawn", "Teleport to the spawn.", AUTHME_BASE);
spawnCommand.setCommandPermissions(AdminPermission.SPAWN, OP_ONLY);
CommandDescription.builder()
.executableCommand(new SpawnCommand())
.parent(AUTHME_BASE)
.labels("spawn", "home")
.description("Teleport to spawn")
.detailedDescription("Teleport to the spawn.")
.permissions(OP_ONLY, AdminPermission.SPAWN)
.withArgument("player", "Player Name", false)
.build();
// Register the setspawn command
CommandDescription setSpawnCommand = new CommandDescription(new SetSpawnCommand(), new ArrayList<String>() {
{
add("setspawn");
add("chgspawn");
}
}, "Change the spawn", "Change the player's spawn to your current position.", AUTHME_BASE);
setSpawnCommand.setCommandPermissions(AdminPermission.SET_SPAWN, OP_ONLY);
CommandDescription.builder()
.executableCommand(new SetSpawnCommand())
.parent(AUTHME_BASE)
.labels("setspawn", "chgspawn")
.description("Change the spawn")
.detailedDescription("Change the player's spawn to your current position.")
.permissions(OP_ONLY, AdminPermission.SET_SPAWN)
.build();
// Register the firstspawn command
CommandDescription firstSpawnCommand = new CommandDescription(new FirstSpawnCommand(), new ArrayList<String>() {
{
add("firstspawn");
add("firsthome");
}
}, "Teleport to first spawn", "Teleport to the first spawn.", AUTHME_BASE);
firstSpawnCommand.setCommandPermissions(AdminPermission.FIRST_SPAWN, OP_ONLY);
CommandDescription.builder()
.executableCommand(new FirstSpawnCommand())
.parent(AUTHME_BASE)
.labels("firstspawn", "firsthome")
.description("Teleport to first spawn")
.detailedDescription("Teleport to the first spawn.")
.permissions(OP_ONLY, AdminPermission.FIRST_SPAWN)
.build();
// Register the setfirstspawn command
CommandDescription setFirstSpawnCommand = new CommandDescription(new SetFirstSpawnCommand(), new ArrayList<String>() {
{
add("setfirstspawn");
add("chgfirstspawn");
}
}, "Change the first spawn", "Change the first player's spawn to your current position.", AUTHME_BASE);
setFirstSpawnCommand.setCommandPermissions(AdminPermission.SET_FIRST_SPAWN, OP_ONLY);
CommandDescription.builder()
.executableCommand(new SetFirstSpawnCommand())
.parent(AUTHME_BASE)
.labels("setfirstspawn", "chgfirstspawn")
.description("Change the first spawn")
.detailedDescription("Change the first player's spawn to your current position.")
.permissions(OP_ONLY, AdminPermission.SET_FIRST_SPAWN)
.build();
// Register the purge command
CommandDescription purgeCommand = new CommandDescription(new PurgeCommand(), new ArrayList<String>() {
{
add("purge");
add("delete");
}
}, "Purge old data", "Purge old AuthMeReloaded data longer than the specified amount of days ago.", AUTHME_BASE);
purgeCommand.setCommandPermissions(AdminPermission.PURGE, OP_ONLY);
purgeCommand.addArgument(new CommandArgumentDescription("days", "Number of days", false));
CommandDescription.builder()
.executableCommand(new PurgeCommand())
.parent(AUTHME_BASE)
.labels("purge", "delete")
.description("Purge old data")
.detailedDescription("Purge old AuthMeReloaded data longer than the specified amount of days ago.")
.permissions(OP_ONLY, AdminPermission.PURGE)
.withArgument("days", "Number of days", false)
.build();
// Register the purgelastposition command
CommandDescription purgeLastPositionCommand = new CommandDescription(new PurgeLastPositionCommand(), new ArrayList<String>() {
{
add("resetpos");
add("purgelastposition");
add("purgelastpos");
add("resetposition");
add("resetlastposition");
add("resetlastpos");
}
}, "Purge player's last position", "Purge the last know position of the specified player.", AUTHME_BASE);
purgeLastPositionCommand.setCommandPermissions(AdminPermission.PURGE_LAST_POSITION, OP_ONLY);
purgeLastPositionCommand.addArgument(new CommandArgumentDescription("player", "Player name", true));
CommandDescription.builder()
.executableCommand(new PurgeLastPositionCommand())
.parent(AUTHME_BASE)
.labels("resetpos", "purgelastposition", "purgelastpos", "resetposition", "resetlastposition", "resetlastpos")
.description("Purge player's last position")
.detailedDescription("Purge the last know position of the specified player.")
.permissions(OP_ONLY, AdminPermission.PURGE_LAST_POSITION)
.withArgument("player", "Player name", false)
.build();
// Register the purgebannedplayers command
CommandDescription purgeBannedPlayersCommand = new CommandDescription(new PurgeBannedPlayersCommand(), new ArrayList<String>() {
{
add("purgebannedplayers");
add("purgebannedplayer");
add("deletebannedplayers");
add("deletebannedplayer");
}
}, "Purge banned palyers data", "Purge all AuthMeReloaded data for banned players.", AUTHME_BASE);
purgeBannedPlayersCommand.setCommandPermissions(AdminPermission.PURGE_BANNED_PLAYERS, OP_ONLY);
CommandDescription purgeBannedPlayersCommand = CommandDescription.builder()
.executableCommand(new PurgeBannedPlayersCommand())
.parent(AUTHME_BASE)
.labels("purgebannedplayers", "purgebannedplayer", "deletebannedplayers", "deletebannedplayer")
.description("Purge banned players data")
.detailedDescription("Purge all AuthMeReloaded data for banned players.")
.permissions(OP_ONLY, AdminPermission.PURGE_BANNED_PLAYERS)
.build();
// Register the switchantibot command
CommandDescription switchAntiBotCommand = new CommandDescription(new SwitchAntiBotCommand(), new ArrayList<String>() {
{
add("switchantibot");
add("toggleantibot");
add("antibot");
}
}, "Switch AntiBot mode", "Switch or toggle the AntiBot mode to the specified state.", AUTHME_BASE);
switchAntiBotCommand.setCommandPermissions(AdminPermission.SWITCH_ANTIBOT, OP_ONLY);
switchAntiBotCommand.addArgument(new CommandArgumentDescription("mode", "ON / OFF", true));
CommandDescription switchAntiBotCommand = CommandDescription.builder()
.executableCommand(new SwitchAntiBotCommand())
.parent(AUTHME_BASE)
.labels("switchantibot", "toggleantibot", "antibot")
.description("Switch AntiBot mode")
.detailedDescription("Switch or toggle the AntiBot mode to the specified state.")
.permissions(OP_ONLY, AdminPermission.SWITCH_ANTIBOT)
.withArgument("mode", "ON / OFF", true)
.build();
// // Register the resetname command
// CommandDescription resetNameCommand = new CommandDescription(
@ -278,26 +284,27 @@ public final class CommandInitializer {
// CommandPermissions.DefaultPermission.OP_ONLY);
// Register the reload command
CommandDescription reloadCommand = new CommandDescription(new ReloadCommand(), new ArrayList<String>() {
{
add("reload");
add("rld");
}
}, "Reload plugin", "Reload the AuthMeReloaded plugin.", AUTHME_BASE);
reloadCommand.setCommandPermissions(AdminPermission.RELOAD, OP_ONLY);
CommandDescription reloadCommand = CommandDescription.builder()
.executableCommand(new ReloadCommand())
.parent(AUTHME_BASE)
.labels("reload", "rld")
.description("Reload plugin")
.detailedDescription("Reload the AutheMeReloaded plugin.")
.permissions(OP_ONLY, AdminPermission.RELOAD)
.build();
// Register the version command
CommandDescription versionCommand = CommandDescription.builder()
.executableCommand(new VersionCommand())
CommandDescription.builder()
.parent(AUTHME_BASE)
.labels("version", "ver", "v", "about", "info")
.description("Version info")
.detailedDescription("Show detailed information about the installed AuthMeReloaded version, and shows the "
+ "developers, contributors, license and other information.")
.parent(AUTHME_BASE)
.executableCommand(new VersionCommand())
.build();
// Register the base login command
CommandDescription loginBaseCommand = CommandDescription.builder()
final CommandDescription LOGIN_BASE = CommandDescription.builder()
.executableCommand(new LoginCommand())
.labels("login", "l")
.description("Login command")
@ -308,159 +315,207 @@ public final class CommandInitializer {
.build();
// Register the help command
CommandDescription loginHelpCommand = new CommandDescription(helpCommandExecutable, helpCommandLabels,
"View help", "View detailed help pages about AuthMeReloaded login commands.", loginBaseCommand);
loginHelpCommand.addArgument(new CommandArgumentDescription("query", "The command or query to view help for.", true));
CommandDescription loginHelpCommand = CommandDescription.builder()
.executableCommand(helpCommandExecutable)
.parent(LOGIN_BASE)
.labels(helpCommandLabels)
.description("View Help")
.detailedDescription("View detailed help pages about AuthMeReloaded login commands.")
.withArgument("query", "The command or query to view help for.", true)
.build();
// Register the base logout command
CommandDescription logoutBaseCommand = new CommandDescription(new LogoutCommand(), new ArrayList<String>() {
{
add("logout");
}
}, "Logout command", "Command to logout using AuthMeReloaded.", null);
logoutBaseCommand.setCommandPermissions(PlayerPermission.LOGOUT, CommandPermissions.DefaultPermission.ALLOWED);
CommandDescription LOGOUT_BASE = CommandDescription.builder()
.executableCommand(new LogoutCommand())
.parent(null)
.labels("logout")
.description("Logout command")
.detailedDescription("Command to logout using AuthMeReloaded.")
.permissions(ALLOWED, PlayerPermission.LOGOUT)
.build();
// Register the help command
CommandDescription logoutHelpCommand = new CommandDescription(helpCommandExecutable, helpCommandLabels,
"View help", "View detailed help pages about AuthMeReloaded logout commands.", logoutBaseCommand);
logoutHelpCommand.addArgument(new CommandArgumentDescription("query", "The command or query to view help for.", true));
CommandDescription logoutHelpCommand = CommandDescription.builder()
.executableCommand(helpCommandExecutable)
.parent(LOGOUT_BASE)
.labels(helpCommandLabels)
.description("View help")
.detailedDescription("View detailed help pages about AuthMeReloaded logout commands.")
.withArgument("query", "The command or query to view help for.", true)
.build();
// Register the base register command
CommandDescription registerBaseCommand = new CommandDescription(new fr.xephi.authme.command.executable.register.RegisterCommand(), new ArrayList<String>() {
{
add("register");
add("reg");
}
}, "Registration command", "Command to register using AuthMeReloaded.", null);
registerBaseCommand.setCommandPermissions(PlayerPermission.REGISTER, CommandPermissions.DefaultPermission.ALLOWED);
registerBaseCommand.addArgument(new CommandArgumentDescription("password", "Password", false));
registerBaseCommand.addArgument(new CommandArgumentDescription("verifyPassword", "Verify password", false));
final CommandDescription REGISTER_BASE = CommandDescription.builder()
.parent(null)
.labels("register", "reg")
.description("Registration command")
.detailedDescription("Command to register using AuthMeReloaded.")
.withArgument("password", "Password", false)
.withArgument("verifyPassword", "Verify password", false)
.permissions(ALLOWED, PlayerPermission.REGISTER)
.executableCommand(new RegisterCommand())
.build();
// Register the help command
CommandDescription registerHelpCommand = new CommandDescription(helpCommandExecutable, helpCommandLabels,
"View help", "View detailed help pages about AuthMeReloaded register commands.", registerBaseCommand);
registerHelpCommand.addArgument(new CommandArgumentDescription("query", "The command or query to view help for.", true));
CommandDescription registerHelpCommand = CommandDescription.builder()
.executableCommand(helpCommandExecutable)
.parent(REGISTER_BASE)
.labels(helpCommandLabels)
.description("View help")
.detailedDescription("View detailed help pages about AuthMeReloaded register commands.")
.withArgument("query", "The command or query to view help for.", true)
.build();
// Register the base unregister command
CommandDescription unregisterBaseCommand = new CommandDescription(new fr.xephi.authme.command.executable.unregister.UnregisterCommand(), new ArrayList<String>() {
{
add("unregister");
add("unreg");
}
}, "Unregistration command", "Command to unregister using AuthMeReloaded.", null);
unregisterBaseCommand.setCommandPermissions(PlayerPermission.UNREGISTER, CommandPermissions.DefaultPermission.ALLOWED);
unregisterBaseCommand.addArgument(new CommandArgumentDescription("password", "Password", false));
CommandDescription UNREGISTER_BASE = CommandDescription.builder()
.executableCommand(new UnregisterCommand())
.parent(null)
.labels("unreg", "unregister")
.description("Unregistration Command")
.detailedDescription("Command to unregister using AuthMeReloaded.")
.permissions(ALLOWED, PlayerPermission.UNREGISTER)
.withArgument("password", "Password", false)
.build();
// Register the help command
CommandDescription unregisterHelpCommand = new CommandDescription(helpCommandExecutable, helpCommandLabels, "View help", "View detailed help pages about AuthMeReloaded unregister commands.", unregisterBaseCommand);
unregisterHelpCommand.addArgument(new CommandArgumentDescription("query", "The command or query to view help for.", true));
CommandDescription unregisterHelpCommand = CommandDescription.builder()
.executableCommand(helpCommandExecutable)
.parent(UNREGISTER_BASE)
.labels(helpCommandLabels)
.description("View help")
.detailedDescription("View detailed help pages about AuthMeReloaded unregister commands.")
.withArgument("query", "The command or query to view help for.", true)
.build();
// Register the base changepassword command
CommandDescription changePasswordBaseCommand = new CommandDescription(new fr.xephi.authme.command.executable.changepassword.ChangePasswordCommand(), new ArrayList<String>() {
{
add("changepassword");
add("changepass");
}
}, "Change password command", "Command to change your password using AuthMeReloaded.", null);
changePasswordBaseCommand.setCommandPermissions(PlayerPermission.CHANGE_PASSWORD, CommandPermissions.DefaultPermission.ALLOWED);
changePasswordBaseCommand.addArgument(new CommandArgumentDescription("password", "Password", false));
changePasswordBaseCommand.addArgument(new CommandArgumentDescription("verifyPassword", "Verify password", false));
final CommandDescription CHANGE_PASSWORD_BASE = CommandDescription.builder()
.executableCommand(new ChangePasswordCommand())
.parent(null)
.labels("changepassword", "changepass", "cp")
.description("Change password Command")
.detailedDescription("Command to change your password using AuthMeReloaded.")
.permissions(ALLOWED, PlayerPermission.CHANGE_PASSWORD)
.withArgument("password", "Password", false)
.withArgument("verifyPassword", "Verify password.", false)
.build();
// Register the help command
CommandDescription changePasswordHelpCommand = new CommandDescription(helpCommandExecutable, helpCommandLabels,
"View help", "View detailed help pages about AuthMeReloaded change password commands.", changePasswordBaseCommand);
changePasswordHelpCommand.addArgument(new CommandArgumentDescription("query", "The command or query to view help for.", true));
CommandDescription changePasswordHelpCommand = CommandDescription.builder()
.executableCommand(helpCommandExecutable)
.parent(CHANGE_PASSWORD_BASE)
.labels(helpCommandLabels)
.description("View help")
.detailedDescription("View detailed help pages about AuthMeReloaded changepassword commands.")
.withArgument("query", "The command or query to view help for.", true)
.build();
// Register the base Dungeon Maze command
CommandDescription emailBaseCommand = new CommandDescription(helpCommandExecutable, new ArrayList<String>() {
{
add("email");
add("mail");
}
}, "E-mail command", "The AuthMe Reloaded E-mail command. The root for all E-mail commands.", null);
// Register the base Email command
CommandDescription EMAIL_BASE = CommandDescription.builder()
.executableCommand(helpCommandExecutable)
.parent(null)
.labels("email", "mail")
.description("Email command")
.detailedDescription("The AuthMeReloaded Email command base.")
.build();
// Register the help command
CommandDescription emailHelpCommand = new CommandDescription(helpCommandExecutable, helpCommandLabels,
"View help", "View detailed help pages about AuthMeReloaded help commands.", emailBaseCommand);
emailHelpCommand.addArgument(new CommandArgumentDescription("query", "The command or query to view help for.", true));
CommandDescription emailHelpCommand = CommandDescription.builder()
.executableCommand(helpCommandExecutable)
.parent(EMAIL_BASE)
.labels(helpCommandLabels)
.description("View help")
.detailedDescription("View detailed help pages about AuthMeReloaded email commands.")
.withArgument("query", "The command or query to view help for.", true)
.build();
// Register the add command
CommandDescription addEmailCommand = new CommandDescription(new AddEmailCommand(), new ArrayList<String>() {
{
add("add");
add("addemail");
add("addmail");
}
}, "Add E-mail", "Add an new E-Mail address to your account.", emailBaseCommand);
addEmailCommand.setCommandPermissions(PlayerPermission.ADD_EMAIL, CommandPermissions.DefaultPermission.ALLOWED);
addEmailCommand.addArgument(new CommandArgumentDescription("email", "Email address", false));
addEmailCommand.addArgument(new CommandArgumentDescription("verifyEmail", "Email address verification", false));
CommandDescription addEmailCommand = CommandDescription.builder()
.executableCommand(new AddEmailCommand())
.parent(EMAIL_BASE)
.labels("add", "addemail", "addmail")
.description("Add Email")
.detailedDescription("Add a new Email address to your account.")
.permissions(ALLOWED, PlayerPermission.ADD_EMAIL)
.withArgument("email", "Email address", false)
.withArgument("verifyEmail", "Email address verification", false)
.build();
// Register the change command
CommandDescription changeEmailCommand = new CommandDescription(new ChangeEmailCommand(), new ArrayList<String>() {
{
add("change");
add("changeemail");
add("changemail");
}
}, "Change E-mail", "Change an E-Mail address of your account.", emailBaseCommand);
changeEmailCommand.setCommandPermissions(PlayerPermission.CHANGE_EMAIL, CommandPermissions.DefaultPermission.ALLOWED);
changeEmailCommand.addArgument(new CommandArgumentDescription("oldEmail", "Old email address", false));
changeEmailCommand.addArgument(new CommandArgumentDescription("newEmail", "New email address", false));
CommandDescription changeEmailCommand = CommandDescription.builder()
.executableCommand(new ChangeEmailCommand())
.parent(EMAIL_BASE)
.labels("change", "changeemail", "changemail")
.description("Change Email")
.detailedDescription("Change an Email address of your account.")
.permissions(ALLOWED, PlayerPermission.CHANGE_EMAIL)
.withArgument("oldEmail", "Old email address", false)
.withArgument("newEmail", "New email address", false)
.build();
// Register the recover command
CommandDescription recoverEmailCommand = new CommandDescription(new RecoverEmailCommand(), new ArrayList<String>() {
{
add("recover");
add("recovery");
add("recoveremail");
add("recovermail");
}
}, "Recover using E-mail", "Recover your account using an E-mail address.", emailBaseCommand);
recoverEmailCommand.setCommandPermissions(PlayerPermission.RECOVER_EMAIL, CommandPermissions.DefaultPermission.ALLOWED);
recoverEmailCommand.addArgument(new CommandArgumentDescription("email", "Email address", false));
CommandDescription recoverEmailCommand = CommandDescription.builder()
.executableCommand(new RecoverEmailCommand())
.parent(EMAIL_BASE)
.labels("recover", "recovery", "recoveremail", "recovermail")
.description("Recover password using Email")
.detailedDescription("Recover your account using an Email address by sending a mail containing a new password.")
.permissions(ALLOWED, PlayerPermission.RECOVER_EMAIL)
.withArgument("email", "Email address", false)
.build();
// Register the base captcha command
CommandDescription captchaBaseCommand = new CommandDescription(new CaptchaCommand(), new ArrayList<String>() {
{
add("captcha");
add("capt");
}
}, "Captcha command", "Captcha command for AuthMeReloaded.", null);
captchaBaseCommand.setCommandPermissions(PlayerPermission.CAPTCHA, CommandPermissions.DefaultPermission.ALLOWED);
captchaBaseCommand.addArgument(new CommandArgumentDescription("captcha", "The captcha", false));
CommandDescription CAPTCHA_BASE = CommandDescription.builder()
.executableCommand(new CaptchaCommand())
.parent(null)
.labels("captcha", "capt")
.description("Captcha Command")
.detailedDescription("Captcha command for AuthMeRelaoded.")
.permissions(ALLOWED, PlayerPermission.CAPTCHA)
.withArgument("captcha", "The Captcha", false)
.build();
// Register the help command
CommandDescription captchaHelpCommand = new CommandDescription(helpCommandExecutable, helpCommandLabels,
"View help", "View detailed help pages about AuthMeReloaded change captcha commands.", captchaBaseCommand);
captchaHelpCommand.addArgument(new CommandArgumentDescription("query", "The command or query to view help for.", true));
CommandDescription captchaHelpCommand = CommandDescription.builder()
.executableCommand(helpCommandExecutable)
.parent(CAPTCHA_BASE)
.labels(helpCommandLabels)
.description("View help")
.detailedDescription("View detailed help pages about AuthMeReloaded captcha commands.")
.withArgument("query", "The command or query to view help for.", true)
.build();
// Register the base converter command
CommandDescription converterBaseCommand = new CommandDescription(new ConverterCommand(), new ArrayList<String>() {
{
add("converter");
add("convert");
add("conv");
}
}, "Convert command", "Convert command for AuthMeReloaded.", null);
converterBaseCommand.setCommandPermissions(AdminPermission.CONVERTER, OP_ONLY);
converterBaseCommand.addArgument(new CommandArgumentDescription("job", "Conversion job: flattosql / flattosqlite /| xauth / crazylogin / rakamak / royalauth / vauth / sqltoflat", false));
CommandDescription CONVERTER_BASE = CommandDescription.builder()
.executableCommand(new ConverterCommand())
.parent(null)
.labels("converter", "convert", "conv")
.description("Converter Command")
.detailedDescription("Converter command for AuthMeRelaoded.")
.permissions(OP_ONLY, AdminPermission.CONVERTER)
.withArgument("job", "Conversion job: flattosql / flattosqlite /| xauth / crazylogin / rakamak / royalauth / vauth / sqltoflat", false)
.build();
// Register the help command
CommandDescription converterHelpCommand = new CommandDescription(helpCommandExecutable, helpCommandLabels,
"View help", "View detailed help pages about AuthMeReloaded change captcha commands.", converterBaseCommand);
converterHelpCommand.addArgument(new CommandArgumentDescription("query", "The command or query to view help for.", true));
CommandDescription converterHelpCommand = CommandDescription.builder()
.executableCommand(helpCommandExecutable)
.parent(CONVERTER_BASE)
.labels(helpCommandLabels)
.description("View help")
.detailedDescription("View detailed help pages about AuthMeReloaded converter commands.")
.withArgument("query", "The command or query to view help for.", true)
.build();
// Add the base commands to the commands array
baseCommands = Arrays.asList(
baseCommands = new HashSet<>(Arrays.asList(
AUTHME_BASE,
loginBaseCommand,
logoutBaseCommand,
registerBaseCommand,
unregisterBaseCommand,
changePasswordBaseCommand,
emailBaseCommand,
captchaBaseCommand,
converterBaseCommand);
LOGIN_BASE,
LOGOUT_BASE,
REGISTER_BASE,
UNREGISTER_BASE,
CHANGE_PASSWORD_BASE,
EMAIL_BASE,
CAPTCHA_BASE,
CONVERTER_BASE));
}
}

View File

@ -14,12 +14,6 @@ public class CommandParts {
*/
private final List<String> parts = new ArrayList<>();
/**
* Constructor.
*/
public CommandParts() {
}
/**
* Constructor.
*
@ -29,15 +23,6 @@ public class CommandParts {
this.parts.add(part);
}
/**
* Constructor.
*
* @param commandParts The command parts instance.
*/
public CommandParts(CommandParts commandParts) {
this.parts.addAll(commandParts.getList());
}
/**
* Constructor.
*
@ -47,17 +32,6 @@ public class CommandParts {
this.parts.addAll(parts);
}
/**
* Constructor.
*
* @param base The base part.
* @param parts The list of additional parts.
*/
public CommandParts(String base, List<String> parts) {
this.parts.add(base);
this.parts.addAll(parts);
}
/**
* Get the command parts.
*
@ -67,41 +41,6 @@ public class CommandParts {
return this.parts;
}
/**
* Add a part.
*
* @param part The part to add.
*
* @return The result.
*/
public boolean add(String part) {
return this.parts.add(part);
}
/**
* Add some parts.
*
* @param parts The parts to add.
*
* @return The result.
*/
public boolean add(List<String> parts) {
return this.parts.addAll(parts);
}
/**
* Add some parts.
*
* @param parts The parts to add.
*
* @return The result.
*/
public boolean add(String[] parts) {
for (String entry : parts)
add(entry);
return true;
}
/**
* Get the number of parts.
*
@ -112,7 +51,7 @@ public class CommandParts {
}
/**
* Get a part by it's index.
* Get a part by its index.
*
* @param i Part index.
*
@ -127,63 +66,6 @@ public class CommandParts {
return this.parts.get(i);
}
/**
* Get a range of the parts starting at the specified index up to the end of the range.
*
* @param start The starting index.
*
* @return The parts range. Arguments that were out of bound are not included.
*/
public List<String> getRange(int start) {
return getRange(start, getCount() - start);
}
/**
* Get a range of the parts.
*
* @param start The starting index.
* @param count The number of parts to get.
*
* @return The parts range. Parts that were out of bound are not included.
*/
public List<String> getRange(int start, int count) {
// Create a new list to put the range into
List<String> elements = new ArrayList<>();
// Get the range
for (int i = start; i < start + count; i++) {
// Get the part and add it if it's valid
String element = get(i);
if (element != null)
elements.add(element);
}
// Return the list of parts
return elements;
}
/**
* Get the difference value between two references.
*
* @param other The other reference.
* @param fullCompare True to compare the full references as far as the range reaches.
*
* @return The result from zero to above. A negative number will be returned on error.
*/
public double getDifference(CommandParts other, boolean fullCompare) {
// Make sure the other reference is correct
if (other == null)
return -1;
// Get the range to use
int range = Math.min(this.getCount(), other.getCount());
// Get and the difference
if (fullCompare)
return StringUtils.getDifference(this.toString(), other.toString());
return StringUtils.getDifference(this.getRange(range - 1, 1).toString(), other.getRange(range - 1, 1).toString());
}
/**
* Convert the parts to a string.
*

View File

@ -1,6 +1,7 @@
package fr.xephi.authme.command;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.permission.DefaultPermission;
import fr.xephi.authme.permission.PermissionsManager;
import fr.xephi.authme.permission.PermissionNode;
import org.bukkit.command.CommandSender;
@ -22,18 +23,6 @@ public class CommandPermissions {
*/
private DefaultPermission defaultPermission;
/**
* Constructor.
*
* @param permissionNode The permission node required to execute a command.
* @param defaultPermission The default permission if the permission nodes couldn't be used.
*/
public CommandPermissions(PermissionNode permissionNode, DefaultPermission defaultPermission) {
this.permissionNodes = new ArrayList<>();
this.permissionNodes.add(permissionNode);
this.defaultPermission = defaultPermission;
}
/**
* Constructor.
*
@ -54,16 +43,6 @@ public class CommandPermissions {
return this.permissionNodes;
}
/**
* Get the number of permission nodes set.
*
* @return Permission node count.
*/
public int getPermissionNodeCount() {
return this.permissionNodes.size();
}
/**
* Check whether this command requires any permission to be executed. This is based on the getPermission() method.
*
@ -73,31 +52,28 @@ public class CommandPermissions {
*/
public boolean hasPermission(CommandSender sender) {
// Make sure any permission node is set
if (getPermissionNodeCount() == 0)
if (permissionNodes.isEmpty()) {
return true;
}
// Get the default permission
PermissionsManager permissionsManager = AuthMe.getInstance().getPermissionsManager();
final boolean defaultPermission = getDefaultPermissionCommandSender(sender);
// Make sure the command sender is a player, if not use the default
if (!(sender instanceof Player))
if (!(sender instanceof Player)) {
return defaultPermission;
}
// Get the player instance
Player player = (Player) sender;
// Get the permissions manager, and make sure it's instance is valid
PermissionsManager permissionsManager = AuthMe.getInstance().getPermissionsManager();
if (permissionsManager == null)
return false;
// Check whether the player has permission, return the result
for (PermissionNode node : this.permissionNodes) {
if (!permissionsManager.hasPermission(player, node, defaultPermission)) {
return false;
}
}
return true;
return permissionsManager.hasPermission(player, this.permissionNodes, defaultPermission);
}
/**
@ -109,14 +85,6 @@ public class CommandPermissions {
return this.defaultPermission;
}
/**
* Set the default permission used if the permission nodes couldn't be used.
*
* @param defaultPermission The default permission.
*/
public void setDefaultPermission(DefaultPermission defaultPermission) {
this.defaultPermission = defaultPermission;
}
/**
* Get the default permission for a specified command sender.
@ -138,12 +106,4 @@ public class CommandPermissions {
return false;
}
}
/**
*/
public enum DefaultPermission {
NOT_ALLOWED,
OP_ONLY,
ALLOWED
}
}

View File

@ -1,5 +1,11 @@
package fr.xephi.authme.command;
import fr.xephi.authme.util.CollectionUtils;
import fr.xephi.authme.util.StringUtils;
import java.util.ArrayList;
import java.util.List;
public final class CommandUtils {
public static int getMinNumberOfArguments(CommandDescription command) {
@ -13,9 +19,40 @@ public final class CommandUtils {
}
public static int getMaxNumberOfArguments(CommandDescription command) {
return command.hasMaximumArguments()
? command.getArguments().size()
: -1;
return command.getArguments().size();
}
/**
* Provide a textual representation of a list of labels to show it as a command. For example, a list containing
* the items ["authme", "register", "player"] it will return "authme register player".
*
* @param labels The labels to format
* @return The space-separated labels
*/
public static String labelsToString(Iterable<String> labels) {
return StringUtils.join(" ", labels);
}
public static double getDifference(List<String> labels1, List<String> labels2, boolean fullCompare) {
// Make sure the other reference is correct
if (labels1 == null || labels2 == null) {
return -1;
}
// Get the range to use
int range = Math.min(labels1.size(), labels2.size());
// Get and the difference
if (fullCompare) {
return StringUtils.getDifference(CommandUtils.labelsToString(labels1), CommandUtils.labelsToString(labels2));
}
return StringUtils.getDifference(
labelsToString(CollectionUtils.getRange(labels1, range - 1, 1)),
labelsToString(CollectionUtils.getRange(labels2, range - 1, 1)));
}
}

View File

@ -61,27 +61,13 @@ public class FoundCommandResult {
return this.commandDescription;
}
/**
* Set the command description.
*
* @param commandDescription The command description.
*/
public void setCommandDescription(CommandDescription commandDescription) {
this.commandDescription = commandDescription;
}
/**
* Check whether the command is executable.
*
* @return True if the command is executable, false otherwise.
*/
public boolean isExecutable() {
// Make sure the command description is valid
if (this.commandDescription == null)
return false;
// Check whether the command is executable, return the result
return this.commandDescription.isExecutable();
return commandDescription != null;
}
/**
@ -153,10 +139,11 @@ public class FoundCommandResult {
*/
public double getDifference() {
// Get the difference through the command found
if (this.commandDescription != null)
if (this.commandDescription != null) {
return this.commandDescription.getCommandDifference(this.queryReference);
}
// Get the difference from the query reference
return this.queryReference.getDifference(commandReference, true);
return CommandUtils.getDifference(queryReference.getList(), commandReference.getList(), true);
}
}

View File

@ -18,7 +18,7 @@ import java.security.NoSuchAlgorithmException;
/**
* Admin command for changing a player's password.
*/
public class ChangePasswordCommand extends ExecutableCommand {
public class ChangePasswordAdminCommand extends ExecutableCommand {
@Override
public boolean executeCommand(final CommandSender sender, CommandParts commandReference, CommandParts commandArguments) {

View File

@ -15,8 +15,9 @@ import org.bukkit.command.CommandSender;
import java.security.NoSuchAlgorithmException;
/**
* Admin command to register a user.
*/
public class RegisterCommand extends ExecutableCommand {
public class RegisterAdminCommand extends ExecutableCommand {
/**
* Execute the command.
@ -42,8 +43,12 @@ public class RegisterCommand extends ExecutableCommand {
final String playerPassLowerCase = playerPass.toLowerCase();
// Command logic
if (playerPassLowerCase.contains("delete") || playerPassLowerCase.contains("where") || playerPassLowerCase.contains("insert") || playerPassLowerCase.contains("modify") || playerPassLowerCase.contains("from") || playerPassLowerCase.contains("select") || playerPassLowerCase.contains(";") || playerPassLowerCase.contains("null") || !playerPassLowerCase.matches(Settings.getPassRegex)) {
m.send(sender, MessageKey.PASSWORD_IS_USERNAME_ERROR);
if (playerPassLowerCase.contains("delete") || playerPassLowerCase.contains("where")
|| playerPassLowerCase.contains("insert") || playerPassLowerCase.contains("modify")
|| playerPassLowerCase.contains("from") || playerPassLowerCase.contains("select")
|| playerPassLowerCase.contains(";") || playerPassLowerCase.contains("null")
|| !playerPassLowerCase.matches(Settings.getPassRegex)) {
m.send(sender, MessageKey.PASSWORD_MATCH_ERROR);
return true;
}
if (playerPassLowerCase.equalsIgnoreCase(playerName)) {

View File

@ -2,11 +2,15 @@ package fr.xephi.authme.command.executable.authme;
import fr.xephi.authme.AntiBot;
import fr.xephi.authme.command.CommandParts;
import fr.xephi.authme.command.CommandUtils;
import fr.xephi.authme.command.ExecutableCommand;
import fr.xephi.authme.command.help.HelpProvider;
import fr.xephi.authme.util.CollectionUtils;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import java.util.List;
/**
*/
public class SwitchAntiBotCommand extends ExecutableCommand {
@ -32,16 +36,16 @@ public class SwitchAntiBotCommand extends ExecutableCommand {
}
// Enable the mod
if (newState.equalsIgnoreCase("ON")) {
if ("ON".equalsIgnoreCase(newState)) {
AntiBot.overrideAntiBotStatus(true);
sender.sendMessage("[AuthMe] AntiBot Manual Ovverride: enabled!");
sender.sendMessage("[AuthMe] AntiBot Manual Override: enabled!");
return true;
}
// Disable the mod
if (newState.equalsIgnoreCase("OFF")) {
if ("OFF".equalsIgnoreCase(newState)) {
AntiBot.overrideAntiBotStatus(false);
sender.sendMessage("[AuthMe] AntiBotMod Manual Ovverride: disabled!");
sender.sendMessage("[AuthMe] AntiBotMod Manual Override: disabled!");
return true;
}
@ -52,8 +56,9 @@ public class SwitchAntiBotCommand extends ExecutableCommand {
HelpProvider.showHelp(sender, commandReference, commandReference, true, false, true, false, false, false);
// Show the command to use for detailed help
CommandParts helpCommandReference = new CommandParts(commandReference.getRange(1));
sender.sendMessage(ChatColor.GOLD + "Detailed help: " + ChatColor.WHITE + "/" + commandReference.get(0) + " help " + helpCommandReference);
List<String> helpCommandReference = CollectionUtils.getRange(commandReference.getList(), 1);
sender.sendMessage(ChatColor.GOLD + "Detailed help: " + ChatColor.WHITE + "/"
+ commandReference.get(0) + " help " + CommandUtils.labelsToString(helpCommandReference));
return true;
}
}

View File

@ -21,8 +21,9 @@ import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.scheduler.BukkitTask;
/**
* Admin command to unregister a player.
*/
public class UnregisterCommand extends ExecutableCommand {
public class UnregisterAdminCommand extends ExecutableCommand {
/**
* Execute the command.

View File

@ -5,14 +5,15 @@ import fr.xephi.authme.command.CommandArgumentDescription;
import fr.xephi.authme.command.CommandDescription;
import fr.xephi.authme.command.CommandParts;
import fr.xephi.authme.command.CommandPermissions;
import fr.xephi.authme.command.CommandUtils;
import fr.xephi.authme.permission.PermissionNode;
import fr.xephi.authme.util.CollectionUtils;
import fr.xephi.authme.util.StringUtils;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
@ -77,10 +78,6 @@ public class HelpPrinter {
// Print the syntax
sender.sendMessage(argString.toString());
}
// Show the unlimited arguments argument
if (!command.hasMaximumArguments())
sender.sendMessage(" " + ChatColor.YELLOW + ChatColor.ITALIC + "... : " + ChatColor.WHITE + "Any additional arguments." + ChatColor.GRAY + ChatColor.ITALIC + " (Optional)");
}
/**
@ -90,14 +87,11 @@ public class HelpPrinter {
* @param command The command to print the permissions help for.
*/
public static void printPermissions(CommandSender sender, CommandDescription command) {
// Get the permissions and make sure it isn't null
// Get the permissions and make sure they aren't missing
CommandPermissions permissions = command.getCommandPermissions();
if (permissions == null)
return;
// Make sure any permission node is set
if (permissions.getPermissionNodeCount() <= 0)
if (permissions == null || CollectionUtils.isEmpty(permissions.getPermissionNodes())) {
return;
}
// Print the header
sender.sendMessage(ChatColor.GOLD + "Permissions:");
@ -112,13 +106,16 @@ public class HelpPrinter {
}
// Print the default permission
// TODO ljacqu 20151205: This is duplicating the logic in PermissionsManager#evaluateDefaultPermission
// Either use the command manager here, or if that's too heavy, look into moving certain permissions logic
// into a Utils class
switch (permissions.getDefaultPermission()) {
case ALLOWED:
sender.sendMessage(ChatColor.GOLD + " Default: " + ChatColor.GRAY + ChatColor.ITALIC + "Permission!");
break;
case OP_ONLY:
final String defaultPermsString = ChatColor.GRAY + (permissions.getDefaultPermissionCommandSender(sender) ? ChatColor.ITALIC + " (Permission!)" : ChatColor.ITALIC + " (No Permission!)");
final String defaultPermsString = ChatColor.GRAY + (sender.isOp() ? ChatColor.ITALIC + " (Permission!)" : ChatColor.ITALIC + " (No Permission!)");
sender.sendMessage(ChatColor.GOLD + " Default: " + ChatColor.YELLOW + ChatColor.ITALIC + "OP's Only!" + defaultPermsString);
break;

View File

@ -3,12 +3,17 @@ package fr.xephi.authme.command.help;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.command.CommandDescription;
import fr.xephi.authme.command.CommandParts;
import fr.xephi.authme.command.CommandUtils;
import fr.xephi.authme.command.FoundCommandResult;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.util.CollectionUtils;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import java.util.ArrayList;
import java.util.List;
/**
*/
public class HelpProvider {
@ -40,7 +45,12 @@ public class HelpProvider {
public static void showHelp(CommandSender sender, CommandParts reference, CommandParts helpQuery, boolean showCommand, boolean showDescription, boolean showArguments, boolean showPermissions, boolean showAlternatives, boolean showCommands) {
// Find the command for this help query, one with and one without a prefixed base command
FoundCommandResult result = AuthMe.getInstance().getCommandHandler().findCommand(new CommandParts(helpQuery.getList()));
CommandParts commandReferenceOther = new CommandParts(reference.get(0), helpQuery.getList());
// TODO ljacqu 20151204 Fix me to nicer code
List<String> parts = new ArrayList<>(helpQuery.getList());
parts.add(0, reference.get(0));
CommandParts commandReferenceOther = new CommandParts(parts);
FoundCommandResult resultOther = AuthMe.getInstance().getCommandHandler().findCommand(commandReferenceOther);
if (resultOther != null) {
if (result == null)
@ -78,13 +88,14 @@ public class HelpProvider {
// Show the unknown command warning
sender.sendMessage(ChatColor.DARK_RED + "No help found for '" + helpQuery + "'!");
// Get the suggested command
CommandParts suggestedCommandParts = new CommandParts(result.getCommandDescription().getCommandReference(commandReference).getRange(1));
// Show a command suggestion if available and the difference isn't too big
if (commandDifference < 0.75)
if (result.getCommandDescription() != null)
sender.sendMessage(ChatColor.YELLOW + "Did you mean " + ChatColor.GOLD + "/" + baseCommand + " help " + suggestedCommandParts + ChatColor.YELLOW + "?");
if (commandDifference < 0.75 && result.getCommandDescription() != null) {
// Get the suggested command
List<String> suggestedCommandParts = CollectionUtils.getRange(
result.getCommandDescription().getCommandReference(commandReference).getList(), 1);
sender.sendMessage(ChatColor.YELLOW + "Did you mean " + ChatColor.GOLD + "/" + baseCommand
+ " help " + CommandUtils.labelsToString(suggestedCommandParts) + ChatColor.YELLOW + "?");
}
// Show the help command
sender.sendMessage(ChatColor.YELLOW + "Use the command " + ChatColor.GOLD + "/" + baseCommand + " help" + ChatColor.YELLOW + " to view help.");
@ -94,10 +105,12 @@ public class HelpProvider {
// Show a message when the command handler is assuming a command
if (commandDifference > 0) {
// Get the suggested command
CommandParts suggestedCommandParts = new CommandParts(result.getCommandDescription().getCommandReference(commandReference).getRange(1));
List<String> suggestedCommandParts = CollectionUtils.getRange(
result.getCommandDescription().getCommandReference(commandReference).getList(), 1);
// Show the suggested command
sender.sendMessage(ChatColor.DARK_RED + "No help found, assuming '" + ChatColor.GOLD + suggestedCommandParts + ChatColor.DARK_RED + "'!");
sender.sendMessage(ChatColor.DARK_RED + "No help found, assuming '" + ChatColor.GOLD
+ CommandUtils.labelsToString(suggestedCommandParts) + ChatColor.DARK_RED + "'!");
}
// Print the help header

View File

@ -3,6 +3,8 @@ package fr.xephi.authme.command.help;
import fr.xephi.authme.command.CommandArgumentDescription;
import fr.xephi.authme.command.CommandDescription;
import fr.xephi.authme.command.CommandParts;
import fr.xephi.authme.command.CommandUtils;
import fr.xephi.authme.util.CollectionUtils;
import fr.xephi.authme.util.StringUtils;
import org.bukkit.ChatColor;
@ -35,8 +37,8 @@ public final class HelpSyntaxHelper {
// Get the help command reference, and the command label
CommandParts helpCommandReference = commandDescription.getCommandReference(commandReference);
final String parentCommand = new CommandParts(
helpCommandReference.getRange(0, helpCommandReference.getCount() - 1)).toString();
final String parentCommand = CommandUtils.labelsToString(
CollectionUtils.getRange(helpCommandReference.getList(), 0, helpCommandReference.getCount() - 1));
// Check whether the alternative label should be used
String commandLabel;
@ -61,11 +63,6 @@ public final class HelpSyntaxHelper {
sb.append(ChatColor.ITALIC).append(formatArgument(arg));
}
// Add some dots if the command allows unlimited arguments
if (!commandDescription.hasMaximumArguments()) {
sb.append(ChatColor.ITALIC).append(" ...");
}
// Return the build command syntax
return sb.toString();
}

View File

@ -8,112 +8,108 @@ public enum AdminPermission implements PermissionNode {
/**
* Administrator command to register a new user.
*/
REGISTER("authme.command.admin.register"),
REGISTER("authme.admin.register"),
/**
* Administrator command to unregister an existing user.
*/
UNREGISTER("authme.command.admin.unregister"),
UNREGISTER("authme.admin.unregister"),
/**
* Administrator command to force-login an existing user.
*/
FORCE_LOGIN("authme.command.admin.forcelogin"),
FORCE_LOGIN("authme.admin.forcelogin"),
/**
* Administrator command to change the password of a user.
*/
CHANGE_PASSWORD("authme.command.admin.changepassword"),
CHANGE_PASSWORD("authme.admin.changepassword"),
/**
* Administrator command to see the last login date and time of an user.
* Administrator command to see the last login date and time of a user.
*/
LAST_LOGIN("authme.command.admin.lastlogin"),
LAST_LOGIN("authme.admin.lastlogin"),
/**
* Administrator command to see all accounts associated with an user.
* Administrator command to see all accounts associated with a user.
*/
ACCOUNTS("authme.command.admin.accounts"),
ACCOUNTS("authme.admin.accounts"),
/**
* Administrator command to get the email address of an user, if set.
* Administrator command to get the email address of a user, if set.
*/
GET_EMAIL("authme.command.admin.getemail"),
GET_EMAIL("authme.admin.getemail"),
/**
* Administrator command to set or change the email adress of an user.
* Administrator command to set or change the email address of a user.
*/
CHANGE_EMAIL("authme.command.admin.changemail"),
CHANGE_EMAIL("authme.admin.changemail"),
/**
* Administrator command to get the last known IP of an user.
* Administrator command to get the last known IP of a user.
*/
GET_IP("authme.command.admin.getip"),
GET_IP("authme.admin.getip"),
/**
* Administrator command to teleport to the AuthMe spawn.
*/
SPAWN("authme.command.admin.spawn"),
SPAWN("authme.admin.spawn"),
/**
* Administrator command to set the AuthMe spawn.
*/
SET_SPAWN("authme.command.admin.setspawn"),
SET_SPAWN("authme.admin.setspawn"),
/**
* Administrator command to teleport to the first AuthMe spawn.
*/
FIRST_SPAWN("authme.command.admin.firstspawn"),
FIRST_SPAWN("authme.admin.firstspawn"),
/**
* Administrator command to set the first AuthMe spawn.
*/
SET_FIRST_SPAWN("authme.command.admin.setfirstspawn"),
SET_FIRST_SPAWN("authme.admin.setfirstspawn"),
/**
* Administrator command to purge old user data.
*/
PURGE("authme.command.admin.purge"),
PURGE("authme.admin.purge"),
/**
* Administrator command to purge the last position of an user.
* Administrator command to purge the last position of a user.
*/
PURGE_LAST_POSITION("authme.command.admin.purgelastpos"),
PURGE_LAST_POSITION("authme.admin.purgelastpos"),
/**
* Administrator command to purge all data associated with banned players.
*/
PURGE_BANNED_PLAYERS("authme.command.admin.purgebannedplayers"),
PURGE_BANNED_PLAYERS("authme.admin.purgebannedplayers"),
/**
* Administrator command to toggle the AntiBot protection status.
*/
SWITCH_ANTIBOT("authme.command.admin.switchantibot"),
SWITCH_ANTIBOT("authme.admin.switchantibot"),
/**
* Administrator command to convert old or other data to AuthMe data.
*/
CONVERTER("authme.command.admin.converter"),
CONVERTER("authme.admin.converter"),
/**
* Administrator command to reload the plugin configuration.
*/
RELOAD("authme.command.admin.reload");
RELOAD("authme.admin.reload"),
/**
* Give access to all admin commands.
*/
ADMIN_ALL("authme.admin.*");
/**
* Permission node.
* The permission node.
*/
private String node;
/**
* Get the permission node.
* @return
*/
@Override
public String getNode() {
return node;
}
/**
* Constructor.
*
@ -122,4 +118,14 @@ public enum AdminPermission implements PermissionNode {
AdminPermission(String node) {
this.node = node;
}
@Override
public String getNode() {
return node;
}
@Override
public PermissionNode getWildcardNode() {
return ADMIN_ALL;
}
}

View File

@ -0,0 +1,16 @@
package fr.xephi.authme.permission;
/**
* The default permission for a command if there is no support for permission nodes.
*/
public enum DefaultPermission {
/** No one can execute the command. */
NOT_ALLOWED,
/** Only players with the OP status may execute the command. */
OP_ONLY,
/** The command can be executed by anyone. */
ALLOWED
}

View File

@ -5,7 +5,18 @@ package fr.xephi.authme.permission;
*/
public interface PermissionNode {
/** Return the node of the permission, e.g. "authme.unregister". */
/**
* Return the node of the permission, e.g. "authme.player.unregister".
*
* @return The name of the permission node
*/
String getNode();
/**
* Return the wildcard node that also grants the permission.
*
* @return The wildcard permission node (e.g. "authme.player.*")
*/
PermissionNode getWildcardNode();
}

View File

@ -5,11 +5,14 @@ import com.nijiko.permissions.PermissionHandler;
import com.nijikokun.bukkit.Permissions.Permissions;
import de.bananaco.bpermissions.api.ApiLayer;
import de.bananaco.bpermissions.api.CalculableType;
import fr.xephi.authme.command.CommandDescription;
import fr.xephi.authme.util.CollectionUtils;
import net.milkbowl.vault.permission.Permission;
import org.anjocaido.groupmanager.GroupManager;
import org.anjocaido.groupmanager.permissions.AnjoPermissionsHandler;
import org.bukkit.Bukkit;
import org.bukkit.Server;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.server.PluginDisableEvent;
import org.bukkit.event.server.PluginEnableEvent;
@ -38,7 +41,7 @@ import java.util.logging.Logger;
* @author Tim Visée, http://timvisee.com
* @version 0.2.1
*/
public class PermissionsManager {
public class PermissionsManager implements PermissionsService {
/**
* Vault instance.
@ -100,8 +103,8 @@ public class PermissionsManager {
*
* @return The name of the permissions system used.
*/
public String getUsedPermissionsSystemType() {
return this.permsType.getName();
public PermissionsSystemType getSystem() {
return permsType;
}
/**
@ -260,7 +263,6 @@ public class PermissionsManager {
*
* @param event Event instance.
*/
// TODO ljacqu 20151129: Misleading name since onPluginEnable is a typical event-based method name
public void onPluginEnable(PluginEnableEvent event) {
// Get the plugin and it's name
Plugin plugin = event.getPlugin();
@ -296,35 +298,7 @@ public class PermissionsManager {
}
}
/**
* Get the logger instance.
*
* @return Logger instance.
*/
public Logger getLogger() {
return this.log;
}
/**
* Set the logger instance.
*
* @param log Logger instance.
*/
public void setLogger(Logger log) {
this.log = log;
}
/**
* Check if the player has permission. If no permissions system is used, the player has to be OP.
*
* @param player The player.
* @param permsNode Permissions node.
*
* @return True if the player has permission.
*/
public boolean hasPermission(Player player, String permsNode) {
return hasPermission(player, permsNode, player.isOp());
}
/**
* Check if the player has permission for the given permissions node. If no permissions system is used,
@ -340,7 +314,42 @@ public class PermissionsManager {
}
public boolean hasPermission(Player player, PermissionNode permissionNode, boolean def) {
return hasPermission(player, permissionNode.getNode(), def);
return hasPermission(player, permissionNode.getNode(), def)
|| hasPermission(player, permissionNode.getWildcardNode().getNode(), def);
}
public boolean hasPermission(Player player, Iterable<PermissionNode> nodes, boolean def) {
for (PermissionNode node : nodes) {
if (!hasPermission(player, node, def)) {
return false;
}
}
return true;
}
public boolean hasPermission(Player player, CommandDescription command) {
if (command.getCommandPermissions() == null
|| CollectionUtils.isEmpty(command.getCommandPermissions().getPermissionNodes())) {
return true;
}
DefaultPermission defaultPermission = command.getCommandPermissions().getDefaultPermission();
boolean def = evaluateDefaultPermission(defaultPermission, player);
return hasPermission(player, command.getCommandPermissions().getPermissionNodes(), def);
}
public static boolean evaluateDefaultPermission(DefaultPermission defaultPermission, CommandSender sender) {
switch (defaultPermission) {
case ALLOWED:
return true;
case OP_ONLY:
return sender.isOp();
case NOT_ALLOWED:
default:
return false;
}
}
/**
@ -352,7 +361,7 @@ public class PermissionsManager {
*
* @return True if the player has permission.
*/
public boolean hasPermission(Player player, String permsNode, boolean def) {
private boolean hasPermission(Player player, String permsNode, boolean def) {
// If no permissions system is used, return the default value
if (!isEnabled())
return def;
@ -915,34 +924,5 @@ public class PermissionsManager {
return removeGroups(player, groupNames);
}
private enum PermissionsSystemType {
NONE("None"),
PERMISSIONS_EX("PermissionsEx"),
PERMISSIONS_BUKKIT("Permissions Bukkit"),
B_PERMISSIONS("bPermissions"),
ESSENTIALS_GROUP_MANAGER("Essentials Group Manager"),
Z_PERMISSIONS("zPermissions"),
VAULT("Vault"),
PERMISSIONS("Permissions");
public final String name;
/**
* Constructor for PermissionsSystemType.
*
* @param name String
*/
PermissionsSystemType(String name) {
this.name = name;
}
/**
* Method getName.
*
* @return String
*/
public String getName() {
return this.name;
}
}
}

View File

@ -0,0 +1,39 @@
package fr.xephi.authme.permission;
import fr.xephi.authme.command.CommandDescription;
import org.bukkit.entity.Player;
/**
* Interface for dealing with permissions.
*/
public interface PermissionsService {
/**
* Check if the player has the given permission.
*
* @param player The player
* @param permission The permission node to check
* @param def Default returned if no permissions system is used
*
* @return True if the player has permission
*/
boolean hasPermission(Player player, PermissionNode permission, boolean def);
/**
* Check if the player has the permissions for the given command.
*
* @param player The player
* @param command The command whose permissions should be checked
*
* @return True if the player may execute the command
*/
boolean hasPermission(Player player, CommandDescription command);
/**
* Return the permission system the service is working with.
*
* @return The permission system AuthMe is hooked into
*/
PermissionsSystemType getSystem();
}

View File

@ -0,0 +1,38 @@
package fr.xephi.authme.permission;
/**
* Enum representing the permissions systems AuthMe supports.
*/
public enum PermissionsSystemType {
NONE("None"),
PERMISSIONS_EX("PermissionsEx"),
PERMISSIONS_BUKKIT("Permissions Bukkit"),
B_PERMISSIONS("bPermissions"),
ESSENTIALS_GROUP_MANAGER("Essentials Group Manager"),
Z_PERMISSIONS("zPermissions"),
VAULT("Vault"),
PERMISSIONS("Permissions");
public final String name;
/**
* Constructor for PermissionsSystemType.
*
* @param name The name the permissions manager goes by
*/
PermissionsSystemType(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}

View File

@ -18,47 +18,47 @@ public enum PlayerPermission implements PermissionNode {
/**
* Command permission to login.
*/
LOGIN("authme.command.player.login"),
LOGIN("authme.player.login"),
/**
* Command permission to logout.
*/
LOGOUT("authme.command.player.logout"),
LOGOUT("authme.player.logout"),
/**
* Command permission to register.
*/
REGISTER("authme.command.player.register"),
REGISTER("authme.player.register"),
/**
* Command permission to unregister.
*/
UNREGISTER("authme.command.player.unregister"),
UNREGISTER("authme.player.unregister"),
/**
* Command permission to change the password.
*/
CHANGE_PASSWORD("authme.command.player.changepassword"),
CHANGE_PASSWORD("authme.player.changepassword"),
/**
* Command permission to add an email address.
*/
ADD_EMAIL("authme.command.player.email.add"),
ADD_EMAIL("authme.player.email.add"),
/**
* Command permission to change the email address.
*/
CHANGE_EMAIL("authme.command.player.email.change"),
CHANGE_EMAIL("authme.player.email.change"),
/**
* Command permission to recover an account using it's email address.
*/
RECOVER_EMAIL("authme.command.player.email.recover"),
RECOVER_EMAIL("authme.player.email.recover"),
/**
* Command permission to use captcha.
*/
CAPTCHA("authme.command.player.captcha"),
CAPTCHA("authme.player.captcha"),
/**
* Permission for users a login can be forced to.
@ -68,33 +68,28 @@ public enum PlayerPermission implements PermissionNode {
/**
* Permission for users to bypass force-survival mode.
*/
BYPASS_FORCE_SURVIVAL("authme.command.player.bypassforcesurvival"),
BYPASS_FORCE_SURVIVAL("authme.player.bypassforcesurvival"),
/**
* Permission for users to allow two accounts.
*/
ALLOW_MULTIPLE_ACCOUNTS("authme.command.player.allow2accounts"),
ALLOW_MULTIPLE_ACCOUNTS("authme.player.allow2accounts"),
/**
* Permission for user to see other accounts.
*/
SEE_OTHER_ACCOUNTS("authme.command.player.seeotheraccounts");
SEE_OTHER_ACCOUNTS("authme.player.seeotheraccounts"),
/**
* Permission to use all player (non-admin) commands.
*/
PLAYER_ALL("authme.player.*");
/**
* Permission node.
* The permission node.
*/
private String node;
/**
* Get the permission node.
*
* @return Permission node.
*/
@Override
public String getNode() {
return node;
}
/**
* Constructor.
*
@ -103,4 +98,14 @@ public enum PlayerPermission implements PermissionNode {
PlayerPermission(String node) {
this.node = node;
}
@Override
public String getNode() {
return node;
}
@Override
public PermissionNode getWildcardNode() {
return PLAYER_ALL;
}
}

View File

@ -80,15 +80,12 @@ public class AsynchronousLogin {
plugin.captcha.remove(name);
plugin.captcha.putIfAbsent(name, i);
}
if (plugin.captcha.containsKey(name) && plugin.captcha.get(name) >= Settings.maxLoginTry) {
plugin.cap.put(name, rdm.nextString());
if (plugin.captcha.containsKey(name) && plugin.captcha.get(name) > Settings.maxLoginTry) {
plugin.cap.putIfAbsent(name, rdm.nextString());
for (String s : m.retrieve(MessageKey.USAGE_CAPTCHA)) {
player.sendMessage(s.replace("THE_CAPTCHA", plugin.cap.get(name)).replace("<theCaptcha>", plugin.cap.get(name)));
}
return true;
} else if (plugin.captcha.containsKey(name) && plugin.captcha.get(name) >= Settings.maxLoginTry) {
plugin.captcha.remove(name);
plugin.cap.remove(name);
}
}
return false;
@ -135,6 +132,13 @@ public class AsynchronousLogin {
m.send(player, MessageKey.ACCOUNT_NOT_ACTIVATED);
return null;
}
if (Settings.preventOtherCase && !player.getName().equals(pAuth.getRealName()))
{
// TODO: Add a message like : MessageKey.INVALID_NAME_CASE
m.send(player, MessageKey.USERNAME_ALREADY_ONLINE_ERROR);
return null;
}
AuthMeAsyncPreLoginEvent event = new AuthMeAsyncPreLoginEvent(player);
Bukkit.getServer().getPluginManager().callEvent(event);
if (!event.canLogin())

View File

@ -73,7 +73,7 @@ public final class Settings {
enableProtection, enableAntiBot, recallEmail, useWelcomeMessage,
broadcastWelcomeMessage, forceRegKick, forceRegLogin,
checkVeryGames, delayJoinLeaveMessages, noTeleport, applyBlindEffect,
customAttributes, generateImage, isRemoveSpeedEnabled;
customAttributes, generateImage, isRemoveSpeedEnabled, preventOtherCase;
public static String helpHeader, getNickRegex, getUnloggedinGroup, getMySQLHost,
getMySQLPort, getMySQLUsername, getMySQLPassword, getMySQLDatabase,
getMySQLTablename, getMySQLColumnName, getMySQLColumnPassword,
@ -294,6 +294,7 @@ public final class Settings {
forceRegisterCommandsAsConsole = configFile.getStringList("settings.forceRegisterCommandsAsConsole");
customAttributes = configFile.getBoolean("Hooks.customAttributes");
generateImage = configFile.getBoolean("Email.generateImage", false);
preventOtherCase = configFile.getBoolean("settings.preventOtherCase", false);
// Load the welcome message
getWelcomeMessage();
@ -713,6 +714,12 @@ public final class Settings {
changes = true;
}
if (!contains("settings.preventOtherCase"))
{
set("settings.preventOtherCase", false);
changes = true;
}
if (contains("Email.mailText"))
{
set("Email.mailText", null);

View File

@ -0,0 +1,52 @@
package fr.xephi.authme.util;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* Utils class for collections.
*/
public final class CollectionUtils {
private CollectionUtils() {
}
/**
* Get a range from a list based on start and count parameters in a safe way.
*
* @param start The start index
* @param count The number of elements to add
*
* @return The sublist consisting at most of {@code count} elements (less if the parameters
* exceed the size of the list)
*/
public static <T> List<T> getRange(List<T> list, int start, int count) {
if (start >= list.size() || count <= 0) {
return new ArrayList<>();
} else if (start < 0) {
start = 0;
}
int end = Math.min(list.size(), start + count);
return list.subList(start, end);
}
/**
* Get all elements from a list starting from the given index.
*
* @param start The start index
*
* @return The sublist of all elements from index {@code start} and on; empty list
* if the start index exceeds the list's size
*/
public static <T> List<T> getRange(List<T> list, int start) {
if (start >= list.size()) {
return new ArrayList<>();
}
return getRange(list, start, list.size() - start);
}
public static <T> boolean isEmpty(Collection<T> coll) {
return coll == null || coll.isEmpty();
}
}

View File

@ -13,8 +13,6 @@ import java.util.Arrays;
*/
public final class StringUtils {
public static final String newline = System.getProperty("line.separator");
private StringUtils() {
// Utility class
}
@ -29,8 +27,9 @@ public final class StringUtils {
*/
public static double getDifference(String first, String second) {
// Make sure the strings are valid.
if (first == null || second == null)
if (first == null || second == null) {
return 1.0;
}
// Create a string similarity service instance, to allow comparison
StringSimilarityService service = new StringSimilarityServiceImpl(new LevenshteinDistanceStrategy());

View File

@ -259,6 +259,9 @@ settings:
delayJoinLeaveMessages: true
# Do we need to add potion effect Blinding before login/register ?
applyBlindEffect: false
# Do we need to prevent people to login without another case ?
# Xephi is registered, also Xephi can login, but not XEPHI/xephi/XePhI
preventOtherCase: false
ExternalBoardOptions:
# MySQL column for the salt , needed for some forum/cms support
mySQLColumnSalt: ''

View File

@ -0,0 +1,135 @@
package fr.xephi.authme.command;
import fr.xephi.authme.permission.DefaultPermission;
import fr.xephi.authme.permission.PlayerPermission;
import fr.xephi.authme.util.WrapperMock;
import org.bukkit.command.CommandSender;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.stringContainsInOrder;
import static org.mockito.BDDMockito.given;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
/**
* Test for {@link CommandHandler}.
*/
public class CommandHandlerTest {
private static Set<CommandDescription> commands;
private static CommandHandler handler;
@BeforeClass
public static void setUpCommandHandler() {
WrapperMock.createInstance();
CommandDescription authMeBase = createCommand(null, null, singletonList("authme"));
createCommand(PlayerPermission.LOGIN, authMeBase, singletonList("login"), newArgument("password", false));
createCommand(PlayerPermission.LOGIN, authMeBase, asList("register", "reg"),
newArgument("password", false), newArgument("confirmation", false));
CommandDescription testBase = createCommand(null, null, singletonList("test"), newArgument("test", true));
commands = new HashSet<>(asList(authMeBase, testBase));
handler = new CommandHandler(commands);
}
@Test
@Ignore
public void shouldForwardCommandToExecutable() {
// given
CommandSender sender = Mockito.mock(CommandSender.class);
given(sender.isOp()).willReturn(true);
String bukkitLabel = "authme";
String[] args = {"login", "password"};
// when
handler.processCommand(sender, bukkitLabel, args);
// then
final CommandDescription loginCmd = getChildWithLabel("login", getCommandWithLabel("authme", commands));
verify(sender, never()).sendMessage(anyString());
verify(loginCmd.getExecutableCommand()).executeCommand(
eq(sender), any(CommandParts.class), any(CommandParts.class));
}
@Test
@Ignore // TODO ljacqu Fix test --> command classes too tightly coupled at the moment
public void shouldRejectCommandWithTooManyArguments() {
// given
CommandSender sender = Mockito.mock(CommandSender.class);
given(sender.isOp()).willReturn(true);
String bukkitLabel = "authme";
String[] args = {"login", "password", "__unneededArgument__"};
// when
boolean result = handler.processCommand(sender, bukkitLabel, args);
// then
assertThat(result, equalTo(true));
assertSenderGotMessageContaining("help", sender);
}
private static CommandDescription createCommand(PlayerPermission permission, CommandDescription parent,
List<String> labels, CommandArgumentDescription... arguments) {
CommandDescription.CommandBuilder command = CommandDescription.builder()
.labels(labels)
.parent(parent)
.permissions(DefaultPermission.OP_ONLY, permission)
.description("Test")
.detailedDescription("Test command")
.executableCommand(mock(ExecutableCommand.class));
if (arguments != null && arguments.length > 0) {
for (CommandArgumentDescription argument : arguments) {
command.withArgument(argument.getLabel(), "Test description", argument.isOptional());
}
}
return command.build();
}
private static CommandArgumentDescription newArgument(String label, boolean isOptional) {
return new CommandArgumentDescription(label, "Test description", isOptional);
}
private void assertSenderGotMessageContaining(String text, CommandSender sender) {
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
verify(sender).sendMessage(captor.capture());
assertThat(captor.getValue(), stringContainsInOrder(text));
}
private static CommandDescription getCommandWithLabel(String label, Collection<CommandDescription> commands) {
for (CommandDescription command : commands) {
if (command.getLabels().contains(label)) {
return command;
}
}
return null;
}
private static CommandDescription getChildWithLabel(String label, CommandDescription command) {
for (CommandDescription child : command.getChildren()) {
if (child.getLabels().contains(label)) {
return child;
}
}
return null;
}
}

View File

@ -1,11 +1,15 @@
package fr.xephi.authme.command;
import fr.xephi.authme.permission.AdminPermission;
import fr.xephi.authme.permission.PermissionNode;
import fr.xephi.authme.util.StringUtils;
import fr.xephi.authme.util.WrapperMock;
import org.junit.BeforeClass;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@ -13,6 +17,7 @@ import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import static fr.xephi.authme.permission.DefaultPermission.OP_ONLY;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.nullValue;
@ -30,7 +35,7 @@ public class CommandInitializerTest {
*/
private static int MAX_ALLOWED_DEPTH = 1;
private static List<CommandDescription> commands;
private static Set<CommandDescription> commands;
@BeforeClass
public static void initializeCommandManager() {
@ -228,15 +233,51 @@ public class CommandInitializerTest {
walkThroughCommands(commands, noArgumentForParentChecker);
}
/**
* Test that commands defined with the OP_ONLY default permission have at least one admin permission node.
*/
@Test
public void shouldNotHavePlayerPermissionIfDefaultsToOpOnly() {
// given
BiConsumer adminPermissionChecker = new BiConsumer() {
// The only exception to this check is the force login command, which should default to OP_ONLY
// but semantically it is a player permission
final List<String> forceLoginLabels = Arrays.asList("forcelogin", "login");
@Override
public void accept(CommandDescription command, int depth) {
CommandPermissions permissions = command.getCommandPermissions();
if (permissions != null && OP_ONLY.equals(permissions.getDefaultPermission())) {
if (!hasAdminNode(permissions) && !command.getLabels().equals(forceLoginLabels)) {
fail("The command with labels " + command.getLabels() + " has OP_ONLY default "
+ "permission but no permission node on admin level");
}
}
}
private boolean hasAdminNode(CommandPermissions permissions) {
for (PermissionNode node : permissions.getPermissionNodes()) {
if (node instanceof AdminPermission) {
return true;
}
}
return false;
}
};
// when/then
walkThroughCommands(commands, adminPermissionChecker);
}
// ------------
// Helper methods
// ------------
private static void walkThroughCommands(List<CommandDescription> commands, BiConsumer consumer) {
private static void walkThroughCommands(Collection<CommandDescription> commands, BiConsumer consumer) {
walkThroughCommands(commands, consumer, 0);
}
private static void walkThroughCommands(List<CommandDescription> commands, BiConsumer consumer, int depth) {
private static void walkThroughCommands(Collection<CommandDescription> commands, BiConsumer consumer, int depth) {
for (CommandDescription command : commands) {
consumer.accept(command, depth);
if (command.hasChildren()) {
@ -259,12 +300,12 @@ public class CommandInitializerTest {
}
/**
* Get the absolute label that a command defines. Note: Assumes that only the passed command might have
* Get the absolute binding that a command defines. Note: Assumes that only the passed command can have
* multiple labels; only considering the first label for all of the command's parents.
*
* @param command The command to verify
* @param command The command to process
*
* @return The full command binding
* @return List of all bindings that lead to the command
*/
private static List<String> getAbsoluteLabels(CommandDescription command) {
String parentPath = "";

View File

@ -3,6 +3,7 @@ package fr.xephi.authme.command;
import org.junit.Test;
import java.util.Arrays;
import java.util.Collections;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
@ -27,7 +28,7 @@ public class CommandPartsTest {
@Test
public void shouldPrintEmptyStringForNoArguments() {
// given
CommandParts parts = new CommandParts();
CommandParts parts = new CommandParts(Collections.EMPTY_LIST);
// when
String str = parts.toString();

View File

@ -15,6 +15,8 @@ import org.junit.Ignore;
import org.junit.Test;
import org.mockito.Mockito;
import java.util.Collections;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.verify;
@ -40,7 +42,7 @@ public class CaptchaCommandTest {
ExecutableCommand command = new CaptchaCommand();
// when
boolean result = command.executeCommand(sender, new CommandParts(), new CommandParts());
boolean result = command.executeCommand(sender, new CommandParts(Collections.EMPTY_LIST), new CommandParts(Collections.EMPTY_LIST));
// then
assertThat(result, equalTo(true));
@ -56,7 +58,7 @@ public class CaptchaCommandTest {
ExecutableCommand command = new CaptchaCommand();
// when
boolean result = command.executeCommand(player, new CommandParts(), new CommandParts());
boolean result = command.executeCommand(player, new CommandParts(Collections.EMPTY_LIST), new CommandParts(Collections.EMPTY_LIST));
// then
assertThat(result, equalTo(true));

View File

@ -18,6 +18,7 @@ import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@ -58,7 +59,7 @@ public class ChangePasswordCommandTest {
CommandParts arguments = mock(CommandParts.class);
// when
command.executeCommand(sender, new CommandParts(), arguments);
command.executeCommand(sender, newParts(), arguments);
// then
verify(arguments, never()).get(anyInt());
@ -72,7 +73,7 @@ public class ChangePasswordCommandTest {
ChangePasswordCommand command = new ChangePasswordCommand();
// when
command.executeCommand(sender, new CommandParts(), new CommandParts("pass"));
command.executeCommand(sender, newParts(), new CommandParts("pass"));
// then
verify(messagesMock).send(sender, MessageKey.NOT_LOGGED_IN);
@ -86,7 +87,7 @@ public class ChangePasswordCommandTest {
ChangePasswordCommand command = new ChangePasswordCommand();
// when
command.executeCommand(sender, new CommandParts(), newParts("old123", "!pass"));
command.executeCommand(sender, newParts(), newParts("old123", "!pass"));
// then
verify(messagesMock).send(sender, MessageKey.PASSWORD_MATCH_ERROR);
@ -101,7 +102,7 @@ public class ChangePasswordCommandTest {
ChangePasswordCommand command = new ChangePasswordCommand();
// when
command.executeCommand(sender, new CommandParts(), newParts("old_", "Tester"));
command.executeCommand(sender, newParts(), newParts("old_", "Tester"));
// then
verify(messagesMock).send(sender, MessageKey.PASSWORD_IS_USERNAME_ERROR);
@ -116,7 +117,7 @@ public class ChangePasswordCommandTest {
Settings.passwordMaxLength = 3;
// when
command.executeCommand(sender, new CommandParts(), newParts("12", "test"));
command.executeCommand(sender, newParts(), newParts("12", "test"));
// then
verify(messagesMock).send(sender, MessageKey.INVALID_PASSWORD_LENGTH);
@ -131,7 +132,7 @@ public class ChangePasswordCommandTest {
Settings.getPasswordMinLen = 7;
// when
command.executeCommand(sender, new CommandParts(), newParts("oldverylongpassword", "tester"));
command.executeCommand(sender, newParts(), newParts("oldverylongpassword", "tester"));
// then
verify(messagesMock).send(sender, MessageKey.INVALID_PASSWORD_LENGTH);
@ -146,7 +147,7 @@ public class ChangePasswordCommandTest {
Settings.unsafePasswords = asList("test", "abc123");
// when
command.executeCommand(sender, new CommandParts(), newParts("oldpw", "abc123"));
command.executeCommand(sender, newParts(), newParts("oldpw", "abc123"));
// then
verify(messagesMock).send(sender, MessageKey.PASSWORD_UNSAFE_ERROR);
@ -160,7 +161,7 @@ public class ChangePasswordCommandTest {
ChangePasswordCommand command = new ChangePasswordCommand();
// when
command.executeCommand(sender, new CommandParts(), newParts("abc123", "abc123"));
command.executeCommand(sender, newParts(), newParts("abc123", "abc123"));
// then
verify(messagesMock, never()).send(eq(sender), any(MessageKey.class));

View File

@ -11,6 +11,7 @@ import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import java.util.ArrayList;
import java.util.Arrays;
import static org.mockito.Mockito.never;
@ -40,7 +41,7 @@ public class AddEmailCommandTest {
AddEmailCommand command = new AddEmailCommand();
// when
command.executeCommand(sender, new CommandParts(), new CommandParts());
command.executeCommand(sender, newParts(), newParts());
// then
verify(authMeMock, never()).getManagement();
@ -53,11 +54,15 @@ public class AddEmailCommandTest {
AddEmailCommand command = new AddEmailCommand();
// when
command.executeCommand(sender, new CommandParts(),
command.executeCommand(sender, newParts(),
new CommandParts(Arrays.asList("mail@example", "other_example")));
// then
verify(authMeMock).getManagement();
verify(managementMock).performAddEmail(sender, "mail@example", "other_example");
}
private static CommandParts newParts() {
return new CommandParts(new ArrayList<String>());
}
}

View File

@ -11,6 +11,7 @@ import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import java.util.ArrayList;
import java.util.Arrays;
import static org.mockito.Mockito.never;
@ -40,7 +41,7 @@ public class ChangeEmailCommandTest {
ChangeEmailCommand command = new ChangeEmailCommand();
// when
command.executeCommand(sender, new CommandParts(), new CommandParts());
command.executeCommand(sender, newParts(), newParts());
// then
verify(authMeMock, never()).getManagement();
@ -53,11 +54,15 @@ public class ChangeEmailCommandTest {
ChangeEmailCommand command = new ChangeEmailCommand();
// when
command.executeCommand(sender, new CommandParts(),
command.executeCommand(sender, newParts(),
new CommandParts(Arrays.asList("new.mail@example.org", "old_mail@example.org")));
// then
verify(authMeMock).getManagement();
verify(managementMock).performChangeEmail(sender, "new.mail@example.org", "old_mail@example.org");
}
private static CommandParts newParts() {
return new CommandParts(new ArrayList<String>());
}
}

View File

@ -9,6 +9,8 @@ import org.junit.Ignore;
import org.junit.Test;
import org.mockito.Mockito;
import java.util.Collections;
/**
* Test for {@link RecoverEmailCommand}.
*/
@ -27,7 +29,7 @@ public class RecoverEmailCommandTest {
RecoverEmailCommand command = new RecoverEmailCommand();
// when
command.executeCommand(sender, new CommandParts(), new CommandParts());
command.executeCommand(sender, new CommandParts(Collections.EMPTY_LIST), new CommandParts(Collections.EMPTY_LIST));
// then
}

View File

@ -11,6 +11,8 @@ import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import java.util.ArrayList;
import static org.mockito.Matchers.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@ -38,7 +40,7 @@ public class LoginCommandTest {
LoginCommand command = new LoginCommand();
// when
command.executeCommand(sender, new CommandParts(), new CommandParts());
command.executeCommand(sender, newParts(), newParts());
// then
Mockito.verify(managementMock, never()).performLogin(any(Player.class), anyString(), anyBoolean());
@ -51,7 +53,7 @@ public class LoginCommandTest {
LoginCommand command = new LoginCommand();
// when
command.executeCommand(sender, new CommandParts(), new CommandParts("password"));
command.executeCommand(sender, newParts(), new CommandParts("password"));
// then
Mockito.verify(managementMock).performLogin(eq(sender), eq("password"), eq(false));
@ -64,11 +66,15 @@ public class LoginCommandTest {
LoginCommand command = new LoginCommand();
// when
command.executeCommand(sender, new CommandParts(), new CommandParts());
command.executeCommand(sender, newParts(), newParts());
// then
// TODO ljacqu 20151121: May make sense to handle null password in LoginCommand instead of forwarding the call
String password = null;
Mockito.verify(managementMock).performLogin(eq(sender), eq(password), eq(false));
}
private static CommandParts newParts() {
return new CommandParts(new ArrayList<String>());
}
}

View File

@ -12,6 +12,8 @@ import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import java.util.ArrayList;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@ -40,7 +42,7 @@ public class LogoutCommandTest {
LogoutCommand command = new LogoutCommand();
// when
command.executeCommand(sender, new CommandParts(), new CommandParts());
command.executeCommand(sender, new CommandParts(new ArrayList<String>()), new CommandParts(new ArrayList<String>()));
// then
Mockito.verify(managementMock, never()).performLogout(any(Player.class));
@ -53,7 +55,7 @@ public class LogoutCommandTest {
LogoutCommand command = new LogoutCommand();
// when
command.executeCommand(sender, new CommandParts(), new CommandParts("password"));
command.executeCommand(sender, new CommandParts(new ArrayList<String>()), new CommandParts("password"));
// then
Mockito.verify(managementMock).performLogout(sender);

View File

@ -14,6 +14,8 @@ import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import java.util.ArrayList;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any;
@ -48,7 +50,7 @@ public class RegisterCommandTest {
ArgumentCaptor<String> messageCaptor = ArgumentCaptor.forClass(String.class);
// when
command.executeCommand(sender, new CommandParts(), new CommandParts());
command.executeCommand(sender, newParts(), newParts());
// then
verify(sender).sendMessage(messageCaptor.capture());
@ -63,7 +65,7 @@ public class RegisterCommandTest {
RegisterCommand command = new RegisterCommand();
// when
command.executeCommand(sender, new CommandParts(), new CommandParts());
command.executeCommand(sender, newParts(), newParts());
// then
verify(messagesMock).send(sender, MessageKey.USAGE_REGISTER);
@ -77,9 +79,13 @@ public class RegisterCommandTest {
RegisterCommand command = new RegisterCommand();
// when
command.executeCommand(sender, new CommandParts(), new CommandParts("password"));
command.executeCommand(sender, newParts(), new CommandParts("password"));
// then
verify(managementMock).performRegister(sender, "password", "");
}
private static CommandParts newParts() {
return new CommandParts(new ArrayList<String>());
}
}

View File

@ -3,10 +3,12 @@ package fr.xephi.authme.command.help;
import fr.xephi.authme.command.CommandDescription;
import fr.xephi.authme.command.CommandParts;
import fr.xephi.authme.command.ExecutableCommand;
import fr.xephi.authme.command.executable.authme.RegisterCommand;
import fr.xephi.authme.command.executable.authme.RegisterAdminCommand;
import org.junit.Test;
import org.mockito.Mockito;
import java.util.ArrayList;
import static org.bukkit.ChatColor.BOLD;
import static org.bukkit.ChatColor.ITALIC;
import static org.bukkit.ChatColor.WHITE;
@ -27,8 +29,7 @@ public class HelpSyntaxHelperTest {
.build();
// when
String result = HelpSyntaxHelper.getCommandSyntax(
description, new CommandParts(), "", false);
String result = HelpSyntaxHelper.getCommandSyntax(description, newParts(), "", false);
// then
assertThat(result, equalTo(WHITE + "/authme register" + ITALIC + " [name]"));
@ -42,8 +43,7 @@ public class HelpSyntaxHelperTest {
.build();
// when
String result = HelpSyntaxHelper.getCommandSyntax(
description, new CommandParts(), null, false);
String result = HelpSyntaxHelper.getCommandSyntax(description, newParts(), null, false);
// then
assertThat(result, equalTo(WHITE + "/authme register" + ITALIC + " <test>"));
@ -58,8 +58,7 @@ public class HelpSyntaxHelperTest {
.build();
// when
String result = HelpSyntaxHelper.getCommandSyntax(
description, new CommandParts(), "", false);
String result = HelpSyntaxHelper.getCommandSyntax(description, newParts(), "", false);
// then
assertThat(result, equalTo(WHITE + "/authme register" + ITALIC + " [name]" + ITALIC + " <test>"));
@ -74,8 +73,7 @@ public class HelpSyntaxHelperTest {
.build();
// when
String result = HelpSyntaxHelper.getCommandSyntax(
description, new CommandParts(), "", true);
String result = HelpSyntaxHelper.getCommandSyntax(description, newParts(), "", true);
// then
assertThat(result, equalTo(WHITE + "/authme "
@ -89,8 +87,7 @@ public class HelpSyntaxHelperTest {
CommandDescription description = getDescriptionBuilder().build();
// when
String result = HelpSyntaxHelper.getCommandSyntax(
description, new CommandParts(), null, true);
String result = HelpSyntaxHelper.getCommandSyntax(description, newParts(), null, true);
// then
assertThat(result, equalTo(WHITE + "/authme " + YELLOW + BOLD + "register" + YELLOW));
@ -104,33 +101,17 @@ public class HelpSyntaxHelperTest {
.build();
// when
String result = HelpSyntaxHelper.getCommandSyntax(
description, new CommandParts(), "alt", false);
String result = HelpSyntaxHelper.getCommandSyntax(description, newParts(), "alt", false);
// then
assertThat(result, equalTo(WHITE + "/authme alt" + ITALIC + " [name]"));
}
@Test
public void shouldHighlightCommandWithAltLabelAndUnlimitedArguments() {
// given
CommandDescription description = getDescriptionBuilder()
.withArgument("name", "", true)
.withArgument("test", "", false)
.noArgumentMaximum(true)
.build();
// when
String result = HelpSyntaxHelper.getCommandSyntax(
description, new CommandParts(), "test", true);
// then
assertThat(result, equalTo(WHITE + "/authme "
+ YELLOW + BOLD + "test"
+ YELLOW + ITALIC + " [name]" + ITALIC + " <test>" + ITALIC + " ..."));
private static CommandParts newParts() {
// TODO ljacqu 20151204: Remove this method once CommandParts has been removed
return new CommandParts(new ArrayList<String>());
}
private static CommandDescription.CommandBuilder getDescriptionBuilder() {
CommandDescription base = CommandDescription.builder()
.labels("authme")
@ -141,7 +122,7 @@ public class HelpSyntaxHelperTest {
.build();
return CommandDescription.builder()
.executableCommand(Mockito.mock(RegisterCommand.class))
.executableCommand(Mockito.mock(RegisterAdminCommand.class))
.labels("register", "r")
.description("Register a player")
.detailedDescription("Register the specified player with the specified password.")

View File

@ -0,0 +1,102 @@
package fr.xephi.authme.util;
import org.junit.Test;
import java.util.Arrays;
import java.util.List;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.hamcrest.Matchers.empty;
/**
* Test for {@link CollectionUtils}.
*/
public class CollectionUtilsTest {
@Test
public void shouldGetFullList() {
// given
List<String> list = Arrays.asList("test", "1", "2", "3", "4");
// when
List<String> result = CollectionUtils.getRange(list, 0, 24);
// then
assertThat(result, equalTo(list));
}
@Test
public void shouldReturnEmptyListForZeroCount() {
// given
List<String> list = Arrays.asList("test", "1", "2", "3", "4");
// when
List<String> result = CollectionUtils.getRange(list, 2, 0);
// then
assertThat(result, empty());
}
@Test
public void shouldReturnEmptyListForTooHighStart() {
// given
List<String> list = Arrays.asList("test", "1", "2", "3", "4");
// when
List<String> result = CollectionUtils.getRange(list, 12, 2);
// then
assertThat(result, empty());
}
@Test
public void shouldReturnSubList() {
// given
List<String> list = Arrays.asList("test", "1", "2", "3", "4");
// when
List<String> result = CollectionUtils.getRange(list, 1, 3);
// then
assertThat(result, contains("1", "2", "3"));
}
@Test
public void shouldReturnTillEnd() {
// given
List<String> list = Arrays.asList("test", "1", "2", "3", "4");
// when
List<String> result = CollectionUtils.getRange(list, 2, 3);
// then
assertThat(result, contains("2", "3", "4"));
}
@Test
public void shouldRemoveFirstTwo() {
// given
List<String> list = Arrays.asList("test", "1", "2", "3", "4");
// when
List<String> result = CollectionUtils.getRange(list, 2);
// then
assertThat(result, contains("2", "3", "4"));
}
@Test
public void shouldHandleNegativeStart() {
// given
List<String> list = Arrays.asList("test", "1", "2", "3", "4");
// when
List<String> result = CollectionUtils.getRange(list, -4);
// then
assertThat(result, equalTo(list));
}
}

3
src/tools/README.md Normal file
View File

@ -0,0 +1,3 @@
# About src/tools
This _tools_ folder provides helpers and extended tests useful during the development of AuthMe.
This folder is not included during the build of AuthMe.

View File

@ -0,0 +1,21 @@
## Bat Helpers
Collection of .bat files to quickly perform some frequent development tasks.
They allow you to quickly build the project and to move the generated JAR to
the plugins folder of your test server.
### Setup
1. Copy the files into a new, convenient directory
2. Open setvars.bat with a text editor and add the correct directories
3. Open `cmd` and navigate to your _bathelpers_ folder (`cd C:\path\the\folder`)
4. Type `list_files.bat` (Hint: Type `l` and hit Tab) to see the available tasks
### Example use case
1. After writing changes, `build_project` to build project
2. `move_plugin` moves the JAR file to the plugin folder
3. `run_server` to start the server with the fresh JAR
4. Problem detected, stop the server
5. Make a small change, use `quick_build` and `move_plugin` to update
6. Verify the change again on the server: `run_server`
All files start with a different letter, so you can conveniently type the
first letter and then complete with Tab.

View File

@ -0,0 +1,6 @@
: Analyze the project with Sonar (requires you install SonarQube)
if "%jarfile%" == "" (
call setvars.bat
)
mvn clean verify sonar:sonar -f "%pomfile%"

View File

@ -0,0 +1,6 @@
: Build the project normally
if "%jarfile%" == "" (
call setvars.bat
)
mvn clean install -f "%pomfile%" -B

View File

@ -0,0 +1,2 @@
: List all bat files in the directory
dir /B *.bat

View File

@ -0,0 +1,11 @@
: Moves the AuthMe JAR file to the plugins folder of the test server
: You will have to hit 'Y' to really replace it if it already exists
if "%jarfile%" == "" (
call setvars.bat
)
if exist %jarfile% (
xcopy %jarfile% %plugins%
) else (
echo Target file not found: '%jarfile%'
)

View File

@ -0,0 +1,6 @@
: Build quickly without cleaning or testing
if "%jarfile%" == "" (
call setvars.bat
)
mvn install -f "%pomfile%" -Dmaven.test.skip

View File

@ -0,0 +1,9 @@
: Start the Minecraft server
if "%jarfile%" == "" (
call setvars.bat
)
cd "%server%"
call java -Xmx1024M -Xms1024M -jar spigot_server.jar
cd "%batdir%"
dir /B *.bat

View File

@ -0,0 +1,14 @@
: The folder in which these .bat files are located
SET batdir=C:\your\path\AUTHME_DEV\bathelpers\
: The location of the generated JAR file
SET jarfile=C:\Users\yourname\IdeaProjects\AuthMeReloaded\target\AuthMe-5.1-SNAPSHOT.jar
: The location of the pom.xml file of the project
SET pomfile=C:\Users\yourname\IdeaProjects\AuthMeReloaded\pom.xml
: The folder in which the server is located
SET server=C:\your\path\AUTHME_DEV\spigot-server\
: The location of the plugins folder of the Minecraft server
SET plugins=%server%\plugins

View File

@ -0,0 +1,43 @@
<!-- AUTO-GENERATED FILE! Do not edit this directly -->
<!-- File auto-generated on Sat Dec 05 21:18:25 CET 2015. See permissions/permission_nodes.tpl.md -->
## AuthMe Permission Nodes
The following are the permission nodes that are currently supported by the latest dev builds.
- **authme.admin.*** Give access to all admin commands.
- **authme.admin.accounts** Administrator command to see all accounts associated with a user.
- **authme.admin.changemail** Administrator command to set or change the email address of a user.
- **authme.admin.changepassword** Administrator command to change the password of a user.
- **authme.admin.converter** Administrator command to convert old or other data to AuthMe data.
- **authme.admin.firstspawn** Administrator command to teleport to the first AuthMe spawn.
- **authme.admin.forcelogin** Administrator command to force-login an existing user.
- **authme.admin.getemail** Administrator command to get the email address of a user, if set.
- **authme.admin.getip** Administrator command to get the last known IP of a user.
- **authme.admin.lastlogin** Administrator command to see the last login date and time of a user.
- **authme.admin.purge** Administrator command to purge old user data.
- **authme.admin.purgebannedplayers** Administrator command to purge all data associated with banned players.
- **authme.admin.purgelastpos** Administrator command to purge the last position of a user.
- **authme.admin.register** Administrator command to register a new user.
- **authme.admin.reload** Administrator command to reload the plugin configuration.
- **authme.admin.setfirstspawn** Administrator command to set the first AuthMe spawn.
- **authme.admin.setspawn** Administrator command to set the AuthMe spawn.
- **authme.admin.spawn** Administrator command to teleport to the AuthMe spawn.
- **authme.admin.switchantibot** Administrator command to toggle the AntiBot protection status.
- **authme.admin.unregister** Administrator command to unregister an existing user.
- **authme.player.*** Permission to use all player (non-admin) commands.
- **authme.player.allow2accounts** Permission for users to allow two accounts.
- **authme.player.bypassantibot** Permission node to bypass AntiBot protection.
- **authme.player.bypassforcesurvival** Permission for users to bypass force-survival mode.
- **authme.player.canbeforced** Permission for users a login can be forced to.
- **authme.player.captcha** Command permission to use captcha.
- **authme.player.changepassword** Command permission to change the password.
- **authme.player.email.add** Command permission to add an email address.
- **authme.player.email.change** Command permission to change the email address.
- **authme.player.email.recover** Command permission to recover an account using it's email address.
- **authme.player.login** Command permission to login.
- **authme.player.logout** Command permission to logout.
- **authme.player.register** Command permission to register.
- **authme.player.seeotheraccounts** Permission for user to see other accounts.
- **authme.player.unregister** Command permission to unregister.
- **authme.player.vip** Permission node to identify VIP users.

View File

@ -0,0 +1,113 @@
package permissions;
import fr.xephi.authme.permission.AdminPermission;
import fr.xephi.authme.permission.PermissionNode;
import fr.xephi.authme.permission.PlayerPermission;
import fr.xephi.authme.util.StringUtils;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Gatherer to generate up-to-date lists of the AuthMe permission nodes.
*/
public class PermissionNodesGatherer {
/** The folder in which the implementations of {@link PermissionNode} reside. */
private static final String PERMISSION_NODE_SOURCE_FOLDER =
"src/main/java/fr/xephi/authme/permission/";
/**
* Regular expression that should match the JavaDoc comment above an enum, <i>including</i>
* the name of the enum value. The first group (i.e. {@code \\1}) should be the JavaDoc description;
* the second group should contain the enum value.
*/
private static final Pattern JAVADOC_WITH_ENUM_PATTERN = Pattern.compile(
"/\\*\\*\\s+\\*" // Match starting '/**' and the '*' on the next line
+ "(.*?)\\s+\\*/" // Capture everything until we encounter '*/'
+ "\\s+([A-Z_]+)\\("); // Match the enum name (e.g. 'LOGIN'), until before the first '('
/**
* Return a sorted collection of all permission nodes.
*
* @return AuthMe permission nodes sorted alphabetically
*/
public Set<String> gatherNodes() {
Set<String> nodes = new TreeSet<>();
for (PermissionNode perm : PlayerPermission.values()) {
nodes.add(perm.getNode());
}
for (PermissionNode perm : AdminPermission.values()) {
nodes.add(perm.getNode());
}
return nodes;
}
/**
* Return a sorted collection of all permission nodes, including its JavaDoc description.
*
* @return Ordered map whose keys are the permission nodes and the values the associated JavaDoc
*/
public Map<String, String> gatherNodesWithJavaDoc() {
Map<String, String> result = new TreeMap<>();
addDescriptionsForClass(PlayerPermission.class, result);
addDescriptionsForClass(AdminPermission.class, result);
return result;
}
private <T extends Enum<T> & PermissionNode> void addDescriptionsForClass(Class<T> clazz,
Map<String, String> descriptions) {
String classSource = getSourceForClass(clazz);
Map<String, String> sourceDescriptions = extractJavaDocFromSource(classSource);
for (T perm : EnumSet.allOf(clazz)) {
String description = sourceDescriptions.get(perm.name());
if (description == null) {
System.out.println("Note: Could not retrieve description for "
+ clazz.getSimpleName() + "#" + perm.name());
description = "";
}
descriptions.put(perm.getNode(), description.trim());
}
}
private static Map<String, String> extractJavaDocFromSource(String source) {
Map<String, String> allMatches = new HashMap<>();
Matcher matcher = JAVADOC_WITH_ENUM_PATTERN.matcher(source);
while (matcher.find()) {
String description = matcher.group(1);
String enumValue = matcher.group(2);
allMatches.put(enumValue, description);
}
return allMatches;
}
/**
* Return the Java source code for the given implementation of {@link PermissionNode}.
*
* @param clazz The clazz to the get the source for
* @param <T> The concrete class
* @return Source code of the file
*/
private static <T extends Enum<T> & PermissionNode> String getSourceForClass(Class<T> clazz) {
String classFile = PERMISSION_NODE_SOURCE_FOLDER + clazz.getSimpleName() + ".java";
Charset cs = Charset.forName("utf-8");
try {
return StringUtils.join("\n",
Files.readAllLines(Paths.get(classFile), cs));
} catch (IOException e) {
throw new RuntimeException("Failed to get the source for class '" + clazz.getSimpleName() + "'");
}
}
}

View File

@ -0,0 +1,86 @@
package permissions;
import utils.ANewMap;
import utils.GeneratedFileWriter;
import utils.TagReplacer;
import utils.ToolsConstants;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
/**
* Class responsible for formatting a permissions node list and
* for writing it to a file if desired.
*/
public class PermissionsListWriter {
private static final String PERMISSIONS_OUTPUT_FILE = ToolsConstants.DOCS_FOLDER + "permission_nodes.md";
public static void main(String[] args) {
// Ask if result should be written to file
Scanner scanner = new Scanner(System.in);
System.out.println("Include description? [Enter 'n' for no]");
boolean includeDescription = !matches("n", scanner);
if (!includeDescription) {
outputSimpleList();
return;
}
System.out.println("Write to file? [Enter 'n' for console output]");
boolean writeToFile = !matches("n", scanner);
scanner.close();
if (writeToFile) {
generateAndWriteFile();
} else {
System.out.println(generatePermissionsList());
}
}
private static void generateAndWriteFile() {
final String permissionsTagValue = generatePermissionsList();
Map<String, Object> tags = ANewMap.<String, Object>with("permissions", permissionsTagValue).build();
GeneratedFileWriter.generateFileFromTemplate(
ToolsConstants.TOOLS_SOURCE_ROOT + "permissions/permission_nodes.tpl.md", PERMISSIONS_OUTPUT_FILE, tags);
System.out.println("Wrote to '" + PERMISSIONS_OUTPUT_FILE + "'");
System.out.println("Before committing, please verify the output!");
}
private static String generatePermissionsList() {
PermissionNodesGatherer gatherer = new PermissionNodesGatherer();
Map<String, String> permissions = gatherer.gatherNodesWithJavaDoc();
final String template = GeneratedFileWriter.readFromToolsFile("permissions/permission_node_entry.tpl.md");
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, String> entry : permissions.entrySet()) {
Map<String, Object> tags = ANewMap.<String, Object>
with("node", entry.getKey())
.and("description", entry.getValue())
.build();
sb.append(TagReplacer.applyReplacements(template, tags));
}
return sb.toString();
}
private static void outputSimpleList() {
PermissionNodesGatherer gatherer = new PermissionNodesGatherer();
Set<String> nodes = gatherer.gatherNodes();
for (String node : nodes) {
System.out.println(node);
}
System.out.println();
System.out.println("Total: " + nodes.size());
}
private static boolean matches(String answer, Scanner sc) {
String userInput = sc.nextLine();
return answer.equalsIgnoreCase(userInput);
}
}

View File

@ -0,0 +1,2 @@
# About
Helper script to generate a page with an up-to-date list of permission nodes.

View File

@ -0,0 +1 @@
- **{node}** {description}

View File

@ -0,0 +1,7 @@
<!-- {gen_warning} -->
<!-- File auto-generated on {gen_date}. See permissions/permission_nodes.tpl.md -->
## AuthMe Permission Nodes
The following are the permission nodes that are currently supported by the latest dev builds.
{permissions}

View File

@ -0,0 +1,36 @@
package utils;
import java.util.HashMap;
import java.util.Map;
/**
* A map builder for the lazy.
* <p />
* Sample usage:
* <code>
* Map&lt;String, Integer> map = ANewMap
* .with("test", 123)
* .and("text", 938)
* .and("abc", 456)
* .build();
* </code>
*/
public class ANewMap<K, V> {
private Map<K, V> map = new HashMap<>();
public static <K, V> ANewMap<K, V> with(K key, V value) {
ANewMap<K, V> instance = new ANewMap<>();
return instance.and(key, value);
}
public ANewMap<K, V> and(K key, V value) {
map.put(key, value);
return this;
}
public Map<K, V> build() {
return map;
}
}

View File

@ -0,0 +1,47 @@
package utils;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Map;
/**
* Utility class for writing a generated file with a timestamp.
*/
public final class GeneratedFileWriter {
private final static Charset CHARSET = Charset.forName("utf-8");
private GeneratedFileWriter() {
}
public static void generateFileFromTemplate(String templateFile, String destinationFile, Map<String, Object> tags) {
String template = readFromFile(templateFile);
String result = TagReplacer.applyReplacements(template, tags);
writeToFile(destinationFile, result);
}
private static void writeToFile(String outputFile, String contents) {
try {
Files.write(Paths.get(outputFile), contents.getBytes());
} catch (IOException e) {
throw new RuntimeException("Failed to write to file '" + outputFile + "'", e);
}
}
public static String readFromFile(String file) {
try {
return new String(Files.readAllBytes(Paths.get(file)), CHARSET);
} catch (IOException e) {
throw new RuntimeException("Could not read from file '" + file + "'", e);
}
}
public static String readFromToolsFile(String file) {
return readFromFile(ToolsConstants.TOOLS_SOURCE_ROOT + file);
}
}

View File

@ -0,0 +1,46 @@
package utils;
import java.util.Date;
import java.util.Map;
/**
* Class responsible for replacing template tags to actual content.
* For all files, the following tags are defined:
* <ul>
* <li>{gen_date} the generation date</li>
* <li>{gen_warning} - warning not to edit the generated file directly</li>
* </ul>
*/
public class TagReplacer {
/**
* Replace a template with default tags and custom ones supplied by a map.
*
* @param template The template to process
* @param tags Map with additional tags, e.g. a map entry with key "foo" and value "bar" will replace
* any occurrences of "{foo}" to "bar".
* @return The filled template
*/
public static String applyReplacements(String template, Map<String, Object> tags) {
String result = template;
for (Map.Entry<String, Object> tagRule : tags.entrySet()) {
result = result.replace("{" + tagRule.getKey() + "}", tagRule.getValue().toString());
}
return applyReplacements(result);
}
/**
* Apply the default tag replacements.
*
* @param template The template to process
* @return The filled template
*/
public static String applyReplacements(String template) {
return template
.replace("{gen_date}", new Date().toString())
.replace("{gen_warning}", "AUTO-GENERATED FILE! Do not edit this directly");
}
}

View File

@ -0,0 +1,17 @@
package utils;
/**
* Constants for the src/tools folder.
*/
public final class ToolsConstants {
private ToolsConstants() {
}
public static final String MAIN_SOURCE_ROOT = "src/main/java/";
public static final String TOOLS_SOURCE_ROOT = "src/tools/";
public static final String DOCS_FOLDER = TOOLS_SOURCE_ROOT + "docs/";
}