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:
@@ -18,6 +18,7 @@ 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.hasSize;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
@@ -32,7 +33,7 @@ public class CommandInitializerTest {
|
||||
*/
|
||||
private static int MAX_ALLOWED_DEPTH = 1;
|
||||
|
||||
private static Set<CommandDescription> commands;
|
||||
private static Collection<CommandDescription> commands;
|
||||
|
||||
@BeforeClass
|
||||
public static void initializeCommandCollection() {
|
||||
@@ -46,7 +47,7 @@ public class CommandInitializerTest {
|
||||
// It obviously doesn't make sense to test much of the concrete data
|
||||
// that is being initialized; we just want to guarantee with this test
|
||||
// that data is indeed being initialized and we take a few "probes"
|
||||
assertThat(commands.size(), equalTo(8));
|
||||
assertThat(commands, hasSize(8));
|
||||
assertThat(commandsIncludeLabel(commands, "authme"), equalTo(true));
|
||||
assertThat(commandsIncludeLabel(commands, "register"), equalTo(true));
|
||||
assertThat(commandsIncludeLabel(commands, "help"), equalTo(false));
|
||||
|
||||
@@ -39,7 +39,7 @@ import static org.mockito.Mockito.mock;
|
||||
@RunWith(DelayedInjectionRunner.class)
|
||||
public class CommandMapperTest {
|
||||
|
||||
private static Set<CommandDescription> commands;
|
||||
private static List<CommandDescription> commands;
|
||||
|
||||
@InjectDelayed
|
||||
private CommandMapper mapper;
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
package fr.xephi.authme.command;
|
||||
|
||||
import fr.xephi.authme.TestHelper;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
@@ -11,6 +18,13 @@ import static org.junit.Assert.assertThat;
|
||||
*/
|
||||
public class CommandUtilsTest {
|
||||
|
||||
private static Collection<CommandDescription> commands;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpTestCommands() {
|
||||
commands = TestCommandsUtil.generateCommands();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnCommandPath() {
|
||||
// given
|
||||
@@ -19,14 +33,14 @@ public class CommandUtilsTest {
|
||||
.description("Base")
|
||||
.detailedDescription("Test base command.")
|
||||
.executableCommand(ExecutableCommand.class)
|
||||
.build();
|
||||
.register();
|
||||
CommandDescription command = CommandDescription.builder()
|
||||
.parent(base)
|
||||
.labels("help", "h", "?")
|
||||
.description("Child")
|
||||
.detailedDescription("Test child command.")
|
||||
.executableCommand(ExecutableCommand.class)
|
||||
.build();
|
||||
.register();
|
||||
|
||||
// when
|
||||
String commandPath = CommandUtils.constructCommandPath(command);
|
||||
@@ -42,7 +56,7 @@ public class CommandUtilsTest {
|
||||
@Test
|
||||
public void shouldComputeMinAndMaxOnEmptyCommand() {
|
||||
// given
|
||||
CommandDescription command = getBuilderForArgsTest().build();
|
||||
CommandDescription command = getBuilderForArgsTest().register();
|
||||
|
||||
// when / then
|
||||
checkArgumentCount(command, 0, 0);
|
||||
@@ -54,7 +68,7 @@ public class CommandUtilsTest {
|
||||
CommandDescription command = getBuilderForArgsTest()
|
||||
.withArgument("Test", "Arg description", false)
|
||||
.withArgument("Test22", "Arg description 2", false)
|
||||
.build();
|
||||
.register();
|
||||
|
||||
// when / then
|
||||
checkArgumentCount(command, 2, 2);
|
||||
@@ -67,7 +81,7 @@ public class CommandUtilsTest {
|
||||
.withArgument("arg1", "Arg description", false)
|
||||
.withArgument("arg2", "Arg description 2", true)
|
||||
.withArgument("arg3", "Arg description 3", true)
|
||||
.build();
|
||||
.register();
|
||||
|
||||
// when / then
|
||||
checkArgumentCount(command, 1, 3);
|
||||
@@ -79,6 +93,46 @@ public class CommandUtilsTest {
|
||||
TestHelper.validateHasOnlyPrivateEmptyConstructor(CommandUtils.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldFormatSimpleArgument() {
|
||||
// given
|
||||
CommandDescription command = TestCommandsUtil.getCommandWithLabel(commands, "authme");
|
||||
List<String> labels = Collections.singletonList("authme");
|
||||
|
||||
// when
|
||||
String result = CommandUtils.buildSyntax(command, labels);
|
||||
|
||||
// then
|
||||
assertThat(result, equalTo(ChatColor.WHITE + "/authme" + ChatColor.YELLOW));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldFormatCommandWithMultipleArguments() {
|
||||
// given
|
||||
CommandDescription command = TestCommandsUtil.getCommandWithLabel(commands, "authme", "register");
|
||||
List<String> labels = Arrays.asList("authme", "reg");
|
||||
|
||||
// when
|
||||
String result = CommandUtils.buildSyntax(command, labels);
|
||||
|
||||
// then
|
||||
assertThat(result, equalTo(ChatColor.WHITE + "/authme" + ChatColor.YELLOW + " reg <password> <confirmation>"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void shouldFormatCommandWithOptionalArgument() {
|
||||
// given
|
||||
CommandDescription command = TestCommandsUtil.getCommandWithLabel(commands, "email");
|
||||
List<String> labels = Collections.singletonList("email");
|
||||
|
||||
// when
|
||||
String result = CommandUtils.buildSyntax(command, labels);
|
||||
|
||||
// then
|
||||
assertThat(result, equalTo(ChatColor.WHITE + "/email" + ChatColor.YELLOW + " [player]"));
|
||||
}
|
||||
|
||||
|
||||
private static void checkArgumentCount(CommandDescription command, int expectedMin, int expectedMax) {
|
||||
assertThat(CommandUtils.getMinNumberOfArguments(command), equalTo(expectedMin));
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package fr.xephi.authme.command;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import fr.xephi.authme.command.executable.HelpCommand;
|
||||
import fr.xephi.authme.permission.AdminPermission;
|
||||
import fr.xephi.authme.permission.PermissionNode;
|
||||
@@ -8,9 +9,7 @@ import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.google.common.collect.Sets.newHashSet;
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Collections.singletonList;
|
||||
|
||||
@@ -27,7 +26,7 @@ public final class TestCommandsUtil {
|
||||
*
|
||||
* @return The generated commands
|
||||
*/
|
||||
public static Set<CommandDescription> generateCommands() {
|
||||
public static List<CommandDescription> generateCommands() {
|
||||
// Register /authme
|
||||
CommandDescription authMeBase = createCommand(null, null, singletonList("authme"), ExecutableCommand.class);
|
||||
// Register /authme login <password>
|
||||
@@ -42,13 +41,13 @@ public final class TestCommandsUtil {
|
||||
newArgument("player", true));
|
||||
// Register /email helptest -- use only to test for help command arguments special case
|
||||
CommandDescription.builder().parent(emailBase).labels("helptest").executableCommand(HelpCommand.class)
|
||||
.description("test").detailedDescription("Test.").withArgument("Query", "", false).build();
|
||||
.description("test").detailedDescription("Test.").withArgument("Query", "", false).register();
|
||||
|
||||
// Register /unregister <player>, alias: /unreg
|
||||
CommandDescription unregisterBase = createCommand(AdminPermission.UNREGISTER, null,
|
||||
asList("unregister", "unreg"), TestUnregisterCommand.class, newArgument("player", false));
|
||||
|
||||
return newHashSet(authMeBase, emailBase, unregisterBase);
|
||||
return ImmutableList.of(authMeBase, emailBase, unregisterBase);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -101,7 +100,7 @@ public final class TestCommandsUtil {
|
||||
}
|
||||
}
|
||||
|
||||
return command.build();
|
||||
return command.register();
|
||||
}
|
||||
|
||||
/** Shortcut command to initialize a new argument description. */
|
||||
|
||||
@@ -20,6 +20,10 @@ import static fr.xephi.authme.command.FoundResultStatus.INCORRECT_ARGUMENTS;
|
||||
import static fr.xephi.authme.command.FoundResultStatus.MISSING_BASE_COMMAND;
|
||||
import static fr.xephi.authme.command.FoundResultStatus.SUCCESS;
|
||||
import static fr.xephi.authme.command.FoundResultStatus.UNKNOWN_LABEL;
|
||||
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;
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
@@ -108,7 +112,7 @@ public class HelpCommandTest {
|
||||
CommandDescription commandDescription = mock(CommandDescription.class);
|
||||
given(commandDescription.getLabelCount()).willReturn(1);
|
||||
FoundCommandResult foundCommandResult = new FoundCommandResult(commandDescription, singletonList("authme"),
|
||||
Collections.<String>emptyList(), 0.0, SUCCESS);
|
||||
Collections.emptyList(), 0.0, SUCCESS);
|
||||
given(commandMapper.mapPartsToCommand(sender, arguments)).willReturn(foundCommandResult);
|
||||
|
||||
// when
|
||||
@@ -116,7 +120,8 @@ public class HelpCommandTest {
|
||||
|
||||
// then
|
||||
verify(sender, never()).sendMessage(anyString());
|
||||
verify(helpProvider).outputHelp(sender, foundCommandResult, HelpProvider.SHOW_CHILDREN);
|
||||
verify(helpProvider).outputHelp(sender, foundCommandResult,
|
||||
SHOW_DESCRIPTION | SHOW_COMMAND | SHOW_CHILDREN | SHOW_ALTERNATIVES);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -126,7 +131,7 @@ public class HelpCommandTest {
|
||||
CommandDescription commandDescription = mock(CommandDescription.class);
|
||||
given(commandDescription.getLabelCount()).willReturn(2);
|
||||
FoundCommandResult foundCommandResult = new FoundCommandResult(commandDescription, asList("authme", "getpos"),
|
||||
Collections.<String>emptyList(), 0.0, INCORRECT_ARGUMENTS);
|
||||
Collections.emptyList(), 0.0, INCORRECT_ARGUMENTS);
|
||||
given(commandMapper.mapPartsToCommand(sender, arguments)).willReturn(foundCommandResult);
|
||||
|
||||
// when
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
package fr.xephi.authme.command.help;
|
||||
|
||||
import fr.xephi.authme.TestHelper;
|
||||
import fr.xephi.authme.command.CommandDescription;
|
||||
import fr.xephi.authme.command.TestCommandsUtil;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* Test for {@link CommandSyntaxHelper}.
|
||||
*/
|
||||
public class CommandSyntaxHelperTest {
|
||||
|
||||
private static Set<CommandDescription> commands;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpTestCommands() {
|
||||
commands = TestCommandsUtil.generateCommands();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldFormatSimpleArgument() {
|
||||
// given
|
||||
CommandDescription command = TestCommandsUtil.getCommandWithLabel(commands, "authme");
|
||||
List<String> labels = Collections.singletonList("authme");
|
||||
|
||||
// when
|
||||
String result = CommandSyntaxHelper.getSyntax(command, labels);
|
||||
|
||||
// then
|
||||
assertThat(result, equalTo(ChatColor.WHITE + "/authme" + ChatColor.YELLOW));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldFormatCommandWithMultipleArguments() {
|
||||
// given
|
||||
CommandDescription command = TestCommandsUtil.getCommandWithLabel(commands, "authme", "register");
|
||||
List<String> labels = Arrays.asList("authme", "reg");
|
||||
|
||||
// when
|
||||
String result = CommandSyntaxHelper.getSyntax(command, labels);
|
||||
|
||||
// then
|
||||
assertThat(result, equalTo(ChatColor.WHITE + "/authme" + ChatColor.YELLOW + " reg <password> <confirmation>"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void shouldFormatCommandWithOptionalArgument() {
|
||||
// given
|
||||
CommandDescription command = TestCommandsUtil.getCommandWithLabel(commands, "email");
|
||||
List<String> labels = Collections.singletonList("email");
|
||||
|
||||
// when
|
||||
String result = CommandSyntaxHelper.getSyntax(command, labels);
|
||||
|
||||
// then
|
||||
assertThat(result, equalTo(ChatColor.WHITE + "/email" + ChatColor.YELLOW + " [player]"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldHaveHiddenConstructor() {
|
||||
// given / when / then
|
||||
TestHelper.validateHasOnlyPrivateEmptyConstructor(CommandSyntaxHelper.class);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,8 +9,8 @@ import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
@@ -78,7 +78,7 @@ public class HelpMessagesConsistencyTest {
|
||||
* @return the CommandDescription object for the {@code /authme register} command.
|
||||
*/
|
||||
private static CommandDescription getAuthMeRegisterDescription() {
|
||||
Set<CommandDescription> commands = new CommandInitializer().getCommands();
|
||||
Collection<CommandDescription> commands = new CommandInitializer().getCommands();
|
||||
|
||||
List<CommandDescription> children = commands.stream()
|
||||
.filter(command -> command.getLabels().contains("authme"))
|
||||
|
||||
@@ -12,10 +12,11 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.Collection;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static fr.xephi.authme.TestHelper.getJarFile;
|
||||
import static fr.xephi.authme.command.TestCommandsUtil.getCommandWithLabel;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.hamcrest.Matchers.sameInstance;
|
||||
@@ -30,7 +31,7 @@ import static org.mockito.Matchers.any;
|
||||
public class HelpMessagesServiceTest {
|
||||
|
||||
private static final String TEST_FILE = "/fr/xephi/authme/command/help/help_test.yml";
|
||||
private static final Set<CommandDescription> COMMANDS = TestCommandsUtil.generateCommands();
|
||||
private static final Collection<CommandDescription> COMMANDS = TestCommandsUtil.generateCommands();
|
||||
|
||||
@InjectDelayed
|
||||
private HelpMessagesService helpMessagesService;
|
||||
@@ -48,7 +49,7 @@ public class HelpMessagesServiceTest {
|
||||
@Test
|
||||
public void shouldReturnLocalizedCommand() {
|
||||
// given
|
||||
CommandDescription command = TestCommandsUtil.getCommandWithLabel(COMMANDS, "authme", "register");
|
||||
CommandDescription command = getCommandWithLabel(COMMANDS, "authme", "register");
|
||||
|
||||
// when
|
||||
CommandDescription localCommand = helpMessagesService.buildLocalizedDescription(command);
|
||||
@@ -68,7 +69,7 @@ public class HelpMessagesServiceTest {
|
||||
@Test
|
||||
public void shouldReturnLocalizedCommandWithDefaults() {
|
||||
// given
|
||||
CommandDescription command = TestCommandsUtil.getCommandWithLabel(COMMANDS, "authme", "login");
|
||||
CommandDescription command = getCommandWithLabel(COMMANDS, "authme", "login");
|
||||
|
||||
// when
|
||||
CommandDescription localCommand = helpMessagesService.buildLocalizedDescription(command);
|
||||
@@ -84,7 +85,7 @@ public class HelpMessagesServiceTest {
|
||||
@Test
|
||||
public void shouldReturnSameCommandForNoLocalization() {
|
||||
// given
|
||||
CommandDescription command = TestCommandsUtil.getCommandWithLabel(COMMANDS, "email");
|
||||
CommandDescription command = getCommandWithLabel(COMMANDS, "email");
|
||||
|
||||
// when
|
||||
CommandDescription localCommand = helpMessagesService.buildLocalizedDescription(command);
|
||||
@@ -96,7 +97,7 @@ public class HelpMessagesServiceTest {
|
||||
@Test
|
||||
public void shouldKeepChildrenInLocalCommand() {
|
||||
// given
|
||||
CommandDescription command = TestCommandsUtil.getCommandWithLabel(COMMANDS, "authme");
|
||||
CommandDescription command = getCommandWithLabel(COMMANDS, "authme");
|
||||
|
||||
// when
|
||||
CommandDescription localCommand = helpMessagesService.buildLocalizedDescription(command);
|
||||
@@ -114,4 +115,28 @@ public class HelpMessagesServiceTest {
|
||||
assertThat(helpMessagesService.getMessage(HelpMessage.RESULT), equalTo("res."));
|
||||
assertThat(helpMessagesService.getMessage(HelpSection.ARGUMENTS), equalTo("arg."));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldGetLocalCommandDescription() {
|
||||
// given
|
||||
CommandDescription command = getCommandWithLabel(COMMANDS, "authme", "register");
|
||||
|
||||
// when
|
||||
String description = helpMessagesService.getDescription(command);
|
||||
|
||||
// then
|
||||
assertThat(description, equalTo("Registration"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldFallbackToDescriptionOnCommandObject() {
|
||||
// given
|
||||
CommandDescription command = getCommandWithLabel(COMMANDS, "unregister");
|
||||
|
||||
// when
|
||||
String description = helpMessagesService.getDescription(command);
|
||||
|
||||
// then
|
||||
assertThat(description, equalTo(command.getDescription()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,9 +20,9 @@ import org.mockito.Mock;
|
||||
import org.mockito.internal.stubbing.answers.ReturnsArgumentAt;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static fr.xephi.authme.command.TestCommandsUtil.getCommandWithLabel;
|
||||
@@ -53,7 +53,7 @@ import static org.mockito.Mockito.verify;
|
||||
@RunWith(DelayedInjectionRunner.class)
|
||||
public class HelpProviderTest {
|
||||
|
||||
private static Set<CommandDescription> commands;
|
||||
private static Collection<CommandDescription> commands;
|
||||
|
||||
@InjectDelayed
|
||||
private HelpProvider helpProvider;
|
||||
@@ -251,6 +251,10 @@ public class HelpProviderTest {
|
||||
// given
|
||||
CommandDescription command = getCommandWithLabel(commands, "authme");
|
||||
FoundCommandResult result = newFoundResult(command, Collections.singletonList("authme"));
|
||||
given(helpMessagesService.getDescription(getCommandWithLabel(commands, "authme", "login")))
|
||||
.willReturn("Command for login [localized]");
|
||||
given(helpMessagesService.getDescription(getCommandWithLabel(commands, "authme", "register")))
|
||||
.willReturn("Registration command [localized]");
|
||||
|
||||
// when
|
||||
helpProvider.outputHelp(sender, result, SHOW_CHILDREN);
|
||||
@@ -258,9 +262,9 @@ public class HelpProviderTest {
|
||||
// then
|
||||
List<String> lines = getLines(sender);
|
||||
assertThat(lines, hasSize(4));
|
||||
assertThat(lines.get(1), containsString("Children:"));
|
||||
assertThat(lines.get(2), containsString("/authme login: login cmd"));
|
||||
assertThat(lines.get(3), containsString("/authme register: register cmd"));
|
||||
assertThat(lines.get(1), equalTo("Children:"));
|
||||
assertThat(lines.get(2), equalTo(" /authme login: Command for login [localized]"));
|
||||
assertThat(lines.get(3), equalTo(" /authme register: Registration command [localized]"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -395,6 +399,24 @@ public class HelpProviderTest {
|
||||
assertThat(lines.get(0), equalTo("Command: /authme register <password> <confirmation>"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldShowAlternativesForRootCommand() {
|
||||
// given
|
||||
CommandDescription command = getCommandWithLabel(commands, "unregister");
|
||||
FoundCommandResult result = newFoundResult(command, Collections.singletonList("unreg"));
|
||||
|
||||
// when
|
||||
helpProvider.outputHelp(sender, result, SHOW_COMMAND | SHOW_ALTERNATIVES);
|
||||
|
||||
// then
|
||||
List<String> lines = getLines(sender);
|
||||
assertThat(lines, hasSize(4));
|
||||
assertThat(lines.get(0), equalTo("Header"));
|
||||
assertThat(lines.get(1), equalTo("Command: /unreg <player>"));
|
||||
assertThat(lines.get(2), equalTo("Alternatives:"));
|
||||
assertThat(lines.get(3), equalTo(" /unregister <player>"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an instance of {@link FoundCommandResult} with the given command and labels. All other fields aren't
|
||||
* retrieved by {@link HelpProvider} and so are initialized to default values for the tests.
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
package fr.xephi.authme.message;
|
||||
|
||||
import fr.xephi.authme.TestHelper;
|
||||
import fr.xephi.authme.util.StringUtils;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* Tests that all YML message files can be loaded.
|
||||
*/
|
||||
public class MessagesFileYamlCheckerTest {
|
||||
|
||||
/** Path in the resources folder where the message files are located. */
|
||||
private static final String MESSAGES_FOLDER = "/messages/";
|
||||
/** Pattern of the message file names. */
|
||||
private static final Pattern MESSAGE_FILE_PATTERN = Pattern.compile("messages_\\w+\\.yml");
|
||||
/** Message key that is present in all files. Used to make sure that text is returned. */
|
||||
private static final MessageKey MESSAGE_KEY = MessageKey.LOGIN_MESSAGE;
|
||||
|
||||
@Test
|
||||
public void shouldAllBeValidYaml() {
|
||||
// given
|
||||
List<File> messageFiles = getMessageFiles();
|
||||
|
||||
// when
|
||||
List<String> errors = new ArrayList<>();
|
||||
for (File file : messageFiles) {
|
||||
String error = null;
|
||||
try {
|
||||
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(file);
|
||||
if (StringUtils.isEmpty(configuration.getString(MESSAGE_KEY.getKey()))) {
|
||||
error = "Message for '" + MESSAGE_KEY + "' is empty";
|
||||
}
|
||||
} catch (Exception e) {
|
||||
error = "Could not load file: " + StringUtils.formatException(e);
|
||||
}
|
||||
if (!StringUtils.isEmpty(error)) {
|
||||
errors.add(file.getName() + ": " + error);
|
||||
}
|
||||
}
|
||||
|
||||
// then
|
||||
if (!errors.isEmpty()) {
|
||||
fail("Errors during verification of message files:\n-" + String.join("\n-", errors));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private List<File> getMessageFiles() {
|
||||
File folder = TestHelper.getJarFile(MESSAGES_FOLDER);
|
||||
File[] files = folder.listFiles();
|
||||
if (files == null) {
|
||||
throw new IllegalStateException("Could not read folder '" + folder.getName() + "'");
|
||||
}
|
||||
|
||||
List<File> messageFiles = new ArrayList<>();
|
||||
for (File file : files) {
|
||||
if (MESSAGE_FILE_PATTERN.matcher(file.getName()).matches()) {
|
||||
messageFiles.add(file);
|
||||
}
|
||||
}
|
||||
if (messageFiles.isEmpty()) {
|
||||
throw new IllegalStateException("Error getting message files: list of files is empty");
|
||||
}
|
||||
return messageFiles;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package fr.xephi.authme.message;
|
||||
|
||||
import fr.xephi.authme.TestHelper;
|
||||
import fr.xephi.authme.command.help.HelpSection;
|
||||
import fr.xephi.authme.util.StringUtils;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* Tests that all YML text files can be loaded.
|
||||
*/
|
||||
public class YamlTextFileCheckerTest {
|
||||
|
||||
/** Path in the resources folder where the message files are located. */
|
||||
private static final String MESSAGES_FOLDER = "/messages/";
|
||||
/** Contains all files of the MESSAGES_FOLDER. */
|
||||
private static List<File> messageFiles;
|
||||
|
||||
@BeforeClass
|
||||
public static void loadMessagesFiles() {
|
||||
File folder = TestHelper.getJarFile(MESSAGES_FOLDER);
|
||||
File[] files = folder.listFiles();
|
||||
if (files == null || files.length == 0) {
|
||||
throw new IllegalStateException("Could not read folder '" + folder.getName() + "'");
|
||||
}
|
||||
messageFiles = Arrays.asList(files);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAllMessagesYmlFiles() {
|
||||
checkFiles(
|
||||
Pattern.compile("messages_\\w+\\.yml"),
|
||||
MessageKey.LOGIN_MESSAGE.getKey());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAllHelpYmlFiles() {
|
||||
checkFiles(
|
||||
Pattern.compile("help_\\w+\\.yml"),
|
||||
HelpSection.ALTERNATIVES.getKey());
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks all files in the messages folder that match the given pattern.
|
||||
*
|
||||
* @param pattern the pattern the file name needs to match
|
||||
* @param mandatoryKey key present in all matched files
|
||||
*/
|
||||
private void checkFiles(Pattern pattern, String mandatoryKey) {
|
||||
List<String> errors = new ArrayList<>();
|
||||
|
||||
boolean hasMatch = false;
|
||||
for (File file : messageFiles) {
|
||||
if (pattern.matcher(file.getName()).matches()) {
|
||||
checkFile(file, mandatoryKey, errors);
|
||||
hasMatch = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!errors.isEmpty()) {
|
||||
fail("Errors while checking files matching '" + pattern + "':\n-" + String.join("\n-", errors));
|
||||
} else if (!hasMatch) {
|
||||
fail("Could not find any files satisfying pattern '" + pattern + "'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the provided YAML file can be loaded and that it contains a non-empty text
|
||||
* for the provided mandatory key.
|
||||
*
|
||||
* @param file the file to check
|
||||
* @param mandatoryKey the key for which text must be present
|
||||
* @param errors collection of errors to add to if the verification fails
|
||||
*/
|
||||
private void checkFile(File file, String mandatoryKey, List<String> errors) {
|
||||
String error = null;
|
||||
try {
|
||||
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(file);
|
||||
if (StringUtils.isEmpty(configuration.getString(mandatoryKey))) {
|
||||
error = "Message for '" + mandatoryKey + "' is empty";
|
||||
}
|
||||
} catch (Exception e) {
|
||||
error = "Could not load file: " + StringUtils.formatException(e);
|
||||
}
|
||||
if (!StringUtils.isEmpty(error)) {
|
||||
errors.add(file.getName() + ": " + error);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,7 @@ public class PermissionConsistencyTest {
|
||||
|
||||
/** All classes defining permission nodes. */
|
||||
private static final Set<Class<? extends PermissionNode>> PERMISSION_CLASSES = ImmutableSet
|
||||
.<Class<? extends PermissionNode>>of(PlayerPermission.class, AdminPermission.class, PlayerStatePermission.class);
|
||||
.of(PlayerPermission.class, AdminPermission.class, PlayerStatePermission.class);
|
||||
|
||||
/** Wildcard permissions (present in plugin.yml but not in the codebase). */
|
||||
private static final Set<String> PLUGIN_YML_PERMISSIONS_WILDCARDS =
|
||||
|
||||
@@ -51,6 +51,7 @@ public class AntiBotServiceTest {
|
||||
@BeforeInjecting
|
||||
public void initSettings() {
|
||||
given(settings.getProperty(ProtectionSettings.ANTIBOT_DURATION)).willReturn(10);
|
||||
given(settings.getProperty(ProtectionSettings.ANTIBOT_INTERVAL)).willReturn(5);
|
||||
given(settings.getProperty(ProtectionSettings.ANTIBOT_SENSIBILITY)).willReturn(5);
|
||||
given(settings.getProperty(ProtectionSettings.ENABLE_ANTIBOT)).willReturn(true);
|
||||
given(settings.getProperty(ProtectionSettings.ANTIBOT_DELAY)).willReturn(8);
|
||||
|
||||
@@ -1,105 +0,0 @@
|
||||
package fr.xephi.authme.settings;
|
||||
|
||||
import com.github.authme.configme.knownproperties.ConfigurationData;
|
||||
import com.github.authme.configme.migration.MigrationService;
|
||||
import com.github.authme.configme.migration.PlainMigrationService;
|
||||
import com.github.authme.configme.properties.Property;
|
||||
import com.github.authme.configme.resource.PropertyResource;
|
||||
import com.github.authme.configme.resource.YamlFileResource;
|
||||
import fr.xephi.authme.TestHelper;
|
||||
import fr.xephi.authme.settings.properties.AuthMeSettingsRetriever;
|
||||
import org.bukkit.configuration.MemorySection;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* Test for {@link Settings} and the project's config.yml,
|
||||
* verifying that no settings are missing from the file.
|
||||
*/
|
||||
public class ConfigFileConsistencyTest {
|
||||
|
||||
/** The file name of the project's sample config file. */
|
||||
private static final String CONFIG_FILE = "/config.yml";
|
||||
|
||||
@Test
|
||||
public void shouldHaveAllConfigs() throws IOException {
|
||||
// given
|
||||
File configFile = TestHelper.getJarFile(CONFIG_FILE);
|
||||
PropertyResource resource = new YamlFileResource(configFile);
|
||||
MigrationService migration = new PlainMigrationService();
|
||||
|
||||
// when
|
||||
boolean result = migration.checkAndMigrate(
|
||||
resource, AuthMeSettingsRetriever.buildConfigurationData().getProperties());
|
||||
|
||||
// then
|
||||
if (result) {
|
||||
Set<String> knownProperties = getAllKnownPropertyPaths();
|
||||
List<String> missingProperties = new ArrayList<>();
|
||||
for (String path : knownProperties) {
|
||||
if (!resource.contains(path)) {
|
||||
missingProperties.add(path);
|
||||
}
|
||||
}
|
||||
fail("Found missing properties!\n-" + String.join("\n-", missingProperties));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotHaveUnknownConfigs() {
|
||||
// given
|
||||
File configFile = TestHelper.getJarFile(CONFIG_FILE);
|
||||
FileConfiguration configuration = YamlConfiguration.loadConfiguration(configFile);
|
||||
Map<String, Object> allReadProperties = configuration.getValues(true);
|
||||
Set<String> knownKeys = getAllKnownPropertyPaths();
|
||||
|
||||
// when
|
||||
List<String> unknownPaths = new ArrayList<>();
|
||||
for (Map.Entry<String, Object> entry : allReadProperties.entrySet()) {
|
||||
// The value being a MemorySection means it's a parent node
|
||||
if (!(entry.getValue() instanceof MemorySection) && !knownKeys.contains(entry.getKey())) {
|
||||
unknownPaths.add(entry.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
// then
|
||||
if (!unknownPaths.isEmpty()) {
|
||||
fail("Found " + unknownPaths.size() + " unknown property paths in the project's config.yml: \n- "
|
||||
+ String.join("\n- ", unknownPaths));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldHaveValueCorrespondingToPropertyDefault() {
|
||||
// given
|
||||
File configFile = TestHelper.getJarFile(CONFIG_FILE);
|
||||
PropertyResource resource = new YamlFileResource(configFile);
|
||||
ConfigurationData configurationData = AuthMeSettingsRetriever.buildConfigurationData();
|
||||
|
||||
// when / then
|
||||
for (Property<?> property : configurationData.getProperties()) {
|
||||
assertThat("Default value of '" + property.getPath() + "' in config.yml should be the same as in Property",
|
||||
property.getValue(resource).equals(property.getDefaultValue()), equalTo(true));
|
||||
}
|
||||
}
|
||||
|
||||
private static Set<String> getAllKnownPropertyPaths() {
|
||||
return AuthMeSettingsRetriever.buildConfigurationData()
|
||||
.getProperties().stream()
|
||||
.map(Property::getPath)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package fr.xephi.authme.settings;
|
||||
|
||||
import com.github.authme.configme.knownproperties.ConfigurationData;
|
||||
import com.github.authme.configme.properties.Property;
|
||||
import fr.xephi.authme.settings.properties.AuthMeSettingsRetriever;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* Tests the consistency of the settings configuration.
|
||||
*/
|
||||
public class SettingsConsistencyTest {
|
||||
|
||||
/**
|
||||
* Maximum characters one comment line may have (prevents horizontal scrolling).
|
||||
*/
|
||||
private static final int MAX_COMMENT_LENGTH = 90;
|
||||
|
||||
private static ConfigurationData configurationData;
|
||||
|
||||
@BeforeClass
|
||||
public static void buildConfigurationData() {
|
||||
configurationData = AuthMeSettingsRetriever.buildConfigurationData();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldHaveCommentOnEachProperty() {
|
||||
// given
|
||||
List<Property<?>> properties = configurationData.getProperties();
|
||||
|
||||
// when / then
|
||||
for (Property<?> property : properties) {
|
||||
if (configurationData.getCommentsForSection(property.getPath()).length == 0) {
|
||||
fail("No comment defined for '" + property + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotHaveVeryLongCommentLines() {
|
||||
// given
|
||||
List<Property<?>> properties = configurationData.getProperties();
|
||||
List<Property<?>> badProperties = new ArrayList<>();
|
||||
|
||||
// when
|
||||
for (Property<?> property : properties) {
|
||||
for (String comment : configurationData.getCommentsForSection(property.getPath())) {
|
||||
if (comment.length() > MAX_COMMENT_LENGTH) {
|
||||
badProperties.add(property);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// then
|
||||
if (!badProperties.isEmpty()) {
|
||||
fail("Comment lines should not be longer than " + MAX_COMMENT_LENGTH + " chars, "
|
||||
+ "but found too long comments for:\n- "
|
||||
+ badProperties.stream().map(Property::getPath).collect(Collectors.joining("\n- ")));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
package fr.xephi.authme.settings;
|
||||
|
||||
import com.github.authme.configme.knownproperties.ConfigurationData;
|
||||
import com.github.authme.configme.resource.PropertyResource;
|
||||
import com.github.authme.configme.resource.YamlFileResource;
|
||||
import com.google.common.io.Files;
|
||||
import fr.xephi.authme.TestHelper;
|
||||
import fr.xephi.authme.settings.properties.AuthMeSettingsRetriever;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.hamcrest.Matchers.arrayWithSize;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assume.assumeThat;
|
||||
|
||||
/**
|
||||
* Test for {@link SettingsMigrationService}.
|
||||
*/
|
||||
public class SettingsMigrationServiceTest {
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder testFolderHandler = new TemporaryFolder();
|
||||
|
||||
private File testFolder;
|
||||
private File configTestFile;
|
||||
|
||||
/**
|
||||
* Ensure that AuthMe regards the JAR's own config.yml as complete.
|
||||
* If something legitimately needs migrating, a test from {@link ConfigFileConsistencyTest} should fail.
|
||||
* If none fails in that class, it means something is wrong with the migration service
|
||||
* as it wants to perform a migration on our up-to-date config.yml.
|
||||
*/
|
||||
@Test
|
||||
public void shouldNotRewriteJarConfig() throws IOException {
|
||||
// given
|
||||
copyConfigToTestFolder();
|
||||
PropertyResource resource = new YamlFileResource(configTestFile);
|
||||
ConfigurationData configurationData = AuthMeSettingsRetriever.buildConfigurationData();
|
||||
assumeThat(testFolder.listFiles(), arrayWithSize(1));
|
||||
SettingsMigrationService migrationService = new SettingsMigrationService(testFolder);
|
||||
|
||||
// when
|
||||
boolean result = migrationService.checkAndMigrate(resource, configurationData.getProperties());
|
||||
|
||||
// then
|
||||
assertThat(result, equalTo(false));
|
||||
assertThat(testFolder.listFiles(), arrayWithSize(1));
|
||||
}
|
||||
|
||||
private void copyConfigToTestFolder() throws IOException {
|
||||
testFolder = testFolderHandler.newFolder("migrationtest");
|
||||
|
||||
final File testConfig = testFolderHandler.newFile("migrationtest/config.yml");
|
||||
final File realConfig = TestHelper.getJarFile("/config.yml");
|
||||
|
||||
Files.copy(realConfig, testConfig);
|
||||
if (!testConfig.exists()) {
|
||||
throw new IOException("Could not copy project's config.yml to test folder");
|
||||
}
|
||||
configTestFile = testConfig;
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,8 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
@@ -47,15 +49,15 @@ public class FileUtilsTest {
|
||||
public void shouldCopyFileFromJar() throws IOException {
|
||||
// given
|
||||
File folder = temporaryFolder.newFolder();
|
||||
File file = new File(folder, "some/folders/config.yml");
|
||||
File file = new File(folder, "some/folders/welcome.txt");
|
||||
|
||||
// when
|
||||
boolean result = FileUtils.copyFileFromResource(file, "config.yml");
|
||||
boolean result = FileUtils.copyFileFromResource(file, "welcome.txt");
|
||||
|
||||
// then
|
||||
assertThat(result, equalTo(true));
|
||||
assertThat(file.exists(), equalTo(true));
|
||||
File configJarFile = TestHelper.getJarFile("/config.yml");
|
||||
File configJarFile = TestHelper.getJarFile("/welcome.txt");
|
||||
assertThat(file.length(), equalTo(configJarFile.length()));
|
||||
}
|
||||
|
||||
@@ -119,6 +121,13 @@ public class FileUtilsTest {
|
||||
// Nothing happens
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldGetResourceFromJar() {
|
||||
// given / when / then
|
||||
assertThat(FileUtils.getResourceFromJar("config.yml"), not(nullValue()));
|
||||
assertThat(FileUtils.getResourceFromJar("does-not-exist"), nullValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldConstructPath() {
|
||||
// given/when
|
||||
|
||||
@@ -12,7 +12,6 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Scanner;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -29,11 +28,6 @@ public class CheckTestMocks implements AutoToolTask {
|
||||
return "checkTestMocks";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Scanner scanner) {
|
||||
executeDefault();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeDefault() {
|
||||
ClassCollector collector = new ClassCollector(TestHelper.TEST_SOURCES_FOLDER, TestHelper.PROJECT_ROOT);
|
||||
|
||||
@@ -1,26 +1,20 @@
|
||||
package tools.docs;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import tools.docs.commands.CommandPageCreater;
|
||||
import tools.docs.hashmethods.HashAlgorithmsDescriptionTask;
|
||||
import tools.docs.permissions.PermissionsListWriter;
|
||||
import tools.docs.translations.TranslationPageGenerator;
|
||||
import fr.xephi.authme.ClassCollector;
|
||||
import fr.xephi.authme.TestHelper;
|
||||
import tools.utils.AutoToolTask;
|
||||
import tools.utils.ToolTask;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Scanner;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Task that runs all tasks which update files in the docs folder.
|
||||
*/
|
||||
public class UpdateDocsTask implements AutoToolTask {
|
||||
|
||||
private static final Set<Class<? extends ToolTask>> TASKS = ImmutableSet
|
||||
.of(CommandPageCreater.class, HashAlgorithmsDescriptionTask.class,
|
||||
PermissionsListWriter.class, TranslationPageGenerator.class);
|
||||
|
||||
@Override
|
||||
public String getTaskName() {
|
||||
return "updateDocs";
|
||||
@@ -40,19 +34,18 @@ public class UpdateDocsTask implements AutoToolTask {
|
||||
});
|
||||
}
|
||||
|
||||
private static ToolTask instantiateTask(Class<? extends ToolTask> clazz) {
|
||||
try {
|
||||
return clazz.newInstance();
|
||||
} catch (IllegalAccessException | InstantiationException e) {
|
||||
throw new UnsupportedOperationException("Could not instantiate task class '" + clazz + "'", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void executeTasks(Consumer<ToolTask> taskRunner) {
|
||||
for (Class<? extends ToolTask> taskClass : TASKS) {
|
||||
ToolTask task = instantiateTask(taskClass);
|
||||
private void executeTasks(Consumer<ToolTask> taskRunner) {
|
||||
for (ToolTask task : getDocTasks()) {
|
||||
System.out.println("\nRunning " + task.getTaskName() + "\n-------------------");
|
||||
taskRunner.accept(task);
|
||||
}
|
||||
}
|
||||
|
||||
private List<ToolTask> getDocTasks() {
|
||||
ClassCollector classCollector =
|
||||
new ClassCollector(TestHelper.TEST_SOURCES_FOLDER, "tools/docs");
|
||||
return classCollector.getInstancesOfType(ToolTask.class).stream()
|
||||
.filter(task -> task.getClass() != getClass())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,14 +6,12 @@ import fr.xephi.authme.command.CommandInitializer;
|
||||
import fr.xephi.authme.command.CommandUtils;
|
||||
import fr.xephi.authme.permission.PermissionNode;
|
||||
import tools.utils.AutoToolTask;
|
||||
import tools.utils.FileUtils;
|
||||
import tools.utils.FileIoUtils;
|
||||
import tools.utils.TagValue.NestedTagValue;
|
||||
import tools.utils.TagValueHolder;
|
||||
import tools.utils.ToolsConstants;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Scanner;
|
||||
import java.util.Set;
|
||||
|
||||
public class CommandPageCreater implements AutoToolTask {
|
||||
|
||||
@@ -24,19 +22,14 @@ public class CommandPageCreater implements AutoToolTask {
|
||||
return "createCommandPage";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Scanner scanner) {
|
||||
executeDefault();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeDefault() {
|
||||
CommandInitializer commandInitializer = new CommandInitializer();
|
||||
final Set<CommandDescription> baseCommands = commandInitializer.getCommands();
|
||||
final Collection<CommandDescription> baseCommands = commandInitializer.getCommands();
|
||||
NestedTagValue commandTags = new NestedTagValue();
|
||||
addCommandsInfo(commandTags, baseCommands);
|
||||
|
||||
FileUtils.generateFileFromTemplate(
|
||||
FileIoUtils.generateFileFromTemplate(
|
||||
ToolsConstants.TOOLS_SOURCE_ROOT + "docs/commands/commands.tpl.md",
|
||||
OUTPUT_FILE,
|
||||
TagValueHolder.create().put("commands", commandTags));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- {gen_warning} -->
|
||||
<!-- File auto-generated on {gen_date}. See commands/commands.tpl.md -->
|
||||
<!-- File auto-generated on {gen_date}. See docs/commands/commands.tpl.md -->
|
||||
|
||||
## AuthMe Commands
|
||||
You can use the following commands to use the features of AuthMe. Mandatory arguments are marked with `< >`
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package tools.docs.config;
|
||||
|
||||
import com.github.authme.configme.SettingsManager;
|
||||
import com.github.authme.configme.resource.YamlFileResource;
|
||||
import fr.xephi.authme.settings.properties.AuthMeSettingsRetriever;
|
||||
import fr.xephi.authme.util.FileUtils;
|
||||
import tools.utils.AutoToolTask;
|
||||
import tools.utils.FileIoUtils;
|
||||
import tools.utils.TagValueHolder;
|
||||
import tools.utils.ToolsConstants;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Task for updating the config docs page.
|
||||
*/
|
||||
public class UpdateConfigPageTask implements AutoToolTask {
|
||||
|
||||
private static final String TEMPLATE_FILE = ToolsConstants.TOOLS_SOURCE_ROOT + "docs/config/config.tpl.md";
|
||||
private static final String OUTPUT_FILE = ToolsConstants.DOCS_FOLDER + "config.md";
|
||||
|
||||
@Override
|
||||
public String getTaskName() {
|
||||
return "updateConfigPage";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeDefault() {
|
||||
File config = null;
|
||||
try {
|
||||
// Create empty temporary .yml file and save the config to it
|
||||
config = File.createTempFile("authme-config-", ".yml");
|
||||
SettingsManager settingsManager = new SettingsManager(
|
||||
new YamlFileResource(config), null, AuthMeSettingsRetriever.buildConfigurationData());
|
||||
settingsManager.save();
|
||||
|
||||
// Get the contents and generate template file
|
||||
TagValueHolder tagValueHolder = TagValueHolder.create()
|
||||
.put("config", FileIoUtils.readFromFile(config.toPath()));
|
||||
FileIoUtils.generateFileFromTemplate(TEMPLATE_FILE, OUTPUT_FILE, tagValueHolder);
|
||||
System.out.println("Wrote to '" + OUTPUT_FILE + "'");
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
} finally {
|
||||
FileUtils.delete(config);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<!-- {gen_warning} -->
|
||||
<!-- File auto-generated on {gen_date}. See docs/config/config.tpl.md -->
|
||||
|
||||
## AuthMe Configuration
|
||||
The first time you run AuthMe it will create a config.yml file in the plugins/AuthMe folder,
|
||||
with which you can configure various settings. This following is the initial contents of
|
||||
the generated config.yml file.
|
||||
|
||||
```yml
|
||||
{config}
|
||||
```
|
||||
|
||||
To change settings on a running server, save your changes to config.yml and use
|
||||
`/authme reload`.
|
||||
|
||||
{gen_footer}
|
||||
@@ -2,13 +2,12 @@ package tools.docs.hashmethods;
|
||||
|
||||
import fr.xephi.authme.security.HashAlgorithm;
|
||||
import tools.utils.AutoToolTask;
|
||||
import tools.utils.FileUtils;
|
||||
import tools.utils.FileIoUtils;
|
||||
import tools.utils.TagValue.NestedTagValue;
|
||||
import tools.utils.TagValueHolder;
|
||||
import tools.utils.ToolsConstants;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* Task for generating the markdown page describing the AuthMe hash algorithms.
|
||||
@@ -20,11 +19,6 @@ public class HashAlgorithmsDescriptionTask implements AutoToolTask {
|
||||
private static final String CUR_FOLDER = ToolsConstants.TOOLS_SOURCE_ROOT + "docs/hashmethods/";
|
||||
private static final String OUTPUT_FILE = ToolsConstants.DOCS_FOLDER + "hash_algorithms.md";
|
||||
|
||||
@Override
|
||||
public void execute(Scanner scanner) {
|
||||
executeDefault();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeDefault() {
|
||||
// Gather info and construct a row for each method
|
||||
@@ -34,7 +28,8 @@ public class HashAlgorithmsDescriptionTask implements AutoToolTask {
|
||||
|
||||
// Write to the docs file
|
||||
TagValueHolder tags = TagValueHolder.create().put("algorithms", methodRows);
|
||||
FileUtils.generateFileFromTemplate(CUR_FOLDER + "hash_algorithms.tpl.md", OUTPUT_FILE, tags);
|
||||
FileIoUtils.generateFileFromTemplate(CUR_FOLDER + "hash_algorithms.tpl.md", OUTPUT_FILE, tags);
|
||||
System.out.println("Wrote to '" + OUTPUT_FILE + "'");
|
||||
}
|
||||
|
||||
private static NestedTagValue constructMethodRows(Map<HashAlgorithm, MethodDescription> descriptions) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- {gen_warning} -->
|
||||
<!-- File auto-generated on {gen_date}. See hashmethods/hash_algorithms.tpl.md -->
|
||||
<!-- File auto-generated on {gen_date}. See docs/hashmethods/hash_algorithms.tpl.md -->
|
||||
|
||||
## Hash Algorithms
|
||||
AuthMe supports the following hash algorithms for storing your passwords safely.
|
||||
|
||||
@@ -2,15 +2,17 @@ package tools.docs.permissions;
|
||||
|
||||
import fr.xephi.authme.ClassCollector;
|
||||
import fr.xephi.authme.permission.PermissionNode;
|
||||
import tools.utils.FileUtils;
|
||||
import tools.utils.FileIoUtils;
|
||||
import tools.utils.ToolsConstants;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Gatherer to generate up-to-date lists of the AuthMe permission nodes.
|
||||
@@ -27,6 +29,11 @@ public class PermissionNodesGatherer {
|
||||
+ "(.*?)\\s+\\*/" // Capture everything until we encounter '*/'
|
||||
+ "\\s+([A-Z_]+)\\("); // Match the enum name (e.g. 'LOGIN'), until before the first '('
|
||||
|
||||
/**
|
||||
* List of all enum classes that implement the {@link PermissionNode} interface.
|
||||
*/
|
||||
private List<Class<? extends PermissionNode>> permissionClasses;
|
||||
|
||||
/**
|
||||
* Return a sorted collection of all permission nodes, including its JavaDoc description.
|
||||
*
|
||||
@@ -39,14 +46,27 @@ public class PermissionNodesGatherer {
|
||||
result.put("authme.player.*", "Permission to use all player (non-admin) commands.");
|
||||
result.put("authme.player.email", "Grants all email permissions.");
|
||||
|
||||
new ClassCollector(ToolsConstants.MAIN_SOURCE_ROOT, "")
|
||||
.collectClasses(PermissionNode.class)
|
||||
.stream()
|
||||
.filter(Class::isEnum)
|
||||
.forEach(clz -> addDescriptionsForClass((Class<T>) clz, result));
|
||||
getPermissionClasses().forEach(clz -> addDescriptionsForClass((Class<T>) clz, result));
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all enum classes implementing the PermissionNode interface.
|
||||
*
|
||||
* @return all permission node enums
|
||||
*/
|
||||
public List<Class<? extends PermissionNode>> getPermissionClasses() {
|
||||
if (permissionClasses == null) {
|
||||
ClassCollector classCollector = new ClassCollector(ToolsConstants.MAIN_SOURCE_ROOT, "");
|
||||
permissionClasses = classCollector
|
||||
.collectClasses(PermissionNode.class)
|
||||
.stream()
|
||||
.filter(Class::isEnum)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
return permissionClasses;
|
||||
}
|
||||
|
||||
private <T extends Enum<T> & PermissionNode> void addDescriptionsForClass(Class<T> clazz,
|
||||
Map<String, String> descriptions) {
|
||||
String classSource = getSourceForClass(clazz);
|
||||
@@ -83,7 +103,7 @@ public class PermissionNodesGatherer {
|
||||
*/
|
||||
private static <T extends Enum<T> & PermissionNode> String getSourceForClass(Class<T> clazz) {
|
||||
String classFile = ToolsConstants.MAIN_SOURCE_ROOT + clazz.getName().replace(".", "/") + ".java";
|
||||
return FileUtils.readFromFile(classFile);
|
||||
return FileIoUtils.readFromFile(classFile);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
package tools.docs.permissions;
|
||||
|
||||
import tools.utils.AutoToolTask;
|
||||
import tools.utils.FileUtils;
|
||||
import tools.utils.FileIoUtils;
|
||||
import tools.utils.TagValue.NestedTagValue;
|
||||
import tools.utils.TagValueHolder;
|
||||
import tools.utils.ToolsConstants;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* Task responsible for formatting a permissions node list and
|
||||
@@ -23,23 +22,13 @@ public class PermissionsListWriter implements AutoToolTask {
|
||||
return "writePermissionsList";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Scanner scanner) {
|
||||
generateAndWriteFile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeDefault() {
|
||||
generateAndWriteFile();
|
||||
}
|
||||
|
||||
private static void generateAndWriteFile() {
|
||||
final NestedTagValue permissionsTagValue = generatePermissionsList();
|
||||
|
||||
TagValueHolder tags = TagValueHolder.create().put("nodes", permissionsTagValue);
|
||||
FileUtils.generateFileFromTemplate(TEMPLATE_FILE, PERMISSIONS_OUTPUT_FILE, tags);
|
||||
FileIoUtils.generateFileFromTemplate(TEMPLATE_FILE, PERMISSIONS_OUTPUT_FILE, tags);
|
||||
System.out.println("Wrote to '" + PERMISSIONS_OUTPUT_FILE + "'");
|
||||
System.out.println("Before committing, please verify the output!");
|
||||
}
|
||||
|
||||
private static NestedTagValue generatePermissionsList() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- {gen_warning} -->
|
||||
<!-- File auto-generated on {gen_date}. See permissions/permission_nodes.tpl.md -->
|
||||
<!-- File auto-generated on {gen_date}. See docs/permissions/permission_nodes.tpl.md -->
|
||||
|
||||
## AuthMe Permission Nodes
|
||||
The following are the permission nodes that are currently supported by the latest dev builds.
|
||||
|
||||
@@ -3,14 +3,13 @@ package tools.docs.translations;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import tools.docs.translations.TranslationsGatherer.TranslationInfo;
|
||||
import tools.utils.AutoToolTask;
|
||||
import tools.utils.FileUtils;
|
||||
import tools.utils.FileIoUtils;
|
||||
import tools.utils.TagValue.NestedTagValue;
|
||||
import tools.utils.TagValueHolder;
|
||||
import tools.utils.ToolsConstants;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.Scanner;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.google.common.base.Objects.firstNonNull;
|
||||
@@ -42,11 +41,6 @@ public class TranslationPageGenerator implements AutoToolTask {
|
||||
return "updateTranslations";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Scanner scanner) {
|
||||
executeDefault();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeDefault() {
|
||||
NestedTagValue translationValuesHolder = new NestedTagValue();
|
||||
@@ -63,7 +57,8 @@ public class TranslationPageGenerator implements AutoToolTask {
|
||||
}
|
||||
|
||||
TagValueHolder tags = TagValueHolder.create().put("languages", translationValuesHolder);
|
||||
FileUtils.generateFileFromTemplate(TEMPLATE_FILE, DOCS_PAGE, tags);
|
||||
FileIoUtils.generateFileFromTemplate(TEMPLATE_FILE, DOCS_PAGE, tags);
|
||||
System.out.println("Wrote to '" + DOCS_PAGE + "'");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- {gen_warning} -->
|
||||
<!-- File auto-generated on {gen_date}. See translations/translations.tpl.md -->
|
||||
<!-- File auto-generated on {gen_date}. See docs/translations/translations.tpl.md -->
|
||||
|
||||
# AuthMe Translations
|
||||
The following translations are available in AuthMe. Set `messagesLanguage` to the language code
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
package tools.filegeneration;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import fr.xephi.authme.command.CommandDescription;
|
||||
import fr.xephi.authme.command.CommandInitializer;
|
||||
import fr.xephi.authme.command.CommandUtils;
|
||||
import fr.xephi.authme.permission.DefaultPermission;
|
||||
import fr.xephi.authme.permission.PermissionNode;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import tools.docs.permissions.PermissionNodesGatherer;
|
||||
import tools.utils.AutoToolTask;
|
||||
import tools.utils.FileIoUtils;
|
||||
import tools.utils.ToolsConstants;
|
||||
|
||||
import java.io.StringReader;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Generates the command and permission section of plugin.yml.
|
||||
*/
|
||||
public class GeneratePluginYml implements AutoToolTask {
|
||||
|
||||
private static final String PLUGIN_YML_FILE = ToolsConstants.MAIN_RESOURCES_ROOT + "plugin.yml";
|
||||
|
||||
private static final Map<String, String> WILDCARD_PERMISSIONS = ImmutableMap.of(
|
||||
"authme.player.*", "Gives access to all player commands",
|
||||
"authme.admin.*", "Gives access to all admin commands",
|
||||
"authme.player.email", "Gives access to all email commands");
|
||||
|
||||
private List<PermissionNode> permissionNodes;
|
||||
|
||||
private String pluginYmlStart;
|
||||
|
||||
@Override
|
||||
public void executeDefault() {
|
||||
FileConfiguration configuration = loadPartialPluginYmlFile();
|
||||
|
||||
configuration.set("commands", generateCommands());
|
||||
configuration.set("permissions", generatePermissions());
|
||||
|
||||
FileIoUtils.writeToFile(PLUGIN_YML_FILE,
|
||||
pluginYmlStart + "\n" + configuration.saveToString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTaskName() {
|
||||
return "generatePluginYml";
|
||||
}
|
||||
|
||||
/**
|
||||
* Because some parts above the commands section have placeholders that aren't valid YAML, we need
|
||||
* to split the contents into an upper part that we ignore and a lower part we load as YAML. When
|
||||
* saving we prepend the YAML export with the stripped off part of the file again.
|
||||
*
|
||||
* @return file configuration with the lower part of the plugin.yml file
|
||||
*/
|
||||
private FileConfiguration loadPartialPluginYmlFile() {
|
||||
List<String> pluginYmlLines = FileIoUtils.readLinesFromFile(Paths.get(PLUGIN_YML_FILE));
|
||||
int lineNr = 0;
|
||||
for (String line : pluginYmlLines) {
|
||||
if (line.equals("commands:")) {
|
||||
break;
|
||||
}
|
||||
++lineNr;
|
||||
}
|
||||
if (lineNr == pluginYmlLines.size()) {
|
||||
throw new IllegalStateException("Could not find line starting 'commands:' section");
|
||||
}
|
||||
pluginYmlStart = String.join("\n", pluginYmlLines.subList(0, lineNr));
|
||||
String yamlContents = String.join("\n", pluginYmlLines.subList(lineNr, pluginYmlLines.size()));
|
||||
return YamlConfiguration.loadConfiguration(new StringReader(yamlContents));
|
||||
}
|
||||
|
||||
private static Map<String, Object> generateCommands() {
|
||||
Collection<CommandDescription> commands = new CommandInitializer().getCommands();
|
||||
Map<String, Object> entries = new LinkedHashMap<>();
|
||||
for (CommandDescription command : commands) {
|
||||
entries.put(command.getLabels().get(0), buildCommandEntry(command));
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
|
||||
private Map<String, Object> generatePermissions() {
|
||||
PermissionNodesGatherer gatherer = new PermissionNodesGatherer();
|
||||
Map<String, String> permissionDescriptions = gatherer.gatherNodesWithJavaDoc();
|
||||
|
||||
permissionNodes = gatherer.getPermissionClasses().stream()
|
||||
// Note ljacqu 20161023: The compiler fails if we use method references below
|
||||
.map(clz -> clz.getEnumConstants())
|
||||
.flatMap((PermissionNode[] nodes) -> Arrays.stream(nodes))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
Map<String, Object> descriptions = new TreeMap<>();
|
||||
for (PermissionNode node : permissionNodes) {
|
||||
descriptions.put(node.getNode(), buildPermissionEntry(node, permissionDescriptions.get(node.getNode())));
|
||||
}
|
||||
addWildcardPermissions(descriptions);
|
||||
return descriptions;
|
||||
}
|
||||
|
||||
private void addWildcardPermissions(Map<String, Object> permissions) {
|
||||
for (Map.Entry<String, String> entry : WILDCARD_PERMISSIONS.entrySet()) {
|
||||
permissions.put(entry.getKey(),
|
||||
buildWildcardPermissionEntry(entry.getValue(), gatherChildren(entry.getKey())));
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, Boolean> gatherChildren(String parentNode) {
|
||||
String parentPath = parentNode.replaceAll("\\.\\*$", "");
|
||||
|
||||
Map<String, Boolean> children = new TreeMap<>();
|
||||
for (PermissionNode node : permissionNodes) {
|
||||
if (node.getNode().startsWith(parentPath)) {
|
||||
children.put(node.getNode(), Boolean.TRUE);
|
||||
}
|
||||
}
|
||||
return children;
|
||||
}
|
||||
|
||||
private static Map<String, Object> buildCommandEntry(CommandDescription command) {
|
||||
if (command.getLabels().size() > 1) {
|
||||
return ImmutableMap.of(
|
||||
"description", command.getDescription(),
|
||||
"usage", buildUsage(command),
|
||||
"aliases", command.getLabels().subList(1, command.getLabels().size()));
|
||||
} else {
|
||||
return ImmutableMap.of(
|
||||
"description", command.getDescription(),
|
||||
"usage", buildUsage(command));
|
||||
}
|
||||
}
|
||||
|
||||
private static String buildUsage(CommandDescription command) {
|
||||
if (!command.getArguments().isEmpty()) {
|
||||
return CommandUtils.buildSyntax(command);
|
||||
}
|
||||
final String commandStart = "/" + command.getLabels().get(0);
|
||||
String usage = commandStart + " " + command.getChildren()
|
||||
.stream()
|
||||
.filter(cmd -> !cmd.getLabels().contains("help"))
|
||||
.map(cmd -> cmd.getLabels().get(0))
|
||||
.collect(Collectors.joining("|"));
|
||||
return usage.trim();
|
||||
}
|
||||
|
||||
private static Map<String, Object> buildPermissionEntry(PermissionNode permissionNode, String description) {
|
||||
return ImmutableMap.of(
|
||||
"description", description,
|
||||
"default", convertDefaultPermission(permissionNode.getDefaultPermission()));
|
||||
}
|
||||
|
||||
private static Map<String, Object> buildWildcardPermissionEntry(String description, Map<String, Boolean> children) {
|
||||
return ImmutableMap.of(
|
||||
"description", description,
|
||||
"children", children);
|
||||
}
|
||||
|
||||
private static Object convertDefaultPermission(DefaultPermission defaultPermission) {
|
||||
switch (defaultPermission) {
|
||||
// Returning true/false as booleans will make SnakeYAML avoid using quotes
|
||||
case ALLOWED: return true;
|
||||
case NOT_ALLOWED: return false;
|
||||
case OP_ONLY: return "op";
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown default permission '" + defaultPermission + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
package tools.helptranslation;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import de.bananaco.bpermissions.imp.YamlConfiguration;
|
||||
import fr.xephi.authme.command.CommandDescription;
|
||||
import fr.xephi.authme.command.CommandInitializer;
|
||||
import fr.xephi.authme.command.CommandUtils;
|
||||
import fr.xephi.authme.command.help.HelpMessage;
|
||||
import fr.xephi.authme.command.help.HelpSection;
|
||||
import org.bukkit.configuration.MemorySection;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.google.common.collect.Lists.newArrayList;
|
||||
|
||||
/**
|
||||
* Verifies a help messages translation.
|
||||
*/
|
||||
public class HelpTranslationVerifier {
|
||||
|
||||
private final FileConfiguration configuration;
|
||||
|
||||
// missing and unknown HelpSection and HelpMessage entries
|
||||
private final List<String> missingSections = new ArrayList<>();
|
||||
private final List<String> unknownSections = new ArrayList<>();
|
||||
// missing and unknown command entries
|
||||
private final List<String> missingCommands = new ArrayList<>();
|
||||
private final List<String> unknownCommands = new ArrayList<>();
|
||||
|
||||
public HelpTranslationVerifier(File translation) {
|
||||
this.configuration = YamlConfiguration.loadConfiguration(translation);
|
||||
checkFile();
|
||||
}
|
||||
|
||||
private void checkFile() {
|
||||
checkHelpSections();
|
||||
checkCommands();
|
||||
}
|
||||
|
||||
public List<String> getMissingSections() {
|
||||
return missingSections;
|
||||
}
|
||||
|
||||
public List<String> getUnknownSections() {
|
||||
return unknownSections;
|
||||
}
|
||||
|
||||
public List<String> getMissingCommands() {
|
||||
// All entries start with "command.", so remove that
|
||||
return missingCommands.stream()
|
||||
.map(s -> s.substring(9)).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public List<String> getUnknownCommands() {
|
||||
// All entries start with "command.", so remove that
|
||||
return unknownCommands.stream()
|
||||
.map(s -> s.substring(9)).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that the file has the expected entries for {@link HelpSection} and {@link HelpMessage}.
|
||||
*/
|
||||
private void checkHelpSections() {
|
||||
Set<String> knownSections = Arrays.stream(HelpSection.values())
|
||||
.map(HelpSection::getKey).collect(Collectors.toSet());
|
||||
knownSections.addAll(Arrays.stream(HelpMessage.values()).map(HelpMessage::getKey).collect(Collectors.toSet()));
|
||||
knownSections.addAll(Arrays.asList("common.defaultPermissions.notAllowed",
|
||||
"common.defaultPermissions.opOnly", "common.defaultPermissions.allowed"));
|
||||
Set<String> sectionKeys = getLeafKeys("section");
|
||||
sectionKeys.addAll(getLeafKeys("common"));
|
||||
|
||||
if (sectionKeys.isEmpty()) {
|
||||
missingSections.addAll(knownSections);
|
||||
} else {
|
||||
missingSections.addAll(Sets.difference(knownSections, sectionKeys));
|
||||
unknownSections.addAll(Sets.difference(sectionKeys, knownSections));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that the file has the expected entries for AuthMe commands.
|
||||
*/
|
||||
private void checkCommands() {
|
||||
Set<String> commandPaths = buildCommandPaths();
|
||||
Set<String> existingKeys = getLeafKeys("commands");
|
||||
if (existingKeys.isEmpty()) {
|
||||
missingCommands.addAll(commandPaths); // commandPaths should be empty in this case
|
||||
} else {
|
||||
missingCommands.addAll(Sets.difference(commandPaths, existingKeys));
|
||||
unknownCommands.addAll(Sets.difference(existingKeys, commandPaths));
|
||||
}
|
||||
}
|
||||
|
||||
private Set<String> buildCommandPaths() {
|
||||
Set<String> commandPaths = new LinkedHashSet<>();
|
||||
for (CommandDescription command : new CommandInitializer().getCommands()) {
|
||||
commandPaths.addAll(getYamlPaths(command));
|
||||
command.getChildren().forEach(child -> commandPaths.addAll(getYamlPaths(child)));
|
||||
}
|
||||
return commandPaths;
|
||||
}
|
||||
|
||||
private List<String> getYamlPaths(CommandDescription command) {
|
||||
// e.g. commands.authme.register
|
||||
String commandPath = "commands." + CommandUtils.constructParentList(command).stream()
|
||||
.map(cmd -> cmd.getLabels().get(0))
|
||||
.collect(Collectors.joining("."));
|
||||
// The entire command is not present, so just add it as a missing command and don't return any YAML path
|
||||
if (!configuration.contains(commandPath)) {
|
||||
missingCommands.add(commandPath);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
// Entries each command can have
|
||||
List<String> paths = newArrayList(commandPath + ".description", commandPath + ".detailedDescription");
|
||||
|
||||
// Add argument entries that may exist
|
||||
for (int argIndex = 1; argIndex <= command.getArguments().size(); ++argIndex) {
|
||||
String argPath = String.format("%s.arg%d", commandPath, argIndex);
|
||||
paths.add(argPath + ".label");
|
||||
paths.add(argPath + ".description");
|
||||
}
|
||||
return paths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the leaf keys of the section at the given path of the file configuration.
|
||||
*
|
||||
* @param path the path whose leaf keys should be retrieved
|
||||
* @return leaf keys of the memory section,
|
||||
* empty set if the configuration does not have a memory section at the given path
|
||||
*/
|
||||
private Set<String> getLeafKeys(String path) {
|
||||
if (!(configuration.get(path) instanceof MemorySection)) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
MemorySection memorySection = (MemorySection) configuration.get(path);
|
||||
|
||||
// MemorySection#getKeys(true) returns all keys on all levels, e.g. if the configuration has
|
||||
// 'commands.authme.register' then it also has 'commands.authme' and 'commands'. We can traverse each node and
|
||||
// build its parents (e.g. for commands.authme.register.description: commands.authme.register, commands.authme,
|
||||
// and commands, which we can remove from the collection since we know they are not a leaf.
|
||||
Set<String> leafKeys = memorySection.getKeys(true);
|
||||
Set<String> allKeys = new HashSet<>(leafKeys);
|
||||
|
||||
for (String key : allKeys) {
|
||||
List<String> pathParts = Arrays.asList(key.split("\\."));
|
||||
|
||||
// We perform construction of parents & their removal in reverse order so we can build the lowest-level
|
||||
// parent of a node first. As soon as the parent doesn't exist in the set already, we know we can continue
|
||||
// with the next node since another node has already removed the concerned parents.
|
||||
for (int i = pathParts.size() - 1; i > 0; --i) {
|
||||
// e.g. for commands.authme.register -> i = {2, 1} => {commands.authme, commands}
|
||||
String parentPath = String.join(".", pathParts.subList(0, i));
|
||||
if (!leafKeys.remove(parentPath)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return leafKeys.stream().map(leaf -> path + "." + leaf).collect(Collectors.toSet());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package tools.helptranslation;
|
||||
|
||||
import tools.utils.ToolTask;
|
||||
import tools.utils.ToolsConstants;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Scanner;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Verifies the help translations for validity and completeness.
|
||||
*/
|
||||
public class VerifyHelpTranslations implements ToolTask {
|
||||
|
||||
private static final Pattern HELP_MESSAGE_PATTERN = Pattern.compile("help_[a-z]{2,7}\\.yml");
|
||||
private static final String FOLDER = ToolsConstants.MAIN_RESOURCES_ROOT + "messages/";
|
||||
|
||||
@Override
|
||||
public String getTaskName() {
|
||||
return "verifyHelpTranslations";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Scanner scanner) {
|
||||
System.out.println("Check specific language file?");
|
||||
System.out.println("Enter the language code for a specific file (e.g. 'it' for help_it.yml)");
|
||||
System.out.println("Empty line will check all files in the resources messages folder (default)");
|
||||
|
||||
String language = scanner.nextLine();
|
||||
if (language.isEmpty()) {
|
||||
getHelpTranslations().forEach(this::processFile);
|
||||
} else {
|
||||
processFile(new File(FOLDER, "help_" + language + ".yml"));
|
||||
}
|
||||
}
|
||||
|
||||
private void processFile(File file) {
|
||||
System.out.println("Checking '" + file.getName() + "'");
|
||||
HelpTranslationVerifier verifier = new HelpTranslationVerifier(file);
|
||||
|
||||
// Check and output errors
|
||||
if (!verifier.getMissingSections().isEmpty()) {
|
||||
System.out.println("Missing sections: " + String.join(", ", verifier.getMissingSections()));
|
||||
}
|
||||
if (!verifier.getUnknownSections().isEmpty()) {
|
||||
System.out.println("Unknown sections: " + String.join(", ", verifier.getUnknownSections()));
|
||||
}
|
||||
if (!verifier.getMissingCommands().isEmpty()) {
|
||||
System.out.println("Missing command entries: " + String.join(", ", verifier.getMissingCommands()));
|
||||
}
|
||||
if (!verifier.getUnknownCommands().isEmpty()) {
|
||||
System.out.println("Unknown command entries: " + String.join(", ", verifier.getUnknownCommands()));
|
||||
}
|
||||
}
|
||||
|
||||
private static List<File> getHelpTranslations() {
|
||||
File[] files = new File(FOLDER).listFiles();
|
||||
if (files == null) {
|
||||
throw new IllegalStateException("Could not get files from '" + FOLDER + "'");
|
||||
}
|
||||
List<File> helpFiles = Arrays.stream(files)
|
||||
.filter(file -> HELP_MESSAGE_PATTERN.matcher(file.getName()).matches())
|
||||
.collect(Collectors.toList());
|
||||
if (helpFiles.isEmpty()) {
|
||||
throw new IllegalStateException("Could not get any matching files!");
|
||||
}
|
||||
return helpFiles;
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ import com.google.common.collect.Multimap;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import tools.utils.FileUtils;
|
||||
import tools.utils.FileIoUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
@@ -104,7 +104,7 @@ public class MessageFileVerifier {
|
||||
* @param defaultMessages The collection of default messages
|
||||
*/
|
||||
public void addMissingKeys(FileConfiguration defaultMessages) {
|
||||
final List<String> fileLines = FileUtils.readLinesFromFile(messagesFile.toPath());
|
||||
final List<String> fileLines = FileIoUtils.readLinesFromFile(messagesFile.toPath());
|
||||
|
||||
List<MissingKey> keysToAdd = new ArrayList<>();
|
||||
for (MissingKey entry : missingKeys) {
|
||||
@@ -135,7 +135,7 @@ public class MessageFileVerifier {
|
||||
addCommentForMissingTags(fileLines, key, entry.getValue());
|
||||
}
|
||||
|
||||
FileUtils.writeToFile(messagesFile.toPath(), String.join("\n", fileLines));
|
||||
FileIoUtils.writeToFile(messagesFile.toPath(), String.join("\n", fileLines));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,7 +7,7 @@ import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import tools.messages.MessageFileVerifier;
|
||||
import tools.messages.VerifyMessagesTask;
|
||||
import tools.utils.FileUtils;
|
||||
import tools.utils.FileIoUtils;
|
||||
import tools.utils.ToolTask;
|
||||
import tools.utils.ToolsConstants;
|
||||
|
||||
@@ -108,9 +108,9 @@ public class ImportMessagesTask implements ToolTask {
|
||||
* @param file The file whose to-do comments should be removed
|
||||
*/
|
||||
private static void removeAllTodoComments(String file) {
|
||||
String contents = FileUtils.readFromFile(file);
|
||||
String contents = FileIoUtils.readFromFile(file);
|
||||
String regex = "^# TODO .*$";
|
||||
contents = Pattern.compile(regex, Pattern.MULTILINE).matcher(contents).replaceAll("");
|
||||
FileUtils.writeToFile(file, contents);
|
||||
FileIoUtils.writeToFile(file, contents);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package tools.messages.translation;
|
||||
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import tools.utils.FileUtils;
|
||||
import tools.utils.FileIoUtils;
|
||||
import tools.utils.ToolsConstants;
|
||||
|
||||
import java.io.File;
|
||||
@@ -31,7 +31,7 @@ public class WriteAllExportsTask extends ExportMessagesTask {
|
||||
for (File file : messageFiles) {
|
||||
String code = file.getName().substring("messages_".length(), file.getName().length() - ".yml".length());
|
||||
String json = convertToJson(code, defaultMessages, YamlConfiguration.loadConfiguration(file));
|
||||
FileUtils.writeToFile(OUTPUT_FOLDER + "messages_" + code + ".json", json);
|
||||
FileIoUtils.writeToFile(OUTPUT_FOLDER + "messages_" + code + ".json", json);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package tools.utils;
|
||||
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* Interface for tasks that can be run automatically, i.e. without any user input.
|
||||
*/
|
||||
@@ -10,4 +12,9 @@ public interface AutoToolTask extends ToolTask {
|
||||
*/
|
||||
void executeDefault();
|
||||
|
||||
@Override
|
||||
default void execute(Scanner scanner) {
|
||||
executeDefault();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+8
-4
@@ -9,11 +9,11 @@ import java.nio.file.StandardOpenOption;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Utility class for reading from and writing to files.
|
||||
* Utility class for I/O operations on files.
|
||||
*/
|
||||
public final class FileUtils {
|
||||
public final class FileIoUtils {
|
||||
|
||||
private FileUtils() {
|
||||
private FileIoUtils() {
|
||||
}
|
||||
|
||||
public static void generateFileFromTemplate(String templateFile, String destinationFile, TagValueHolder tags) {
|
||||
@@ -43,8 +43,12 @@ public final class FileUtils {
|
||||
}
|
||||
|
||||
public static String readFromFile(String file) {
|
||||
return readFromFile(Paths.get(file));
|
||||
}
|
||||
|
||||
public static String readFromFile(Path file) {
|
||||
try {
|
||||
return new String(Files.readAllBytes(Paths.get(file)), StandardCharsets.UTF_8);
|
||||
return new String(Files.readAllBytes(file), StandardCharsets.UTF_8);
|
||||
} catch (IOException e) {
|
||||
throw new UnsupportedOperationException("Could not read from file '" + file + "'", e);
|
||||
}
|
||||
@@ -9,9 +9,6 @@ public final class ToolsConstants {
|
||||
|
||||
public static final String MAIN_RESOURCES_ROOT = "src/main/resources/";
|
||||
|
||||
// Add specific `fr.xephi.authme` package as not to include the tool tasks in the `tools` package
|
||||
public static final String TEST_SOURCE_ROOT = "src/test/java/fr/xephi/authme";
|
||||
|
||||
public static final String TOOLS_SOURCE_ROOT = "src/test/java/tools/";
|
||||
|
||||
public static final String DOCS_FOLDER = "docs/";
|
||||
|
||||
Reference in New Issue
Block a user