#1180 Create command for performing a backup

This commit is contained in:
ljacqu 2017-04-23 20:23:40 +02:00
parent e75e22d624
commit 0e923b6a70
11 changed files with 168 additions and 90 deletions

View File

@ -1,5 +1,5 @@
<!-- AUTO-GENERATED FILE! Do not edit this directly --> <!-- AUTO-GENERATED FILE! Do not edit this directly -->
<!-- File auto-generated on Fri Apr 14 18:52:29 CEST 2017. See docs/commands/commands.tpl.md --> <!-- File auto-generated on Sun Apr 23 19:29:43 CEST 2017. See docs/commands/commands.tpl.md -->
## AuthMe Commands ## AuthMe Commands
You can use the following commands to use the features of AuthMe. Mandatory arguments are marked with `< >` You can use the following commands to use the features of AuthMe. Mandatory arguments are marked with `< >`
@ -32,8 +32,10 @@ brackets; optional arguments are enclosed in square brackets (`[ ]`).
<br />Requires `authme.admin.firstspawn` <br />Requires `authme.admin.firstspawn`
- **/authme setfirstspawn**: Change the first player's spawn to your current position. - **/authme setfirstspawn**: Change the first player's spawn to your current position.
<br />Requires `authme.admin.setfirstspawn` <br />Requires `authme.admin.setfirstspawn`
- **/authme purge** &lt;days> [all]: Purge old AuthMeReloaded data longer than the specified amount of days ago. - **/authme purge** &lt;days> [all]: Purge old AuthMeReloaded data longer than the specified number of days ago.
<br />Requires `authme.admin.purge` <br />Requires `authme.admin.purge`
- **/authme backup**: Creates a backup of the registered users.
<br />Requires `authme.admin.backup`
- **/authme resetpos** &lt;player/*>: Purge the last know position of the specified player or all of them. - **/authme resetpos** &lt;player/*>: Purge the last know position of the specified player or all of them.
<br />Requires `authme.admin.purgelastpos` <br />Requires `authme.admin.purgelastpos`
- **/authme purgebannedplayers**: Purge all AuthMeReloaded data for banned players. - **/authme purgebannedplayers**: Purge all AuthMeReloaded data for banned players.
@ -85,4 +87,4 @@ brackets; optional arguments are enclosed in square brackets (`[ ]`).
--- ---
This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Fri Apr 14 18:52:29 CEST 2017 This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Sun Apr 23 19:29:43 CEST 2017

View File

@ -1,5 +1,5 @@
<!-- AUTO-GENERATED FILE! Do not edit this directly --> <!-- AUTO-GENERATED FILE! Do not edit this directly -->
<!-- File auto-generated on Tue Mar 28 21:48:52 CEST 2017. See docs/config/config.tpl.md --> <!-- File auto-generated on Sun Apr 23 19:30:08 CEST 2017. See docs/config/config.tpl.md -->
## AuthMe Configuration ## AuthMe Configuration
The first time you run AuthMe it will create a config.yml file in the plugins/AuthMe folder, The first time you run AuthMe it will create a config.yml file in the plugins/AuthMe folder,
@ -481,13 +481,13 @@ limbo:
# See above for a description of the values. # See above for a description of the values.
restoreWalkSpeed: 'MAX_RESTORE' restoreWalkSpeed: 'MAX_RESTORE'
BackupSystem: BackupSystem:
# Enable or disable automatic backup # General configuration for backups: if false, no backups are possible
ActivateBackup: false ActivateBackup: false
# Set backup at every start of server # Create backup at every start of server
OnServerStart: false OnServerStart: false
# Set backup at every stop of server # Create backup at every stop of server
OnServerStop: true OnServerStop: true
# Windows only mysql installation Path # Windows only: MySQL installation path
MysqlWindowsPath: 'C:\Program Files\MySQL\MySQL Server 5.1\' MysqlWindowsPath: 'C:\Program Files\MySQL\MySQL Server 5.1\'
Converter: Converter:
Rakamak: Rakamak:
@ -507,4 +507,4 @@ To change settings on a running server, save your changes to config.yml and use
--- ---
This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Tue Mar 28 21:48:52 CEST 2017 This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Sun Apr 23 19:30:08 CEST 2017

View File

