From a8b3fe2648d2c1aac7809576391a4b0aed03c936 Mon Sep 17 00:00:00 2001 From: ljacqu Date: Sat, 5 Dec 2015 12:08:09 +0100 Subject: [PATCH 01/17] RegisterAdminCommand - fix wrong message key --- .../command/executable/authme/RegisterAdminCommand.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/RegisterAdminCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/RegisterAdminCommand.java index df204200..1d7302d1 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/RegisterAdminCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/RegisterAdminCommand.java @@ -43,8 +43,12 @@ public class RegisterAdminCommand extends ExecutableCommand { final String playerPassLowerCase = playerPass.toLowerCase(); // Command logic - if (playerPassLowerCase.contains("delete") || playerPassLowerCase.contains("where") || playerPassLowerCase.contains("insert") || playerPassLowerCase.contains("modify") || playerPassLowerCase.contains("from") || playerPassLowerCase.contains("select") || playerPassLowerCase.contains(";") || playerPassLowerCase.contains("null") || !playerPassLowerCase.matches(Settings.getPassRegex)) { - m.send(sender, MessageKey.PASSWORD_IS_USERNAME_ERROR); + if (playerPassLowerCase.contains("delete") || playerPassLowerCase.contains("where") + || playerPassLowerCase.contains("insert") || playerPassLowerCase.contains("modify") + || playerPassLowerCase.contains("from") || playerPassLowerCase.contains("select") + || playerPassLowerCase.contains(";") || playerPassLowerCase.contains("null") + || !playerPassLowerCase.matches(Settings.getPassRegex)) { + m.send(sender, MessageKey.PASSWORD_MATCH_ERROR); return true; } if (playerPassLowerCase.equalsIgnoreCase(playerName)) { From e81bcf9bf7f80fdc6cf8089ed0d34bd924649164 Mon Sep 17 00:00:00 2001 From: ljacqu Date: Sat, 5 Dec 2015 14:13:20 +0100 Subject: [PATCH 02/17] Create GeneratedFileWriter and basic permission nodes list creater --- src/tools/README.md | 3 + .../PermissionNodesListCreater.java | 26 ++++++++ .../PermissionsListWriter.java | 37 +++++++++++ src/tools/permissionstree/README.md | 2 + src/tools/utils/CommentType.java | 11 ++++ src/tools/utils/GeneratedFileWriter.java | 61 +++++++++++++++++++ 6 files changed, 140 insertions(+) create mode 100644 src/tools/README.md create mode 100644 src/tools/permissionstree/PermissionNodesListCreater.java create mode 100644 src/tools/permissionstree/PermissionsListWriter.java create mode 100644 src/tools/permissionstree/README.md create mode 100644 src/tools/utils/CommentType.java create mode 100644 src/tools/utils/GeneratedFileWriter.java diff --git a/src/tools/README.md b/src/tools/README.md new file mode 100644 index 00000000..b61dabea --- /dev/null +++ b/src/tools/README.md @@ -0,0 +1,3 @@ +# About src/tools +This _tools_ folder provides helpers and extended tests useful during the development of AuthMe. +This folder is not included during the build of AuthMe. diff --git a/src/tools/permissionstree/PermissionNodesListCreater.java b/src/tools/permissionstree/PermissionNodesListCreater.java new file mode 100644 index 00000000..bfc1a3b7 --- /dev/null +++ b/src/tools/permissionstree/PermissionNodesListCreater.java @@ -0,0 +1,26 @@ +package permissionstree; + +import fr.xephi.authme.permission.AdminPermission; +import fr.xephi.authme.permission.PermissionNode; +import fr.xephi.authme.permission.PlayerPermission; + +import java.util.Set; +import java.util.TreeSet; + +/** + * Generate all permission nodes like a tree. + */ +public class PermissionNodesListCreater { + + public Set gatherNodes() { + Set nodes = new TreeSet<>(); + for (PermissionNode perm : PlayerPermission.values()) { + nodes.add(perm.getNode()); + } + for (PermissionNode perm : AdminPermission.values()) { + nodes.add(perm.getNode()); + } + return nodes; + } + +} diff --git a/src/tools/permissionstree/PermissionsListWriter.java b/src/tools/permissionstree/PermissionsListWriter.java new file mode 100644 index 00000000..2f3e40f5 --- /dev/null +++ b/src/tools/permissionstree/PermissionsListWriter.java @@ -0,0 +1,37 @@ +package permissionstree; + +import fr.xephi.authme.util.StringUtils; +import utils.CommentType; +import utils.GeneratedFileWriter; + +import java.util.Scanner; +import java.util.Set; + +/** + * Class responsible for formatting a permissions node list and + * for writing it to a file if desired. + */ +public class PermissionsListWriter { + + private static final String PERMISSIONS_TREE_FILE = "gen_permtree.txt"; + + public static void main(String[] args) { + // Ask if result should be written to file + Scanner scanner = new Scanner(System.in); + System.out.println("Write to file? [y = yes]"); + String answer = scanner.next(); + boolean writeToFile = "y".equalsIgnoreCase(answer); + + // Generate connections and output or write + PermissionNodesListCreater creater = new PermissionNodesListCreater(); + Set nodes = creater.gatherNodes(); + String output = StringUtils.join("\n", nodes); + + if (writeToFile) { + GeneratedFileWriter.createGeneratedFile(PERMISSIONS_TREE_FILE, output, CommentType.YML); + } else { + System.out.println(output); + } + } + +} diff --git a/src/tools/permissionstree/README.md b/src/tools/permissionstree/README.md new file mode 100644 index 00000000..5364c846 --- /dev/null +++ b/src/tools/permissionstree/README.md @@ -0,0 +1,2 @@ +# About +Helper script to generate a list of all permission nodes. diff --git a/src/tools/utils/CommentType.java b/src/tools/utils/CommentType.java new file mode 100644 index 00000000..fbc4c9b8 --- /dev/null +++ b/src/tools/utils/CommentType.java @@ -0,0 +1,11 @@ +package utils; + +/** + * Enum for different comment formats. + */ +public enum CommentType { + + JAVA, + YML + +} diff --git a/src/tools/utils/GeneratedFileWriter.java b/src/tools/utils/GeneratedFileWriter.java new file mode 100644 index 00000000..07f87c43 --- /dev/null +++ b/src/tools/utils/GeneratedFileWriter.java @@ -0,0 +1,61 @@ +package utils; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.util.Date; + +/** + * Utility class for writing a generated file with a timestamp. + */ +public final class GeneratedFileWriter { + + private GeneratedFileWriter() { + } + + public static void createGeneratedFile(File file, String contents, CommentType commentFormat) { + validateFile(file); + + try (OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(file))) { + osw.write(generateComment(commentFormat)); + osw.write(contents); + } catch (IOException e) { + throw new RuntimeException("Could not write to file '" + file.getName() + "'", e); + } + } + + public static void createGeneratedFile(String fileName, String contents, CommentType commentFormat) { + createGeneratedFile(new File(fileName), contents, commentFormat); + } + + private static String generateComment(CommentType commentFormat) { + String comment = "Auto-generated file, generated on " + new Date() + "\n\n"; + switch (commentFormat) { + case JAVA: + return "// " + comment; + case YML: + return "# " + comment; + default: + throw new RuntimeException("Unknown comment format '" + commentFormat + "'"); + } + } + + private static void validateFile(File file) { + if (!file.exists()) { + System.out.println("File '" + file.getName() + "' doesn't exist; attempting to create it"); + try { + boolean success = file.createNewFile(); + if (!success) { + throw new RuntimeException("Failed to create file '" + file.getName() + "'"); + } + } catch (IOException e) { + throw new RuntimeException("Could not create file '" + file.getName() + "'", e); + } + } + if (!file.canWrite()) { + throw new RuntimeException("File '" + file.getName() + "' is not writable"); + } + } + +} From c91fb469517890932f92b2832073a178814ccb57 Mon Sep 17 00:00:00 2001 From: ljacqu Date: Sat, 5 Dec 2015 15:26:50 +0100 Subject: [PATCH 03/17] Include the JavaDoc description for permission node enums --- .../PermissionNodesGatherer.java | 113 ++++++++++++++++++ .../PermissionNodesListCreater.java | 26 ---- .../PermissionsListWriter.java | 37 +++++- 3 files changed, 144 insertions(+), 32 deletions(-) create mode 100644 src/tools/permissionstree/PermissionNodesGatherer.java delete mode 100644 src/tools/permissionstree/PermissionNodesListCreater.java diff --git a/src/tools/permissionstree/PermissionNodesGatherer.java b/src/tools/permissionstree/PermissionNodesGatherer.java new file mode 100644 index 00000000..5da8841c --- /dev/null +++ b/src/tools/permissionstree/PermissionNodesGatherer.java @@ -0,0 +1,113 @@ +package permissionstree; + +import fr.xephi.authme.permission.AdminPermission; +import fr.xephi.authme.permission.PermissionNode; +import fr.xephi.authme.permission.PlayerPermission; +import fr.xephi.authme.util.StringUtils; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Gatherer to generate up-to-date lists of the AuthMe permission nodes. + */ +public class PermissionNodesGatherer { + + /** The folder in which the implementations of {@link PermissionNode} reside. */ + private static final String PERMISSION_NODE_SOURCE_FOLDER = + "src/main/java/fr/xephi/authme/permission/"; + + /** + * Regular expression that should match the JavaDoc comment above an enum, including + * the name of the enum value. The first group (i.e. {@code \\1}) should be the JavaDoc description; + * the second group should contain the enum value. + */ + private static final Pattern JAVADOC_WITH_ENUM_PATTERN = Pattern.compile( + "/\\*\\*\\s+\\*" // Match starting '/**' and the '*' on the next line + + "(.*?)\\s+\\*/" // Capture everything until we encounter '*/' + + "\\s+([A-Z_]+)\\("); // Match the enum name (e.g. 'LOGIN'), until before the first '(' + + /** + * Return a sorted collection of all permission nodes. + * + * @return AuthMe permission nodes sorted alphabetically + */ + public Set gatherNodes() { + Set nodes = new TreeSet<>(); + for (PermissionNode perm : PlayerPermission.values()) { + nodes.add(perm.getNode()); + } + for (PermissionNode perm : AdminPermission.values()) { + nodes.add(perm.getNode()); + } + return nodes; + } + + /** + * Return a sorted collection of all permission nodes, including its JavaDoc description. + * + * @return Ordered map whose keys are the permission nodes and the values the associated JavaDoc + */ + public Map gatherNodesWithJavaDoc() { + Map result = new TreeMap<>(); + addDescriptionsForClass(PlayerPermission.class, result); + addDescriptionsForClass(AdminPermission.class, result); + return result; + } + + private & PermissionNode> void addDescriptionsForClass(Class clazz, + Map descriptions) { + String classSource = getSourceForClass(clazz); + Map sourceDescriptions = extractJavaDocFromSource(classSource); + + for (T perm : EnumSet.allOf(clazz)) { + String description = sourceDescriptions.get(perm.name()); + if (description == null) { + System.out.println("Note: Could not retrieve description for " + + clazz.getSimpleName() + "#" + perm.name()); + description = ""; + } + descriptions.put(perm.getNode(), description.trim()); + } + } + + private static Map extractJavaDocFromSource(String source) { + Map allMatches = new HashMap<>(); + Matcher matcher = JAVADOC_WITH_ENUM_PATTERN.matcher(source); + while (matcher.find()) { + String description = matcher.group(1); + String enumValue = matcher.group(2); + allMatches.put(enumValue, description); + } + return allMatches; + } + + /** + * Return the Java source code for the given implementation of {@link PermissionNode}. + * + * @param clazz The clazz to the get the source for + * @param The concrete class + * @return Source code of the file + */ + private static & PermissionNode> String getSourceForClass(Class clazz) { + String classFile = PERMISSION_NODE_SOURCE_FOLDER + clazz.getSimpleName() + ".java"; + Charset cs = Charset.forName("utf-8"); + try { + return StringUtils.join("\n", + Files.readAllLines(Paths.get(classFile), cs)); + } catch (IOException e) { + throw new RuntimeException("Failed to get the source for class '" + clazz.getSimpleName() + "'"); + } + } + +} diff --git a/src/tools/permissionstree/PermissionNodesListCreater.java b/src/tools/permissionstree/PermissionNodesListCreater.java deleted file mode 100644 index bfc1a3b7..00000000 --- a/src/tools/permissionstree/PermissionNodesListCreater.java +++ /dev/null @@ -1,26 +0,0 @@ -package permissionstree; - -import fr.xephi.authme.permission.AdminPermission; -import fr.xephi.authme.permission.PermissionNode; -import fr.xephi.authme.permission.PlayerPermission; - -import java.util.Set; -import java.util.TreeSet; - -/** - * Generate all permission nodes like a tree. - */ -public class PermissionNodesListCreater { - - public Set gatherNodes() { - Set nodes = new TreeSet<>(); - for (PermissionNode perm : PlayerPermission.values()) { - nodes.add(perm.getNode()); - } - for (PermissionNode perm : AdminPermission.values()) { - nodes.add(perm.getNode()); - } - return nodes; - } - -} diff --git a/src/tools/permissionstree/PermissionsListWriter.java b/src/tools/permissionstree/PermissionsListWriter.java index 2f3e40f5..7d1cd1c2 100644 --- a/src/tools/permissionstree/PermissionsListWriter.java +++ b/src/tools/permissionstree/PermissionsListWriter.java @@ -4,6 +4,7 @@ import fr.xephi.authme.util.StringUtils; import utils.CommentType; import utils.GeneratedFileWriter; +import java.util.Map; import java.util.Scanner; import java.util.Set; @@ -18,14 +19,15 @@ public class PermissionsListWriter { public static void main(String[] args) { // Ask if result should be written to file Scanner scanner = new Scanner(System.in); - System.out.println("Write to file? [y = yes]"); - String answer = scanner.next(); - boolean writeToFile = "y".equalsIgnoreCase(answer); + System.out.println("Include description? [Enter 'n' for no]"); + boolean includeDescription = !matches("n", scanner); + + System.out.println("Write to file? [Enter 'y' for yes]"); + boolean writeToFile = matches("y", scanner); + scanner.close(); // Generate connections and output or write - PermissionNodesListCreater creater = new PermissionNodesListCreater(); - Set nodes = creater.gatherNodes(); - String output = StringUtils.join("\n", nodes); + String output = generatedOutput(includeDescription); if (writeToFile) { GeneratedFileWriter.createGeneratedFile(PERMISSIONS_TREE_FILE, output, CommentType.YML); @@ -34,4 +36,27 @@ public class PermissionsListWriter { } } + private static String generatedOutput(boolean includeDescription) { + PermissionNodesGatherer creater = new PermissionNodesGatherer(); + if (!includeDescription) { + Set nodes = creater.gatherNodes(); + return StringUtils.join("\n", nodes); + } + + Map permissions = creater.gatherNodesWithJavaDoc(); + StringBuilder sb = new StringBuilder(); + for (Map.Entry entry : permissions.entrySet()) { + sb.append(entry.getKey()) + .append(": ") + .append(entry.getValue()) + .append("\n"); + } + return sb.toString(); + } + + private static boolean matches(String answer, Scanner sc) { + String userInput = sc.nextLine(); + return answer.equalsIgnoreCase(userInput); + } + } From 1db24adb5d7eaa84686fd401d995ecd8952e1c40 Mon Sep 17 00:00:00 2001 From: Xephi Date: Sat, 5 Dec 2015 19:00:44 +0100 Subject: [PATCH 04/17] Add a wildcard command permission --- .../authme/command/CommandInitializer.java | 20 +++++++++---------- .../authme/permission/AdminPermission.java | 7 ++++++- .../authme/permission/PlayerPermission.java | 7 ++++++- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/main/java/fr/xephi/authme/command/CommandInitializer.java b/src/main/java/fr/xephi/authme/command/CommandInitializer.java index a8dceff0..664c59e5 100644 --- a/src/main/java/fr/xephi/authme/command/CommandInitializer.java +++ b/src/main/java/fr/xephi/authme/command/CommandInitializer.java @@ -90,7 +90,7 @@ public final class CommandInitializer { .detailedDescription("Register the specified player with the specified password.") .withArgument("player", "Player name", false) .withArgument("password", "Password", false) - .permissions(OP_ONLY, AdminPermission.REGISTER) + .permissions(OP_ONLY, AdminPermission.REGISTER, AdminPermission.ALL) .executableCommand(new RegisterAdminCommand()) .build(); @@ -101,7 +101,7 @@ public final class CommandInitializer { .description("Unregister a player") .detailedDescription("Unregister the specified player.") .withArgument("player", "Player name", false) - .permissions(OP_ONLY, AdminPermission.UNREGISTER) + .permissions(OP_ONLY, AdminPermission.UNREGISTER, AdminPermission.ALL) .executableCommand(new UnregisterAdminCommand()) .build(); @@ -112,7 +112,7 @@ public final class CommandInitializer { .description("Enforce login player") .detailedDescription("Enforce the specified player to login.") .withArgument("player", "Online player name", true) - .permissions(OP_ONLY, PlayerPermission.CAN_LOGIN_BE_FORCED) + .permissions(OP_ONLY, PlayerPermission.CAN_LOGIN_BE_FORCED, AdminPermission.ALL) .executableCommand(new ForceLoginCommand()) .build(); @@ -124,7 +124,7 @@ public final class CommandInitializer { .detailedDescription("Change the password of a player.") .withArgument("player", "Player name", false) .withArgument("pwd", "New password", false) - .permissions(OP_ONLY, AdminPermission.CHANGE_PASSWORD) + .permissions(OP_ONLY, AdminPermission.CHANGE_PASSWORD, AdminPermission.ALL) .executableCommand(new ChangePasswordAdminCommand()) .build(); @@ -135,7 +135,7 @@ public final class CommandInitializer { .description("Player's last login") .detailedDescription("View the date of the specified players last login.") .withArgument("player", "Player name", true) - .permissions(OP_ONLY, AdminPermission.LAST_LOGIN) + .permissions(OP_ONLY, AdminPermission.LAST_LOGIN, AdminPermission.ALL) .executableCommand(new LastLoginCommand()) .build(); @@ -146,7 +146,7 @@ public final class CommandInitializer { .description("Display player accounts") .detailedDescription("Display all accounts of a player by his player name or IP.") .withArgument("player", "Player name or IP", true) - .permissions(OP_ONLY, AdminPermission.ACCOUNTS) + .permissions(OP_ONLY, AdminPermission.ACCOUNTS, AdminPermission.ALL) .executableCommand(new AccountsCommand()) .build(); @@ -156,7 +156,7 @@ public final class CommandInitializer { .labels("getemail", "getmail", "email", "mail") .description("Display player's email") .detailedDescription("Display the email address of the specified player if set.") - .permissions(OP_ONLY, AdminPermission.GET_EMAIL) + .permissions(OP_ONLY, AdminPermission.GET_EMAIL, AdminPermission.ALL) .withArgument("player", "Player name", true) .executableCommand(new GetEmailCommand()) .build(); @@ -168,7 +168,7 @@ public final class CommandInitializer { .labels("chgemail", "chgmail", "setemail", "setmail") .description("Change player's email") .detailedDescription("Change the email address of the specified player.") - .permissions(OP_ONLY, AdminPermission.CHANGE_EMAIL) + .permissions(OP_ONLY, AdminPermission.CHANGE_EMAIL, AdminPermission.ALL) .withArgument("player", "Player name", false) .withArgument("email", "Player email", false) .build(); @@ -304,7 +304,7 @@ public final class CommandInitializer { .description("Login command") .detailedDescription("Command to log in using AuthMeReloaded.") .parent(null) - .permissions(ALLOWED, PlayerPermission.LOGIN) + .permissions(ALLOWED, PlayerPermission.LOGIN, PlayerPermission.ALL_COMMANDS) .withArgument("password", "Login password", false) .build(); @@ -334,7 +334,7 @@ public final class CommandInitializer { .detailedDescription("Command to register using AuthMeReloaded.") .withArgument("password", "Password", false) .withArgument("verifyPassword", "Verify password", false) - .permissions(ALLOWED, PlayerPermission.REGISTER) + .permissions(ALLOWED, PlayerPermission.REGISTER, PlayerPermission.ALL_COMMANDS) .executableCommand(new RegisterCommand()) .build(); diff --git a/src/main/java/fr/xephi/authme/permission/AdminPermission.java b/src/main/java/fr/xephi/authme/permission/AdminPermission.java index 335875a8..5e1528fa 100644 --- a/src/main/java/fr/xephi/authme/permission/AdminPermission.java +++ b/src/main/java/fr/xephi/authme/permission/AdminPermission.java @@ -98,7 +98,12 @@ public enum AdminPermission implements PermissionNode { /** * Administrator command to reload the plugin configuration. */ - RELOAD("authme.command.admin.reload"); + RELOAD("authme.command.admin.reload"), + + /** + * Give access to all admin commands + */ + ALL("authme.command.admin.*"); /** * Permission node. diff --git a/src/main/java/fr/xephi/authme/permission/PlayerPermission.java b/src/main/java/fr/xephi/authme/permission/PlayerPermission.java index 0488a67a..38fef513 100644 --- a/src/main/java/fr/xephi/authme/permission/PlayerPermission.java +++ b/src/main/java/fr/xephi/authme/permission/PlayerPermission.java @@ -78,7 +78,12 @@ public enum PlayerPermission implements PermissionNode { /** * Permission for user to see other accounts. */ - SEE_OTHER_ACCOUNTS("authme.command.player.seeotheraccounts"); + SEE_OTHER_ACCOUNTS("authme.command.player.seeotheraccounts"), + + /** + * + */ + ALL_COMMANDS("authme.command.player.*"); /** * Permission node. From 8460725c8300637defac4ee3386e35fd2f90b324 Mon Sep 17 00:00:00 2001 From: Xephi Date: Sat, 5 Dec 2015 19:16:16 +0100 Subject: [PATCH 05/17] Part of CommandBuilder rework 1/? --- .../authme/command/CommandInitializer.java | 118 +++++++++--------- 1 file changed, 62 insertions(+), 56 deletions(-) diff --git a/src/main/java/fr/xephi/authme/command/CommandInitializer.java b/src/main/java/fr/xephi/authme/command/CommandInitializer.java index 664c59e5..f1765add 100644 --- a/src/main/java/fr/xephi/authme/command/CommandInitializer.java +++ b/src/main/java/fr/xephi/authme/command/CommandInitializer.java @@ -174,74 +174,80 @@ public final class CommandInitializer { .build(); // Register the getip command - CommandDescription getIpCommand = new CommandDescription(new GetIpCommand(), new ArrayList() { - { - add("getip"); - add("ip"); - } - }, "Get player's IP", "Get the IP address of the specified online player.", AUTHME_BASE); - getIpCommand.setCommandPermissions(AdminPermission.GET_IP, OP_ONLY); - getIpCommand.addArgument(new CommandArgumentDescription("player", "Online player name", true)); + CommandDescription getIpCommand = CommandDescription.builder() + .executableCommand(new GetIpCommand()) + .parent(AUTHME_BASE) + .labels("getip", "ip") + .description("Get player's IP") + .detailedDescription("Get the IP address of the specified online player.") + .permissions(OP_ONLY, AdminPermission.GET_IP, AdminPermission.ALL) + .withArgument("player", "Player Name", false) + .build(); + // Register the spawn command - CommandDescription spawnCommand = new CommandDescription(new SpawnCommand(), new ArrayList() { - { - add("spawn"); - add("home"); - } - }, "Teleport to spawn", "Teleport to the spawn.", AUTHME_BASE); - spawnCommand.setCommandPermissions(AdminPermission.SPAWN, OP_ONLY); + CommandDescription spawnCommand = CommandDescription.builder() + .executableCommand(new SpawnCommand()) + .parent(AUTHME_BASE) + .labels("spawn", "home") + .description("Teleport to spawn") + .detailedDescription("Teleport to the spawn") + .permissions(OP_ONLY, AdminPermission.SPAWN, AdminPermission.ALL) + .withArgument("player", "Player Name", false) + .build(); // Register the setspawn command - CommandDescription setSpawnCommand = new CommandDescription(new SetSpawnCommand(), new ArrayList() { - { - add("setspawn"); - add("chgspawn"); - } - }, "Change the spawn", "Change the player's spawn to your current position.", AUTHME_BASE); - setSpawnCommand.setCommandPermissions(AdminPermission.SET_SPAWN, OP_ONLY); + CommandDescription setSpawnCommand = CommandDescription.builder() + .executableCommand(new SetSpawnCommand()) + .parent(AUTHME_BASE) + .labels("setspawn", "chgspawn") + .description("Change the spawn") + .detailedDescription("Change the player's spawn to your current position.") + .permissions(OP_ONLY, AdminPermission.SET_SPAWN, AdminPermission.ALL) + .build(); // Register the firstspawn command - CommandDescription firstSpawnCommand = new CommandDescription(new FirstSpawnCommand(), new ArrayList() { - { - add("firstspawn"); - add("firsthome"); - } - }, "Teleport to first spawn", "Teleport to the first spawn.", AUTHME_BASE); - firstSpawnCommand.setCommandPermissions(AdminPermission.FIRST_SPAWN, OP_ONLY); + CommandDescription firstSpawnCommand = CommandDescription.builder() + .executableCommand(new FirstSpawnCommand()) + .parent(AUTHME_BASE) + .labels("firstspawn", "firsthome") + .description("Teleport to first spawn") + .detailedDescription("Teleport to the first spawn.") + .permissions(OP_ONLY, AdminPermission.FIRST_SPAWN, AdminPermission.ALL) + .build(); + // Register the setfirstspawn command - CommandDescription setFirstSpawnCommand = new CommandDescription(new SetFirstSpawnCommand(), new ArrayList() { - { - add("setfirstspawn"); - add("chgfirstspawn"); - } - }, "Change the first spawn", "Change the first player's spawn to your current position.", AUTHME_BASE); - setFirstSpawnCommand.setCommandPermissions(AdminPermission.SET_FIRST_SPAWN, OP_ONLY); + CommandDescription setFirstSpawnCommand = CommandDescription.builder() + .executableCommand(new SetFirstSpawnCommand()) + .parent(AUTHME_BASE) + .labels("setfirstspawn", "chgfirstspawn") + .description("Change the first spawn") + .detailedDescription("Change the first player's spawn to your current position.") + .permissions(OP_ONLY, AdminPermission.SET_FIRST_SPAWN, AdminPermission.ALL) + .build(); // Register the purge command - CommandDescription purgeCommand = new CommandDescription(new PurgeCommand(), new ArrayList() { - { - add("purge"); - add("delete"); - } - }, "Purge old data", "Purge old AuthMeReloaded data longer than the specified amount of days ago.", AUTHME_BASE); - purgeCommand.setCommandPermissions(AdminPermission.PURGE, OP_ONLY); - purgeCommand.addArgument(new CommandArgumentDescription("days", "Number of days", false)); + CommandDescription purgeCommand = CommandDescription.builder() + .executableCommand(new PurgeCommand()) + .parent(AUTHME_BASE) + .labels("purge", "delete") + .description("Purge old data") + .detailedDescription("Purge old AuthMeReloaded data longer than the specified amount of days ago.") + .permissions(OP_ONLY, AdminPermission.PURGE, AdminPermission.ALL) + .withArgument("days", "Number of days", false) + .build(); // Register the purgelastposition command - CommandDescription purgeLastPositionCommand = new CommandDescription(new PurgeLastPositionCommand(), new ArrayList() { - { - add("resetpos"); - add("purgelastposition"); - add("purgelastpos"); - add("resetposition"); - add("resetlastposition"); - add("resetlastpos"); - } - }, "Purge player's last position", "Purge the last know position of the specified player.", AUTHME_BASE); - purgeLastPositionCommand.setCommandPermissions(AdminPermission.PURGE_LAST_POSITION, OP_ONLY); - purgeLastPositionCommand.addArgument(new CommandArgumentDescription("player", "Player name", true)); + CommandDescription purgeLastPositionCommand = CommandDescription.builder() + .executableCommand(new PurgeLastPositionCommand()) + .parent(AUTHME_BASE) + .labels("resetpos", "purgelastposition", "purgelastpos", "resetposition", "resetlastposition", "resetlastpos") + .description("Purge player's last position") + .detailedDescription("Purge the last know position of the specified player.") + .permissions(OP_ONLY, AdminPermission.PURGE_LAST_POSITION, AdminPermission.ALL) + .withArgument("player", "Player name", false) + .build(); // Register the purgebannedplayers command CommandDescription purgeBannedPlayersCommand = new CommandDescription(new PurgeBannedPlayersCommand(), new ArrayList() { From 4d082388a549c7997e918aa09d8f5148b66d7c1c Mon Sep 17 00:00:00 2001 From: ljacqu Date: Sat, 5 Dec 2015 20:53:44 +0100 Subject: [PATCH 06/17] Create tag template / auto-generate page for all permissions incl. description --- src/tools/docs/permission_nodes.md | 41 +++++++++ .../PermissionNodesGatherer.java | 2 +- .../permissions/PermissionsListWriter.java | 86 +++++++++++++++++++ src/tools/permissions/README.md | 2 + .../permissions/permission_node_entry.tpl.md | 1 + src/tools/permissions/permission_nodes.tpl.md | 7 ++ .../PermissionsListWriter.java | 62 ------------- src/tools/permissionstree/README.md | 2 - src/tools/utils/ANewMap.java | 36 ++++++++ src/tools/utils/CommentType.java | 11 --- src/tools/utils/GeneratedFileWriter.java | 62 ++++++------- src/tools/utils/TagReplacer.java | 46 ++++++++++ src/tools/utils/ToolsConstants.java | 17 ++++ 13 files changed, 261 insertions(+), 114 deletions(-) create mode 100644 src/tools/docs/permission_nodes.md rename src/tools/{permissionstree => permissions}/PermissionNodesGatherer.java (99%) create mode 100644 src/tools/permissions/PermissionsListWriter.java create mode 100644 src/tools/permissions/README.md create mode 100644 src/tools/permissions/permission_node_entry.tpl.md create mode 100644 src/tools/permissions/permission_nodes.tpl.md delete mode 100644 src/tools/permissionstree/PermissionsListWriter.java delete mode 100644 src/tools/permissionstree/README.md create mode 100644 src/tools/utils/ANewMap.java delete mode 100644 src/tools/utils/CommentType.java create mode 100644 src/tools/utils/TagReplacer.java create mode 100644 src/tools/utils/ToolsConstants.java diff --git a/src/tools/docs/permission_nodes.md b/src/tools/docs/permission_nodes.md new file mode 100644 index 00000000..309584e4 --- /dev/null +++ b/src/tools/docs/permission_nodes.md @@ -0,0 +1,41 @@ + + + +## AuthMe Permission Nodes +The following are the permission nodes that are currently supported by the latest dev builds. + +- **authme.command.admin.accounts** – Administrator command to see all accounts associated with an user. +- **authme.command.admin.changemail** – Administrator command to set or change the email adress of an user. +- **authme.command.admin.changepassword** – Administrator command to change the password of a user. +- **authme.command.admin.converter** – Administrator command to convert old or other data to AuthMe data. +- **authme.command.admin.firstspawn** – Administrator command to teleport to the first AuthMe spawn. +- **authme.command.admin.forcelogin** – Administrator command to force-login an existing user. +- **authme.command.admin.getemail** – Administrator command to get the email address of an user, if set. +- **authme.command.admin.getip** – Administrator command to get the last known IP of an user. +- **authme.command.admin.lastlogin** – Administrator command to see the last login date and time of an user. +- **authme.command.admin.purge** – Administrator command to purge old user data. +- **authme.command.admin.purgebannedplayers** – Administrator command to purge all data associated with banned players. +- **authme.command.admin.purgelastpos** – Administrator command to purge the last position of an user. +- **authme.command.admin.register** – Administrator command to register a new user. +- **authme.command.admin.reload** – Administrator command to reload the plugin configuration. +- **authme.command.admin.setfirstspawn** – Administrator command to set the first AuthMe spawn. +- **authme.command.admin.setspawn** – Administrator command to set the AuthMe spawn. +- **authme.command.admin.spawn** – Administrator command to teleport to the AuthMe spawn. +- **authme.command.admin.switchantibot** – Administrator command to toggle the AntiBot protection status. +- **authme.command.admin.unregister** – Administrator command to unregister an existing user. +- **authme.command.player.allow2accounts** – Permission for users to allow two accounts. +- **authme.command.player.bypassforcesurvival** – Permission for users to bypass force-survival mode. +- **authme.command.player.captcha** – Command permission to use captcha. +- **authme.command.player.changepassword** – Command permission to change the password. +- **authme.command.player.email.add** – Command permission to add an email address. +- **authme.command.player.email.change** – Command permission to change the email address. +- **authme.command.player.email.recover** – Command permission to recover an account using it's email address. +- **authme.command.player.login** – Command permission to login. +- **authme.command.player.logout** – Command permission to logout. +- **authme.command.player.register** – Command permission to register. +- **authme.command.player.seeotheraccounts** – Permission for user to see other accounts. +- **authme.command.player.unregister** – Command permission to unregister. +- **authme.player.bypassantibot** – Permission node to bypass AntiBot protection. +- **authme.player.canbeforced** – Permission for users a login can be forced to. +- **authme.player.vip** – Permission node to identify VIP users. + diff --git a/src/tools/permissionstree/PermissionNodesGatherer.java b/src/tools/permissions/PermissionNodesGatherer.java similarity index 99% rename from src/tools/permissionstree/PermissionNodesGatherer.java rename to src/tools/permissions/PermissionNodesGatherer.java index 5da8841c..5b61adbe 100644 --- a/src/tools/permissionstree/PermissionNodesGatherer.java +++ b/src/tools/permissions/PermissionNodesGatherer.java @@ -1,4 +1,4 @@ -package permissionstree; +package permissions; import fr.xephi.authme.permission.AdminPermission; import fr.xephi.authme.permission.PermissionNode; diff --git a/src/tools/permissions/PermissionsListWriter.java b/src/tools/permissions/PermissionsListWriter.java new file mode 100644 index 00000000..7d361b1c --- /dev/null +++ b/src/tools/permissions/PermissionsListWriter.java @@ -0,0 +1,86 @@ +package permissions; + +import utils.ANewMap; +import utils.GeneratedFileWriter; +import utils.TagReplacer; +import utils.ToolsConstants; + +import java.util.Map; +import java.util.Scanner; +import java.util.Set; + +/** + * Class responsible for formatting a permissions node list and + * for writing it to a file if desired. + */ +public class PermissionsListWriter { + + private static final String PERMISSIONS_OUTPUT_FILE = ToolsConstants.DOCS_FOLDER + "permission_nodes.md"; + + public static void main(String[] args) { + // Ask if result should be written to file + Scanner scanner = new Scanner(System.in); + System.out.println("Include description? [Enter 'n' for no]"); + boolean includeDescription = !matches("n", scanner); + + if (!includeDescription) { + outputSimpleList(); + return; + } + + System.out.println("Write to file? [Enter 'n' for console output]"); + boolean writeToFile = !matches("n", scanner); + scanner.close(); + + + if (writeToFile) { + generateAndWriteFile(); + } else { + System.out.println(generatePermissionsList()); + } + } + + + private static void generateAndWriteFile() { + final String permissionsTagValue = generatePermissionsList(); + + Map tags = ANewMap.with("permissions", permissionsTagValue).build(); + GeneratedFileWriter.generateFileFromTemplate( + ToolsConstants.TOOLS_SOURCE_ROOT + "permissions/permission_nodes.tpl.md", PERMISSIONS_OUTPUT_FILE, tags); + System.out.println("Wrote to '" + PERMISSIONS_OUTPUT_FILE + "'"); + System.out.println("Before committing, please verify the output!"); + } + + private static String generatePermissionsList() { + PermissionNodesGatherer gatherer = new PermissionNodesGatherer(); + Map permissions = gatherer.gatherNodesWithJavaDoc(); + + final String template = GeneratedFileWriter.readFromToolsFile("permissions/permission_node_entry.tpl.md"); + StringBuilder sb = new StringBuilder(); + + for (Map.Entry entry : permissions.entrySet()) { + Map tags = ANewMap. + with("node", entry.getKey()) + .and("description", entry.getValue()) + .build(); + sb.append(TagReplacer.applyReplacements(template, tags)); + } + return sb.toString(); + } + + private static void outputSimpleList() { + PermissionNodesGatherer gatherer = new PermissionNodesGatherer(); + Set nodes = gatherer.gatherNodes(); + for (String node : nodes) { + System.out.println(node); + } + System.out.println(); + System.out.println("Total: " + nodes.size()); + } + + private static boolean matches(String answer, Scanner sc) { + String userInput = sc.nextLine(); + return answer.equalsIgnoreCase(userInput); + } + +} diff --git a/src/tools/permissions/README.md b/src/tools/permissions/README.md new file mode 100644 index 00000000..9603cd38 --- /dev/null +++ b/src/tools/permissions/README.md @@ -0,0 +1,2 @@ +# About +Helper script to generate a page with an up-to-date list of permission nodes. diff --git a/src/tools/permissions/permission_node_entry.tpl.md b/src/tools/permissions/permission_node_entry.tpl.md new file mode 100644 index 00000000..ab7f0687 --- /dev/null +++ b/src/tools/permissions/permission_node_entry.tpl.md @@ -0,0 +1 @@ +- **{node}** – {description} diff --git a/src/tools/permissions/permission_nodes.tpl.md b/src/tools/permissions/permission_nodes.tpl.md new file mode 100644 index 00000000..641d28df --- /dev/null +++ b/src/tools/permissions/permission_nodes.tpl.md @@ -0,0 +1,7 @@ + + + +## AuthMe Permission Nodes +The following are the permission nodes that are currently supported by the latest dev builds. + +{permissions} diff --git a/src/tools/permissionstree/PermissionsListWriter.java b/src/tools/permissionstree/PermissionsListWriter.java deleted file mode 100644 index 7d1cd1c2..00000000 --- a/src/tools/permissionstree/PermissionsListWriter.java +++ /dev/null @@ -1,62 +0,0 @@ -package permissionstree; - -import fr.xephi.authme.util.StringUtils; -import utils.CommentType; -import utils.GeneratedFileWriter; - -import java.util.Map; -import java.util.Scanner; -import java.util.Set; - -/** - * Class responsible for formatting a permissions node list and - * for writing it to a file if desired. - */ -public class PermissionsListWriter { - - private static final String PERMISSIONS_TREE_FILE = "gen_permtree.txt"; - - public static void main(String[] args) { - // Ask if result should be written to file - Scanner scanner = new Scanner(System.in); - System.out.println("Include description? [Enter 'n' for no]"); - boolean includeDescription = !matches("n", scanner); - - System.out.println("Write to file? [Enter 'y' for yes]"); - boolean writeToFile = matches("y", scanner); - scanner.close(); - - // Generate connections and output or write - String output = generatedOutput(includeDescription); - - if (writeToFile) { - GeneratedFileWriter.createGeneratedFile(PERMISSIONS_TREE_FILE, output, CommentType.YML); - } else { - System.out.println(output); - } - } - - private static String generatedOutput(boolean includeDescription) { - PermissionNodesGatherer creater = new PermissionNodesGatherer(); - if (!includeDescription) { - Set nodes = creater.gatherNodes(); - return StringUtils.join("\n", nodes); - } - - Map permissions = creater.gatherNodesWithJavaDoc(); - StringBuilder sb = new StringBuilder(); - for (Map.Entry entry : permissions.entrySet()) { - sb.append(entry.getKey()) - .append(": ") - .append(entry.getValue()) - .append("\n"); - } - return sb.toString(); - } - - private static boolean matches(String answer, Scanner sc) { - String userInput = sc.nextLine(); - return answer.equalsIgnoreCase(userInput); - } - -} diff --git a/src/tools/permissionstree/README.md b/src/tools/permissionstree/README.md deleted file mode 100644 index 5364c846..00000000 --- a/src/tools/permissionstree/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# About -Helper script to generate a list of all permission nodes. diff --git a/src/tools/utils/ANewMap.java b/src/tools/utils/ANewMap.java new file mode 100644 index 00000000..de37bd74 --- /dev/null +++ b/src/tools/utils/ANewMap.java @@ -0,0 +1,36 @@ +package utils; + +import java.util.HashMap; +import java.util.Map; + +/** + * A map builder for the lazy. + *

+ * Sample usage: + * + * Map<String, Integer> map = ANewMap + * .with("test", 123) + * .and("text", 938) + * .and("abc", 456) + * .build(); + * + */ +public class ANewMap { + + private Map map = new HashMap<>(); + + public static ANewMap with(K key, V value) { + ANewMap instance = new ANewMap<>(); + return instance.and(key, value); + } + + public ANewMap and(K key, V value) { + map.put(key, value); + return this; + } + + public Map build() { + return map; + } + +} diff --git a/src/tools/utils/CommentType.java b/src/tools/utils/CommentType.java deleted file mode 100644 index fbc4c9b8..00000000 --- a/src/tools/utils/CommentType.java +++ /dev/null @@ -1,11 +0,0 @@ -package utils; - -/** - * Enum for different comment formats. - */ -public enum CommentType { - - JAVA, - YML - -} diff --git a/src/tools/utils/GeneratedFileWriter.java b/src/tools/utils/GeneratedFileWriter.java index 07f87c43..06cbcaf3 100644 --- a/src/tools/utils/GeneratedFileWriter.java +++ b/src/tools/utils/GeneratedFileWriter.java @@ -1,61 +1,47 @@ package utils; -import java.io.File; -import java.io.FileOutputStream; import java.io.IOException; -import java.io.OutputStreamWriter; -import java.util.Date; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Map; /** * Utility class for writing a generated file with a timestamp. */ public final class GeneratedFileWriter { + private final static Charset CHARSET = Charset.forName("utf-8"); + private GeneratedFileWriter() { } - public static void createGeneratedFile(File file, String contents, CommentType commentFormat) { - validateFile(file); + public static void generateFileFromTemplate(String templateFile, String destinationFile, Map tags) { + String template = readFromFile(templateFile); + String result = TagReplacer.applyReplacements(template, tags); - try (OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(file))) { - osw.write(generateComment(commentFormat)); - osw.write(contents); + writeToFile(destinationFile, result); + } + + private static void writeToFile(String outputFile, String contents) { + try { + Files.write(Paths.get(outputFile), contents.getBytes()); } catch (IOException e) { - throw new RuntimeException("Could not write to file '" + file.getName() + "'", e); + throw new RuntimeException("Failed to write to file '" + outputFile + "'", e); } } - public static void createGeneratedFile(String fileName, String contents, CommentType commentFormat) { - createGeneratedFile(new File(fileName), contents, commentFormat); - } - - private static String generateComment(CommentType commentFormat) { - String comment = "Auto-generated file, generated on " + new Date() + "\n\n"; - switch (commentFormat) { - case JAVA: - return "// " + comment; - case YML: - return "# " + comment; - default: - throw new RuntimeException("Unknown comment format '" + commentFormat + "'"); + public static String readFromFile(String file) { + try { + return new String(Files.readAllBytes(Paths.get(file)), CHARSET); + } catch (IOException e) { + throw new RuntimeException("Could not read from file '" + file + "'", e); } } - private static void validateFile(File file) { - if (!file.exists()) { - System.out.println("File '" + file.getName() + "' doesn't exist; attempting to create it"); - try { - boolean success = file.createNewFile(); - if (!success) { - throw new RuntimeException("Failed to create file '" + file.getName() + "'"); - } - } catch (IOException e) { - throw new RuntimeException("Could not create file '" + file.getName() + "'", e); - } - } - if (!file.canWrite()) { - throw new RuntimeException("File '" + file.getName() + "' is not writable"); - } + public static String readFromToolsFile(String file) { + return readFromFile(ToolsConstants.TOOLS_SOURCE_ROOT + file); } + } diff --git a/src/tools/utils/TagReplacer.java b/src/tools/utils/TagReplacer.java new file mode 100644 index 00000000..404857b7 --- /dev/null +++ b/src/tools/utils/TagReplacer.java @@ -0,0 +1,46 @@ +package utils; + +import java.util.Date; +import java.util.Map; + +/** + * Class responsible for replacing template tags to actual content. + * For all files, the following tags are defined: + *

    + *
  • {gen_date} – the generation date
  • + *
  • {gen_warning} - warning not to edit the generated file directly
  • + *
+ */ +public class TagReplacer { + + /** + * Replace a template with default tags and custom ones supplied by a map. + * + * @param template The template to process + * @param tags Map with additional tags, e.g. a map entry with key "foo" and value "bar" will replace + * any occurrences of "{foo}" to "bar". + * @return The filled template + */ + public static String applyReplacements(String template, Map tags) { + String result = template; + for (Map.Entry tagRule : tags.entrySet()) { + result = result.replace("{" + tagRule.getKey() + "}", tagRule.getValue().toString()); + } + + return applyReplacements(result); + } + + /** + * Apply the default tag replacements. + * + * @param template The template to process + * @return The filled template + */ + public static String applyReplacements(String template) { + return template + .replace("{gen_date}", new Date().toString()) + .replace("{gen_warning}", "AUTO-GENERATED FILE! Do not edit this directly"); + } + + +} diff --git a/src/tools/utils/ToolsConstants.java b/src/tools/utils/ToolsConstants.java new file mode 100644 index 00000000..30cb0f41 --- /dev/null +++ b/src/tools/utils/ToolsConstants.java @@ -0,0 +1,17 @@ +package utils; + +/** + * Constants for the src/tools folder. + */ +public final class ToolsConstants { + + private ToolsConstants() { + } + + public static final String MAIN_SOURCE_ROOT = "src/main/java/"; + + public static final String TOOLS_SOURCE_ROOT = "src/tools/"; + + public static final String DOCS_FOLDER = TOOLS_SOURCE_ROOT + "docs/"; + +} From c399508736837c54c3c3002765aef401b9ff4b25 Mon Sep 17 00:00:00 2001 From: ljacqu Date: Sat, 5 Dec 2015 21:00:35 +0100 Subject: [PATCH 07/17] Change code style not to use wildcard imports Set code style settings not to use wildcard imports --- .idea/codeStyleSettings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.idea/codeStyleSettings.xml b/.idea/codeStyleSettings.xml index 174665cb..26493260 100644 --- a/.idea/codeStyleSettings.xml +++ b/.idea/codeStyleSettings.xml @@ -5,6 +5,8 @@