mirror of
https://github.com/AuthMe/AuthMeReloaded.git
synced 2025-01-22 23:51:33 +01:00
Merge branch 'master' of https://github.com/AuthMe/AuthMeReloaded into explicit-getters-from-db
This commit is contained in:
commit
b7c35cb3a7
@ -1,5 +1,5 @@
|
||||
<!-- AUTO-GENERATED FILE! Do not edit this directly -->
|
||||
<!-- File auto-generated on Wed Mar 22 23:10:32 CET 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
|
||||
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`
|
||||
- **/authme setfirstspawn**: Change the first player's spawn to your current position.
|
||||
<br />Requires `authme.admin.setfirstspawn`
|
||||
- **/authme purge** <days> [all]: Purge old AuthMeReloaded data longer than the specified amount of days ago.
|
||||
- **/authme purge** <days> [all]: Purge old AuthMeReloaded data longer than the specified number of days ago.
|
||||
<br />Requires `authme.admin.purge`
|
||||
- **/authme backup**: Creates a backup of the registered users.
|
||||
<br />Requires `authme.admin.backup`
|
||||
- **/authme resetpos** <player/*>: Purge the last know position of the specified player or all of them.
|
||||
<br />Requires `authme.admin.purgelastpos`
|
||||
- **/authme purgebannedplayers**: Purge all AuthMeReloaded data for banned players.
|
||||
@ -47,8 +49,8 @@ brackets; optional arguments are enclosed in square brackets (`[ ]`).
|
||||
<br />Requires `authme.admin.converter`
|
||||
- **/authme messages**: Adds missing messages to the current messages file.
|
||||
<br />Requires `authme.admin.updatemessages`
|
||||
- **/authme debug** [child] [params]: Allows various operations for debugging.
|
||||
<br />Requires `authme.debug`
|
||||
- **/authme debug** [child] [arg] [arg]: Allows various operations for debugging.
|
||||
<br />Requires `authme.debug.command`
|
||||
- **/authme help** [query]: View detailed help for /authme commands.
|
||||
- **/login** <password>: Command to log in using AuthMeReloaded.
|
||||
<br />Requires `authme.player.login`
|
||||
@ -82,6 +84,7 @@ brackets; optional arguments are enclosed in square brackets (`[ ]`).
|
||||
<br />Requires `authme.player.captcha`
|
||||
- **/captcha help** [query]: View detailed help for /captcha commands.
|
||||
|
||||
|
||||
---
|
||||
|
||||
This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Wed Mar 22 23:10:32 CET 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!-- 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
|
||||
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.
|
||||
restoreWalkSpeed: 'MAX_RESTORE'
|
||||
BackupSystem:
|
||||
# Enable or disable automatic backup
|
||||
# General configuration for backups: if false, no backups are possible
|
||||
ActivateBackup: false
|
||||
# Set backup at every start of server
|
||||
# Create backup at every start of server
|
||||
OnServerStart: false
|
||||
# Set backup at every stop of server
|
||||
# Create backup at every stop of server
|
||||
OnServerStop: true
|
||||
# Windows only mysql installation Path
|
||||
# Windows only: MySQL installation path
|
||||
MysqlWindowsPath: 'C:\Program Files\MySQL\MySQL Server 5.1\'
|
||||
Converter:
|
||||
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
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!-- AUTO-GENERATED FILE! Do not edit this directly -->
|
||||
<!-- File auto-generated on Sun Oct 23 15:38:58 CEST 2016. See 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
|
||||
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.accounts** – Administrator command to see all accounts associated with a user.
|
||||
- **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.changepassword** – Administrator command to change the password of a user.
|
||||
- **authme.admin.converter** – Administrator command to convert old or other data to AuthMe data.
|
||||
@ -31,6 +32,16 @@ The following are the permission nodes that are currently supported by the lates
|
||||
- **authme.bypassantibot** – Permission node to bypass AntiBot protection.
|
||||
- **authme.bypassforcesurvival** – Permission for users to bypass force-survival mode.
|
||||
- **authme.bypasspurge** – Permission to bypass the purging process.
|
||||
- **authme.debug.command** – General permission to use the /authme debug command.
|
||||
- **authme.debug.country** – Permission to use the country lookup section.
|
||||
- **authme.debug.db** – Permission to view data from the database.
|
||||
- **authme.debug.group** – Permission to view permission groups.
|
||||
- **authme.debug.limbo** – Permission to use the limbo data viewer.
|
||||
- **authme.debug.mail** – Permission to use the test email sender.
|
||||
- **authme.debug.perm** – Permission to use the permission checker.
|
||||
- **authme.debug.spawn** – Permission to view spawn information.
|
||||
- **authme.debug.stats** – Permission to use the stats section.
|
||||
- **authme.debug.valid** – Permission to use sample validation.
|
||||
- **authme.player.*** – Permission to use all player (non-admin) commands.
|
||||
- **authme.player.canbeforced** – Permission for users a login can be forced to.
|
||||
- **authme.player.captcha** – Command permission to use captcha.
|
||||
@ -49,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 Sun Oct 23 15:38:58 CEST 2016
|
||||
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
|
||||
|
2
pom.xml
2
pom.xml
@ -568,7 +568,7 @@
|
||||
<dependency>
|
||||
<groupId>com.comphenix.protocol</groupId>
|
||||
<artifactId>ProtocolLib-API</artifactId>
|
||||
<version>4.2.0</version>
|
||||
<version>4.2.1</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
|
@ -72,6 +72,7 @@ public class AuthMe extends JavaPlugin {
|
||||
private DataSource database;
|
||||
private BukkitService bukkitService;
|
||||
private Injector injector;
|
||||
private BackupService backupService;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@ -154,7 +155,7 @@ public class AuthMe extends JavaPlugin {
|
||||
}
|
||||
|
||||
// Do a backup on start
|
||||
new BackupService(this, settings).doBackup(BackupService.BackupCause.START);
|
||||
backupService.doBackup(BackupService.BackupCause.START);
|
||||
|
||||
// Set up Metrics
|
||||
OnStartupTasks.sendMetrics(this, settings);
|
||||
@ -257,6 +258,7 @@ public class AuthMe extends JavaPlugin {
|
||||
permsMan = injector.getSingleton(PermissionsManager.class);
|
||||
bukkitService = injector.getSingleton(BukkitService.class);
|
||||
commandHandler = injector.getSingleton(CommandHandler.class);
|
||||
backupService = injector.getSingleton(BackupService.class);
|
||||
|
||||
// Trigger construction of API classes; they will keep track of the singleton
|
||||
injector.getSingleton(fr.xephi.authme.api.v3.AuthMeApi.class);
|
||||
@ -352,8 +354,8 @@ public class AuthMe extends JavaPlugin {
|
||||
}
|
||||
|
||||
// Do backup on stop if enabled
|
||||
if (settings != null) {
|
||||
new BackupService(this, settings).doBackup(BackupService.BackupCause.STOP);
|
||||
if (backupService != null) {
|
||||
backupService.doBackup(BackupService.BackupCause.STOP);
|
||||
}
|
||||
|
||||
// Wait for tasks and close data source
|
||||
|
@ -4,6 +4,7 @@ import com.google.common.collect.ImmutableList;
|
||||
import fr.xephi.authme.command.executable.HelpCommand;
|
||||
import fr.xephi.authme.command.executable.authme.AccountsCommand;
|
||||
import fr.xephi.authme.command.executable.authme.AuthMeCommand;
|
||||
import fr.xephi.authme.command.executable.authme.BackupCommand;
|
||||
import fr.xephi.authme.command.executable.authme.ChangePasswordAdminCommand;
|
||||
import fr.xephi.authme.command.executable.authme.ConverterCommand;
|
||||
import fr.xephi.authme.command.executable.authme.FirstSpawnCommand;
|
||||
@ -39,8 +40,8 @@ import fr.xephi.authme.command.executable.logout.LogoutCommand;
|
||||
import fr.xephi.authme.command.executable.register.RegisterCommand;
|
||||
import fr.xephi.authme.command.executable.unregister.UnregisterCommand;
|
||||
import fr.xephi.authme.permission.AdminPermission;
|
||||
import fr.xephi.authme.permission.DebugSectionPermissions;
|
||||
import fr.xephi.authme.permission.PlayerPermission;
|
||||
import fr.xephi.authme.permission.PlayerStatePermission;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
@ -226,13 +227,23 @@ public class CommandInitializer {
|
||||
.parent(AUTHME_BASE)
|
||||
.labels("purge", "delete")
|
||||
.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("all", "Add 'all' at the end to also purge players with lastlogin = 0", true)
|
||||
.permission(AdminPermission.PURGE)
|
||||
.executableCommand(PurgeCommand.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)
|
||||
@ -312,10 +323,9 @@ public class CommandInitializer {
|
||||
.description("Debug features")
|
||||
.detailedDescription("Allows various operations for debugging.")
|
||||
.withArgument("child", "The child to execute", true)
|
||||
.withArgument(".", "meaning varies", true)
|
||||
.withArgument(".", "meaning varies", true)
|
||||
.withArgument(".", "meaning varies", true)
|
||||
.permission(PlayerStatePermission.DEBUG_COMMAND)
|
||||
.withArgument("arg", "argument (depends on debug section)", true)
|
||||
.withArgument("arg", "argument (depends on debug section)", true)
|
||||
.permission(DebugSectionPermissions.DEBUG_COMMAND)
|
||||
.executableCommand(DebugCommand.class)
|
||||
.register();
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -2,6 +2,8 @@ package fr.xephi.authme.command.executable.authme.debug;
|
||||
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.permission.DebugSectionPermissions;
|
||||
import fr.xephi.authme.permission.PermissionNode;
|
||||
import fr.xephi.authme.service.GeoIpService;
|
||||
import fr.xephi.authme.service.ValidationService;
|
||||
import fr.xephi.authme.settings.properties.ProtectionSettings;
|
||||
@ -54,6 +56,11 @@ class CountryLookup implements DebugSection {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionNode getRequiredPermission() {
|
||||
return DebugSectionPermissions.COUNTRY_LOOKUP;
|
||||
}
|
||||
|
||||
private void outputInfoForIpAddr(CommandSender sender, String ipAddr) {
|
||||
sender.sendMessage("IP '" + ipAddr + "' maps to country '" + geoIpService.getCountryCode(ipAddr)
|
||||
+ "' (" + geoIpService.getCountryName(ipAddr) + ")");
|
||||
|
@ -8,6 +8,8 @@ import fr.xephi.authme.initialization.HasCleanup;
|
||||
import fr.xephi.authme.initialization.Reloadable;
|
||||
import fr.xephi.authme.initialization.SettingsDependent;
|
||||
import fr.xephi.authme.initialization.factory.SingletonStore;
|
||||
import fr.xephi.authme.permission.DebugSectionPermissions;
|
||||
import fr.xephi.authme.permission.PermissionNode;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@ -52,6 +54,11 @@ class DataStatistics implements DebugSection {
|
||||
outputInjectorStats(sender);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionNode getRequiredPermission() {
|
||||
return DebugSectionPermissions.DATA_STATISTICS;
|
||||
}
|
||||
|
||||
private void outputDatabaseStats(CommandSender sender) {
|
||||
sender.sendMessage("Total players in DB: " + dataSource.getAccountsRegistered());
|
||||
if (dataSource instanceof CacheDataSource) {
|
||||
|
@ -3,6 +3,8 @@ package fr.xephi.authme.command.executable.authme.debug;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import fr.xephi.authme.command.ExecutableCommand;
|
||||
import fr.xephi.authme.initialization.factory.Factory;
|
||||
import fr.xephi.authme.permission.PermissionsManager;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@ -24,27 +26,48 @@ public class DebugCommand implements ExecutableCommand {
|
||||
@Inject
|
||||
private Factory<DebugSection> debugSectionFactory;
|
||||
|
||||
@Inject
|
||||
private PermissionsManager permissionsManager;
|
||||
|
||||
private Map<String, DebugSection> sections;
|
||||
|
||||
@Override
|
||||
public void executeCommand(CommandSender sender, List<String> arguments) {
|
||||
DebugSection debugSection = getDebugSection(arguments);
|
||||
DebugSection debugSection = findDebugSection(arguments);
|
||||
if (debugSection == null) {
|
||||
sender.sendMessage("Available sections:");
|
||||
getSections().values()
|
||||
.forEach(e -> sender.sendMessage("- " + e.getName() + ": " + e.getDescription()));
|
||||
sendAvailableSections(sender);
|
||||
} else {
|
||||
debugSection.execute(sender, arguments.subList(1, arguments.size()));
|
||||
executeSection(debugSection, sender, arguments);
|
||||
}
|
||||
}
|
||||
|
||||
private DebugSection getDebugSection(List<String> arguments) {
|
||||
private DebugSection findDebugSection(List<String> arguments) {
|
||||
if (arguments.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return getSections().get(arguments.get(0).toLowerCase());
|
||||
}
|
||||
|
||||
private void sendAvailableSections(CommandSender sender) {
|
||||
sender.sendMessage("Sections available to you:");
|
||||
long availableSections = getSections().values().stream()
|
||||
.filter(section -> permissionsManager.hasPermission(sender, section.getRequiredPermission()))
|
||||
.peek(e -> sender.sendMessage("- " + e.getName() + ": " + e.getDescription()))
|
||||
.count();
|
||||
|
||||
if (availableSections == 0) {
|
||||
sender.sendMessage(ChatColor.RED + "You don't have permission to view any debug section");
|
||||
}
|
||||
}
|
||||
|
||||
private void executeSection(DebugSection section, CommandSender sender, List<String> arguments) {
|
||||
if (permissionsManager.hasPermission(sender, section.getRequiredPermission())) {
|
||||
section.execute(sender, arguments.subList(1, arguments.size()));
|
||||
} else {
|
||||
sender.sendMessage(ChatColor.RED + "You don't have permission for this section. See /authme debug");
|
||||
}
|
||||
}
|
||||
|
||||
// Lazy getter
|
||||
private Map<String, DebugSection> getSections() {
|
||||
if (sections == null) {
|
||||
|
@ -1,5 +1,6 @@
|
||||
package fr.xephi.authme.command.executable.authme.debug;
|
||||
|
||||
import fr.xephi.authme.permission.PermissionNode;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.util.List;
|
||||
@ -27,4 +28,9 @@ interface DebugSection {
|
||||
*/
|
||||
void execute(CommandSender sender, List<String> arguments);
|
||||
|
||||
/**
|
||||
* @return permission required to run this section
|
||||
*/
|
||||
PermissionNode getRequiredPermission();
|
||||
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package fr.xephi.authme.command.executable.authme.debug;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import fr.xephi.authme.permission.AdminPermission;
|
||||
import fr.xephi.authme.permission.DebugSectionPermissions;
|
||||
import fr.xephi.authme.permission.DefaultPermission;
|
||||
import fr.xephi.authme.permission.PermissionNode;
|
||||
import fr.xephi.authme.permission.PermissionsManager;
|
||||
@ -25,8 +26,8 @@ import java.util.function.BiFunction;
|
||||
*/
|
||||
class HasPermissionChecker implements DebugSection {
|
||||
|
||||
static final List<Class<? extends PermissionNode>> PERMISSION_NODE_CLASSES =
|
||||
ImmutableList.of(AdminPermission.class, PlayerPermission.class, PlayerStatePermission.class);
|
||||
static final List<Class<? extends PermissionNode>> PERMISSION_NODE_CLASSES = ImmutableList.of(
|
||||
AdminPermission.class, PlayerPermission.class, PlayerStatePermission.class, DebugSectionPermissions.class);
|
||||
|
||||
@Inject
|
||||
private PermissionsManager permissionsManager;
|
||||
@ -69,6 +70,11 @@ class HasPermissionChecker implements DebugSection {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionNode getRequiredPermission() {
|
||||
return DebugSectionPermissions.HAS_PERMISSION_CHECK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a permission check and informs the given sender of the result. {@code permissionChecker} is the
|
||||
* permission check to perform with the given {@code node} and the {@code player}.
|
||||
@ -90,7 +96,6 @@ class HasPermissionChecker implements DebugSection {
|
||||
sender.sendMessage(ChatColor.DARK_RED + "Check failed: player '" + player.getName()
|
||||
+ "' does NOT have permission '" + node + "'");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3,6 +3,8 @@ package fr.xephi.authme.command.executable.authme.debug;
|
||||
import fr.xephi.authme.listener.FailedVerificationException;
|
||||
import fr.xephi.authme.listener.OnJoinVerifier;
|
||||
import fr.xephi.authme.message.Messages;
|
||||
import fr.xephi.authme.permission.DebugSectionPermissions;
|
||||
import fr.xephi.authme.permission.PermissionNode;
|
||||
import fr.xephi.authme.service.ValidationService;
|
||||
import fr.xephi.authme.service.ValidationService.ValidationResult;
|
||||
import org.bukkit.ChatColor;
|
||||
@ -60,6 +62,11 @@ class InputValidator implements DebugSection {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionNode getRequiredPermission() {
|
||||
return DebugSectionPermissions.INPUT_VALIDATOR;
|
||||
}
|
||||
|
||||
private void displayUsageHint(CommandSender sender) {
|
||||
sender.sendMessage("You can define forbidden emails and passwords in your config.yml");
|
||||
sender.sendMessage("This command allows you to test some of the values:");
|
||||
|
@ -3,6 +3,8 @@ package fr.xephi.authme.command.executable.authme.debug;
|
||||
import fr.xephi.authme.data.limbo.LimboPlayer;
|
||||
import fr.xephi.authme.data.limbo.LimboService;
|
||||
import fr.xephi.authme.data.limbo.persistence.LimboPersistence;
|
||||
import fr.xephi.authme.permission.DebugSectionPermissions;
|
||||
import fr.xephi.authme.permission.PermissionNode;
|
||||
import fr.xephi.authme.permission.PermissionsManager;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import org.bukkit.ChatColor;
|
||||
@ -71,6 +73,11 @@ class LimboPlayerViewer implements DebugSection {
|
||||
.sendEntry("Group", LimboPlayer::getGroup, permissionsManager::getPrimaryGroup);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionNode getRequiredPermission() {
|
||||
return DebugSectionPermissions.LIMBO_PLAYER_VIEWER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the info for the given LimboPlayer and Player to the provided CommandSender.
|
||||
*/
|
||||
|
@ -1,5 +1,7 @@
|
||||
package fr.xephi.authme.command.executable.authme.debug;
|
||||
|
||||
import fr.xephi.authme.permission.DebugSectionPermissions;
|
||||
import fr.xephi.authme.permission.PermissionNode;
|
||||
import fr.xephi.authme.permission.PermissionsManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
@ -38,4 +40,9 @@ class PermissionGroups implements DebugSection {
|
||||
sender.sendMessage("Primary group is: " + permissionsManager.getGroups(player));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionNode getRequiredPermission() {
|
||||
return DebugSectionPermissions.PERM_GROUPS;
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,8 @@ package fr.xephi.authme.command.executable.authme.debug;
|
||||
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.permission.DebugSectionPermissions;
|
||||
import fr.xephi.authme.permission.PermissionNode;
|
||||
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||
import fr.xephi.authme.util.StringUtils;
|
||||
import org.bukkit.ChatColor;
|
||||
@ -50,6 +52,11 @@ class PlayerAuthViewer implements DebugSection {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionNode getRequiredPermission() {
|
||||
return DebugSectionPermissions.PLAYER_AUTH_VIEWER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs the PlayerAuth information to the given sender.
|
||||
*
|
||||
|
@ -1,5 +1,7 @@
|
||||
package fr.xephi.authme.command.executable.authme.debug;
|
||||
|
||||
import fr.xephi.authme.permission.DebugSectionPermissions;
|
||||
import fr.xephi.authme.permission.PermissionNode;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.SpawnLoader;
|
||||
@ -49,6 +51,11 @@ class SpawnLocationViewer implements DebugSection {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionNode getRequiredPermission() {
|
||||
return DebugSectionPermissions.SPAWN_LOCATION;
|
||||
}
|
||||
|
||||
private void showGeneralInfo(CommandSender sender) {
|
||||
sender.sendMessage("Spawn priority: "
|
||||
+ String.join(", ", settings.getProperty(RestrictionSettings.SPAWN_PRIORITY)));
|
||||
|
@ -4,6 +4,8 @@ import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.datasource.DataSourceResult;
|
||||
import fr.xephi.authme.mail.SendMailSsl;
|
||||
import fr.xephi.authme.permission.DebugSectionPermissions;
|
||||
import fr.xephi.authme.permission.PermissionNode;
|
||||
import fr.xephi.authme.util.StringUtils;
|
||||
import fr.xephi.authme.util.Utils;
|
||||
import org.apache.commons.mail.EmailException;
|
||||
@ -61,6 +63,11 @@ class TestEmailSender implements DebugSection {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionNode getRequiredPermission() {
|
||||
return DebugSectionPermissions.TEST_EMAIL;
|
||||
}
|
||||
|
||||
private String getEmail(CommandSender sender, List<String> arguments) {
|
||||
if (arguments.isEmpty()) {
|
||||
DataSourceResult<String> emailResult = dataSource.getEmail(sender.getName());
|
||||
|
@ -41,10 +41,7 @@ class DistributedFilesPersistenceHandler implements LimboPersistenceHandler {
|
||||
@Inject
|
||||
DistributedFilesPersistenceHandler(@DataFolder File dataFolder, BukkitService bukkitService, Settings settings) {
|
||||
cacheFolder = new File(dataFolder, "playerdata");
|
||||
if (!cacheFolder.exists()) {
|
||||
// TODO ljacqu 20170313: Create FileUtils#mkdirs
|
||||
cacheFolder.mkdirs();
|
||||
}
|
||||
FileUtils.createDirectory(cacheFolder);
|
||||
|
||||
gson = new GsonBuilder()
|
||||
.registerTypeAdapter(LimboPlayer.class, new LimboPlayerSerializer())
|
||||
|
@ -8,6 +8,7 @@ import fr.xephi.authme.security.PasswordSecurity;
|
||||
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.properties.ConverterSettings;
|
||||
import fr.xephi.authme.util.Utils;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@ -85,8 +86,7 @@ public class RakamakConverter implements Converter {
|
||||
.build();
|
||||
database.saveAuth(auth);
|
||||
}
|
||||
ConsoleLogger.info("Rakamak database has been imported correctly");
|
||||
sender.sendMessage("Rakamak database has been imported correctly");
|
||||
Utils.logAndSendMessage(sender, "Rakamak database has been imported correctly");
|
||||
} catch (IOException ex) {
|
||||
ConsoleLogger.logException("Can't open the rakamak database file! Does it exist?", ex);
|
||||
}
|
||||
|
@ -113,7 +113,12 @@ public enum AdminPermission implements PermissionNode {
|
||||
/**
|
||||
* 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.
|
||||
|
@ -0,0 +1,58 @@
|
||||
package fr.xephi.authme.permission;
|
||||
|
||||
/**
|
||||
* Permissions for the debug sections (/authme debug).
|
||||
*/
|
||||
public enum DebugSectionPermissions implements PermissionNode {
|
||||
|
||||
/** General permission to use the /authme debug command. */
|
||||
DEBUG_COMMAND("authme.debug.command"),
|
||||
|
||||
/** Permission to use the country lookup section. */
|
||||
COUNTRY_LOOKUP("authme.debug.country"),
|
||||
|
||||
/** Permission to use the stats section. */
|
||||
DATA_STATISTICS("authme.debug.stats"),
|
||||
|
||||
/** Permission to use the permission checker. */
|
||||
HAS_PERMISSION_CHECK("authme.debug.perm"),
|
||||
|
||||
/** Permission to use sample validation. */
|
||||
INPUT_VALIDATOR("authme.debug.valid"),
|
||||
|
||||
/** Permission to use the limbo data viewer. */
|
||||
LIMBO_PLAYER_VIEWER("authme.debug.limbo"),
|
||||
|
||||
/** Permission to view permission groups. */
|
||||
PERM_GROUPS("authme.debug.group"),
|
||||
|
||||
/** Permission to view data from the database. */
|
||||
PLAYER_AUTH_VIEWER("authme.debug.db"),
|
||||
|
||||
/** Permission to view spawn information. */
|
||||
SPAWN_LOCATION("authme.debug.spawn"),
|
||||
|
||||
/** Permission to use the test email sender. */
|
||||
TEST_EMAIL("authme.debug.mail");
|
||||
|
||||
private final String node;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param node the permission node
|
||||
*/
|
||||
DebugSectionPermissions(String node) {
|
||||
this.node = node;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNode() {
|
||||
return node;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultPermission getDefaultPermission() {
|
||||
return DefaultPermission.OP_ONLY;
|
||||
}
|
||||
}
|
@ -29,12 +29,7 @@ public enum PlayerStatePermission implements PermissionNode {
|
||||
/**
|
||||
* Permission to bypass the purging process.
|
||||
*/
|
||||
BYPASS_PURGE("authme.bypasspurge", DefaultPermission.NOT_ALLOWED),
|
||||
|
||||
/**
|
||||
* Permission to use the /authme debug command.
|
||||
*/
|
||||
DEBUG_COMMAND("authme.debug", DefaultPermission.OP_ONLY);
|
||||
BYPASS_PURGE("authme.bypasspurge", DefaultPermission.NOT_ALLOWED);
|
||||
|
||||
/**
|
||||
* The permission node.
|
||||
|
@ -85,12 +85,22 @@ public final class HashUtils {
|
||||
* @param algorithm The algorithm to hash the message with
|
||||
* @return The digest in its hexadecimal representation
|
||||
*/
|
||||
private static String hash(String message, MessageDigestAlgorithm algorithm) {
|
||||
MessageDigest md = getDigest(algorithm);
|
||||
md.reset();
|
||||
md.update(message.getBytes());
|
||||
byte[] digest = md.digest();
|
||||
public static String hash(String message, MessageDigest algorithm) {
|
||||
algorithm.reset();
|
||||
algorithm.update(message.getBytes());
|
||||
byte[] digest = algorithm.digest();
|
||||
return String.format("%0" + (digest.length << 1) + "x", new BigInteger(1, digest));
|
||||
}
|
||||
|
||||
/**
|
||||
* Hash the message with the given algorithm and return the hash in its hexadecimal notation.
|
||||
*
|
||||
* @param message The message to hash
|
||||
* @param algorithm The algorithm to hash the message with
|
||||
* @return The digest in its hexadecimal representation
|
||||
*/
|
||||
private static String hash(String message, MessageDigestAlgorithm algorithm) {
|
||||
return hash(message, getDigest(algorithm));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,14 +1,17 @@
|
||||
package fr.xephi.authme.security.crypts;
|
||||
|
||||
import fr.xephi.authme.security.HashUtils;
|
||||
import fr.xephi.authme.security.MessageDigestAlgorithm;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
|
||||
public class RoyalAuth extends UnsaltedMethod {
|
||||
|
||||
@Override
|
||||
public String computeHash(String password) {
|
||||
for (int i = 0; i < 25; i++) {
|
||||
// TODO ljacqu 20151228: HashUtils#sha512 gets a new message digest each time...
|
||||
password = HashUtils.sha512(password);
|
||||
MessageDigest algorithm = HashUtils.getDigest(MessageDigestAlgorithm.SHA512);
|
||||
for (int i = 0; i < 25; ++i) {
|
||||
password = HashUtils.hash(password, algorithm);
|
||||
}
|
||||
return password;
|
||||
}
|
||||
|
@ -1,12 +1,15 @@
|
||||
package fr.xephi.authme.service;
|
||||
|
||||
import fr.xephi.authme.AuthMe;
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.datasource.DataSourceType;
|
||||
import fr.xephi.authme.initialization.DataFolder;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.properties.BackupSettings;
|
||||
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.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
@ -16,80 +19,80 @@ import java.io.OutputStream;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
import static fr.xephi.authme.util.Utils.logAndSendMessage;
|
||||
import static fr.xephi.authme.util.Utils.logAndSendWarning;
|
||||
|
||||
/**
|
||||
* The backup management class
|
||||
*
|
||||
* @author stefano
|
||||
* Performs a backup of the data source.
|
||||
*/
|
||||
public class BackupService {
|
||||
|
||||
private static final SimpleDateFormat DATE_FORMAT = 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 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd_HH-mm");
|
||||
private final File dataFolder;
|
||||
private final File backupFolder;
|
||||
private final Settings settings;
|
||||
|
||||
/**
|
||||
* Constructor for PerformBackup.
|
||||
* Constructor.
|
||||
*
|
||||
* @param instance AuthMe
|
||||
* @param settings The plugin settings
|
||||
* @param dataFolder the data folder
|
||||
* @param settings the plugin settings
|
||||
*/
|
||||
public BackupService(AuthMe instance, Settings settings) {
|
||||
this.dataFolder = instance.getDataFolder();
|
||||
this.settings = settings;
|
||||
this.dbName = settings.getProperty(DatabaseSettings.MYSQL_DATABASE);
|
||||
this.dbUserName = settings.getProperty(DatabaseSettings.MYSQL_USERNAME);
|
||||
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);
|
||||
@Inject
|
||||
public BackupService(@DataFolder File dataFolder, Settings settings) {
|
||||
this.dataFolder = dataFolder;
|
||||
this.backupFolder = new File(dataFolder, "backups");
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
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)) {
|
||||
// Print a warning if the backup was requested via command or by another plugin
|
||||
if (cause == BackupCause.COMMAND || cause == BackupCause.OTHER) {
|
||||
ConsoleLogger.warning("Can't perform a Backup: disabled in configuration. Cause of the Backup: "
|
||||
+ cause.name());
|
||||
logAndSendWarning(sender,
|
||||
"Can't perform a backup: disabled in configuration. Cause of the backup: " + cause.name());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Check whether a backup should be made at the specified point in time
|
||||
if (BackupCause.START.equals(cause) && !settings.getProperty(BackupSettings.ON_SERVER_START)
|
||||
|| BackupCause.STOP.equals(cause) && !settings.getProperty(BackupSettings.ON_SERVER_STOP)) {
|
||||
} else if (BackupCause.START == cause && !settings.getProperty(BackupSettings.ON_SERVER_START)
|
||||
|| BackupCause.STOP == cause && !settings.getProperty(BackupSettings.ON_SERVER_STOP)) {
|
||||
// Don't perform backup on start or stop if so configured
|
||||
return;
|
||||
}
|
||||
|
||||
// Do backup and check return value!
|
||||
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 {
|
||||
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);
|
||||
switch (dataSourceType) {
|
||||
case FILE:
|
||||
return fileBackup("auths.db");
|
||||
return performFileBackup("auths.db");
|
||||
case MYSQL:
|
||||
return mySqlBackup();
|
||||
return performMySqlBackup();
|
||||
case SQLITE:
|
||||
return fileBackup(dbName + ".db");
|
||||
String dbName = settings.getProperty(DatabaseSettings.MYSQL_DATABASE);
|
||||
return performFileBackup(dbName + ".db");
|
||||
default:
|
||||
ConsoleLogger.warning("Unknown data source type '" + dataSourceType + "' for backup");
|
||||
}
|
||||
@ -97,17 +100,15 @@ public class BackupService {
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean mySqlBackup() {
|
||||
File dirBackup = new File(dataFolder + File.separator + "backups");
|
||||
private boolean performMySqlBackup() {
|
||||
FileUtils.createDirectory(backupFolder);
|
||||
File sqlBackupFile = constructBackupFile("sql");
|
||||
|
||||
if (!dirBackup.exists()) {
|
||||
dirBackup.mkdir();
|
||||
}
|
||||
String backupWindowsPath = settings.getProperty(BackupSettings.MYSQL_WINDOWS_PATH);
|
||||
boolean isUsingWindows = checkWindows(backupWindowsPath);
|
||||
boolean isUsingWindows = useWindowsCommand(backupWindowsPath);
|
||||
String backupCommand = isUsingWindows
|
||||
? backupWindowsPath + "\\bin\\mysqldump.exe" + buildMysqlDumpArguments()
|
||||
: "mysqldump" + buildMysqlDumpArguments();
|
||||
? backupWindowsPath + "\\bin\\mysqldump.exe" + buildMysqlDumpArguments(sqlBackupFile)
|
||||
: "mysqldump" + buildMysqlDumpArguments(sqlBackupFile);
|
||||
|
||||
try {
|
||||
Process runtimeProcess = Runtime.getRuntime().exec(backupCommand);
|
||||
@ -124,14 +125,12 @@ public class BackupService {
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean fileBackup(String backend) {
|
||||
File dirBackup = new File(dataFolder + File.separator + "backups");
|
||||
|
||||
if (!dirBackup.exists())
|
||||
dirBackup.mkdir();
|
||||
private boolean performFileBackup(String filename) {
|
||||
FileUtils.createDirectory(backupFolder);
|
||||
File backupFile = constructBackupFile("db");
|
||||
|
||||
try {
|
||||
copy("plugins" + File.separator + "AuthMe" + File.separator + backend, path + ".db");
|
||||
copy(new File(dataFolder, filename), backupFile);
|
||||
return true;
|
||||
} catch (IOException ex) {
|
||||
ConsoleLogger.logException("Encountered an error during file backup:", ex);
|
||||
@ -146,7 +145,7 @@ public class BackupService {
|
||||
* @param windowsPath The path to check
|
||||
* @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();
|
||||
if (isWin.contains("win")) {
|
||||
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.
|
||||
*
|
||||
* @param sqlBackupFile the file to back up to
|
||||
* @return the mysqldump command line arguments
|
||||
*/
|
||||
private String buildMysqlDumpArguments() {
|
||||
return " -u " + dbUserName + " -p" + dbPassword + " " + dbName
|
||||
+ " --tables " + tblname + " -r " + path + ".sql";
|
||||
private String buildMysqlDumpArguments(File sqlBackupFile) {
|
||||
String dbUsername = settings.getProperty(DatabaseSettings.MYSQL_USERNAME);
|
||||
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);
|
||||
OutputStream out = new FileOutputStream(dst);
|
||||
/**
|
||||
* Constructs the file name to back up the data source to.
|
||||
*
|
||||
* @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
|
||||
byte[] buf = new byte[1024];
|
||||
int len;
|
||||
while ((len = in.read(buf)) > 0) {
|
||||
out.write(buf, 0, len);
|
||||
private static void copy(File src, File dst) throws IOException {
|
||||
try (InputStream in = new FileInputStream(src);
|
||||
OutputStream out = new FileOutputStream(dst)) {
|
||||
// Transfer bytes from in to out
|
||||
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.
|
||||
*/
|
||||
|
@ -45,7 +45,6 @@ public class SpawnLoader implements Reloadable {
|
||||
*/
|
||||
@Inject
|
||||
SpawnLoader(@DataFolder File pluginFolder, Settings settings, PluginHookService pluginHookService) {
|
||||
// TODO ljacqu 20160312: Check if resource could be copied and handle the case if not
|
||||
File spawnFile = new File(pluginFolder, "spawn.yml");
|
||||
FileUtils.copyFileFromResource(spawnFile, "spawn.yml");
|
||||
this.authMeConfigurationFile = spawnFile;
|
||||
|
@ -8,19 +8,19 @@ import static ch.jalu.configme.properties.PropertyInitializer.newProperty;
|
||||
|
||||
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 =
|
||||
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 =
|
||||
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 =
|
||||
newProperty("BackupSystem.OnServerStop", true);
|
||||
|
||||
@Comment("Windows only mysql installation Path")
|
||||
@Comment("Windows only: MySQL installation path")
|
||||
public static final Property<String> MYSQL_WINDOWS_PATH =
|
||||
newProperty("BackupSystem.MysqlWindowsPath", "C:\\Program Files\\MySQL\\MySQL Server 5.1\\");
|
||||
|
||||
|
@ -194,7 +194,6 @@ class PurgeExecutor {
|
||||
}
|
||||
|
||||
// TODO: What is this method for? Is it correct?
|
||||
// TODO: Make it work with OfflinePlayers group data.
|
||||
synchronized void purgePermissions(Collection<OfflinePlayer> cleared) {
|
||||
if (!settings.getProperty(PurgeSettings.REMOVE_PERMISSIONS)) {
|
||||
return;
|
||||
|
@ -30,7 +30,7 @@ public final class FileUtils {
|
||||
public static boolean copyFileFromResource(File destinationFile, String resourcePath) {
|
||||
if (destinationFile.exists()) {
|
||||
return true;
|
||||
} else if (!destinationFile.getParentFile().exists() && !destinationFile.getParentFile().mkdirs()) {
|
||||
} else if (!createDirectory(destinationFile.getParentFile())) {
|
||||
ConsoleLogger.warning("Cannot create parent directories for '" + destinationFile + "'");
|
||||
return false;
|
||||
}
|
||||
@ -50,6 +50,20 @@ public final class FileUtils {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the given directory.
|
||||
*
|
||||
* @param dir the directory to create
|
||||
* @return true upon success, false otherwise
|
||||
*/
|
||||
public static boolean createDirectory(File dir) {
|
||||
if (!dir.exists() && !dir.mkdirs()) {
|
||||
ConsoleLogger.warning("Could not create directory '" + dir + "'");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a JAR file as stream. Returns null if it doesn't exist.
|
||||
*
|
||||
|
@ -1,6 +1,7 @@
|
||||
package fr.xephi.authme.util;
|
||||
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
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.
|
||||
*
|
||||
|
@ -49,9 +49,9 @@ two_factor_create: '&2O seu código secreto é %code. Você pode verificá-lo a
|
||||
recovery_code_sent: 'Um código de recuperação para redefinir sua senha foi enviada para o seu e-mail.'
|
||||
# TODO: Missing tags %count
|
||||
recovery_code_incorrect: 'O código de recuperação esta incorreto! Use /email recovery [email] para gerar um novo!'
|
||||
# TODO recovery_tries_exceeded: 'You have exceeded the maximum number attempts to enter the recovery code. Use "/email recovery [email]" to generate a new one.'
|
||||
# TODO recovery_code_correct: 'Recovery code entered correctly!'
|
||||
# TODO recovery_change_password: 'Please use the command /email setpassword <new password> to change your password immediately.'
|
||||
recovery_tries_exceeded: 'Você excedeu o limite de tentativas de usar o código de recuperação! Use "/email recovery [email]" para gerar um novo.'
|
||||
recovery_code_correct: 'Código de recuperação aceito!'
|
||||
recovery_change_password: 'Por favor, use o comando /email setpassword <nova senha> para alterar sua senha imediatamente!'
|
||||
vb_nonActiv: '&cA sua conta ainda não está ativada, por favor, verifique seus e-mails!'
|
||||
usage_unreg: '&cUse: /unregister <senha>'
|
||||
pwd_changed: '&2Senha alterada com sucesso!'
|
||||
@ -92,8 +92,8 @@ email_send_failure: '&cO e-mail não pôde ser enviado, reporte isso a um admini
|
||||
show_no_email: '&2Você atualmente não têm endereço de e-mail associado a esta conta.'
|
||||
add_email: '&3Por favor, adicione seu e-mail para a sua conta com o comando "/email add <seuEmail> <seuEmail>"'
|
||||
recovery_email: '&3Esqueceu sua senha? Por favor, use o comando "/email recovery <seuEmail>"'
|
||||
# TODO change_password_expired: 'You cannot change your password using this command anymore.'
|
||||
# TODO email_cooldown_error: '&cAn email was already sent recently. You must wait %time before you can send a new one.'
|
||||
change_password_expired: 'Você não pode mais usar esse comando de recuperação de senha!'
|
||||
email_cooldown_error: '&cUm e-mail já foi enviado, espere mais %time antes de enviar novamente!'
|
||||
|
||||
# Captcha
|
||||
usage_captcha: '&3Para iniciar sessão você tem que resolver um código captcha, utilize o comando "/captcha <theCaptcha>"'
|
||||
@ -101,11 +101,11 @@ wrong_captcha: '&cCaptcha errado, por favor, escreva "/captcha THE_CAPTCHA" no c
|
||||
valid_captcha: '&2Código Captcha resolvido corretamente!'
|
||||
|
||||
# Time units
|
||||
# TODO second: 'second'
|
||||
# TODO seconds: 'seconds'
|
||||
# TODO minute: 'minute'
|
||||
# TODO minutes: 'minutes'
|
||||
# TODO hour: 'hour'
|
||||
# TODO hours: 'hours'
|
||||
# TODO day: 'day'
|
||||
# TODO days: 'days'
|
||||
second: 'segundo'
|
||||
seconds: 'segundos'
|
||||
minute: 'minuto'
|
||||
minutes: 'minutos'
|
||||
hour: 'hora'
|
||||
hours: 'horas'
|
||||
day: 'dia'
|
||||
days: 'dias'
|
||||
|
@ -48,9 +48,9 @@ two_factor_create: '&2Tu código secreto es %code. Lo puedes escanear desde aqu
|
||||
recovery_code_sent: 'El código de recuperación para recuperar tu contraseña se ha enviado a tu correo.'
|
||||
# TODO: Missing tags %count
|
||||
recovery_code_incorrect: '¡El código de recuperación no es correcto! Usa "/email recovery [email]" para generar uno nuevo'
|
||||
# TODO recovery_tries_exceeded: 'You have exceeded the maximum number attempts to enter the recovery code. Use "/email recovery [email]" to generate a new one.'
|
||||
# TODO recovery_code_correct: 'Recovery code entered correctly!'
|
||||
# TODO recovery_change_password: 'Please use the command /email setpassword <new password> to change your password immediately.'
|
||||
recovery_tries_exceeded: 'Has excedido el número máximo de intentos para introducir el código de recuperación. Escribe "/email recovery [tuEmail]" para generar uno nuevo.'
|
||||
recovery_code_correct: '¡Código de recuperación introducido correctamente!'
|
||||
recovery_change_password: 'Por favor usa el comando "/email setpassword <nuevaContraseña>" para cambiar tu contraseña inmediatamente.'
|
||||
vb_nonActiv: '&fTu cuenta no está activada aún, ¡revisa tu correo!'
|
||||
usage_unreg: '&cUso: /unregister contraseña'
|
||||
pwd_changed: '&c¡Contraseña cambiada!'
|
||||
@ -91,7 +91,7 @@ email_send_failure: 'No se ha podido enviar el correo electrónico. Por favor, c
|
||||
show_no_email: '&2No tienes ningun E-Mail asociado en esta cuenta.'
|
||||
add_email: '&cPor favor agrega tu e-mail con: /email add tuEmail confirmarEmail'
|
||||
recovery_email: '&c¿Olvidaste tu contraseña? Por favor usa /email recovery <tuEmail>'
|
||||
# TODO change_password_expired: 'You cannot change your password using this command anymore.'
|
||||
change_password_expired: 'No puedes cambiar la contraseña utilizando este comando.'
|
||||
email_cooldown_error: '&cEl correo ha sido enviado recientemente. Debes esperar %time antes de volver a enviar uno nuevo.'
|
||||
|
||||
# Captcha
|
||||
|
@ -17,7 +17,7 @@ softdepend:
|
||||
commands:
|
||||
authme:
|
||||
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:
|
||||
description: Login command
|
||||
usage: /login <password>
|
||||
@ -45,7 +45,7 @@ commands:
|
||||
- cp
|
||||
email:
|
||||
description: Add email or recover password
|
||||
usage: /email show|add|change|recover
|
||||
usage: /email show|add|change|recover|code|setpassword
|
||||
captcha:
|
||||
description: Captcha Command
|
||||
usage: /captcha <captcha>
|
||||
@ -55,6 +55,7 @@ permissions:
|
||||
children:
|
||||
authme.admin.accounts: true
|
||||
authme.admin.antibotmessages: true
|
||||
authme.admin.backup: true
|
||||
authme.admin.changemail: true
|
||||
authme.admin.changepassword: true
|
||||
authme.admin.converter: true
|
||||
@ -81,6 +82,9 @@ permissions:
|
||||
authme.admin.antibotmessages:
|
||||
description: Permission to see Antibot messages.
|
||||
default: op
|
||||
authme.admin.backup:
|
||||
description: Allows to use the backup command.
|
||||
default: op
|
||||
authme.admin.changemail:
|
||||
description: Administrator command to set or change the email address of a user.
|
||||
default: op
|
||||
@ -154,7 +158,47 @@ permissions:
|
||||
description: Permission to bypass the purging process.
|
||||
default: false
|
||||
authme.debug:
|
||||
description: Permission to use the /authme debug command.
|
||||
description: Gives access to /authme debug and all its sections
|
||||
children:
|
||||
authme.debug.command: true
|
||||
authme.debug.country: true
|
||||
authme.debug.db: true
|
||||
authme.debug.group: true
|
||||
authme.debug.limbo: true
|
||||
authme.debug.mail: true
|
||||
authme.debug.perm: true
|
||||
authme.debug.spawn: true
|
||||
authme.debug.stats: true
|
||||
authme.debug.valid: true
|
||||
authme.debug.command:
|
||||
description: General permission to use the /authme debug command.
|
||||
default: op
|
||||
authme.debug.country:
|
||||
description: Permission to use the country lookup section.
|
||||
default: op
|
||||
authme.debug.db:
|
||||
description: Permission to view data from the database.
|
||||
default: op
|
||||
authme.debug.group:
|
||||
description: Permission to view permission groups.
|
||||
default: op
|
||||
authme.debug.limbo:
|
||||
description: Permission to use the limbo data viewer.
|
||||
default: op
|
||||
authme.debug.mail:
|
||||
description: Permission to use the test email sender.
|
||||
default: op
|
||||
authme.debug.perm:
|
||||
description: Permission to use the permission checker.
|
||||
default: op
|
||||
authme.debug.spawn:
|
||||
description: Permission to view spawn information.
|
||||
default: op
|
||||
authme.debug.stats:
|
||||
description: Permission to use the stats section.
|
||||
default: op
|
||||
authme.debug.valid:
|
||||
description: Permission to use sample validation.
|
||||
default: op
|
||||
authme.player.*:
|
||||
description: Gives access to all player commands
|
||||
|
@ -0,0 +1,84 @@
|
||||
package fr.xephi.authme;
|
||||
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.Matcher;
|
||||
import org.hamcrest.TypeSafeMatcher;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* Matcher which checks with reflection that all fields have the same value.
|
||||
* This matcher considers all non-static fields until the Object parent.
|
||||
*/
|
||||
public final class IsEqualByReflectionMatcher<T> extends TypeSafeMatcher<T> {
|
||||
|
||||
private final T expected;
|
||||
|
||||
private IsEqualByReflectionMatcher(T expected) {
|
||||
this.expected = expected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a matcher that checks if all fields are the same as on the {@code expected} object.
|
||||
*
|
||||
* @param expected the object to match
|
||||
* @param <T> the object's type
|
||||
* @return the matcher for the expected object
|
||||
*/
|
||||
public static <T> Matcher<T> isEqualTo(T expected) {
|
||||
return new IsEqualByReflectionMatcher<>(expected);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean matchesSafely(T item) {
|
||||
return assertAreFieldsEqual(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeTo(Description description) {
|
||||
description.appendText("parameters " + expected);
|
||||
}
|
||||
|
||||
private boolean assertAreFieldsEqual(T item) {
|
||||
if (expected.getClass() != item.getClass()) {
|
||||
fail("Classes don't match, got " + expected.getClass().getSimpleName()
|
||||
+ " and " + item.getClass().getSimpleName());
|
||||
return false;
|
||||
}
|
||||
|
||||
List<Field> fieldsToCheck = getAllFields(expected);
|
||||
for (Field field : fieldsToCheck) {
|
||||
Object lhsValue = ReflectionTestUtils.getFieldValue(field, expected);
|
||||
Object rhsValue = ReflectionTestUtils.getFieldValue(field, item);
|
||||
if (!Objects.equals(lhsValue, rhsValue)) {
|
||||
fail("Field '" + field.getName() + "' does not have same value: '"
|
||||
+ lhsValue + "' vs. '" + rhsValue + "'");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static List<Field> getAllFields(Object object) {
|
||||
List<Field> fields = new ArrayList<>();
|
||||
Class<?> currentClass = object.getClass();
|
||||
while (currentClass != null) {
|
||||
for (Field f : currentClass.getDeclaredFields()) {
|
||||
if (!Modifier.isStatic(f.getModifiers())) {
|
||||
fields.add(f);
|
||||
}
|
||||
}
|
||||
if (currentClass == Object.class) {
|
||||
break;
|
||||
}
|
||||
currentClass = currentClass.getSuperclass();
|
||||
}
|
||||
return fields;
|
||||
}
|
||||
}
|
@ -0,0 +1,154 @@
|
||||
package fr.xephi.authme.command.executable.authme.debug;
|
||||
|
||||
import fr.xephi.authme.initialization.factory.Factory;
|
||||
import fr.xephi.authme.permission.DebugSectionPermissions;
|
||||
import fr.xephi.authme.permission.PermissionNode;
|
||||
import fr.xephi.authme.permission.PermissionsManager;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static java.util.Collections.emptyList;
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyList;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.atLeast;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.hamcrest.MockitoHamcrest.argThat;
|
||||
|
||||
/**
|
||||
* Test for {@link DebugCommand}.
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class DebugCommandTest {
|
||||
|
||||
/**
|
||||
* Number we test against if we expect an action to have been performed for each debug section.
|
||||
* This is a minimum number so tests don't fail each time a new debug section is added; however,
|
||||
* it should be close to the total.
|
||||
*/
|
||||
private static final int MIN_DEBUG_SECTIONS = 9;
|
||||
|
||||
@InjectMocks
|
||||
private DebugCommand command;
|
||||
|
||||
@Mock
|
||||
private Factory<DebugSection> debugSectionFactory;
|
||||
|
||||
@Mock
|
||||
private PermissionsManager permissionsManager;
|
||||
|
||||
@Before
|
||||
@SuppressWarnings("unchecked")
|
||||
public void initFactory() {
|
||||
given(debugSectionFactory.newInstance(any(Class.class))).willAnswer(
|
||||
invocation -> {
|
||||
Class<?> classArgument = invocation.getArgument(0);
|
||||
checkArgument(DebugSection.class.isAssignableFrom(classArgument));
|
||||
return spy(classArgument);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldListAllAvailableDebugSections() {
|
||||
// given
|
||||
CommandSender sender = mock(CommandSender.class);
|
||||
given(permissionsManager.hasPermission(eq(sender), any(PermissionNode.class))).willReturn(false);
|
||||
given(permissionsManager.hasPermission(sender, DebugSectionPermissions.INPUT_VALIDATOR)).willReturn(true);
|
||||
given(permissionsManager.hasPermission(sender, DebugSectionPermissions.DATA_STATISTICS)).willReturn(true);
|
||||
|
||||
// when
|
||||
command.executeCommand(sender, emptyList());
|
||||
|
||||
// then
|
||||
verify(debugSectionFactory, atLeast(MIN_DEBUG_SECTIONS)).newInstance(any(Class.class));
|
||||
verify(permissionsManager, atLeast(MIN_DEBUG_SECTIONS)).hasPermission(eq(sender), any(DebugSectionPermissions.class));
|
||||
|
||||
ArgumentCaptor<String> strCaptor = ArgumentCaptor.forClass(String.class);
|
||||
verify(sender, times(3)).sendMessage(strCaptor.capture());
|
||||
assertThat(strCaptor.getAllValues(), contains(
|
||||
containsString("Sections available to you"),
|
||||
containsString("stats: Outputs general data statistics"),
|
||||
containsString("valid: Check if email / password is valid")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotListAnyDebugSection() {
|
||||
// given
|
||||
CommandSender sender = mock(CommandSender.class);
|
||||
given(permissionsManager.hasPermission(eq(sender), any(PermissionNode.class))).willReturn(false);
|
||||
|
||||
// when
|
||||
command.executeCommand(sender, emptyList());
|
||||
|
||||
// then
|
||||
verify(debugSectionFactory, atLeast(MIN_DEBUG_SECTIONS)).newInstance(any(Class.class));
|
||||
verify(permissionsManager, atLeast(MIN_DEBUG_SECTIONS)).hasPermission(eq(sender), any(DebugSectionPermissions.class));
|
||||
|
||||
ArgumentCaptor<String> strCaptor = ArgumentCaptor.forClass(String.class);
|
||||
verify(sender, times(2)).sendMessage(strCaptor.capture());
|
||||
assertThat(strCaptor.getAllValues(), contains(
|
||||
equalTo("Sections available to you:"),
|
||||
containsString("You don't have permission to view any debug section")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldRunSection() {
|
||||
// given
|
||||
DebugSection section = spy(InputValidator.class);
|
||||
doNothing().when(section).execute(any(CommandSender.class), anyList());
|
||||
// Mockito throws a runtime error if below we use the usual "given(factory.newInstance(...)).willReturn(...)"
|
||||
doReturn(section).when(debugSectionFactory).newInstance(InputValidator.class);
|
||||
|
||||
CommandSender sender = mock(CommandSender.class);
|
||||
given(permissionsManager.hasPermission(sender, section.getRequiredPermission())).willReturn(true);
|
||||
List<String> arguments = Arrays.asList(section.getName().toUpperCase(), "test", "toast");
|
||||
|
||||
// when
|
||||
command.executeCommand(sender, arguments);
|
||||
|
||||
// then
|
||||
verify(permissionsManager).hasPermission(sender, section.getRequiredPermission());
|
||||
verify(section).execute(sender, Arrays.asList("test", "toast"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotRunSectionForMissingPermission() {
|
||||
// given
|
||||
DebugSection section = spy(InputValidator.class);
|
||||
// Mockito throws a runtime error if below we use the usual "given(factory.newInstance(...)).willReturn(...)"
|
||||
doReturn(section).when(debugSectionFactory).newInstance(InputValidator.class);
|
||||
|
||||
CommandSender sender = mock(CommandSender.class);
|
||||
given(permissionsManager.hasPermission(sender, section.getRequiredPermission())).willReturn(false);
|
||||
List<String> arguments = Arrays.asList(section.getName().toUpperCase(), "test");
|
||||
|
||||
// when
|
||||
command.executeCommand(sender, arguments);
|
||||
|
||||
// then
|
||||
verify(permissionsManager).hasPermission(sender, section.getRequiredPermission());
|
||||
verify(section, never()).execute(any(CommandSender.class), anyList());
|
||||
verify(sender).sendMessage(argThat(containsString("You don't have permission")));
|
||||
}
|
||||
}
|
@ -20,9 +20,9 @@ import java.util.stream.Collectors;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Collections.emptyList;
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.atLeast;
|
||||
@ -55,8 +55,7 @@ public class HasPermissionCheckerTest {
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// when / then
|
||||
assertThat(HasPermissionChecker.PERMISSION_NODE_CLASSES.containsAll(permissionClasses), equalTo(true));
|
||||
assertThat(HasPermissionChecker.PERMISSION_NODE_CLASSES, hasSize(permissionClasses.size()));
|
||||
assertThat(HasPermissionChecker.PERMISSION_NODE_CLASSES, containsInAnyOrder(permissionClasses.toArray()));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -1,6 +1,5 @@
|
||||
package fr.xephi.authme.command.executable.register;
|
||||
|
||||
import fr.xephi.authme.ReflectionTestUtils;
|
||||
import fr.xephi.authme.TestHelper;
|
||||
import fr.xephi.authme.mail.EmailService;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
@ -10,7 +9,6 @@ import fr.xephi.authme.process.register.RegistrationType;
|
||||
import fr.xephi.authme.process.register.executors.EmailRegisterParams;
|
||||
import fr.xephi.authme.process.register.executors.PasswordRegisterParams;
|
||||
import fr.xephi.authme.process.register.executors.RegistrationMethod;
|
||||
import fr.xephi.authme.process.register.executors.RegistrationParameters;
|
||||
import fr.xephi.authme.process.register.executors.TwoFactorRegisterParams;
|
||||
import fr.xephi.authme.security.HashAlgorithm;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
@ -20,9 +18,6 @@ import fr.xephi.authme.settings.properties.SecuritySettings;
|
||||
import org.bukkit.command.BlockCommandSender;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.Matcher;
|
||||
import org.hamcrest.TypeSafeMatcher;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
@ -31,16 +26,11 @@ import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static fr.xephi.authme.IsEqualByReflectionMatcher.isEqualTo;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
@ -306,56 +296,4 @@ public class RegisterCommandTest {
|
||||
verify(management).performRegister(eq(RegistrationMethod.PASSWORD_REGISTRATION),
|
||||
argThat(isEqualTo(PasswordRegisterParams.of(player, "myPass", null))));
|
||||
}
|
||||
|
||||
|
||||
// TODO ljacqu 20170317: Document and extract as util
|
||||
|
||||
private static <P extends RegistrationParameters> Matcher<P> isEqualTo(P expected) {
|
||||
return new TypeSafeMatcher<P>() {
|
||||
@Override
|
||||
protected boolean matchesSafely(RegistrationParameters item) {
|
||||
assertAreParamsEqual(expected, item);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeTo(Description description) {
|
||||
description.appendText("parameters " + expected);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static void assertAreParamsEqual(RegistrationParameters lhs, RegistrationParameters rhs) {
|
||||
if (lhs.getClass() != rhs.getClass()) {
|
||||
fail("Params classes don't match, got " + lhs.getClass().getSimpleName()
|
||||
+ " and " + rhs.getClass().getSimpleName());
|
||||
}
|
||||
|
||||
List<Field> fieldsToCheck = getFields(lhs);
|
||||
for (Field field : fieldsToCheck) {
|
||||
Object lhsValue = ReflectionTestUtils.getFieldValue(field, lhs);
|
||||
Object rhsValue = ReflectionTestUtils.getFieldValue(field, rhs);
|
||||
if (!Objects.equals(lhsValue, rhsValue)) {
|
||||
fail("Field '" + field.getName() + "' does not have same value: '"
|
||||
+ lhsValue + "' vs. '" + rhsValue + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static List<Field> getFields(RegistrationParameters params) {
|
||||
List<Field> fields = new ArrayList<>();
|
||||
Class<?> currentClass = params.getClass();
|
||||
while (currentClass != null) {
|
||||
for (Field f : currentClass.getDeclaredFields()) {
|
||||
if (!Modifier.isStatic(f.getModifiers())) {
|
||||
fields.add(f);
|
||||
}
|
||||
}
|
||||
if (currentClass == RegistrationParameters.class) {
|
||||
break;
|
||||
}
|
||||
currentClass = currentClass.getSuperclass();
|
||||
}
|
||||
return fields;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,52 @@
|
||||
package fr.xephi.authme.permission;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* Has common tests for enums implementing {@link PermissionNode}.
|
||||
*/
|
||||
public abstract class AbstractPermissionsEnumTest {
|
||||
|
||||
@Test
|
||||
public void shouldAllStartWitRequiredPrefix() {
|
||||
// given
|
||||
String requiredPrefix = getRequiredPrefix();
|
||||
|
||||
// when/then
|
||||
for (PermissionNode permission : getPermissionNodes()) {
|
||||
if (!permission.getNode().startsWith(requiredPrefix)) {
|
||||
fail("The permission '" + permission + "' does not start with the required prefix '"
|
||||
+ requiredPrefix + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldHaveUniqueNodes() {
|
||||
// given
|
||||
Set<String> nodes = new HashSet<>();
|
||||
|
||||
// when/then
|
||||
for (PermissionNode permission : getPermissionNodes()) {
|
||||
if (!nodes.add(permission.getNode())) {
|
||||
fail("More than one enum value defines the node '" + permission.getNode() + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the permission nodes to test
|
||||
*/
|
||||
protected abstract PermissionNode[] getPermissionNodes();
|
||||
|
||||
/**
|
||||
* @return text with which all permission nodes must start with
|
||||
*/
|
||||
protected abstract String getRequiredPrefix();
|
||||
|
||||
}
|
@ -1,42 +1,18 @@
|
||||
package fr.xephi.authme.permission;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* Test for {@link AdminPermission}.
|
||||
*/
|
||||
public class AdminPermissionTest {
|
||||
public class AdminPermissionTest extends AbstractPermissionsEnumTest {
|
||||
|
||||
@Test
|
||||
public void shouldStartWithAuthMeAdminPrefix() {
|
||||
// given
|
||||
String requiredPrefix = "authme.admin.";
|
||||
|
||||
// when/then
|
||||
for (AdminPermission permission : AdminPermission.values()) {
|
||||
if (!permission.getNode().startsWith(requiredPrefix)) {
|
||||
fail("The permission '" + permission + "' does not start with the required prefix '"
|
||||
+ requiredPrefix + "'");
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected PermissionNode[] getPermissionNodes() {
|
||||
return AdminPermission.values();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldHaveUniqueNodes() {
|
||||
// given
|
||||
Set<String> nodes = new HashSet<>();
|
||||
|
||||
// when/then
|
||||
for (AdminPermission permission : AdminPermission.values()) {
|
||||
if (!nodes.add(permission.getNode())) {
|
||||
fail("More than one enum value defines the node '" + permission.getNode() + "'");
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected String getRequiredPrefix() {
|
||||
return "authme.admin.";
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,17 @@
|
||||
package fr.xephi.authme.permission;
|
||||
|
||||
/**
|
||||
* Test for {@link DebugSectionPermissions}.
|
||||
*/
|
||||
public class DebugSectionPermissionsTest extends AbstractPermissionsEnumTest {
|
||||
|
||||
@Override
|
||||
protected PermissionNode[] getPermissionNodes() {
|
||||
return DebugSectionPermissions.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getRequiredPrefix() {
|
||||
return "authme.debug.";
|
||||
}
|
||||
}
|
@ -31,7 +31,7 @@ public class PermissionConsistencyTest {
|
||||
|
||||
/** Wildcard permissions (present in plugin.yml but not in the codebase). */
|
||||
private static final Set<String> PLUGIN_YML_PERMISSIONS_WILDCARDS =
|
||||
ImmutableSet.of("authme.admin.*", "authme.player.*", "authme.player.email");
|
||||
ImmutableSet.of("authme.admin.*", "authme.player.*", "authme.player.email", "authme.debug");
|
||||
|
||||
/** Name of the fields that make up a permission entry in plugin.yml. */
|
||||
private static final Set<String> PERMISSION_FIELDS = ImmutableSet.of("description", "default", "children");
|
||||
|
@ -1,41 +1,17 @@
|
||||
package fr.xephi.authme.permission;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* Test for {@link PlayerPermission}.
|
||||
*/
|
||||
public class PlayerPermissionTest {
|
||||
public class PlayerPermissionTest extends AbstractPermissionsEnumTest {
|
||||
|
||||
@Test
|
||||
public void shouldStartWithPlayerPrefix() {
|
||||
// given
|
||||
String playerBranch = "authme.player.";
|
||||
|
||||
// when/then
|
||||
for (PlayerPermission permission : PlayerPermission.values()) {
|
||||
if (!permission.getNode().startsWith(playerBranch)) {
|
||||
fail("The permission '" + permission + "' should use a node with the player-specific branch '"
|
||||
+ playerBranch + "'");
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected PermissionNode[] getPermissionNodes() {
|
||||
return PlayerPermission.values();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldHaveUniqueNodes() {
|
||||
// given
|
||||
Set<String> nodes = new HashSet<>();
|
||||
|
||||
// when/then
|
||||
for (PlayerPermission permission : PlayerPermission.values()) {
|
||||
if (!nodes.add(permission.getNode())) {
|
||||
fail("More than one enum value defines the node '" + permission.getNode() + "'");
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected String getRequiredPrefix() {
|
||||
return "authme.player.";
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ package fr.xephi.authme.permission;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.google.common.collect.Sets.newHashSet;
|
||||
@ -11,39 +11,32 @@ import static org.junit.Assert.fail;
|
||||
/**
|
||||
* Test for {@link PlayerStatePermission}.
|
||||
*/
|
||||
public class PlayerStatePermissionTest {
|
||||
public class PlayerStatePermissionTest extends AbstractPermissionsEnumTest {
|
||||
|
||||
@Test
|
||||
public void shouldStartWithAuthMeAdminPrefix() {
|
||||
public void shouldNotStartWithOtherPrefixes() {
|
||||
// given
|
||||
String requiredPrefix = "authme.";
|
||||
Set<String> forbiddenPrefixes = newHashSet("authme.player", "authme.admin");
|
||||
Set<String> forbiddenPrefixes = newHashSet("authme.player", "authme.admin", "authme.debug");
|
||||
|
||||
// when/then
|
||||
for (PlayerStatePermission permission : PlayerStatePermission.values()) {
|
||||
if (!permission.getNode().startsWith(requiredPrefix)) {
|
||||
fail("The permission '" + permission + "' does not start with the required prefix '"
|
||||
+ requiredPrefix + "'");
|
||||
} else if (hasAnyPrefix(permission.getNode(), forbiddenPrefixes)) {
|
||||
if (startsWithAny(permission.getNode(), forbiddenPrefixes)) {
|
||||
fail("The permission '" + permission + "' should not start with any of " + forbiddenPrefixes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldHaveUniqueNodes() {
|
||||
// given
|
||||
Set<String> nodes = new HashSet<>();
|
||||
|
||||
// when/then
|
||||
for (PlayerStatePermission permission : PlayerStatePermission.values()) {
|
||||
if (!nodes.add(permission.getNode())) {
|
||||
fail("More than one enum value defines the node '" + permission.getNode() + "'");
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected PermissionNode[] getPermissionNodes() {
|
||||
return PlayerStatePermission.values();
|
||||
}
|
||||
|
||||
private static boolean hasAnyPrefix(String node, Set<String> prefixes) {
|
||||
@Override
|
||||
protected String getRequiredPrefix() {
|
||||
return "authme.";
|
||||
}
|
||||
|
||||
private static boolean startsWithAny(String node, Collection<String> prefixes) {
|
||||
for (String prefix : prefixes) {
|
||||
if (node.startsWith(prefix)) {
|
||||
return true;
|
||||
@ -51,5 +44,4 @@ public class PlayerStatePermissionTest {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -11,7 +11,6 @@ import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.properties.ProtectionSettings;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
@ -82,7 +81,6 @@ public class AntiBotServiceTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore // TODO ljacqu 20161030: Fix test
|
||||
public void shouldActivateAntibot() {
|
||||
// given - listening antibot
|
||||
runSyncDelayedTaskWithDelay(bukkitService);
|
||||
|
@ -25,7 +25,7 @@ public class PermissionNodesGatherer {
|
||||
* 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+\\*)?" // Match starting '/**' and optional whitespace with a '*'
|
||||
+ "(.*?)\\s+\\*/" // Capture everything until we encounter '*/'
|
||||
+ "\\s+([A-Z_]+)\\("); // Match the enum name (e.g. 'LOGIN'), until before the first '('
|
||||
|
||||
@ -87,8 +87,8 @@ public class PermissionNodesGatherer {
|
||||
Map<String, String> allMatches = new HashMap<>();
|
||||
Matcher matcher = JAVADOC_WITH_ENUM_PATTERN.matcher(source);
|
||||
while (matcher.find()) {
|
||||
String description = matcher.group(1);
|
||||
String enumValue = matcher.group(2);
|
||||
String description = matcher.group(2);
|
||||
String enumValue = matcher.group(3);
|
||||
allMatches.put(enumValue, description);
|
||||
}
|
||||
return allMatches;
|
||||
|
@ -32,8 +32,9 @@ public class GeneratePluginYml implements AutoToolTask {
|
||||
|
||||
private static final Map<String, String> WILDCARD_PERMISSIONS = ImmutableMap.of(
|
||||
"authme.player.*", "Gives access to all player commands",
|
||||
"authme.player.email", "Gives access to all email commands",
|
||||
"authme.admin.*", "Gives access to all admin commands",
|
||||
"authme.player.email", "Gives access to all email commands");
|
||||
"authme.debug", "Gives access to /authme debug and all its sections");
|
||||
|
||||
private List<PermissionNode> permissionNodes;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user