@ -1,5 +1,5 @@
<!-- AUTO-GENERATED FILE! Do not edit this directly --> <!-- AUTO-GENERATED FILE! Do not edit this directly -->
<!-- File auto-generated on Fri Apr 14 18:52:32 CEST 2017. See docs/permissions/permission_nodes.tpl.md --> <!-- File auto-generated on Sun Apr 23 19:32:06 CEST 2017. See docs/permissions/permission_nodes.tpl.md -->
## AuthMe Permission Nodes ## AuthMe Permission Nodes
The following are the permission nodes that are currently supported by the latest dev builds. The following are the permission nodes that are currently supported by the latest dev builds.
@ -7,6 +7,7 @@ The following are the permission nodes that are currently supported by the lates
- **authme.admin.*** Give access to all admin commands. - **authme.admin.*** Give access to all admin commands.
- **authme.admin.accounts** Administrator command to see all accounts associated with a user. - **authme.admin.accounts** Administrator command to see all accounts associated with a user.
- **authme.admin.antibotmessages** Permission to see Antibot messages. - **authme.admin.antibotmessages** Permission to see Antibot messages.
- **authme.admin.backup** Allows to use the backup command.
- **authme.admin.changemail** Administrator command to set or change the email address of a user. - **authme.admin.changemail** Administrator command to set or change the email address of a user.
- **authme.admin.changepassword** Administrator command to change the password of a user. - **authme.admin.changepassword** Administrator command to change the password of a user.
- **authme.admin.converter** Administrator command to convert old or other data to AuthMe data. - **authme.admin.converter** Administrator command to convert old or other data to AuthMe data.
@ -59,4 +60,4 @@ The following are the permission nodes that are currently supported by the lates
--- ---
This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Fri Apr 14 18:52:32 CEST 2017 This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Sun Apr 23 19:32:06 CEST 2017

View File

