Merge branch 'master' of https://github.com/AuthMe-Team/AuthMeReloaded into antibot-improvement

Conflicts:
	src/main/java/fr/xephi/authme/service/AntiBotService.java
This commit is contained in:
ljacqu
2016-10-30 08:56:16 +01:00
73 changed files with 2075 additions and 1163 deletions
@@ -199,6 +199,9 @@ public class AuthMe extends JavaPlugin {
ConsoleLogger.setLogger(getLogger());
ConsoleLogger.setLogFile(new File(getDataFolder(), LOG_FILENAME));
// Create plugin folder
getDataFolder().mkdir();
// Load settings and set up the console and console filter
settings = Initializer.createSettings(this);
bukkitService = new BukkitService(this, settings);
@@ -56,16 +56,10 @@ public class CommandDescription {
private PermissionNode permission;
/**
* Private constructor. Use {@link CommandDescription#builder()} to create instances of this class.
* Private constructor.
* <p>
* Note for developers: Instances should be created with {@link CommandDescription#createInstance} to be properly
* Note for developers: Instances should be created with {@link CommandBuilder#register()} to be properly
* registered in the command tree.
*/
private CommandDescription() {
}
/**
* Create an instance.
*
* @param labels command labels
* @param description description of the command
@@ -74,30 +68,17 @@ public class CommandDescription {
* @param parent parent command
* @param arguments command arguments
* @param permission permission node required to execute this command
*
* @return the created instance
* @see CommandDescription#builder()
*/
private static CommandDescription createInstance(List<String> labels, String description,
String detailedDescription, Class<? extends ExecutableCommand> executableCommand, CommandDescription parent,
List<CommandArgumentDescription> arguments, PermissionNode permission) {
CommandDescription instance = new CommandDescription();
instance.labels = labels;
instance.description = description;
instance.detailedDescription = detailedDescription;
instance.executableCommand = executableCommand;
instance.parent = parent;
instance.arguments = arguments;
instance.permission = permission;
if (parent != null) {
parent.addChild(instance);
}
return instance;
}
private void addChild(CommandDescription command) {
children.add(command);
private CommandDescription(List<String> labels, String description, String detailedDescription,
Class<? extends ExecutableCommand> executableCommand, CommandDescription parent,
List<CommandArgumentDescription> arguments, PermissionNode permission) {
this.labels = labels;
this.description = description;
this.detailedDescription = detailedDescription;
this.executableCommand = executableCommand;
this.parent = parent;
this.arguments = arguments;
this.permission = permission;
}
/**
@@ -224,8 +205,21 @@ public class CommandDescription {
private PermissionNode permission;
/**
* Build a CommandDescription from the builder or throw an exception if a mandatory
* field has not been set.
* Build a CommandDescription and register it onto the parent if available.
*
* @return The generated CommandDescription object
*/
public CommandDescription register() {
CommandDescription command = build();
if (command.parent != null) {
command.parent.children.add(command);
}
return command;
}
/**
* Build a CommandDescription (without registering it on the parent).
*
* @return The generated CommandDescription object
*/
@@ -236,8 +230,8 @@ public class CommandDescription {
checkArgument(executableCommand != null, "Executable command must be set");
// parents and permissions may be null; arguments may be empty
return createInstance(labels, description, detailedDescription, executableCommand,
parent, arguments, permission);
return new CommandDescription(labels, description, detailedDescription, executableCommand,
parent, arguments, permission);
}
public CommandBuilder labels(List<String> labels) {
@@ -1,6 +1,6 @@
package fr.xephi.authme.command;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableList;
import fr.xephi.authme.command.executable.HelpCommand;
import fr.xephi.authme.command.executable.authme.AccountsCommand;
import fr.xephi.authme.command.executable.authme.AuthMeCommand;
@@ -11,6 +11,7 @@ import fr.xephi.authme.command.executable.authme.ForceLoginCommand;
import fr.xephi.authme.command.executable.authme.GetEmailCommand;
import fr.xephi.authme.command.executable.authme.GetIpCommand;
import fr.xephi.authme.command.executable.authme.LastLoginCommand;
import fr.xephi.authme.command.executable.authme.MessagesCommand;
import fr.xephi.authme.command.executable.authme.PurgeBannedPlayersCommand;
import fr.xephi.authme.command.executable.authme.PurgeCommand;
import fr.xephi.authme.command.executable.authme.PurgeLastPositionCommand;
@@ -40,14 +41,13 @@ import fr.xephi.authme.permission.PlayerPermission;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Set;
/**
* Initializes all available AuthMe commands.
*/
public class CommandInitializer {
private Set<CommandDescription> commands;
private List<CommandDescription> commands;
public CommandInitializer() {
buildCommands();
@@ -58,7 +58,7 @@ public class CommandInitializer {
*
* @return the command descriptions
*/
public Set<CommandDescription> getCommands() {
public List<CommandDescription> getCommands() {
return commands;
}
@@ -66,10 +66,10 @@ public class CommandInitializer {
// Register the base AuthMe Reloaded command
final CommandDescription AUTHME_BASE = CommandDescription.builder()
.labels("authme")
.description("Main command")
.description("AuthMe op commands")
.detailedDescription("The main AuthMeReloaded command. The root for all admin commands.")
.executableCommand(AuthMeCommand.class)
.build();
.register();
// Register the register command
CommandDescription.builder()
@@ -81,7 +81,7 @@ public class CommandInitializer {
.withArgument("password", "Password", false)
.permission(AdminPermission.REGISTER)
.executableCommand(RegisterAdminCommand.class)
.build();
.register();
// Register the unregister command
CommandDescription.builder()
@@ -92,7 +92,7 @@ public class CommandInitializer {
.withArgument("player", "Player name", false)
.permission(AdminPermission.UNREGISTER)
.executableCommand(UnregisterAdminCommand.class)
.build();
.register();
// Register the forcelogin command
CommandDescription.builder()
@@ -103,7 +103,7 @@ public class CommandInitializer {
.withArgument("player", "Online player name", true)
.permission(AdminPermission.FORCE_LOGIN)
.executableCommand(ForceLoginCommand.class)
.build();
.register();
// Register the changepassword command
CommandDescription.builder()
@@ -115,7 +115,7 @@ public class CommandInitializer {
.withArgument("pwd", "New password", false)
.permission(AdminPermission.CHANGE_PASSWORD)
.executableCommand(ChangePasswordAdminCommand.class)
.build();
.register();
// Register the last login command
CommandDescription.builder()
@@ -126,7 +126,7 @@ public class CommandInitializer {
.withArgument("player", "Player name", true)
.permission(AdminPermission.LAST_LOGIN)
.executableCommand(LastLoginCommand.class)
.build();
.register();
// Register the accounts command
CommandDescription.builder()
@@ -137,7 +137,7 @@ public class CommandInitializer {
.withArgument("player", "Player name or IP", true)
.permission(AdminPermission.ACCOUNTS)
.executableCommand(AccountsCommand.class)
.build();
.register();
// Register the getemail command
CommandDescription.builder()
@@ -148,7 +148,7 @@ public class CommandInitializer {
.withArgument("player", "Player name", true)
.permission(AdminPermission.GET_EMAIL)
.executableCommand(GetEmailCommand.class)
.build();
.register();
// Register the setemail command
CommandDescription.builder()
@@ -160,7 +160,7 @@ public class CommandInitializer {
.withArgument("email", "Player email", false)
.permission(AdminPermission.CHANGE_EMAIL)
.executableCommand(SetEmailCommand.class)
.build();
.register();
// Register the getip command
CommandDescription.builder()
@@ -171,7 +171,7 @@ public class CommandInitializer {
.withArgument("player", "Player name", false)
.permission(AdminPermission.GET_IP)
.executableCommand(GetIpCommand.class)
.build();
.register();
// Register the spawn command
CommandDescription.builder()
@@ -181,7 +181,7 @@ public class CommandInitializer {
.detailedDescription("Teleport to the spawn.")
.permission(AdminPermission.SPAWN)
.executableCommand(SpawnCommand.class)
.build();
.register();
// Register the setspawn command
CommandDescription.builder()
@@ -191,7 +191,7 @@ public class CommandInitializer {
.detailedDescription("Change the player's spawn to your current position.")
.permission(AdminPermission.SET_SPAWN)
.executableCommand(SetSpawnCommand.class)
.build();
.register();
// Register the firstspawn command
CommandDescription.builder()
@@ -201,7 +201,7 @@ public class CommandInitializer {
.detailedDescription("Teleport to the first spawn.")
.permission(AdminPermission.FIRST_SPAWN)
.executableCommand(FirstSpawnCommand.class)
.build();
.register();
// Register the setfirstspawn command
CommandDescription.builder()
@@ -211,7 +211,7 @@ public class CommandInitializer {
.detailedDescription("Change the first player's spawn to your current position.")
.permission(AdminPermission.SET_FIRST_SPAWN)
.executableCommand(SetFirstSpawnCommand.class)
.build();
.register();
// Register the purge command
CommandDescription.builder()
@@ -223,7 +223,7 @@ public class CommandInitializer {
.withArgument("all", "Add 'all' at the end to also purge players with lastlogin = 0", true)
.permission(AdminPermission.PURGE)
.executableCommand(PurgeCommand.class)
.build();
.register();
// Register the purgelastposition command
CommandDescription.builder()
@@ -235,7 +235,7 @@ public class CommandInitializer {
.withArgument("player/*", "Player name or * for all players", false)
.permission(AdminPermission.PURGE_LAST_POSITION)
.executableCommand(PurgeLastPositionCommand.class)
.build();
.register();
// Register the purgebannedplayers command
CommandDescription.builder()
@@ -245,7 +245,7 @@ public class CommandInitializer {
.detailedDescription("Purge all AuthMeReloaded data for banned players.")
.permission(AdminPermission.PURGE_BANNED_PLAYERS)
.executableCommand(PurgeBannedPlayersCommand.class)
.build();
.register();
// Register the switchantibot command
CommandDescription.builder()
@@ -256,7 +256,7 @@ public class CommandInitializer {
.withArgument("mode", "ON / OFF", true)
.permission(AdminPermission.SWITCH_ANTIBOT)
.executableCommand(SwitchAntiBotCommand.class)
.build();
.register();
// Register the reload command
CommandDescription.builder()
@@ -266,7 +266,7 @@ public class CommandInitializer {
.detailedDescription("Reload the AuthMeReloaded plugin.")
.permission(AdminPermission.RELOAD)
.executableCommand(ReloadCommand.class)
.build();
.register();
// Register the version command
CommandDescription.builder()
@@ -276,7 +276,7 @@ public class CommandInitializer {
.detailedDescription("Show detailed information about the installed AuthMeReloaded version, the "
+ "developers, contributors, and license.")
.executableCommand(VersionCommand.class)
.build();
.register();
CommandDescription.builder()
.parent(AUTHME_BASE)
@@ -287,7 +287,16 @@ public class CommandInitializer {
"royalauth / vauth / sqliteToSql / mysqlToSqlite", false)
.permission(AdminPermission.CONVERTER)
.executableCommand(ConverterCommand.class)
.build();
.register();
CommandDescription.builder()
.parent(AUTHME_BASE)
.labels("messages", "msg")
.description("Add missing messages")
.detailedDescription("Adds missing messages to the current messages file.")
.permission(AdminPermission.UPDATE_MESSAGES)
.executableCommand(MessagesCommand.class)
.register();
// Register the base login command
final CommandDescription LOGIN_BASE = CommandDescription.builder()
@@ -298,7 +307,7 @@ public class CommandInitializer {
.withArgument("password", "Login password", false)
.permission(PlayerPermission.LOGIN)
.executableCommand(LoginCommand.class)
.build();
.register();
// Register the base logout command
CommandDescription LOGOUT_BASE = CommandDescription.builder()
@@ -308,51 +317,51 @@ public class CommandInitializer {
.detailedDescription("Command to logout using AuthMeReloaded.")
.permission(PlayerPermission.LOGOUT)
.executableCommand(LogoutCommand.class)
.build();
.register();
// Register the base register command
final CommandDescription REGISTER_BASE = CommandDescription.builder()
.parent(null)
.labels("register", "reg")
.description("Registration command")
.description("Register an account")
.detailedDescription("Command to register using AuthMeReloaded.")
.withArgument("password", "Password", true)
.withArgument("verifyPassword", "Verify password", true)
.permission(PlayerPermission.REGISTER)
.executableCommand(RegisterCommand.class)
.build();
.register();
// Register the base unregister command
CommandDescription UNREGISTER_BASE = CommandDescription.builder()
.parent(null)
.labels("unregister", "unreg")
.description("Unregistration Command")
.description("Unregister an account")
.detailedDescription("Command to unregister using AuthMeReloaded.")
.withArgument("password", "Password", false)
.permission(PlayerPermission.UNREGISTER)
.executableCommand(UnregisterCommand.class)
.build();
.register();
// Register the base changepassword command
final CommandDescription CHANGE_PASSWORD_BASE = CommandDescription.builder()
.parent(null)
.labels("changepassword", "changepass", "cp")
.description("Change password Command")
.description("Change password of an account")
.detailedDescription("Command to change your password using AuthMeReloaded.")
.withArgument("oldPassword", "Old Password", false)
.withArgument("newPassword", "New Password.", false)
.withArgument("oldPassword", "Old password", false)
.withArgument("newPassword", "New password", false)
.permission(PlayerPermission.CHANGE_PASSWORD)
.executableCommand(ChangePasswordCommand.class)
.build();
.register();
// Register the base Email command
CommandDescription EMAIL_BASE = CommandDescription.builder()
.parent(null)
.labels("email")
.description("Email command")
.detailedDescription("The AuthMeReloaded Email command base.")
.description("Add email or recover password")
.detailedDescription("The AuthMeReloaded email command base.")
.executableCommand(EmailBaseCommand.class)
.build();
.register();
// Register the show command
CommandDescription.builder()
@@ -361,7 +370,7 @@ public class CommandInitializer {
.description("Show Email")
.detailedDescription("Show your current email address.")
.executableCommand(ShowEmailCommand.class)
.build();
.register();
// Register the add command
CommandDescription.builder()
@@ -373,7 +382,7 @@ public class CommandInitializer {
.withArgument("verifyEmail", "Email address verification", false)
.permission(PlayerPermission.ADD_EMAIL)
.executableCommand(AddEmailCommand.class)
.build();
.register();
// Register the change command
CommandDescription.builder()
@@ -385,20 +394,20 @@ public class CommandInitializer {
.withArgument("newEmail", "New email address", false)
.permission(PlayerPermission.CHANGE_EMAIL)
.executableCommand(ChangeEmailCommand.class)
.build();
.register();
// Register the recover command
CommandDescription.builder()
.parent(EMAIL_BASE)
.labels("recover", "recovery", "recoveremail", "recovermail")
.description("Recover password using Email")
.description("Recover password using email")
.detailedDescription("Recover your account using an Email address by sending a mail containing " +
"a new password.")
.withArgument("email", "Email address", false)
.withArgument("code", "Recovery code", true)
.permission(PlayerPermission.RECOVER_EMAIL)
.executableCommand(RecoverEmailCommand.class)
.build();
.register();
// Register the base captcha command
CommandDescription CAPTCHA_BASE = CommandDescription.builder()
@@ -409,9 +418,9 @@ public class CommandInitializer {
.withArgument("captcha", "The Captcha", false)
.permission(PlayerPermission.CAPTCHA)
.executableCommand(CaptchaCommand.class)
.build();
.register();
Set<CommandDescription> baseCommands = ImmutableSet.of(
List<CommandDescription> baseCommands = ImmutableList.of(
AUTHME_BASE,
LOGIN_BASE,
LOGOUT_BASE,
@@ -441,7 +450,7 @@ public class CommandInitializer {
.detailedDescription("View detailed help for /" + base.getLabels().get(0) + " commands.")
.withArgument("query", "The command or query to view help for.", true)
.executableCommand(HelpCommand.class)
.build();
.register();
}
}
}
@@ -8,6 +8,7 @@ import org.bukkit.command.CommandSender;
import javax.inject.Inject;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -26,7 +27,7 @@ public class CommandMapper {
*/
private static final Class<? extends ExecutableCommand> HELP_COMMAND_CLASS = HelpCommand.class;
private final Set<CommandDescription> baseCommands;
private final Collection<CommandDescription> baseCommands;
private final PermissionsManager permissionsManager;
@Inject
@@ -1,9 +1,11 @@
package fr.xephi.authme.command;
import com.google.common.collect.Lists;
import org.bukkit.ChatColor;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public final class CommandUtils {
@@ -34,6 +36,14 @@ public final class CommandUtils {
return sb.toString();
}
/**
* Constructs a hierarchical list of commands for the given command. The commands are in order:
* the parents of the given command precede the provided command. For example, given the command
* for {@code /authme register}, a list with {@code [{authme}, {authme register}]} is returned.
*
* @param command the command to build a parent list for
* @return the parent list
*/
public static List<CommandDescription> constructParentList(CommandDescription command) {
List<CommandDescription> commands = new ArrayList<>();
CommandDescription currentCommand = command;
@@ -43,4 +53,35 @@ public final class CommandUtils {
}
return Lists.reverse(commands);
}
public static String buildSyntax(CommandDescription command) {
String arguments = command.getArguments().stream()
.map(arg -> formatArgument(arg))
.collect(Collectors.joining(" "));
return (constructCommandPath(command) + " " + arguments).trim();
}
public static String buildSyntax(CommandDescription command, List<String> correctLabels) {
String commandSyntax = ChatColor.WHITE + "/" + correctLabels.get(0) + ChatColor.YELLOW;
for (int i = 1; i < correctLabels.size(); ++i) {
commandSyntax += " " + correctLabels.get(i);
}
for (CommandArgumentDescription argument : command.getArguments()) {
commandSyntax += " " + formatArgument(argument);
}
return commandSyntax;
}
/**
* Format a command argument with the proper type of brackets.
*
* @param argument the argument to format
* @return the formatted argument
*/
public static String formatArgument(CommandArgumentDescription argument) {
if (argument.isOptional()) {
return "[" + argument.getName() + "]";
}
return "<" + argument.getName() + ">";
}
}
@@ -14,6 +14,11 @@ import java.util.List;
import static fr.xephi.authme.command.FoundResultStatus.MISSING_BASE_COMMAND;
import static fr.xephi.authme.command.FoundResultStatus.UNKNOWN_LABEL;
import static fr.xephi.authme.command.help.HelpProvider.ALL_OPTIONS;
import static fr.xephi.authme.command.help.HelpProvider.SHOW_ALTERNATIVES;
import static fr.xephi.authme.command.help.HelpProvider.SHOW_CHILDREN;
import static fr.xephi.authme.command.help.HelpProvider.SHOW_COMMAND;
import static fr.xephi.authme.command.help.HelpProvider.SHOW_DESCRIPTION;
public class HelpCommand implements ExecutableCommand {
@@ -46,9 +51,9 @@ public class HelpCommand implements ExecutableCommand {
int mappedCommandLevel = result.getCommandDescription().getLabelCount();
if (mappedCommandLevel == 1) {
helpProvider.outputHelp(sender, result, HelpProvider.SHOW_CHILDREN);
helpProvider.outputHelp(sender, result, SHOW_COMMAND | SHOW_DESCRIPTION | SHOW_CHILDREN | SHOW_ALTERNATIVES);
} else {
helpProvider.outputHelp(sender, result, HelpProvider.ALL_OPTIONS);
helpProvider.outputHelp(sender, result, ALL_OPTIONS);
}
}
@@ -0,0 +1,54 @@
package fr.xephi.authme.command.executable.authme;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.command.ExecutableCommand;
import fr.xephi.authme.initialization.DataFolder;
import fr.xephi.authme.message.Messages;
import fr.xephi.authme.service.MessageUpdater;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.properties.PluginSettings;
import org.bukkit.command.CommandSender;
import javax.inject.Inject;
import java.io.File;
import java.util.List;
/**
* Messages command, updates the user's messages file with any missing files
* from the provided file in the JAR.
*/
public class MessagesCommand implements ExecutableCommand {
private static final String DEFAULT_LANGUAGE = "en";
@Inject
private Settings settings;
@Inject
@DataFolder
private File dataFolder;
@Inject
private Messages messages;
@Override
public void executeCommand(CommandSender sender, List<String> arguments) {
final String language = settings.getProperty(PluginSettings.MESSAGES_LANGUAGE);
try {
boolean isFileUpdated = new MessageUpdater(
new File(dataFolder, getMessagePath(language)),
getMessagePath(language),
getMessagePath(DEFAULT_LANGUAGE))
.executeCopy(sender);
if (isFileUpdated) {
messages.reload();
}
} catch (Exception e) {
sender.sendMessage("Could not update messages: " + e.getMessage());
ConsoleLogger.logException("Could not update messages:", e);
}
}
private static String getMessagePath(String code) {
return "messages/messages_" + code + ".yml";
}
}
@@ -1,36 +0,0 @@
package fr.xephi.authme.command.help;
import fr.xephi.authme.command.CommandArgumentDescription;
import fr.xephi.authme.command.CommandDescription;
import org.bukkit.ChatColor;
import java.util.List;
/**
* Helper class for displaying the syntax of a command properly to a user.
*/
final class CommandSyntaxHelper {
private CommandSyntaxHelper() {
}
public static String getSyntax(CommandDescription command, List<String> correctLabels) {
String commandSyntax = ChatColor.WHITE + "/" + correctLabels.get(0) + ChatColor.YELLOW;
for (int i = 1; i < correctLabels.size(); ++i) {
commandSyntax += " " + correctLabels.get(i);
}
for (CommandArgumentDescription argument : command.getArguments()) {
commandSyntax += " " + formatArgument(argument);
}
return commandSyntax;
}
/** Format a command argument with the proper type of brackets. */
private static String formatArgument(CommandArgumentDescription argument) {
if (argument.isOptional()) {
return "[" + argument.getName() + "]";
}
return "<" + argument.getName() + ">";
}
}
@@ -67,6 +67,10 @@ public class HelpMessagesService implements Reloadable {
return localCommand;
}
public String getDescription(CommandDescription command) {
return getText(getCommandPath(command) + DESCRIPTION_SUFFIX, command::getDescription);
}
public String getMessage(HelpMessage message) {
return messageFileHandler.getMessage(message.getKey());
}
@@ -15,11 +15,12 @@ import org.bukkit.command.CommandSender;
import javax.inject.Inject;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import static fr.xephi.authme.command.help.HelpSection.DETAILED_DESCRIPTION;
import static fr.xephi.authme.command.help.HelpSection.SHORT_DESCRIPTION;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
/**
@@ -79,7 +80,7 @@ public class HelpProvider implements Reloadable {
if (hasFlag(SHOW_COMMAND, options)) {
lines.add(ChatColor.GOLD + helpMessagesService.getMessage(HelpSection.COMMAND) + ": "
+ CommandSyntaxHelper.getSyntax(command, correctLabels));
+ CommandUtils.buildSyntax(command, correctLabels));
}
if (hasFlag(SHOW_DESCRIPTION, options)) {
lines.add(ChatColor.GOLD + helpMessagesService.getMessage(SHORT_DESCRIPTION) + ": "
@@ -171,19 +172,29 @@ public class HelpProvider implements Reloadable {
}
private void printAlternatives(CommandDescription command, List<String> correctLabels, List<String> lines) {
if (command.getLabels().size() <= 1 || correctLabels.size() <= 1) {
if (command.getLabels().size() <= 1) {
return;
}
lines.add(ChatColor.GOLD + helpMessagesService.getMessage(HelpSection.ALTERNATIVES) + ":");
// Get the label used
final String parentLabel = correctLabels.get(0);
final String childLabel = correctLabels.get(1);
// Label with which the command was called -> don't show it as an alternative
final String usedLabel;
// Takes alternative label and constructs list of labels, e.g. "reg" -> [authme, reg]
final Function<String, List<String>> commandLabelsFn;
if (correctLabels.size() == 1) {
usedLabel = correctLabels.get(0);
commandLabelsFn = label -> singletonList(label);
} else {
usedLabel = correctLabels.get(1);
commandLabelsFn = label -> Arrays.asList(correctLabels.get(0), label);
}
// Create a list of alternatives
for (String entry : command.getLabels()) {
if (!entry.equalsIgnoreCase(childLabel)) {
lines.add(" " + CommandSyntaxHelper.getSyntax(command, asList(parentLabel, entry)));
for (String label : command.getLabels()) {
if (!label.equalsIgnoreCase(usedLabel)) {
lines.add(" " + CommandUtils.buildSyntax(command, commandLabelsFn.apply(label)));
}
}
}
@@ -238,7 +249,7 @@ public class HelpProvider implements Reloadable {
String parentCommandPath = String.join(" ", parentLabels);
for (CommandDescription child : command.getChildren()) {
lines.add(" /" + parentCommandPath + " " + child.getLabels().get(0)
+ ChatColor.GRAY + ChatColor.ITALIC + ": " + child.getDescription());
+ ChatColor.GRAY + ChatColor.ITALIC + ": " + helpMessagesService.getDescription(child));
}
}
@@ -40,6 +40,7 @@ public class MySQL implements DataSource {
private String password;
private String database;
private String tableName;
private int poolSize;
private List<String> columnOthers;
private Columns col;
private HashAlgorithm hashAlgorithm;
@@ -98,6 +99,10 @@ public class MySQL implements DataSource {
this.phpBbPrefix = settings.getProperty(HooksSettings.PHPBB_TABLE_PREFIX);
this.phpBbGroup = settings.getProperty(HooksSettings.PHPBB_ACTIVATED_GROUP_ID);
this.wordpressPrefix = settings.getProperty(HooksSettings.WORDPRESS_TABLE_PREFIX);
this.poolSize = settings.getProperty(DatabaseSettings.MYSQL_POOL_SIZE);
if(poolSize == -1) {
poolSize = RuntimeUtils.getCoreCount();
}
}
private void setConnectionArguments() throws RuntimeException {
@@ -105,7 +110,7 @@ public class MySQL implements DataSource {
ds.setPoolName("AuthMeMYSQLPool");
// Pool size
ds.setMaximumPoolSize(RuntimeUtils.getCoreCount());
ds.setMaximumPoolSize(poolSize);
// Database URL
ds.setJdbcUrl("jdbc:mysql://" + this.host + ":" + this.port + "/" + this.database);
@@ -62,13 +62,13 @@ public class Initializer {
*/
public static Settings createSettings(AuthMe authMe) throws Exception {
File configFile = new File(authMe.getDataFolder(), "config.yml");
if (FileUtils.copyFileFromResource(configFile, "config.yml")) {
PropertyResource resource = new YamlFileResource(configFile);
SettingsMigrationService migrationService = new SettingsMigrationService(authMe.getDataFolder());
ConfigurationData configurationData = AuthMeSettingsRetriever.buildConfigurationData();
return new Settings(authMe.getDataFolder(), resource, migrationService, configurationData);
if(!configFile.exists()) {
configFile.createNewFile();
}
throw new Exception("Could not copy config.yml from JAR to plugin folder");
PropertyResource resource = new YamlFileResource(configFile);
SettingsMigrationService migrationService = new SettingsMigrationService(authMe.getDataFolder());
ConfigurationData configurationData = AuthMeSettingsRetriever.buildConfigurationData();
return new Settings(authMe.getDataFolder(), resource, migrationService, configurationData);
}
/**
@@ -8,126 +8,125 @@ public enum AdminPermission implements PermissionNode {
/**
* Administrator command to register a new user.
*/
REGISTER("authme.admin.register", DefaultPermission.OP_ONLY),
REGISTER("authme.admin.register"),
/**
* Administrator command to unregister an existing user.
*/
UNREGISTER("authme.admin.unregister", DefaultPermission.OP_ONLY),
UNREGISTER("authme.admin.unregister"),
/**
* Administrator command to force-login an existing user.
*/
FORCE_LOGIN("authme.admin.forcelogin", DefaultPermission.OP_ONLY),
FORCE_LOGIN("authme.admin.forcelogin"),
/**
* Administrator command to change the password of a user.
*/
CHANGE_PASSWORD("authme.admin.changepassword", DefaultPermission.OP_ONLY),
CHANGE_PASSWORD("authme.admin.changepassword"),
/**
* Administrator command to see the last login date and time of a user.
*/
LAST_LOGIN("authme.admin.lastlogin", DefaultPermission.OP_ONLY),
LAST_LOGIN("authme.admin.lastlogin"),
/**
* Administrator command to see all accounts associated with a user.
*/
ACCOUNTS("authme.admin.accounts", DefaultPermission.OP_ONLY),
ACCOUNTS("authme.admin.accounts"),
/**
* Administrator command to get the email address of a user, if set.
*/
GET_EMAIL("authme.admin.getemail", DefaultPermission.OP_ONLY),
GET_EMAIL("authme.admin.getemail"),
/**
* Administrator command to set or change the email address of a user.
*/
CHANGE_EMAIL("authme.admin.changemail", DefaultPermission.OP_ONLY),
CHANGE_EMAIL("authme.admin.changemail"),
/**
* Administrator command to get the last known IP of a user.
*/
GET_IP("authme.admin.getip", DefaultPermission.OP_ONLY),
GET_IP("authme.admin.getip"),
/**
* Administrator command to teleport to the AuthMe spawn.
*/
SPAWN("authme.admin.spawn", DefaultPermission.OP_ONLY),
SPAWN("authme.admin.spawn"),
/**
* Administrator command to set the AuthMe spawn.
*/
SET_SPAWN("authme.admin.setspawn", DefaultPermission.OP_ONLY),
SET_SPAWN("authme.admin.setspawn"),
/**
* Administrator command to teleport to the first AuthMe spawn.
*/
FIRST_SPAWN("authme.admin.firstspawn", DefaultPermission.OP_ONLY),
FIRST_SPAWN("authme.admin.firstspawn"),
/**
* Administrator command to set the first AuthMe spawn.
*/
SET_FIRST_SPAWN("authme.admin.setfirstspawn", DefaultPermission.OP_ONLY),
SET_FIRST_SPAWN("authme.admin.setfirstspawn"),
/**
* Administrator command to purge old user data.
*/
PURGE("authme.admin.purge", DefaultPermission.OP_ONLY),
PURGE("authme.admin.purge"),
/**
* Administrator command to purge the last position of a user.
*/
PURGE_LAST_POSITION("authme.admin.purgelastpos", DefaultPermission.OP_ONLY),
PURGE_LAST_POSITION("authme.admin.purgelastpos"),
/**
* Administrator command to purge all data associated with banned players.
*/
PURGE_BANNED_PLAYERS("authme.admin.purgebannedplayers", DefaultPermission.OP_ONLY),
PURGE_BANNED_PLAYERS("authme.admin.purgebannedplayers"),
/**
* Administrator command to toggle the AntiBot protection status.
*/
SWITCH_ANTIBOT("authme.admin.switchantibot", DefaultPermission.OP_ONLY),
SWITCH_ANTIBOT("authme.admin.switchantibot"),
/**
* Administrator command to convert old or other data to AuthMe data.
*/
CONVERTER("authme.admin.converter", DefaultPermission.OP_ONLY),
CONVERTER("authme.admin.converter"),
/**
* Administrator command to reload the plugin configuration.
*/
RELOAD("authme.admin.reload", DefaultPermission.OP_ONLY),
RELOAD("authme.admin.reload"),
/**
* Permission to see Antibot messages.
*/
ANTIBOT_MESSAGES("authme.admin.antibotmessages", DefaultPermission.OP_ONLY),
ANTIBOT_MESSAGES("authme.admin.antibotmessages"),
/**
* Permission to use the update messages command.
*/
UPDATE_MESSAGES("authme.admin.updatemessages"),
/**
* Permission to see the other accounts of the players that log in.
*/
SEE_OTHER_ACCOUNTS("authme.admin.seeotheraccounts", DefaultPermission.OP_ONLY);
SEE_OTHER_ACCOUNTS("authme.admin.seeotheraccounts");
/**
* The permission node.
*/
private String node;
/**
* The default permission level
*/
private DefaultPermission defaultPermission;
/**
* Constructor.
*
* @param node Permission node.
*/
AdminPermission(String node, DefaultPermission defaultPermission) {
AdminPermission(String node) {
this.node = node;
this.defaultPermission = defaultPermission;
}
@Override
@@ -137,6 +136,6 @@ public enum AdminPermission implements PermissionNode {
@Override
public DefaultPermission getDefaultPermission() {
return defaultPermission;
return DefaultPermission.OP_ONLY;
}
}
@@ -8,76 +8,70 @@ public enum PlayerPermission implements PermissionNode {
/**
* Command permission to login.
*/
LOGIN("authme.player.login", DefaultPermission.ALLOWED),
LOGIN("authme.player.login"),
/**
* Command permission to logout.
*/
LOGOUT("authme.player.logout", DefaultPermission.ALLOWED),
LOGOUT("authme.player.logout"),
/**
* Command permission to register.
*/
REGISTER("authme.player.register", DefaultPermission.ALLOWED),
REGISTER("authme.player.register"),
/**
* Command permission to unregister.
*/
UNREGISTER("authme.player.unregister", DefaultPermission.ALLOWED),
UNREGISTER("authme.player.unregister"),
/**
* Command permission to change the password.
*/
CHANGE_PASSWORD("authme.player.changepassword", DefaultPermission.ALLOWED),
CHANGE_PASSWORD("authme.player.changepassword"),
/**
* Command permission to add an email address.
*/
ADD_EMAIL("authme.player.email.add", DefaultPermission.ALLOWED),
ADD_EMAIL("authme.player.email.add"),
/**
* Command permission to change the email address.
*/
CHANGE_EMAIL("authme.player.email.change", DefaultPermission.ALLOWED),
CHANGE_EMAIL("authme.player.email.change"),
/**
* Command permission to recover an account using it's email address.
* Command permission to recover an account using its email address.
*/
RECOVER_EMAIL("authme.player.email.recover", DefaultPermission.ALLOWED),
RECOVER_EMAIL("authme.player.email.recover"),
/**
* Command permission to use captcha.
*/
CAPTCHA("authme.player.captcha", DefaultPermission.ALLOWED),
CAPTCHA("authme.player.captcha"),
/**
* Permission for users a login can be forced to.
*/
CAN_LOGIN_BE_FORCED("authme.player.canbeforced", DefaultPermission.ALLOWED),
CAN_LOGIN_BE_FORCED("authme.player.canbeforced"),
/**
* Permission to use to see own other accounts.
*/
SEE_OWN_ACCOUNTS("authme.player.seeownaccounts", DefaultPermission.ALLOWED);
SEE_OWN_ACCOUNTS("authme.player.seeownaccounts");
/**
* The permission node.
*/
private String node;
/**
* The default permission level
*/
private DefaultPermission defaultPermission;
/**
* Constructor.
*
* @param node Permission node.
*/
PlayerPermission(String node, DefaultPermission defaultPermission) {
PlayerPermission(String node) {
this.node = node;
this.defaultPermission = defaultPermission;
}
@Override
@@ -87,7 +81,7 @@ public enum PlayerPermission implements PermissionNode {
@Override
public DefaultPermission getDefaultPermission() {
return defaultPermission;
return DefaultPermission.ALLOWED;
}
}
@@ -17,7 +17,7 @@ public enum PlayerStatePermission implements PermissionNode {
BYPASS_FORCE_SURVIVAL("authme.bypassforcesurvival", DefaultPermission.OP_ONLY),
/**
* Permission node to identify VIP users.
* When the server is full and someone with this permission joins the server, someone will be kicked.
*/
IS_VIP("authme.vip", DefaultPermission.OP_ONLY),
@@ -27,7 +27,7 @@ public enum PlayerStatePermission implements PermissionNode {
ALLOW_MULTIPLE_ACCOUNTS("authme.allowmultipleaccounts", DefaultPermission.OP_ONLY),
/**
* Permission to bypass the purging process
* Permission to bypass the purging process.
*/
BYPASS_PURGE("authme.bypasspurge", DefaultPermission.NOT_ALLOWED);
@@ -44,7 +44,8 @@ public enum PlayerStatePermission implements PermissionNode {
/**
* Constructor.
*
* @param node Permission node.
* @param node Permission node
* @param defaultPermission The default permission
*/
PlayerStatePermission(String node, DefaultPermission defaultPermission) {
this.node = node;
@@ -0,0 +1,139 @@
package fr.xephi.authme.service;
import com.github.authme.configme.SettingsManager;
import com.github.authme.configme.knownproperties.ConfigurationData;
import com.github.authme.configme.properties.Property;
import com.github.authme.configme.properties.StringProperty;
import com.github.authme.configme.resource.YamlFileResource;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.message.MessageKey;
import fr.xephi.authme.util.FileUtils;
import fr.xephi.authme.util.StringUtils;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* Updates a user's messages file with messages from the JAR files.
*/
public class MessageUpdater {
private final FileConfiguration userConfiguration;
private final FileConfiguration localJarConfiguration;
private final FileConfiguration defaultJarConfiguration;
private final List<Property<String>> properties;
private final SettingsManager settingsManager;
private boolean hasMissingMessages = false;
/**
* Constructor.
*
* @param userFile messages file in the data folder
* @param localJarFile path to messages file in JAR in local language
* @param defaultJarFile path to messages file in JAR for default language
* @throws Exception if userFile does not exist or no JAR messages file can be loaded
*/
public MessageUpdater(File userFile, String localJarFile, String defaultJarFile) throws Exception {
if (!userFile.exists()) {
throw new Exception("Local messages file does not exist");
}
userConfiguration = YamlConfiguration.loadConfiguration(userFile);
localJarConfiguration = loadJarFileOrSendError(localJarFile);
defaultJarConfiguration = localJarFile.equals(defaultJarFile) ? null : loadJarFileOrSendError(defaultJarFile);
if (localJarConfiguration == null && defaultJarConfiguration == null) {
throw new Exception("Could not load any JAR messages file to copy from");
}
properties = buildPropertyEntriesForMessageKeys();
settingsManager = new SettingsManager(
new YamlFileResource(userFile), (r, p) -> true, new ConfigurationData((List) properties));
}
/**
* Copies missing messages to the messages file.
*
* @param sender sender starting the copy process
* @return true if the messages file was updated, false otherwise
* @throws Exception if an error occurs during saving
*/
public boolean executeCopy(CommandSender sender) throws Exception {
copyMissingMessages();
if (!hasMissingMessages) {
sender.sendMessage("No new messages to add");
return false;
}
// Save user configuration file
try {
settingsManager.save();
sender.sendMessage("Message file updated with new messages");
return true;
} catch (Exception e) {
throw new Exception("Could not save to messages file: " + StringUtils.formatException(e));
}
}
@SuppressWarnings("unchecked")
private void copyMissingMessages() {
for (Property<String> property : properties) {
String message = userConfiguration.getString(property.getPath());
if (message == null) {
hasMissingMessages = true;
message = getMessageFromJar(property.getPath());
}
settingsManager.setProperty(property, message);
}
}
private String getMessageFromJar(String key) {
String message = (localJarConfiguration == null ? null : localJarConfiguration.getString(key));
if (message != null) {
return message;
}
return (defaultJarConfiguration == null) ? null : defaultJarConfiguration.getString(key);
}
private static FileConfiguration loadJarFileOrSendError(String jarPath) {
try (InputStream stream = FileUtils.getResourceFromJar(jarPath)) {
if (stream == null) {
ConsoleLogger.info("Could not load '" + jarPath + "' from JAR");
return null;
}
InputStreamReader isr = new InputStreamReader(stream);
FileConfiguration configuration = YamlConfiguration.loadConfiguration(isr);
close(isr);
return configuration;
} catch (IOException e) {
ConsoleLogger.logException("Exception while handling JAR path '" + jarPath + "'", e);
}
return null;
}
private static List<Property<String>> buildPropertyEntriesForMessageKeys() {
return Arrays.stream(MessageKey.values())
.map(key -> new StringProperty(key.getKey(), ""))
.collect(Collectors.toList());
}
private static void close(Closeable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (IOException e) {
ConsoleLogger.info("Cannot close '" + closeable + "': " + StringUtils.formatException(e));
}
}
}
}
@@ -98,6 +98,10 @@ public class DatabaseSettings implements SettingsHolder {
public static final Property<String> MYSQL_COL_GROUP =
newProperty("ExternalBoardOptions.mySQLColumnGroup", "");
@Comment("Overrides the size of the DB Connection Pool, -1 = Auto")
public static final Property<Integer> MYSQL_POOL_SIZE =
newProperty("DataSource.poolSize", -1);
private DatabaseSettings() {
}
@@ -36,7 +36,10 @@ public class PluginSettings implements SettingsHolder {
public static final Property<Boolean> SESSIONS_EXPIRE_ON_IP_CHANGE =
newProperty("settings.sessions.sessionExpireOnIpChange", true);
@Comment("Message language, available: en, de, br, cz, pl, fr, ru, hu, sk, es, zhtw, fi, zhcn, lt, it, ko, pt")
@Comment({
"Message language, available languages:",
"https://github.com/AuthMe/AuthMeReloaded/blob/master/docs/translations.md"
})
public static final Property<String> MESSAGES_LANGUAGE =
newProperty("settings.messagesLanguage", "en");
@@ -65,8 +68,8 @@ public class PluginSettings implements SettingsHolder {
newProperty(LogLevel.class, "settings.logLevel", LogLevel.FINE);
@Comment({
"By default we schedule async tasks when talking to the database",
"If you want typical communication with the database to happen synchronously, set this to false"
"By default we schedule async tasks when talking to the database. If you want",
"typical communication with the database to happen synchronously, set this to false"
})
public static final Property<Boolean> USE_ASYNC_TASKS =
newProperty("settings.useAsyncTasks", true);
@@ -20,13 +20,16 @@ public class ProtectionSettings implements SettingsHolder {
public static final Property<Boolean> ENABLE_PROTECTION_REGISTERED =
newProperty("Protection.enableProtectionRegistered", true);
@Comment({"Countries allowed to join the server and register, see http://dev.bukkit.org/bukkit-plugins/authme-reloaded/pages/countries-codes/ for countries' codes",
"PLEASE USE QUOTES!"})
@Comment({
"Countries allowed to join the server and register. For country codes, see",
"http://dev.bukkit.org/bukkit-plugins/authme-reloaded/pages/countries-codes/",
"PLEASE USE QUOTES!"})
public static final Property<List<String>> COUNTRIES_WHITELIST =
newListProperty("Protection.countries", "US", "GB");
@Comment({"Countries not allowed to join the server and register",
"PLEASE USE QUOTES!"})
@Comment({
"Countries not allowed to join the server and register",
"PLEASE USE QUOTES!"})
public static final Property<List<String>> COUNTRIES_BLACKLIST =
newListProperty("Protection.countriesBlacklist", "A1");
@@ -34,7 +37,13 @@ public class ProtectionSettings implements SettingsHolder {
public static final Property<Boolean> ENABLE_ANTIBOT =
newProperty("Protection.enableAntiBot", true);
@Comment("Max number of players allowed to login in 5 secs before the AntiBot system is enabled automatically")
@Comment("The interval in seconds")
public static final Property<Integer> ANTIBOT_INTERVAL =
newProperty("Protection.antiBotInterval", 5);
@Comment({
"Max number of players allowed to login in the interval",
"before the AntiBot system is enabled automatically"})
public static final Property<Integer> ANTIBOT_SENSIBILITY =
newProperty("Protection.antiBotSensibility", 10);
@@ -12,7 +12,7 @@ public class PurgeSettings implements SettingsHolder {
public static final Property<Boolean> USE_AUTO_PURGE =
newProperty("Purge.useAutoPurge", false);
@Comment("Number of Days an account become Unused")
@Comment("Number of days after which an account should be purged")
public static final Property<Integer> DAYS_BEFORE_REMOVE_PLAYER =
newProperty("Purge.daysBeforeRemovePlayer", 60);
@@ -28,7 +28,7 @@ public class PurgeSettings implements SettingsHolder {
public static final Property<String> DEFAULT_WORLD =
newProperty("Purge.defaultWorld", "world");
@Comment("Do we need to remove LimitedCreative/inventories/player.yml, player_creative.yml files during purge process ?")
@Comment("Remove LimitedCreative/inventories/player.yml, player_creative.yml files during purge?")
public static final Property<Boolean> REMOVE_LIMITED_CREATIVE_INVENTORIES =
newProperty("Purge.removeLimitedCreativesInventories", false);
@@ -52,8 +52,9 @@ public class RegistrationSettings implements SettingsHolder {
public static final Property<List<String>> FORCE_COMMANDS =
newListProperty("settings.forceCommands");
@Comment("Force these commands after /login as service console, without any '/'. "
+ "Use %p to replace with player name")
@Comment({
"Force these commands after /login as service console, without any '/'.",
"Use %p to replace with player name"})
public static final Property<List<String>> FORCE_COMMANDS_AS_CONSOLE =
newListProperty("settings.forceCommandsAsConsole");
@@ -61,22 +62,25 @@ public class RegistrationSettings implements SettingsHolder {
public static final Property<List<String>> FORCE_REGISTER_COMMANDS =
newListProperty("settings.forceRegisterCommands");
@Comment("Force these commands after /register as a server console, without any '/'. "
+ "Use %p to replace with player name")
@Comment({
"Force these commands after /register as a server console, without any '/'.",
"Use %p to replace with player name"})
public static final Property<List<String>> FORCE_REGISTER_COMMANDS_AS_CONSOLE =
newListProperty("settings.forceRegisterCommandsAsConsole");
@Comment({
"Enable to display the welcome message (welcome.txt) after a login",
"You can use colors in this welcome.txt + some replaced strings:",
"{PLAYER}: player name, {ONLINE}: display number of online players, {MAXPLAYERS}: display server slots,",
"{IP}: player ip, {LOGINS}: number of players logged, {WORLD}: player current world, {SERVER}: server name",
"{PLAYER}: player name, {ONLINE}: display number of online players,",
"{MAXPLAYERS}: display server slots, {IP}: player ip, {LOGINS}: number of players logged,",
"{WORLD}: player current world, {SERVER}: server name",
"{VERSION}: get current bukkit version, {COUNTRY}: player country"})
public static final Property<Boolean> USE_WELCOME_MESSAGE =
newProperty("settings.useWelcomeMessage", true);
@Comment("Do we need to broadcast the welcome message to all server or only to the player? set true for "
+ "server or false for player")
@Comment({
"Broadcast the welcome message to the server or only to the player?",
"set true for server or false for player"})
public static final Property<Boolean> BROADCAST_WELCOME_MESSAGE =
newProperty("settings.broadcastWelcomeMessage", false);
@@ -36,7 +36,7 @@ public class RestrictionSettings implements SettingsHolder {
@Comment("Minimum allowed username length")
public static final Property<Integer> MIN_NICKNAME_LENGTH =
newProperty("settings.restrictions.minNicknameLength", 4);
newProperty("settings.restrictions.minNicknameLength", 3);
@Comment("Maximum allowed username length")
public static final Property<Integer> MAX_NICKNAME_LENGTH =
@@ -50,9 +50,9 @@ public class RestrictionSettings implements SettingsHolder {
newProperty("settings.restrictions.ForceSingleSession", true);
@Comment({
"If enabled, every player that spawn in one of the world listed in \"ForceSpawnLocOnJoin.worlds\"",
"will be teleported to the spawnpoint after successful authentication.",
"The quit location of the player will be overwritten.",
"If enabled, every player that spawn in one of the world listed in",
"\"ForceSpawnLocOnJoin.worlds\" will be teleported to the spawnpoint after successful",
"authentication. The quit location of the player will be overwritten.",
"This is different from \"teleportUnAuthedToSpawn\" that teleport player",
"to the spawnpoint on join."})
public static final Property<Boolean> FORCE_SPAWN_LOCATION_AFTER_LOGIN =
@@ -18,10 +18,6 @@ public class SecuritySettings implements SettingsHolder {
public static final Property<Boolean> STOP_SERVER_ON_PROBLEM =
newProperty("Security.SQLProblem.stopServer", true);
@Comment("/reload support")
public static final Property<Boolean> USE_RELOAD_COMMAND_SUPPORT =
newProperty("Security.ReloadCommand.useReloadCommandSupport", true);
@Comment("Remove passwords from console?")
public static final Property<Boolean> REMOVE_PASSWORD_FROM_CONSOLE =
newProperty("Security.console.removePassword", true);
@@ -85,11 +81,13 @@ public class SecuritySettings implements SettingsHolder {
newProperty("settings.security.supportOldPasswordHash", false);
@Comment({"Prevent unsafe passwords from being used; put them in lowercase!",
"You should always set 'help' as unsafePassword due to possible conflicts.",
"unsafePasswords:",
"- '123456'",
"- 'password'"})
"- 'password'",
"- 'help'"})
public static final Property<List<String>> UNSAFE_PASSWORDS =
newLowercaseListProperty("settings.security.unsafePasswords", "123456", "password", "qwerty", "12345", "54321", "123456789");
newLowercaseListProperty("settings.security.unsafePasswords", "123456", "password", "qwerty", "12345", "54321", "123456789", "help");
@Comment("Tempban a user's IP address if they enter the wrong password too many times")
public static final Property<Boolean> TEMPBAN_ON_MAX_LOGINS =
@@ -23,7 +23,7 @@ public final class FileUtils {
* Copy a resource file (from the JAR) to the given file if it doesn't exist.
*
* @param destinationFile The file to check and copy to (outside of JAR)
* @param resourcePath Absolute path to the resource file (path to file within JAR)
* @param resourcePath Local path to the resource file (path to file within JAR)
*
* @return False if the file does not exist and could not be copied, true otherwise
*/
@@ -35,9 +35,7 @@ public final class FileUtils {
return false;
}
// ClassLoader#getResourceAsStream does not deal with the '\' path separator: replace to '/'
final String normalizedPath = resourcePath.replace("\\", "/");
try (InputStream is = AuthMe.class.getClassLoader().getResourceAsStream(normalizedPath)) {
try (InputStream is = getResourceFromJar(resourcePath)) {
if (is == null) {
ConsoleLogger.warning(format("Cannot copy resource '%s' to file '%s': cannot load resource",
resourcePath, destinationFile.getPath()));
@@ -52,6 +50,18 @@ public final class FileUtils {
return false;
}
/**
* Returns a JAR file as stream. Returns null if it doesn't exist.
*
* @param path the local path (starting from resources project, e.g. "config.yml" for 'resources/config.yml')
* @return the stream if the file exists, or false otherwise
*/
public static InputStream getResourceFromJar(String path) {
// ClassLoader#getResourceAsStream does not deal with the '\' path separator: replace to '/'
final String normalizedPath = path.replace("\\", "/");
return AuthMe.class.getClassLoader().getResourceAsStream(normalizedPath);
}
/**
* Delete a given directory and all its content.
*