Fix Checkstyle violations

- Mostly missing Javadoc on large methods
- CommandInitializer: split command building method into multiple methods
This commit is contained in:
ljacqu 2017-07-16 23:07:13 +02:00
parent 4ac980111d
commit f88350b06d
16 changed files with 421 additions and 331 deletions

View File

@ -150,7 +150,7 @@
<property name="scope" value="package"/> <property name="scope" value="package"/>
<property name="allowMissingThrowsTags" value="true"/> <property name="allowMissingThrowsTags" value="true"/>
<property name="minLineCount" value="4"/> <property name="minLineCount" value="4"/>
<property name="allowedAnnotations" value="Override, Test, SectionComments, EventHandler"/> <property name="allowedAnnotations" value="Override, Test, SectionComments, EventHandler, Before, BeforeClass"/>
<property name="tokens" value="METHOD_DEF, ANNOTATION_FIELD_DEF"/> <!-- exclude CTOR_DEF --> <property name="tokens" value="METHOD_DEF, ANNOTATION_FIELD_DEF"/> <!-- exclude CTOR_DEF -->
</module> </module>
<module name="JavadocMethod"> <module name="JavadocMethod">

View File

@ -69,6 +69,12 @@ public class CommandHandler {
return !FoundResultStatus.MISSING_BASE_COMMAND.equals(result.getResultStatus()); return !FoundResultStatus.MISSING_BASE_COMMAND.equals(result.getResultStatus());
} }
/**
* Processes the given {@link FoundCommandResult} for the provided command sender.
*
* @param sender the command sender who executed the command
* @param result the command mapping result
*/
private void handleCommandResult(CommandSender sender, FoundCommandResult result) { private void handleCommandResult(CommandSender sender, FoundCommandResult result) {
switch (result.getResultStatus()) { switch (result.getResultStatus()) {
case SUCCESS: case SUCCESS:

View File

@ -71,279 +71,13 @@ public class CommandInitializer {
/** /**
* Builds the command description objects for all available AuthMe commands. * Builds the command description objects for all available AuthMe commands.
*/ */
@SuppressWarnings({"checkstyle:LocalVariableName", "checkstyle:AbbreviationAsWordInName"})
private void buildCommands() { private void buildCommands() {
// Register the base AuthMe Reloaded command // Register /authme and /email commands
final CommandDescription AUTHME_BASE = CommandDescription.builder() CommandDescription authMeBase = buildAuthMeBaseCommand();
.labels("authme") CommandDescription emailBase = buildEmailBaseCommand();
.description("AuthMe op commands")
.detailedDescription("The main AuthMeReloaded command. The root for all admin commands.")
.executableCommand(AuthMeCommand.class)
.register();
// Register the register command
CommandDescription.builder()
.parent(AUTHME_BASE)
.labels("register", "reg", "r")
.description("Register a player")
.detailedDescription("Register the specified player with the specified password.")
.withArgument("player", "Player name", false)
.withArgument("password", "Password", false)
.permission(AdminPermission.REGISTER)
.executableCommand(RegisterAdminCommand.class)
.register();
// Register the unregister command
CommandDescription.builder()
.parent(AUTHME_BASE)
.labels("unregister", "unreg", "unr")
.description("Unregister a player")
.detailedDescription("Unregister the specified player.")
.withArgument("player", "Player name", false)
.permission(AdminPermission.UNREGISTER)
.executableCommand(UnregisterAdminCommand.class)
.register();
// Register the forcelogin command
CommandDescription.builder()
.parent(AUTHME_BASE)
.labels("forcelogin", "login")
.description("Enforce login player")
.detailedDescription("Enforce the specified player to login.")
.withArgument("player", "Online player name", true)
.permission(AdminPermission.FORCE_LOGIN)
.executableCommand(ForceLoginCommand.class)
.register();
// Register the changepassword command
CommandDescription.builder()
.parent(AUTHME_BASE)
.labels("password", "changepassword", "changepass", "cp")
.description("Change a player's password")
.detailedDescription("Change the password of a player.")
.withArgument("player", "Player name", false)
.withArgument("pwd", "New password", false)
.permission(AdminPermission.CHANGE_PASSWORD)
.executableCommand(ChangePasswordAdminCommand.class)
.register();
// Register the last login command
CommandDescription.builder()
.parent(AUTHME_BASE)
.labels("lastlogin", "ll")
.description("Player's last login")
.detailedDescription("View the date of the specified players last login.")
.withArgument("player", "Player name", true)
.permission(AdminPermission.LAST_LOGIN)
.executableCommand(LastLoginCommand.class)
.register();
// Register the accounts command
CommandDescription.builder()
.parent(AUTHME_BASE)
.labels("accounts", "account")
.description("Display player accounts")
.detailedDescription("Display all accounts of a player by his player name or IP.")
.withArgument("player", "Player name or IP", true)
.permission(AdminPermission.ACCOUNTS)
.executableCommand(AccountsCommand.class)
.register();
// Register the getemail command
CommandDescription.builder()
.parent(AUTHME_BASE)
.labels("email", "mail", "getemail", "getmail")
.description("Display player's email")
.detailedDescription("Display the email address of the specified player if set.")
.withArgument("player", "Player name", true)
.permission(AdminPermission.GET_EMAIL)
.executableCommand(GetEmailCommand.class)
.register();
// Register the setemail command
CommandDescription.builder()
.parent(AUTHME_BASE)
.labels("setemail", "setmail", "chgemail", "chgmail")
.description("Change player's email")
.detailedDescription("Change the email address of the specified player.")
.withArgument("player", "Player name", false)
.withArgument("email", "Player email", false)
.permission(AdminPermission.CHANGE_EMAIL)
.executableCommand(SetEmailCommand.class)
.register();
// Register the getip command
CommandDescription.builder()
.parent(AUTHME_BASE)
.labels("getip", "ip")
.description("Get player's IP")
.detailedDescription("Get the IP address of the specified online player.")
.withArgument("player", "Player name", false)
.permission(AdminPermission.GET_IP)
.executableCommand(GetIpCommand.class)
.register();
// Register the spawn command
CommandDescription.builder()
.parent(AUTHME_BASE)
.labels("spawn", "home")
.description("Teleport to spawn")
.detailedDescription("Teleport to the spawn.")
.permission(AdminPermission.SPAWN)
.executableCommand(SpawnCommand.class)
.register();
// Register the setspawn command
CommandDescription.builder()
.parent(AUTHME_BASE)
.labels("setspawn", "chgspawn")
.description("Change the spawn")
.detailedDescription("Change the player's spawn to your current position.")
.permission(AdminPermission.SET_SPAWN)
.executableCommand(SetSpawnCommand.class)
.register();
// Register the firstspawn command
CommandDescription.builder()
.parent(AUTHME_BASE)
.labels("firstspawn", "firsthome")
.description("Teleport to first spawn")
.detailedDescription("Teleport to the first spawn.")
.permission(AdminPermission.FIRST_SPAWN)
.executableCommand(FirstSpawnCommand.class)
.register();
// Register the setfirstspawn command
CommandDescription.builder()
.parent(AUTHME_BASE)
.labels("setfirstspawn", "chgfirstspawn")
.description("Change the first spawn")
.detailedDescription("Change the first player's spawn to your current position.")
.permission(AdminPermission.SET_FIRST_SPAWN)
.executableCommand(SetFirstSpawnCommand.class)
.register();
// Register the purge command
CommandDescription.builder()
.parent(AUTHME_BASE)
.labels("purge", "delete")
.description("Purge old data")
.detailedDescription("Purge old AuthMeReloaded data longer than the specified number of days ago.")
.withArgument("days", "Number of days", false)
.withArgument("all", "Add 'all' at the end to also purge players with lastlogin = 0", true)
.permission(AdminPermission.PURGE)
.executableCommand(PurgeCommand.class)
.register();
// Purge player command
CommandDescription.builder()
.parent(AUTHME_BASE)
.labels("purgeplayer")
.description("Purges the data of one player")
.detailedDescription("Purges data of the given player.")
.withArgument("player", "The player to purge", false)
.withArgument("options", "'force' to run without checking if player is registered", true)
.permission(AdminPermission.PURGE_PLAYER)
.executableCommand(PurgePlayerCommand.class)
.register();
// Backup command
CommandDescription.builder()
.parent(AUTHME_BASE)
.labels("backup")
.description("Perform a backup")
.detailedDescription("Creates a backup of the registered users.")
.permission(AdminPermission.BACKUP)
.executableCommand(BackupCommand.class)
.register();
// Register the purgelastposition command
CommandDescription.builder()
.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 or all of them.")
.withArgument("player/*", "Player name or * for all players", false)
.permission(AdminPermission.PURGE_LAST_POSITION)
.executableCommand(PurgeLastPositionCommand.class)
.register();
// Register the purgebannedplayers command
CommandDescription.builder()
.parent(AUTHME_BASE)
.labels("purgebannedplayers", "purgebannedplayer", "deletebannedplayers", "deletebannedplayer")
.description("Purge banned players data")
.detailedDescription("Purge all AuthMeReloaded data for banned players.")
.permission(AdminPermission.PURGE_BANNED_PLAYERS)
.executableCommand(PurgeBannedPlayersCommand.class)
.register();
// Register the switchantibot command
CommandDescription.builder()
.parent(AUTHME_BASE)
.labels("switchantibot", "toggleantibot", "antibot")
.description("Switch AntiBot mode")
.detailedDescription("Switch or toggle the AntiBot mode to the specified state.")
.withArgument("mode", "ON / OFF", true)
.permission(AdminPermission.SWITCH_ANTIBOT)
.executableCommand(SwitchAntiBotCommand.class)
.register();
// Register the reload command
CommandDescription.builder()
.parent(AUTHME_BASE)
.labels("reload", "rld")
.description("Reload plugin")
.detailedDescription("Reload the AuthMeReloaded plugin.")
.permission(AdminPermission.RELOAD)
.executableCommand(ReloadCommand.class)
.register();
// Register the version command
CommandDescription.builder()
.parent(AUTHME_BASE)
.labels("version", "ver", "v", "about", "info")
.description("Version info")
.detailedDescription("Show detailed information about the installed AuthMeReloaded version, the "
+ "developers, contributors, and license.")
.executableCommand(VersionCommand.class)
.register();
CommandDescription.builder()
.parent(AUTHME_BASE)
.labels("converter", "convert", "conv")
.description("Converter command")
.detailedDescription("Converter command for AuthMeReloaded.")
.withArgument("job", "Conversion job: xauth / crazylogin / rakamak / "
+ "royalauth / vauth / sqliteToSql / mysqlToSqlite / loginsecurity", true)
.permission(AdminPermission.CONVERTER)
.executableCommand(ConverterCommand.class)
.register();
CommandDescription.builder()
.parent(AUTHME_BASE)
.labels("messages", "msg")
.description("Add missing messages")
.detailedDescription("Adds missing messages to the current messages file.")
.permission(AdminPermission.UPDATE_MESSAGES)
.executableCommand(MessagesCommand.class)
.register();
CommandDescription.builder()
.parent(AUTHME_BASE)
.labels("debug", "dbg")
.description("Debug features")
.detailedDescription("Allows various operations for debugging.")
.withArgument("child", "The child to execute", true)
.withArgument("arg", "argument (depends on debug section)", true)
.withArgument("arg", "argument (depends on debug section)", true)
.permission(DebugSectionPermissions.DEBUG_COMMAND)
.executableCommand(DebugCommand.class)
.register();
// Register the base login command // Register the base login command
final CommandDescription LOGIN_BASE = CommandDescription.builder() CommandDescription loginBase = CommandDescription.builder()
.parent(null) .parent(null)
.labels("login", "l", "log") .labels("login", "l", "log")
.description("Login command") .description("Login command")
@ -354,7 +88,7 @@ public class CommandInitializer {
.register(); .register();
// Register the base logout command // Register the base logout command
CommandDescription LOGOUT_BASE = CommandDescription.builder() CommandDescription logoutBase = CommandDescription.builder()
.parent(null) .parent(null)
.labels("logout") .labels("logout")
.description("Logout command") .description("Logout command")
@ -364,7 +98,7 @@ public class CommandInitializer {
.register(); .register();
// Register the base register command // Register the base register command
final CommandDescription REGISTER_BASE = CommandDescription.builder() CommandDescription registerBase = CommandDescription.builder()
.parent(null) .parent(null)
.labels("register", "reg") .labels("register", "reg")
.description("Register an account") .description("Register an account")
@ -376,7 +110,7 @@ public class CommandInitializer {
.register(); .register();
// Register the base unregister command // Register the base unregister command
CommandDescription UNREGISTER_BASE = CommandDescription.builder() CommandDescription unregisterBase = CommandDescription.builder()
.parent(null) .parent(null)
.labels("unregister", "unreg") .labels("unregister", "unreg")
.description("Unregister an account") .description("Unregister an account")
@ -387,7 +121,7 @@ public class CommandInitializer {
.register(); .register();
// Register the base changepassword command // Register the base changepassword command
final CommandDescription CHANGE_PASSWORD_BASE = CommandDescription.builder() CommandDescription changePasswordBase = CommandDescription.builder()
.parent(null) .parent(null)
.labels("changepassword", "changepass", "cp") .labels("changepassword", "changepass", "cp")
.description("Change password of an account") .description("Change password of an account")
@ -398,8 +132,317 @@ public class CommandInitializer {
.executableCommand(ChangePasswordCommand.class) .executableCommand(ChangePasswordCommand.class)
.register(); .register();
// Register the base captcha command
CommandDescription captchaBase = CommandDescription.builder()
.parent(null)
.labels("captcha")
.description("Captcha Command")
.detailedDescription("Captcha command for AuthMeReloaded.")
.withArgument("captcha", "The Captcha", false)
.permission(PlayerPermission.CAPTCHA)
.executableCommand(CaptchaCommand.class)
.register();
List<CommandDescription> baseCommands = ImmutableList.of(
authMeBase,
emailBase,
loginBase,
logoutBase,
registerBase,
unregisterBase,
changePasswordBase,
captchaBase);
setHelpOnAllBases(baseCommands);
commands = baseCommands;
}
/**
* Creates a command description object for {@code /authme} including its children.
*
* @return the authme base command description
*/
private CommandDescription buildAuthMeBaseCommand() {
// Register the base AuthMe Reloaded command
CommandDescription authmeBase = CommandDescription.builder()
.labels("authme")
.description("AuthMe op commands")
.detailedDescription("The main AuthMeReloaded command. The root for all admin commands.")
.executableCommand(AuthMeCommand.class)
.register();
// Register the register command
CommandDescription.builder()
.parent(authmeBase)
.labels("register", "reg", "r")
.description("Register a player")
.detailedDescription("Register the specified player with the specified password.")
.withArgument("player", "Player name", false)
.withArgument("password", "Password", false)
.permission(AdminPermission.REGISTER)
.executableCommand(RegisterAdminCommand.class)
.register();
// Register the unregister command
CommandDescription.builder()
.parent(authmeBase)
.labels("unregister", "unreg", "unr")
.description("Unregister a player")
.detailedDescription("Unregister the specified player.")
.withArgument("player", "Player name", false)
.permission(AdminPermission.UNREGISTER)
.executableCommand(UnregisterAdminCommand.class)
.register();
// Register the forcelogin command
CommandDescription.builder()
.parent(authmeBase)
.labels("forcelogin", "login")
.description("Enforce login player")
.detailedDescription("Enforce the specified player to login.")
.withArgument("player", "Online player name", true)
.permission(AdminPermission.FORCE_LOGIN)
.executableCommand(ForceLoginCommand.class)
.register();
// Register the changepassword command
CommandDescription.builder()
.parent(authmeBase)
.labels("password", "changepassword", "changepass", "cp")
.description("Change a player's password")
.detailedDescription("Change the password of a player.")
.withArgument("player", "Player name", false)
.withArgument("pwd", "New password", false)
.permission(AdminPermission.CHANGE_PASSWORD)
.executableCommand(ChangePasswordAdminCommand.class)
.register();
// Register the last login command
CommandDescription.builder()
.parent(authmeBase)
.labels("lastlogin", "ll")
.description("Player's last login")
.detailedDescription("View the date of the specified players last login.")
.withArgument("player", "Player name", true)
.permission(AdminPermission.LAST_LOGIN)
.executableCommand(LastLoginCommand.class)
.register();
// Register the accounts command
CommandDescription.builder()
.parent(authmeBase)
.labels("accounts", "account")
.description("Display player accounts")
.detailedDescription("Display all accounts of a player by his player name or IP.")
.withArgument("player", "Player name or IP", true)
.permission(AdminPermission.ACCOUNTS)
.executableCommand(AccountsCommand.class)
.register();
// Register the getemail command
CommandDescription.builder()
.parent(authmeBase)
.labels("email", "mail", "getemail", "getmail")
.description("Display player's email")
.detailedDescription("Display the email address of the specified player if set.")
.withArgument("player", "Player name", true)
.permission(AdminPermission.GET_EMAIL)
.executableCommand(GetEmailCommand.class)
.register();
// Register the setemail command
CommandDescription.builder()
.parent(authmeBase)
.labels("setemail", "setmail", "chgemail", "chgmail")
.description("Change player's email")
.detailedDescription("Change the email address of the specified player.")
.withArgument("player", "Player name", false)
.withArgument("email", "Player email", false)
.permission(AdminPermission.CHANGE_EMAIL)
.executableCommand(SetEmailCommand.class)
.register();
// Register the getip command
CommandDescription.builder()
.parent(authmeBase)
.labels("getip", "ip")
.description("Get player's IP")
.detailedDescription("Get the IP address of the specified online player.")
.withArgument("player", "Player name", false)
.permission(AdminPermission.GET_IP)
.executableCommand(GetIpCommand.class)
.register();
// Register the spawn command
CommandDescription.builder()
.parent(authmeBase)
.labels("spawn", "home")
.description("Teleport to spawn")
.detailedDescription("Teleport to the spawn.")
.permission(AdminPermission.SPAWN)
.executableCommand(SpawnCommand.class)
.register();
// Register the setspawn command
CommandDescription.builder()
.parent(authmeBase)
.labels("setspawn", "chgspawn")
.description("Change the spawn")
.detailedDescription("Change the player's spawn to your current position.")
.permission(AdminPermission.SET_SPAWN)
.executableCommand(SetSpawnCommand.class)
.register();
// Register the firstspawn command
CommandDescription.builder()
.parent(authmeBase)
.labels("firstspawn", "firsthome")
.description("Teleport to first spawn")
.detailedDescription("Teleport to the first spawn.")
.permission(AdminPermission.FIRST_SPAWN)
.executableCommand(FirstSpawnCommand.class)
.register();
// Register the setfirstspawn command
CommandDescription.builder()
.parent(authmeBase)
.labels("setfirstspawn", "chgfirstspawn")
.description("Change the first spawn")
.detailedDescription("Change the first player's spawn to your current position.")
.permission(AdminPermission.SET_FIRST_SPAWN)
.executableCommand(SetFirstSpawnCommand.class)
.register();
// Register the purge command
CommandDescription.builder()
.parent(authmeBase)
.labels("purge", "delete")
.description("Purge old data")
.detailedDescription("Purge old AuthMeReloaded data longer than the specified number of days ago.")
.withArgument("days", "Number of days", false)
.withArgument("all", "Add 'all' at the end to also purge players with lastlogin = 0", true)
.permission(AdminPermission.PURGE)
.executableCommand(PurgeCommand.class)
.register();
// Purge player command
CommandDescription.builder()
.parent(authmeBase)
.labels("purgeplayer")
.description("Purges the data of one player")
.detailedDescription("Purges data of the given player.")
.withArgument("player", "The player to purge", false)
.withArgument("options", "'force' to run without checking if player is registered", true)
.permission(AdminPermission.PURGE_PLAYER)
.executableCommand(PurgePlayerCommand.class)
.register();
// Backup command
CommandDescription.builder()
.parent(authmeBase)
.labels("backup")
.description("Perform a backup")
.detailedDescription("Creates a backup of the registered users.")
.permission(AdminPermission.BACKUP)
.executableCommand(BackupCommand.class)
.register();
// Register the purgelastposition command
CommandDescription.builder()
.parent(authmeBase)
.labels("resetpos", "purgelastposition", "purgelastpos", "resetposition",
"resetlastposition", "resetlastpos")
.description("Purge player's last position")
.detailedDescription("Purge the last know position of the specified player or all of them.")
.withArgument("player/*", "Player name or * for all players", false)
.permission(AdminPermission.PURGE_LAST_POSITION)
.executableCommand(PurgeLastPositionCommand.class)
.register();
// Register the purgebannedplayers command
CommandDescription.builder()
.parent(authmeBase)
.labels("purgebannedplayers", "purgebannedplayer", "deletebannedplayers", "deletebannedplayer")
.description("Purge banned players data")
.detailedDescription("Purge all AuthMeReloaded data for banned players.")
.permission(AdminPermission.PURGE_BANNED_PLAYERS)
.executableCommand(PurgeBannedPlayersCommand.class)
.register();
// Register the switchantibot command
CommandDescription.builder()
.parent(authmeBase)
.labels("switchantibot", "toggleantibot", "antibot")
.description("Switch AntiBot mode")
.detailedDescription("Switch or toggle the AntiBot mode to the specified state.")
.withArgument("mode", "ON / OFF", true)
.permission(AdminPermission.SWITCH_ANTIBOT)
.executableCommand(SwitchAntiBotCommand.class)
.register();
// Register the reload command
CommandDescription.builder()
.parent(authmeBase)
.labels("reload", "rld")
.description("Reload plugin")
.detailedDescription("Reload the AuthMeReloaded plugin.")
.permission(AdminPermission.RELOAD)
.executableCommand(ReloadCommand.class)
.register();
// Register the version command
CommandDescription.builder()
.parent(authmeBase)
.labels("version", "ver", "v", "about", "info")
.description("Version info")
.detailedDescription("Show detailed information about the installed AuthMeReloaded version, the "
+ "developers, contributors, and license.")
.executableCommand(VersionCommand.class)
.register();
CommandDescription.builder()
.parent(authmeBase)
.labels("converter", "convert", "conv")
.description("Converter command")
.detailedDescription("Converter command for AuthMeReloaded.")
.withArgument("job", "Conversion job: xauth / crazylogin / rakamak / "
+ "royalauth / vauth / sqliteToSql / mysqlToSqlite / loginsecurity", true)
.permission(AdminPermission.CONVERTER)
.executableCommand(ConverterCommand.class)
.register();
CommandDescription.builder()
.parent(authmeBase)
.labels("messages", "msg")
.description("Add missing messages")
.detailedDescription("Adds missing messages to the current messages file.")
.permission(AdminPermission.UPDATE_MESSAGES)
.executableCommand(MessagesCommand.class)
.register();
CommandDescription.builder()
.parent(authmeBase)
.labels("debug", "dbg")
.description("Debug features")
.detailedDescription("Allows various operations for debugging.")
.withArgument("child", "The child to execute", true)
.withArgument("arg", "argument (depends on debug section)", true)
.withArgument("arg", "argument (depends on debug section)", true)
.permission(DebugSectionPermissions.DEBUG_COMMAND)
.executableCommand(DebugCommand.class)
.register();
return authmeBase;
}
/**
* Creates a command description for {@code /email} including its children.
*
* @return the email base command description
*/
private CommandDescription buildEmailBaseCommand() {
// Register the base Email command // Register the base Email command
CommandDescription EMAIL_BASE = CommandDescription.builder() CommandDescription emailBase = CommandDescription.builder()
.parent(null) .parent(null)
.labels("email") .labels("email")
.description("Add email or recover password") .description("Add email or recover password")
@ -409,7 +452,7 @@ public class CommandInitializer {
// Register the show command // Register the show command
CommandDescription.builder() CommandDescription.builder()
.parent(EMAIL_BASE) .parent(emailBase)
.labels("show", "myemail") .labels("show", "myemail")
.description("Show Email") .description("Show Email")
.detailedDescription("Show your current email address.") .detailedDescription("Show your current email address.")
@ -418,7 +461,7 @@ public class CommandInitializer {
// Register the add command // Register the add command
CommandDescription.builder() CommandDescription.builder()
.parent(EMAIL_BASE) .parent(emailBase)
.labels("add", "addemail", "addmail") .labels("add", "addemail", "addmail")
.description("Add Email") .description("Add Email")
.detailedDescription("Add a new email address to your account.") .detailedDescription("Add a new email address to your account.")
@ -430,7 +473,7 @@ public class CommandInitializer {
// Register the change command // Register the change command
CommandDescription.builder() CommandDescription.builder()
.parent(EMAIL_BASE) .parent(emailBase)
.labels("change", "changeemail", "changemail") .labels("change", "changeemail", "changemail")
.description("Change Email") .description("Change Email")
.detailedDescription("Change an email address of your account.") .detailedDescription("Change an email address of your account.")
@ -442,7 +485,7 @@ public class CommandInitializer {
// Register the recover command // Register the recover command
CommandDescription.builder() CommandDescription.builder()
.parent(EMAIL_BASE) .parent(emailBase)
.labels("recover", "recovery", "recoveremail", "recovermail") .labels("recover", "recovery", "recoveremail", "recovermail")
.description("Recover password using email") .description("Recover password using email")
.detailedDescription("Recover your account using an Email address by sending a mail containing " .detailedDescription("Recover your account using an Email address by sending a mail containing "
@ -454,7 +497,7 @@ public class CommandInitializer {
// Register the process recovery code command // Register the process recovery code command
CommandDescription.builder() CommandDescription.builder()
.parent(EMAIL_BASE) .parent(emailBase)
.labels("code") .labels("code")
.description("Submit code to recover password") .description("Submit code to recover password")
.detailedDescription("Recover your account by submitting a code delivered to your email.") .detailedDescription("Recover your account by submitting a code delivered to your email.")
@ -465,7 +508,7 @@ public class CommandInitializer {
// Register the change password after recovery command // Register the change password after recovery command
CommandDescription.builder() CommandDescription.builder()
.parent(EMAIL_BASE) .parent(emailBase)
.labels("setpassword") .labels("setpassword")
.description("Set new password after recovery") .description("Set new password after recovery")
.detailedDescription("Set a new password after successfully recovering your account.") .detailedDescription("Set a new password after successfully recovering your account.")
@ -474,29 +517,7 @@ public class CommandInitializer {
.executableCommand(SetPasswordCommand.class) .executableCommand(SetPasswordCommand.class)
.register(); .register();
// Register the base captcha command return emailBase;
CommandDescription CAPTCHA_BASE = CommandDescription.builder()
.parent(null)
.labels("captcha")
.description("Captcha Command")
.detailedDescription("Captcha command for AuthMeReloaded.")
.withArgument("captcha", "The Captcha", false)
.permission(PlayerPermission.CAPTCHA)
.executableCommand(CaptchaCommand.class)
.register();
List<CommandDescription> baseCommands = ImmutableList.of(
AUTHME_BASE,
LOGIN_BASE,
LOGOUT_BASE,
REGISTER_BASE,
UNREGISTER_BASE,
CHANGE_PASSWORD_BASE,
EMAIL_BASE,
CAPTCHA_BASE);
setHelpOnAllBases(baseCommands);
commands = baseCommands;
} }
/** /**

View File

@ -114,7 +114,7 @@ class DistributedFilesPersistenceHandler implements LimboPersistenceHandler {
} }
try { try {
return gson.fromJson(Files.toString(file, StandardCharsets.UTF_8), LIMBO_MAP_TYPE); return gson.fromJson(Files.asCharSource(file, StandardCharsets.UTF_8).read(), LIMBO_MAP_TYPE);
} catch (Exception e) { } catch (Exception e) {
ConsoleLogger.logException("Failed reading '" + file + "':", e); ConsoleLogger.logException("Failed reading '" + file + "':", e);
} }

View File

@ -46,7 +46,7 @@ class IndividualFilesPersistenceHandler implements LimboPersistenceHandler {
} }
try { try {
String str = Files.toString(file, StandardCharsets.UTF_8); String str = Files.asCharSource(file, StandardCharsets.UTF_8).read();
return gson.fromJson(str, LimboPlayer.class); return gson.fromJson(str, LimboPlayer.class);
} catch (IOException e) { } catch (IOException e) {
ConsoleLogger.logException("Could not read player data on disk for '" + player.getName() + "'", e); ConsoleLogger.logException("Could not read player data on disk for '" + player.getName() + "'", e);

View File

@ -6,7 +6,6 @@ import fr.xephi.authme.security.crypts.HashedPassword;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.BufferedWriter; import java.io.BufferedWriter;
import java.io.Closeable;
import java.io.File; import java.io.File;
import java.io.FileReader; import java.io.FileReader;
import java.io.FileWriter; import java.io.FileWriter;
@ -80,7 +79,9 @@ public class FlatFile implements DataSource {
return false; return false;
} }
try (BufferedWriter bw = new BufferedWriter(new FileWriter(source, true))) { try (BufferedWriter bw = new BufferedWriter(new FileWriter(source, true))) {
bw.write(auth.getNickname() + ":" + auth.getPassword().getHash() + ":" + auth.getIp() + ":" + auth.getLastLogin() + ":" + auth.getQuitLocX() + ":" + auth.getQuitLocY() + ":" + auth.getQuitLocZ() + ":" + auth.getWorld() + ":" + auth.getEmail() + "\n"); bw.write(auth.getNickname() + ":" + auth.getPassword().getHash() + ":" + auth.getIp()
+ ":" + auth.getLastLogin() + ":" + auth.getQuitLocX() + ":" + auth.getQuitLocY()
+ ":" + auth.getQuitLocZ() + ":" + auth.getWorld() + ":" + auth.getEmail() + "\n");
} catch (IOException ex) { } catch (IOException ex) {
ConsoleLogger.warning(ex.getMessage()); ConsoleLogger.warning(ex.getMessage());
return false; return false;
@ -203,7 +204,7 @@ public class FlatFile implements DataSource {
return false; return false;
} }
ArrayList<String> lines = new ArrayList<>(); ArrayList<String> lines = new ArrayList<>();
try (BufferedReader br = new BufferedReader(new FileReader(source));) { try (BufferedReader br = new BufferedReader(new FileReader(source))) {
String line; String line;
while ((line = br.readLine()) != null) { while ((line = br.readLine()) != null) {
@ -379,6 +380,13 @@ public class FlatFile implements DataSource {
throw new UnsupportedOperationException("Flat file no longer supported"); throw new UnsupportedOperationException("Flat file no longer supported");
} }
/**
* Creates a PlayerAuth object from the read data.
*
* @param args the data read from the line
* @return the player auth object with the data
*/
@SuppressWarnings("checkstyle:NeedBraces")
private static PlayerAuth buildAuthFromArray(String[] args) { private static PlayerAuth buildAuthFromArray(String[] args) {
// Format allows 2, 3, 4, 7, 8, 9 fields. Anything else is unknown // Format allows 2, 3, 4, 7, 8, 9 fields. Anything else is unknown
if (args.length >= 2 && args.length <= 9 && args.length != 5 && args.length != 6) { if (args.length >= 2 && args.length <= 9 && args.length != 5 && args.length != 6) {

View File

@ -73,6 +73,11 @@ public class AsynchronousJoin implements AsynchronousProcess {
AsynchronousJoin() { AsynchronousJoin() {
} }
/**
* Processes the given player that has just joined.
*
* @param player the player to process
*/
public void processJoin(final Player player) { public void processJoin(final Player player) {
final String name = player.getName().toLowerCase(); final String name = player.getName().toLowerCase();
final String ip = PlayerUtils.getPlayerIp(player); final String ip = PlayerUtils.getPlayerIp(player);
@ -91,15 +96,7 @@ public class AsynchronousJoin implements AsynchronousProcess {
} }
if (!validationService.fulfillsNameRestrictions(player)) { if (!validationService.fulfillsNameRestrictions(player)) {
bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(new Runnable() { handlePlayerWithUnmetNameRestriction(player, ip);
@Override
public void run() {
player.kickPlayer(service.retrieveSingleMessage(MessageKey.NOT_OWNER_ERROR));
if (service.getProperty(RestrictionSettings.BAN_UNKNOWN_IP)) {
server.banIP(ip);
}
}
});
return; return;
} }
@ -124,7 +121,8 @@ public class AsynchronousJoin implements AsynchronousProcess {
if (canResumeSession(player)) { if (canResumeSession(player)) {
service.send(player, MessageKey.SESSION_RECONNECTION); service.send(player, MessageKey.SESSION_RECONNECTION);
// Run commands // Run commands
bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(() -> commandManager.runCommandsOnSessionLogin(player)); bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(
() -> commandManager.runCommandsOnSessionLogin(player));
bukkitService.runTaskOptionallyAsync(() -> asynchronousLogin.forceLogin(player)); bukkitService.runTaskOptionallyAsync(() -> asynchronousLogin.forceLogin(player));
return; return;
} }
@ -133,6 +131,26 @@ public class AsynchronousJoin implements AsynchronousProcess {
return; return;
} }
processJoinSync(player, isAuthAvailable);
}
private void handlePlayerWithUnmetNameRestriction(Player player, String ip) {
bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(() -> {
player.kickPlayer(service.retrieveSingleMessage(MessageKey.NOT_OWNER_ERROR));
if (service.getProperty(RestrictionSettings.BAN_UNKNOWN_IP)) {
server.banIP(ip);
}
});
}
/**
* Performs various operations in sync mode for an unauthenticated player (such as blindness effect and
* limbo player creation).
*
* @param player the player to process
* @param isAuthAvailable true if the player is registered, false otherwise
*/
private void processJoinSync(Player player, boolean isAuthAvailable) {
final int registrationTimeout = service.getProperty(RestrictionSettings.TIMEOUT) * TICKS_PER_SECOND; final int registrationTimeout = service.getProperty(RestrictionSettings.TIMEOUT) * TICKS_PER_SECOND;
bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(() -> { bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(() -> {

View File

@ -37,7 +37,7 @@ class TwoFactorRegisterExecutor extends AbstractPasswordRegisterExecutor<TwoFact
// to two-factor authentication. Therefore, the hashed password is the result of the TwoFactor EncryptionMethod // to two-factor authentication. Therefore, the hashed password is the result of the TwoFactor EncryptionMethod
// implementation (contains the TOTP secret). // implementation (contains the TOTP secret).
String hash = params.getHashedPassword().getHash(); String hash = params.getHashedPassword().getHash();
String qrCodeUrl = TwoFactor.getQRBarcodeURL(params.getPlayerName(), Bukkit.getIp(), hash); String qrCodeUrl = TwoFactor.getQrBarcodeUrl(params.getPlayerName(), Bukkit.getIp(), hash);
commonService.send(params.getPlayer(), MessageKey.TWO_FACTOR_CREATE, hash, qrCodeUrl); commonService.send(params.getPlayer(), MessageKey.TWO_FACTOR_CREATE, hash, qrCodeUrl);
} }
} }

View File

@ -19,6 +19,11 @@ import java.util.Arrays;
import java.util.Calendar; import java.util.Calendar;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/**
* Two factor authentication.
*
* @see <a href="http://thegreyblog.blogspot.com/2011/12/google-authenticator-using-it-in-your.html">Original source</a>
*/
@Recommendation(Usage.DOES_NOT_WORK) @Recommendation(Usage.DOES_NOT_WORK)
@HasSalt(SaltType.NONE) @HasSalt(SaltType.NONE)
public class TwoFactor extends UnsaltedMethod { public class TwoFactor extends UnsaltedMethod {
@ -30,7 +35,15 @@ public class TwoFactor extends UnsaltedMethod {
private static final int TIME_PRECISION = 3; private static final int TIME_PRECISION = 3;
private static final String CRYPTO_ALGO = "HmacSHA1"; private static final String CRYPTO_ALGO = "HmacSHA1";
public static String getQRBarcodeURL(String user, String host, String secret) { /**
* Creates a link to a QR barcode with the provided secret.
*
* @param user the player's name
* @param host the server host
* @param secret the TOTP secret
* @return URL leading to a QR code
*/
public static String getQrBarcodeUrl(String user, String host, String secret) {
String format = "https://www.google.com/chart?chs=130x130&chld=M%%7C0&cht=qr&chl=" String format = "https://www.google.com/chart?chs=130x130&chld=M%%7C0&cht=qr&chl="
+ "otpauth://totp/" + "otpauth://totp/"
+ "%s@%s%%3Fsecret%%3D%s"; + "%s@%s%%3Fsecret%%3D%s";
@ -72,18 +85,17 @@ public class TwoFactor extends UnsaltedMethod {
} }
long currentTime = Calendar.getInstance().getTimeInMillis() / TimeUnit.SECONDS.toMillis(30); long currentTime = Calendar.getInstance().getTimeInMillis() / TimeUnit.SECONDS.toMillis(30);
return check_code(secretKey, code, currentTime); return checkCode(secretKey, code, currentTime);
} }
private boolean check_code(String secret, long code, long t) private boolean checkCode(String secret, long code, long t) throws NoSuchAlgorithmException, InvalidKeyException {
throws NoSuchAlgorithmException, InvalidKeyException {
byte[] decodedKey = BaseEncoding.base32().decode(secret); byte[] decodedKey = BaseEncoding.base32().decode(secret);
// Window is used to check codes generated in the near past. // Window is used to check codes generated in the near past.
// You can use this value to tune how far you're willing to go. // You can use this value to tune how far you're willing to go.
int window = TIME_PRECISION; int window = TIME_PRECISION;
for (int i = -window; i <= window; ++i) { for (int i = -window; i <= window; ++i) {
long hash = verify_code(decodedKey, t + i); long hash = verifyCode(decodedKey, t + i);
if (hash == code) { if (hash == code) {
return true; return true;
@ -94,7 +106,7 @@ public class TwoFactor extends UnsaltedMethod {
return false; return false;
} }
private int verify_code(byte[] key, long t) throws NoSuchAlgorithmException, InvalidKeyException { private int verifyCode(byte[] key, long t) throws NoSuchAlgorithmException, InvalidKeyException {
byte[] data = new byte[8]; byte[] data = new byte[8];
long value = t; long value = t;
for (int i = 8; i-- > 0; value >>>= 8) { for (int i = 8; i-- > 0; value >>>= 8) {

View File

@ -42,6 +42,12 @@ public class XfBCrypt implements EncryptionMethod {
return false; return false;
} }
/**
* Extracts the password hash from the given BLOB.
*
* @param blob the blob to process
* @return the extracted hash
*/
public static String getHashFromBlob(byte[] blob) { public static String getHashFromBlob(byte[] blob) {
String line = new String(blob); String line = new String(blob);
Matcher m = HASH_PATTERN.matcher(line); Matcher m = HASH_PATTERN.matcher(line);

View File

@ -76,7 +76,7 @@ public class Settings extends SettingsManager {
final File file = new File(pluginFolder, filename); final File file = new File(pluginFolder, filename);
if (copyFileFromResource(file, filename)) { if (copyFileFromResource(file, filename)) {
try { try {
return Files.toString(file, StandardCharsets.UTF_8); return Files.asCharSource(file, StandardCharsets.UTF_8).read();
} catch (IOException e) { } catch (IOException e) {
ConsoleLogger.logException("Failed to read file '" + filename + "':", e); ConsoleLogger.logException("Failed to read file '" + filename + "':", e);
} }

View File

@ -25,7 +25,7 @@ public class TwoFactorTest {
String secret = "3AK6Y4KWGRLJMEQW"; String secret = "3AK6Y4KWGRLJMEQW";
// when // when
String url = TwoFactor.getQRBarcodeURL(user, host, secret); String url = TwoFactor.getQrBarcodeUrl(user, host, secret);
// then // then
String expected = "https://www.google.com/chart?chs=130x130&chld=M%7C0&cht=qr" String expected = "https://www.google.com/chart?chs=130x130&chld=M%7C0&cht=qr"

View File

@ -28,7 +28,6 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.hamcrest.MockitoHamcrest.argThat; import static org.mockito.hamcrest.MockitoHamcrest.argThat;
import static fr.xephi.authme.AuthMeMatchers.equalToHash;
/** /**
* Test for {@link MigrationService}. * Test for {@link MigrationService}.

View File

@ -178,6 +178,19 @@ public class CommandManagerTest {
verifyZeroInteractions(bukkitService, geoIpService); verifyZeroInteractions(bukkitService, geoIpService);
} }
@Test
public void shouldExecuteCommandOnUnregister() {
// given
copyJarFileAsCommandsYml(TEST_FILES_FOLDER + "commands.incomplete.yml");
initManager();
// when
manager.runCommandsOnUnregister(player);
// then
verify(bukkitService).dispatchConsoleCommand("msg Bobby sad to see you go!");
}
@Test @Test
public void shouldHaveHiddenConstructorInSettingsHolderClass() { public void shouldHaveHiddenConstructorInSettingsHolderClass() {
// given / when / then // given / when / then

View File

@ -30,7 +30,7 @@ import static org.mockito.Mockito.when;
*/ */
public class EncryptionMethodInfoGatherer { public class EncryptionMethodInfoGatherer {
private final static Set<Class<? extends Annotation>> RELEVANT_ANNOTATIONS = private static final Set<Class<? extends Annotation>> RELEVANT_ANNOTATIONS =
ImmutableSet.of(HasSalt.class, Recommendation.class, AsciiRestricted.class); ImmutableSet.of(HasSalt.class, Recommendation.class, AsciiRestricted.class);
private static Injector injector = createInitializer(); private static Injector injector = createInitializer();
@ -104,6 +104,9 @@ public class EncryptionMethodInfoGatherer {
/** /**
* Returns the super class of the given encryption method if it is also of EncryptionMethod type. * Returns the super class of the given encryption method if it is also of EncryptionMethod type.
* (Anything beyond EncryptionMethod is not of interest.) * (Anything beyond EncryptionMethod is not of interest.)
*
* @param methodClass the class to process
* @return the super class of the given class if it is also an EncryptionMethod type, otherwise null
*/ */
private static Class<?> getSuperClass(Class<?> methodClass) { private static Class<?> getSuperClass(Class<?> methodClass) {
Class<?> zuper = methodClass.getSuperclass(); Class<?> zuper = methodClass.getSuperclass();

View File

@ -18,3 +18,7 @@ doesNotExist:
wrongEntry: wrongEntry:
command: 'should be ignored' command: 'should be ignored'
executor: PLAYER executor: PLAYER
onUnregister:
farewell:
command: 'msg %p sad to see you go!'
executor: CONSOLE