@ -73,6 +73,7 @@ public class AuthMe extends JavaPlugin {
private DataSource database; private DataSource database;
private BukkitService bukkitService; private BukkitService bukkitService;
private Injector injector; private Injector injector;
private BackupService backupService;
/** /**
* Constructor. * Constructor.
@ -155,7 +156,7 @@ public class AuthMe extends JavaPlugin {
} }
// Do a backup on start // Do a backup on start
new BackupService(this, settings).doBackup(BackupService.BackupCause.START); backupService.doBackup(BackupService.BackupCause.START);
// Set up Metrics // Set up Metrics
OnStartupTasks.sendMetrics(this, settings); OnStartupTasks.sendMetrics(this, settings);
@ -262,6 +263,7 @@ public class AuthMe extends JavaPlugin {
permsMan = injector.getSingleton(PermissionsManager.class); permsMan = injector.getSingleton(PermissionsManager.class);
bukkitService = injector.getSingleton(BukkitService.class); bukkitService = injector.getSingleton(BukkitService.class);
commandHandler = injector.getSingleton(CommandHandler.class); commandHandler = injector.getSingleton(CommandHandler.class);
backupService = injector.getSingleton(BackupService.class);
// Trigger construction of API classes; they will keep track of the singleton // Trigger construction of API classes; they will keep track of the singleton
injector.getSingleton(fr.xephi.authme.api.v3.AuthMeApi.class); injector.getSingleton(fr.xephi.authme.api.v3.AuthMeApi.class);
@ -357,8 +359,8 @@ public class AuthMe extends JavaPlugin {
} }
// Do backup on stop if enabled // Do backup on stop if enabled
if (settings != null) { if (backupService != null) {
new BackupService(this, settings).doBackup(BackupService.BackupCause.STOP); backupService.doBackup(BackupService.BackupCause.STOP);
} }
// Wait for tasks and close data source // Wait for tasks and close data source

View File

@ -4,6 +4,7 @@ import com.google.common.collect.ImmutableList;
import fr.xephi.authme.command.executable.HelpCommand; import fr.xephi.authme.command.executable.HelpCommand;
import fr.xephi.authme.command.executable.authme.AccountsCommand; import fr.xephi.authme.command.executable.authme.AccountsCommand;
import fr.xephi.authme.command.executable.authme.AuthMeCommand; import fr.xephi.authme.command.executable.authme.AuthMeCommand;
import fr.xephi.authme.command.executable.authme.BackupCommand;
import fr.xephi.authme.command.executable.authme.ChangePasswordAdminCommand; import fr.xephi.authme.command.executable.authme.ChangePasswordAdminCommand;
import fr.xephi.authme.command.executable.authme.ConverterCommand; import fr.xephi.authme.command.executable.authme.ConverterCommand;
import fr.xephi.authme.command.executable.authme.FirstSpawnCommand; import fr.xephi.authme.command.executable.authme.FirstSpawnCommand;
@ -226,13 +227,23 @@ public class CommandInitializer {
.parent(AUTHME_BASE) .parent(AUTHME_BASE)
.labels("purge", "delete") .labels("purge", "delete")
.description("Purge old data") .description("Purge old data")
.detailedDescription("Purge old AuthMeReloaded data longer than the specified amount of days ago.") .detailedDescription("Purge old AuthMeReloaded data longer than the specified number of days ago.")
.withArgument("days", "Number of days", false) .withArgument("days", "Number of days", false)
.withArgument("all", "Add 'all' at the end to also purge players with lastlogin = 0", true) .withArgument("all", "Add 'all' at the end to also purge players with lastlogin = 0", true)
.permission(AdminPermission.PURGE) .permission(AdminPermission.PURGE)
.executableCommand(PurgeCommand.class) .executableCommand(PurgeCommand.class)
.register(); .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 // Register the purgelastposition command
CommandDescription.builder() CommandDescription.builder()
.parent(AUTHME_BASE) .parent(AUTHME_BASE)

View File

@ -0,0 +1,23 @@
package fr.xephi.authme.command.executable.authme;
import fr.xephi.authme.command.ExecutableCommand;
import fr.xephi.authme.service.BackupService;
import fr.xephi.authme.service.BackupService.BackupCause;
import org.bukkit.command.CommandSender;
import javax.inject.Inject;
import java.util.List;
/**
* Command to perform a backup.
*/
public class BackupCommand implements ExecutableCommand {
@Inject
private BackupService backupService;
@Override
public void executeCommand(CommandSender sender, List<String> arguments) {
backupService.doBackup(BackupCause.COMMAND, sender);
}
}

View File

@ -113,7 +113,12 @@ public enum AdminPermission implements PermissionNode {
/** /**
* Permission to see the other accounts of the players that log in. * Permission to see the other accounts of the players that log in.
*/ */
SEE_OTHER_ACCOUNTS("authme.admin.seeotheraccounts"); SEE_OTHER_ACCOUNTS("authme.admin.seeotheraccounts"),
/**
* Allows to use the backup command.
*/
BACKUP("authme.admin.backup");
/** /**
* The permission node. * The permission node.

View File

@ -1,12 +1,15 @@
package fr.xephi.authme.service; package fr.xephi.authme.service;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.datasource.DataSourceType; import fr.xephi.authme.datasource.DataSourceType;
import fr.xephi.authme.initialization.DataFolder;
import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.properties.BackupSettings; import fr.xephi.authme.settings.properties.BackupSettings;
import fr.xephi.authme.settings.properties.DatabaseSettings; import fr.xephi.authme.settings.properties.DatabaseSettings;
import fr.xephi.authme.util.FileUtils;
import org.bukkit.command.CommandSender;
import javax.inject.Inject;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
@ -16,80 +19,80 @@ import java.io.OutputStream;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import static fr.xephi.authme.util.Utils.logAndSendMessage;
import static fr.xephi.authme.util.Utils.logAndSendWarning;
/** /**
* The backup management class * Performs a backup of the data source.
*
* @author stefano
*/ */
public class BackupService { public class BackupService {
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd_HH-mm"); private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd_HH-mm");
private final String dbName;
private final String dbUserName;
private final String dbPassword;
private final String tblname;
private final String path;
private final File dataFolder; private final File dataFolder;
private final File backupFolder;
private final Settings settings; private final Settings settings;
/** /**
* Constructor for PerformBackup. * Constructor.
* *
* @param instance AuthMe * @param dataFolder the data folder
* @param settings The plugin settings * @param settings the plugin settings
*/ */
public BackupService(AuthMe instance, Settings settings) { @Inject
this.dataFolder = instance.getDataFolder(); public BackupService(@DataFolder File dataFolder, Settings settings) {
this.settings = settings; this.dataFolder = dataFolder;
this.dbName = settings.getProperty(DatabaseSettings.MYSQL_DATABASE); this.backupFolder = new File(dataFolder, "backups");
this.dbUserName = settings.getProperty(DatabaseSettings.MYSQL_USERNAME); this.settings = settings;
this.dbPassword = settings.getProperty(DatabaseSettings.MYSQL_PASSWORD);
this.tblname = settings.getProperty(DatabaseSettings.MYSQL_TABLE);
String dateString = DATE_FORMAT.format(new Date());
this.path = String.join(File.separator,
instance.getDataFolder().getPath(), "backups", "backup" + dateString);
} }
/** /**
* Perform a backup with the given reason. * Performs a backup for the given reason.
* *
* @param cause The cause of the backup. * @param cause backup reason
*/ */
public void doBackup(BackupCause cause) { public void doBackup(BackupCause cause) {
doBackup(cause, null);
}
/**
* Performs a backup for the given reason.
*
* @param cause backup reason
* @param sender the command sender (nullable)
*/
public void doBackup(BackupCause cause, CommandSender sender) {
if (!settings.getProperty(BackupSettings.ENABLED)) { if (!settings.getProperty(BackupSettings.ENABLED)) {
// Print a warning if the backup was requested via command or by another plugin // Print a warning if the backup was requested via command or by another plugin
if (cause == BackupCause.COMMAND || cause == BackupCause.OTHER) { if (cause == BackupCause.COMMAND || cause == BackupCause.OTHER) {
ConsoleLogger.warning("Can't perform a Backup: disabled in configuration. Cause of the Backup: " logAndSendWarning(sender,
+ cause.name()); "Can't perform a backup: disabled in configuration. Cause of the backup: " + cause.name());
} }
return; return;
} } else if (BackupCause.START == cause && !settings.getProperty(BackupSettings.ON_SERVER_START)
|| BackupCause.STOP == cause && !settings.getProperty(BackupSettings.ON_SERVER_STOP)) {
// Check whether a backup should be made at the specified point in time // Don't perform backup on start or stop if so configured
if (BackupCause.START.equals(cause) && !settings.getProperty(BackupSettings.ON_SERVER_START)
|| BackupCause.STOP.equals(cause) && !settings.getProperty(BackupSettings.ON_SERVER_STOP)) {
return; return;
} }
// Do backup and check return value! // Do backup and check return value!
if (doBackup()) { if (doBackup()) {
ConsoleLogger.info("A backup has been performed successfully. Cause of the Backup: " + cause.name()); logAndSendMessage(sender,
"A backup has been performed successfully. Cause of the backup: " + cause.name());
} else { } else {
ConsoleLogger.warning("Error while performing a backup! Cause of the Backup: " + cause.name()); logAndSendWarning(sender, "Error while performing a backup! Cause of the backup: " + cause.name());
} }
} }
public boolean doBackup() { private boolean doBackup() {
DataSourceType dataSourceType = settings.getProperty(DatabaseSettings.BACKEND); DataSourceType dataSourceType = settings.getProperty(DatabaseSettings.BACKEND);
switch (dataSourceType) { switch (dataSourceType) {
case FILE: case FILE:
return fileBackup("auths.db"); return performFileBackup("auths.db");
case MYSQL: case MYSQL:
return mySqlBackup(); return performMySqlBackup();
case SQLITE: case SQLITE:
return fileBackup(dbName + ".db"); String dbName = settings.getProperty(DatabaseSettings.MYSQL_DATABASE);
return performFileBackup(dbName + ".db");
default: default:
ConsoleLogger.warning("Unknown data source type '" + dataSourceType + "' for backup"); ConsoleLogger.warning("Unknown data source type '" + dataSourceType + "' for backup");
} }
@ -97,17 +100,15 @@ public class BackupService {
return false; return false;
} }
private boolean mySqlBackup() { private boolean performMySqlBackup() {
File dirBackup = new File(dataFolder + File.separator + "backups"); FileUtils.createDirectory(backupFolder);
File sqlBackupFile = constructBackupFile("sql");
if (!dirBackup.exists()) {
dirBackup.mkdir();
}
String backupWindowsPath = settings.getProperty(BackupSettings.MYSQL_WINDOWS_PATH); String backupWindowsPath = settings.getProperty(BackupSettings.MYSQL_WINDOWS_PATH);
boolean isUsingWindows = checkWindows(backupWindowsPath); boolean isUsingWindows = useWindowsCommand(backupWindowsPath);
String backupCommand = isUsingWindows String backupCommand = isUsingWindows
? backupWindowsPath + "\\bin\\mysqldump.exe" + buildMysqlDumpArguments() ? backupWindowsPath + "\\bin\\mysqldump.exe" + buildMysqlDumpArguments(sqlBackupFile)
: "mysqldump" + buildMysqlDumpArguments(); : "mysqldump" + buildMysqlDumpArguments(sqlBackupFile);
try { try {
Process runtimeProcess = Runtime.getRuntime().exec(backupCommand); Process runtimeProcess = Runtime.getRuntime().exec(backupCommand);
@ -124,14 +125,12 @@ public class BackupService {
return false; return false;
} }
private boolean fileBackup(String backend) { private boolean performFileBackup(String filename) {
File dirBackup = new File(dataFolder + File.separator + "backups"); FileUtils.createDirectory(backupFolder);
File backupFile = constructBackupFile("db");
if (!dirBackup.exists())
dirBackup.mkdir();
try { try {
copy("plugins" + File.separator + "AuthMe" + File.separator + backend, path + ".db"); copy(new File(dataFolder, filename), backupFile);
return true; return true;
} catch (IOException ex) { } catch (IOException ex) {
ConsoleLogger.logException("Encountered an error during file backup:", ex); ConsoleLogger.logException("Encountered an error during file backup:", ex);
@ -146,7 +145,7 @@ public class BackupService {
* @param windowsPath The path to check * @param windowsPath The path to check
* @return True if the path is correct, false if it is incorrect or the OS is not Windows * @return True if the path is correct, false if it is incorrect or the OS is not Windows
*/ */
private static boolean checkWindows(String windowsPath) { private static boolean useWindowsCommand(String windowsPath) {
String isWin = System.getProperty("os.name").toLowerCase(); String isWin = System.getProperty("os.name").toLowerCase();
if (isWin.contains("win")) { if (isWin.contains("win")) {
if (new File(windowsPath + "\\bin\\mysqldump.exe").exists()) { if (new File(windowsPath + "\\bin\\mysqldump.exe").exists()) {
@ -162,28 +161,42 @@ public class BackupService {
/** /**
* Builds the command line arguments to pass along when running the {@code mysqldump} command. * Builds the command line arguments to pass along when running the {@code mysqldump} command.
* *
* @param sqlBackupFile the file to back up to
* @return the mysqldump command line arguments * @return the mysqldump command line arguments
*/ */
private String buildMysqlDumpArguments() { private String buildMysqlDumpArguments(File sqlBackupFile) {
return " -u " + dbUserName + " -p" + dbPassword + " " + dbName String dbUsername = settings.getProperty(DatabaseSettings.MYSQL_USERNAME);
+ " --tables " + tblname + " -r " + path + ".sql"; String dbPassword = settings.getProperty(DatabaseSettings.MYSQL_PASSWORD);
String dbName = settings.getProperty(DatabaseSettings.MYSQL_DATABASE);
String tableName = settings.getProperty(DatabaseSettings.MYSQL_TABLE);
return " -u " + dbUsername + " -p" + dbPassword + " " + dbName
+ " --tables " + tableName + " -r " + sqlBackupFile.getPath() + ".sql";
} }
private static void copy(String src, String dst) throws IOException { /**
InputStream in = new FileInputStream(src); * Constructs the file name to back up the data source to.
OutputStream out = new FileOutputStream(dst); *
* @param fileExtension the file extension to use (e.g. sql)
* @return the file to back up the data to
*/
private File constructBackupFile(String fileExtension) {
String dateString = dateFormat.format(new Date());
return new File(backupFolder, "backup" + dateString + "." + fileExtension);
}
// Transfer bytes from in to out private static void copy(File src, File dst) throws IOException {
byte[] buf = new byte[1024]; try (InputStream in = new FileInputStream(src);
int len; OutputStream out = new FileOutputStream(dst)) {
while ((len = in.read(buf)) > 0) { // Transfer bytes from in to out
out.write(buf, 0, len); byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
} }
in.close();
out.close();
} }
/** /**
* Possible backup causes. * Possible backup causes.
*/ */

View File

@ -8,19 +8,19 @@ import static ch.jalu.configme.properties.PropertyInitializer.newProperty;
public final class BackupSettings implements SettingsHolder { public final class BackupSettings implements SettingsHolder {
@Comment("Enable or disable automatic backup") @Comment("General configuration for backups: if false, no backups are possible")
public static final Property<Boolean> ENABLED = public static final Property<Boolean> ENABLED =
newProperty("BackupSystem.ActivateBackup", false); newProperty("BackupSystem.ActivateBackup", false);
@Comment("Set backup at every start of server") @Comment("Create backup at every start of server")
public static final Property<Boolean> ON_SERVER_START = public static final Property<Boolean> ON_SERVER_START =
newProperty("BackupSystem.OnServerStart", false); newProperty("BackupSystem.OnServerStart", false);
@Comment("Set backup at every stop of server") @Comment("Create backup at every stop of server")
public static final Property<Boolean> ON_SERVER_STOP = public static final Property<Boolean> ON_SERVER_STOP =
newProperty("BackupSystem.OnServerStop", true); newProperty("BackupSystem.OnServerStop", true);
@Comment("Windows only mysql installation Path") @Comment("Windows only: MySQL installation path")
public static final Property<String> MYSQL_WINDOWS_PATH = public static final Property<String> MYSQL_WINDOWS_PATH =
newProperty("BackupSystem.MysqlWindowsPath", "C:\\Program Files\\MySQL\\MySQL Server 5.1\\"); newProperty("BackupSystem.MysqlWindowsPath", "C:\\Program Files\\MySQL\\MySQL Server 5.1\\");

View File

@ -1,6 +1,7 @@
package fr.xephi.authme.util; package fr.xephi.authme.util;
import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.ConsoleLogger;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender; import org.bukkit.command.ConsoleCommandSender;
@ -69,6 +70,22 @@ public final class Utils {
} }
} }
/**
* Sends a warning to the given sender (null safe), and logs the warning to the console.
* This method is aware that the command sender might be the console sender and avoids
* displaying the message twice in this case.
*
* @param sender the sender to inform
* @param message the warning to log and send
*/
public static void logAndSendWarning(CommandSender sender, String message) {
ConsoleLogger.warning(message);
// Make sure sender is not console user, which will see the message from ConsoleLogger already
if (sender != null && !(sender instanceof ConsoleCommandSender)) {
sender.sendMessage(ChatColor.RED + message);
}
}
/** /**
* Null-safe way to check whether a collection is empty or not. * Null-safe way to check whether a collection is empty or not.
* *

View File

@ -17,7 +17,7 @@ softdepend:
commands: commands:
authme: authme:
description: AuthMe op commands description: AuthMe op commands
usage: /authme register|unregister|forcelogin|password|lastlogin|accounts|email|setemail|getip|spawn|setspawn|firstspawn|setfirstspawn|purge|resetpos|purgebannedplayers|switchantibot|reload|version|converter|messages|debug usage: /authme register|unregister|forcelogin|password|lastlogin|accounts|email|setemail|getip|spawn|setspawn|firstspawn|setfirstspawn|purge|backup|resetpos|purgebannedplayers|switchantibot|reload|version|converter|messages|debug
login: login:
description: Login command description: Login command
usage: /login <password> usage: /login <password>
@ -55,6 +55,7 @@ permissions:
children: children:
authme.admin.accounts: true authme.admin.accounts: true
authme.admin.antibotmessages: true authme.admin.antibotmessages: true
authme.admin.backup: true
authme.admin.changemail: true authme.admin.changemail: true
authme.admin.changepassword: true authme.admin.changepassword: true
authme.admin.converter: true authme.admin.converter: true
@ -81,6 +82,9 @@ permissions:
authme.admin.antibotmessages: authme.admin.antibotmessages:
description: Permission to see Antibot messages. description: Permission to see Antibot messages.
default: op default: op
authme.admin.backup:
description: Allows to use the backup command.
default: op
authme.admin.changemail: authme.admin.changemail:
description: Administrator command to set or change the email address of a user. description: Administrator command to set or change the email address of a user.
default: op default: op