diff --git a/.travis.yml b/.travis.yml index 06d6183c0..bca4843fd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ sudo: false language: java -jdk: oraclejdk7 +jdk: oraclejdk8 script: mvn clean verify -B diff --git a/README.md b/README.md index d270887da..e3e4b937e 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ Outdated!
#####Compiling Requirements: ->- JDK 1.7 +>- JDK 1.8 >- Maven >- Git/Github (Optional) @@ -54,7 +54,7 @@ Outdated! >- Execute command "mvn clean install" #####Running Requirements: ->- Java 1.7 or 1.8 +>- Java 1.8 >- PaperSpigot, Spigot or CraftBukkit (1.7.10, 1.8.X, 1.9.X, 1.10.X) >- ProtocolLib (optional, required by the protectInventory feature) diff --git a/circle.yml b/circle.yml index dea5e80c1..80201e5e8 100644 --- a/circle.yml +++ b/circle.yml @@ -1,6 +1,6 @@ machine: java: - version: oraclejdk7 + version: oraclejdk8 general: artifacts: - "target/AuthMe-*.jar" diff --git a/pom.xml b/pom.xml index 01ac56157..4dd41e51b 100644 --- a/pom.xml +++ b/pom.xml @@ -46,7 +46,7 @@ UTF-8 - 1.7 + 1.8 AuthMe @@ -98,38 +98,38 @@ true - - org.spigotmc - spigot-api - ${bukkit.version} - provided - - - junit - junit - - - json-simple - com.googlecode.json-simple - - - persistence-api - javax.persistence - - - guava - com.google.guava - - - bungeecord-chat - net.md-5 - - - gson - com.google.code.gson - - - + + org.spigotmc + spigot-api + ${bukkit.version} + provided + + + junit + junit + + + json-simple + com.googlecode.json-simple + + + persistence-api + javax.persistence + + + guava + com.google.guava + + + bungeecord-chat + net.md-5 + + + gson + com.google.code.gson + + + @@ -244,31 +244,35 @@ - - com.zaxxer.hikari - fr.xephi.authme.libs.zaxxer.hikari - - - org.slf4j - fr.xephi.authme.libs.slf4j.slf4j - - - com.maxmind.geoip - fr.xephi.authme.libs.maxmind.geoip - - - net.ricecode.similarity - fr.xephi.authme.libs.ricecode.similarity - - - javax.inject - fr.xephi.authme.libs.javax.inject - - - - org.mcstats - fr.xephi.authme - + + ch.jalu.injector + fr.xephi.authme.libs.jalu.injector + + + com.zaxxer.hikari + fr.xephi.authme.libs.zaxxer.hikari + + + org.slf4j + fr.xephi.authme.libs.slf4j.slf4j + + + com.maxmind.geoip + fr.xephi.authme.libs.maxmind.geoip + + + net.ricecode.similarity + fr.xephi.authme.libs.ricecode.similarity + + + javax.inject + fr.xephi.authme.libs.javax.inject + + + + org.mcstats + fr.xephi.authme + target/${project.finalName}-spigot.jar @@ -287,6 +291,10 @@ com.google fr.xephi.authme.libs.google + + ch.jalu.injector + fr.xephi.authme.libs.jalu.injector + com.zaxxer.hikari fr.xephi.authme.libs.zaxxer.hikari @@ -421,42 +429,22 @@ - + + + - com.zaxxer - HikariCP - 2.4.7 - compile - - - slf4j-api - org.slf4j - - - true - - - - org.slf4j - slf4j-simple - 1.7.21 + ch.jalu + injector + 0.3 compile true - + - org.apache.logging.log4j - log4j-core - 2.5 - provided - - - - - org.apache.commons - commons-email - 1.4 + net.ricecode + string-similarity + 1.0.0 compile true @@ -479,15 +467,6 @@ true - - - javax.inject - javax.inject - 1 - compile - true - - com.maxmind.geoip @@ -497,6 +476,51 @@ true + + + org.apache.commons + commons-email + 1.4 + compile + true + + + + + org.apache.logging.log4j + log4j-core + 2.5 + provided + + + + + com.zaxxer + HikariCP + 2.5.0-SNAPSHOT + compile + + + slf4j-api + org.slf4j + + + true + + + + org.slf4j + slf4j-simple + 1.7.21 + compile + true + + + + + + + org.mcstats.bukkit @@ -512,14 +536,11 @@ true - - - - + com.comphenix.protocol - ProtocolLib - 3.6.5-SNAPSHOT + ProtocolLib-API + 4.1.0-SNAPSHOT provided @@ -537,7 +558,7 @@ ru.tehkode PermissionsEx - 1.23.1 + 1.23.4 provided @@ -559,20 +580,6 @@ - - - org.anjocaido - groupmanagerx - 2.2-SNAPSHOT - provided - - - org.bukkit - bukkit - - - - de.bananaco @@ -591,7 +598,7 @@ org.tyrannyofheaven.bukkit zPermissions - 1.3-SNAPSHOT + 1.3.1-SNAPSHOT provided @@ -625,7 +632,7 @@ net.milkbowl.vault VaultAPI - 1.5 + 1.6 provided @@ -692,12 +699,12 @@ junit - spigot-api - org.spigotmc + spigot-api + org.spigotmc - jettison - org.codehaus.jettison + jettison + org.codehaus.jettison @@ -724,7 +731,7 @@ net.minelink CombatTagPlus - 1.2.2-SNAPSHOT + 1.3.0-SNAPSHOT provided @@ -791,6 +798,24 @@ metrics-lite org.mcstats.bukkit + + net.minelink + CombatTagPlusCompat-v1_9_R1 + + + net.minelink + CombatTagPlusCompat-v1_9_R2 + + + net.minelink + + CombatTagPlusCompat-v1_10_R1 + + + + com.google.code.findbugs + jsr305 + @@ -836,22 +861,6 @@ - - - ch.jalu - injector - 0.3 - - - - - net.ricecode - string-similarity - 1.0.0 - compile - true - - com.github.authme @@ -860,18 +869,21 @@ + junit junit test 4.12 + org.hamcrest java-hamcrest test 2.0.0.0 + org.mockito mockito-core @@ -884,6 +896,7 @@ + org.xerial @@ -897,5 +910,6 @@ 1.4.192 test + diff --git a/src/main/java/fr/xephi/authme/AuthMe.java b/src/main/java/fr/xephi/authme/AuthMe.java index 8d01e4131..42b3bc33d 100644 --- a/src/main/java/fr/xephi/authme/AuthMe.java +++ b/src/main/java/fr/xephi/authme/AuthMe.java @@ -151,7 +151,7 @@ public class AuthMe extends JavaPlugin { ConsoleLogger.info("Do you want a good game server? Look at our sponsor GameHosting.it leader in Italy as Game Server Provider!"); // Successful message - ConsoleLogger.info("AuthMe " + getPluginVersion() + " build n°" + getPluginBuildNumber() + " correctly enabled!"); + ConsoleLogger.info("AuthMe " + getPluginVersion() + " build n." + getPluginBuildNumber() + " correctly enabled!"); // Purge on start if enabled PurgeService purgeService = injector.getSingleton(PurgeService.class); diff --git a/src/main/java/fr/xephi/authme/command/CommandInitializer.java b/src/main/java/fr/xephi/authme/command/CommandInitializer.java index ce02b9a8d..0d5c6da07 100644 --- a/src/main/java/fr/xephi/authme/command/CommandInitializer.java +++ b/src/main/java/fr/xephi/authme/command/CommandInitializer.java @@ -282,7 +282,7 @@ public class CommandInitializer { .description("Converter command") .detailedDescription("Converter command for AuthMeReloaded.") .withArgument("job", "Conversion job: xauth / crazylogin / rakamak / " + - "royalauth / vauth / sqlitetosql", false) + "royalauth / vauth / sqliteToSql / mysqlToSqlite", false) .permission(AdminPermission.CONVERTER) .executableCommand(ConverterCommand.class) .build(); diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/ConverterCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/ConverterCommand.java index a4a064869..a615f3ec9 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/ConverterCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/ConverterCommand.java @@ -2,11 +2,13 @@ package fr.xephi.authme.command.executable.authme; import ch.jalu.injector.Injector; import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.ImmutableMap; import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.command.CommandService; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.converter.Converter; import fr.xephi.authme.converter.CrazyLoginConverter; +import fr.xephi.authme.converter.MySqlToSqlite; import fr.xephi.authme.converter.RakamakConverter; import fr.xephi.authme.converter.RoyalAuthConverter; import fr.xephi.authme.converter.SqliteToSql; @@ -18,12 +20,16 @@ import org.bukkit.command.CommandSender; import javax.inject.Inject; import java.util.List; +import java.util.Map; /** * Converter command: launches conversion based on its parameters. */ public class ConverterCommand implements ExecutableCommand { + @VisibleForTesting + static final Map> CONVERTERS = getConverters(); + @Inject private CommandService commandService; @@ -39,14 +45,14 @@ public class ConverterCommand implements ExecutableCommand { String job = arguments.get(0); // Determine the job type - ConvertType jobType = ConvertType.fromName(job); - if (jobType == null) { - commandService.send(sender, MessageKey.ERROR); + Class converterClass = CONVERTERS.get(job.toLowerCase()); + if (converterClass == null) { + sender.sendMessage("[AuthMe] Converter does not exist!"); return; } // Get the proper converter instance - final Converter converter = injector.newInstance(jobType.getConverterClass()); + final Converter converter = injector.newInstance(converterClass); // Run the convert job bukkitService.runTaskAsynchronously(new Runnable() { @@ -55,47 +61,31 @@ public class ConverterCommand implements ExecutableCommand { try { converter.execute(sender); } catch (Exception e) { + commandService.send(sender, MessageKey.ERROR); ConsoleLogger.logException("Error during conversion:", e); } } }); // Show a status message - sender.sendMessage("[AuthMe] Successfully converted from " + jobType.getName()); + sender.sendMessage("[AuthMe] Successfully started " + job); } - @VisibleForTesting - enum ConvertType { - XAUTH("xauth", xAuthConverter.class), - CRAZYLOGIN("crazylogin", CrazyLoginConverter.class), - RAKAMAK("rakamak", RakamakConverter.class), - ROYALAUTH("royalauth", RoyalAuthConverter.class), - VAUTH("vauth", vAuthConverter.class), - SQLITETOSQL("sqlitetosql", SqliteToSql.class); - - private final String name; - private final Class converterClass; - - ConvertType(String name, Class converterClass) { - this.name = name; - this.converterClass = converterClass; - } - - public static ConvertType fromName(String name) { - for (ConvertType type : ConvertType.values()) { - if (type.getName().equalsIgnoreCase(name)) { - return type; - } - } - return null; - } - - public String getName() { - return this.name; - } - - public Class getConverterClass() { - return converterClass; - } + /** + * Initializes a map with all available converters. + * + * @return map with all available converters + */ + private static Map> getConverters() { + return ImmutableMap.>builder() + .put("xauth", xAuthConverter.class) + .put("crazylogin", CrazyLoginConverter.class) + .put("rakamak", RakamakConverter.class) + .put("royalauth", RoyalAuthConverter.class) + .put("vauth", vAuthConverter.class) + .put("sqlitetosql", SqliteToSql.class) + .put("mysqltosqlite", MySqlToSqlite.class) + .build(); } + } diff --git a/src/main/java/fr/xephi/authme/converter/AbstractDataSourceConverter.java b/src/main/java/fr/xephi/authme/converter/AbstractDataSourceConverter.java new file mode 100644 index 000000000..19be41c33 --- /dev/null +++ b/src/main/java/fr/xephi/authme/converter/AbstractDataSourceConverter.java @@ -0,0 +1,90 @@ +package fr.xephi.authme.converter; + +import fr.xephi.authme.ConsoleLogger; +import fr.xephi.authme.cache.auth.PlayerAuth; +import fr.xephi.authme.datasource.DataSource; +import fr.xephi.authme.datasource.DataSourceType; +import fr.xephi.authme.util.StringUtils; +import org.bukkit.command.CommandSender; +import org.bukkit.command.ConsoleCommandSender; + +import java.util.ArrayList; +import java.util.List; + +/** + * Converts from one AuthMe data source type to another. + * + * @param the source type to convert from + */ +public abstract class AbstractDataSourceConverter implements Converter { + + private DataSource destination; + private DataSourceType destinationType; + + /** + * Constructor. + * + * @param destination the data source to convert to + * @param destinationType the data source type of the destination. The given data source is checked that its + * type corresponds to this type before the conversion is started, enabling us to just pass + * the current data source and letting this class check that the types correspond. + */ + public AbstractDataSourceConverter(DataSource destination, DataSourceType destinationType) { + this.destination = destination; + this.destinationType = destinationType; + } + + // Implementation note: Because of ForceFlatToSqlite it is possible that the CommandSender is null, + // which is never the case when a converter is launched from the /authme converter command. + @Override + public void execute(CommandSender sender) { + if (!destinationType.equals(destination.getType())) { + if (sender != null) { + sender.sendMessage("Please configure your connection to " + + destinationType + " and re-run this command"); + } + return; + } + + S source; + try { + source = getSource(); + } catch (Exception e) { + logAndSendMessage(sender, "The data source to convert from could not be initialized"); + ConsoleLogger.logException("Could not initialize source:", e); + return; + } + + List skippedPlayers = new ArrayList<>(); + for (PlayerAuth auth : source.getAllAuths()) { + if (destination.isAuthAvailable(auth.getNickname())) { + skippedPlayers.add(auth.getNickname()); + } else { + destination.saveAuth(auth); + destination.updateQuitLoc(auth); + } + } + + if (!skippedPlayers.isEmpty()) { + logAndSendMessage(sender, "Skipped conversion for players which were already in " + + destinationType + ": " + StringUtils.join(", ", skippedPlayers)); + } + logAndSendMessage(sender, "Database successfully converted from " + source.getType() + + " to " + destinationType); + } + + /** + * @return the data source to convert from + * @throws Exception during initialization of source + */ + protected abstract S getSource() throws Exception; + + private static void logAndSendMessage(CommandSender sender, String message) { + ConsoleLogger.info(message); + // Make sure sender is not console user, which will see the message from ConsoleLogger already + if (sender != null && !(sender instanceof ConsoleCommandSender)) { + sender.sendMessage(message); + } + } + +} diff --git a/src/main/java/fr/xephi/authme/converter/ForceFlatToSqlite.java b/src/main/java/fr/xephi/authme/converter/ForceFlatToSqlite.java index 64f89b7e5..321ef2463 100644 --- a/src/main/java/fr/xephi/authme/converter/ForceFlatToSqlite.java +++ b/src/main/java/fr/xephi/authme/converter/ForceFlatToSqlite.java @@ -1,21 +1,14 @@ package fr.xephi.authme.converter; -import fr.xephi.authme.ConsoleLogger; -import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.datasource.FlatFile; -import fr.xephi.authme.util.StringUtils; - -import java.util.ArrayList; -import java.util.List; /** * Mandatory migration from the deprecated flat file datasource to SQLite. */ -public class ForceFlatToSqlite { +public class ForceFlatToSqlite extends AbstractDataSourceConverter { - private final DataSource source; - private final DataSource destination; + private final FlatFile source; /** * Constructor. @@ -24,29 +17,12 @@ public class ForceFlatToSqlite { * @param destination The datasource to copy the data to (sqlite) */ public ForceFlatToSqlite(FlatFile source, DataSource destination) { + super(destination, destination.getType()); this.source = source; - this.destination = destination; } - /** - * Perform the conversion. - */ - public void run() { - List skippedPlayers = new ArrayList<>(); - for (PlayerAuth auth : source.getAllAuths()) { - if (destination.isAuthAvailable(auth.getNickname())) { - skippedPlayers.add(auth.getNickname()); - } else { - destination.saveAuth(auth); - destination.updateQuitLoc(auth); - } - } - - if (!skippedPlayers.isEmpty()) { - ConsoleLogger.warning("Warning: skipped conversion for players which were already in SQLite: " - + StringUtils.join(", ", skippedPlayers)); - } - ConsoleLogger.info("Database successfully converted from " + source.getClass().getSimpleName() - + " to " + destination.getClass().getSimpleName()); + @Override + public FlatFile getSource() { + return source; } } diff --git a/src/main/java/fr/xephi/authme/converter/MySqlToSqlite.java b/src/main/java/fr/xephi/authme/converter/MySqlToSqlite.java new file mode 100644 index 000000000..76e58f960 --- /dev/null +++ b/src/main/java/fr/xephi/authme/converter/MySqlToSqlite.java @@ -0,0 +1,28 @@ +package fr.xephi.authme.converter; + +import fr.xephi.authme.datasource.DataSource; +import fr.xephi.authme.datasource.DataSourceType; +import fr.xephi.authme.datasource.MySQL; +import fr.xephi.authme.settings.Settings; + +import javax.inject.Inject; +import java.sql.SQLException; + +/** + * Converts from MySQL to SQLite. + */ +public class MySqlToSqlite extends AbstractDataSourceConverter { + + private final Settings settings; + + @Inject + MySqlToSqlite(DataSource dataSource, Settings settings) { + super(dataSource, DataSourceType.SQLITE); + this.settings = settings; + } + + @Override + protected MySQL getSource() throws SQLException, ClassNotFoundException { + return new MySQL(settings); + } +} diff --git a/src/main/java/fr/xephi/authme/converter/SqliteToSql.java b/src/main/java/fr/xephi/authme/converter/SqliteToSql.java index dbb127f5e..fafa7e27d 100644 --- a/src/main/java/fr/xephi/authme/converter/SqliteToSql.java +++ b/src/main/java/fr/xephi/authme/converter/SqliteToSql.java @@ -1,45 +1,28 @@ package fr.xephi.authme.converter; -import fr.xephi.authme.ConsoleLogger; -import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.datasource.DataSourceType; import fr.xephi.authme.datasource.SQLite; -import fr.xephi.authme.output.MessageKey; -import fr.xephi.authme.output.Messages; import fr.xephi.authme.settings.Settings; -import org.bukkit.command.CommandSender; import javax.inject.Inject; +import java.sql.SQLException; -public class SqliteToSql implements Converter { +/** + * Converts from SQLite to MySQL. + */ +public class SqliteToSql extends AbstractDataSourceConverter { private final Settings settings; - private final DataSource dataSource; - private final Messages messages; @Inject - SqliteToSql(Settings settings, DataSource dataSource, Messages messages) { + SqliteToSql(Settings settings, DataSource dataSource) { + super(dataSource, DataSourceType.MYSQL); this.settings = settings; - this.dataSource = dataSource; - this.messages = messages; } @Override - public void execute(CommandSender sender) { - if (dataSource.getType() != DataSourceType.MYSQL) { - sender.sendMessage("Please configure your mySQL connection and re-run this command"); - return; - } - try { - SQLite data = new SQLite(settings); - for (PlayerAuth auth : data.getAllAuths()) { - dataSource.saveAuth(auth); - } - } catch (Exception e) { - messages.send(sender, MessageKey.ERROR); - ConsoleLogger.logException("Problem during SQLite to SQL conversion:", e); - } + protected SQLite getSource() throws SQLException, ClassNotFoundException { + return new SQLite(settings); } - } diff --git a/src/main/java/fr/xephi/authme/permission/PermissionsManager.java b/src/main/java/fr/xephi/authme/permission/PermissionsManager.java index 1db9fbfd6..c0c6981aa 100644 --- a/src/main/java/fr/xephi/authme/permission/PermissionsManager.java +++ b/src/main/java/fr/xephi/authme/permission/PermissionsManager.java @@ -3,7 +3,6 @@ package fr.xephi.authme.permission; import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.initialization.Reloadable; import fr.xephi.authme.permission.handlers.BPermissionsHandler; -import fr.xephi.authme.permission.handlers.GroupManagerHandler; import fr.xephi.authme.permission.handlers.PermissionHandler; import fr.xephi.authme.permission.handlers.PermissionHandlerException; import fr.xephi.authme.permission.handlers.PermissionsBukkitHandler; @@ -11,7 +10,6 @@ import fr.xephi.authme.permission.handlers.PermissionsExHandler; import fr.xephi.authme.permission.handlers.VaultHandler; import fr.xephi.authme.permission.handlers.ZPermissionsHandler; import fr.xephi.authme.util.StringUtils; -import org.anjocaido.groupmanager.GroupManager; import org.bukkit.OfflinePlayer; import org.bukkit.Server; import org.bukkit.command.CommandSender; @@ -110,8 +108,6 @@ public class PermissionsManager implements Reloadable { switch (type) { case PERMISSIONS_EX: return new PermissionsExHandler(); - case ESSENTIALS_GROUP_MANAGER: - return new GroupManagerHandler((GroupManager) plugin); case Z_PERMISSIONS: return new ZPermissionsHandler(); case VAULT: diff --git a/src/main/java/fr/xephi/authme/permission/PermissionsSystemType.java b/src/main/java/fr/xephi/authme/permission/PermissionsSystemType.java index 88b09d193..1410bc668 100644 --- a/src/main/java/fr/xephi/authme/permission/PermissionsSystemType.java +++ b/src/main/java/fr/xephi/authme/permission/PermissionsSystemType.java @@ -20,11 +20,6 @@ public enum PermissionsSystemType { */ B_PERMISSIONS("bPermissions", "bPermissions"), - /** - * Essentials Group Manager. - */ - ESSENTIALS_GROUP_MANAGER("Essentials Group Manager", "GroupManager"), - /** * zPermissions. */ diff --git a/src/main/java/fr/xephi/authme/permission/handlers/GroupManagerHandler.java b/src/main/java/fr/xephi/authme/permission/handlers/GroupManagerHandler.java deleted file mode 100644 index a952c124d..000000000 --- a/src/main/java/fr/xephi/authme/permission/handlers/GroupManagerHandler.java +++ /dev/null @@ -1,84 +0,0 @@ -package fr.xephi.authme.permission.handlers; - -import fr.xephi.authme.permission.PermissionNode; -import fr.xephi.authme.permission.PermissionsSystemType; -import org.anjocaido.groupmanager.GroupManager; -import org.anjocaido.groupmanager.permissions.AnjoPermissionsHandler; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -public class GroupManagerHandler implements PermissionHandler { - - private GroupManager groupManager; - - public GroupManagerHandler(GroupManager groupManager) { - this.groupManager = groupManager; - } - - @Override - public boolean addToGroup(Player player, String group) { - return Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "manuaddsub " + player.getName() + " " + group); - } - - @Override - public boolean hasGroupSupport() { - return true; - } - - @Override - public boolean hasPermissionOffline(String name, PermissionNode node) { - final AnjoPermissionsHandler handler = groupManager.getWorldsHolder().getWorldPermissionsByPlayerName(name); - if(handler == null) { - return false; - } - - List perms = handler.getAllPlayersPermissions(name); - return perms.contains(node.getNode()); - } - - @Override - public boolean isInGroup(Player player, String group) { - final AnjoPermissionsHandler handler = groupManager.getWorldsHolder().getWorldPermissions(player); - return handler != null && handler.inGroup(player.getName(), group); - } - - @Override - public boolean removeFromGroup(Player player, String group) { - return Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "manudelsub " + player.getName() + " " + group); - } - - @Override - public boolean setGroup(Player player, String group) { - final AnjoPermissionsHandler handler = groupManager.getWorldsHolder().getWorldPermissions(player); - for (String groupName : handler.getGroups(player.getName())) { - removeFromGroup(player, groupName); - } - - return Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "manuadd " + player.getName() + " " + group); - } - - @Override - public List getGroups(Player player) { - final AnjoPermissionsHandler handler = groupManager.getWorldsHolder().getWorldPermissions(player); - if (handler == null) - return new ArrayList<>(); - return Arrays.asList(handler.getGroups(player.getName())); - } - - @Override - public String getPrimaryGroup(Player player) { - final AnjoPermissionsHandler handler = groupManager.getWorldsHolder().getWorldPermissions(player); - if (handler == null) - return null; - return handler.getGroup(player.getName()); - } - - @Override - public PermissionsSystemType getPermissionSystem() { - return PermissionsSystemType.ESSENTIALS_GROUP_MANAGER; - } -} diff --git a/src/main/java/fr/xephi/authme/settings/properties/SecuritySettings.java b/src/main/java/fr/xephi/authme/settings/properties/SecuritySettings.java index ac5b90a6e..aa3f3783d 100644 --- a/src/main/java/fr/xephi/authme/settings/properties/SecuritySettings.java +++ b/src/main/java/fr/xephi/authme/settings/properties/SecuritySettings.java @@ -89,7 +89,7 @@ public class SecuritySettings implements SettingsHolder { "- '123456'", "- 'password'"}) public static final Property> UNSAFE_PASSWORDS = - newLowercaseListProperty("settings.security.unsafePasswords", "123456", "password", "qwerty", "12345", "54321"); + newLowercaseListProperty("settings.security.unsafePasswords", "123456", "password", "qwerty", "12345", "54321", "123456789"); @Comment("Tempban a user's IP address if they enter the wrong password too many times") public static final Property TEMPBAN_ON_MAX_LOGINS = diff --git a/src/main/java/fr/xephi/authme/util/MigrationService.java b/src/main/java/fr/xephi/authme/util/MigrationService.java index cc0ef72a4..7b0a32d0a 100644 --- a/src/main/java/fr/xephi/authme/util/MigrationService.java +++ b/src/main/java/fr/xephi/authme/util/MigrationService.java @@ -69,7 +69,7 @@ public final class MigrationService { try { SQLite sqlite = new SQLite(settings); ForceFlatToSqlite converter = new ForceFlatToSqlite(flatFile, sqlite); - converter.run(); + converter.execute(null); settings.setProperty(DatabaseSettings.BACKEND, DataSourceType.SQLITE); settings.save(); return sqlite; diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index bfa09d74e..07f3c3c7e 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -206,6 +206,7 @@ settings: - 'qwerty' - '12345' - '54321' + - '123456789' registration: # enable registration on the server? enabled: true diff --git a/src/main/resources/messages/messages_pt.yml b/src/main/resources/messages/messages_pt.yml index c6a714c75..4b2cb410a 100644 --- a/src/main/resources/messages/messages_pt.yml +++ b/src/main/resources/messages/messages_pt.yml @@ -7,12 +7,11 @@ wrong_pwd: '&cPassword errada!' unregistered: '&cRegisto eliminado com sucesso!' reg_disabled: '&cRegito de novos utilizadores desactivado' valid_session: '&cSessão válida' -login: '&cAutenticado com sucesso!' +login: '&bAutenticado com sucesso!' vb_nonActiv: '&fA sua conta não foi ainda activada, verifique o seu email onde irá receber indicações para activação de conta. ' user_regged: '&cUtilizador já registado' usage_reg: '&cUse: /register seu@email.com seu@email.com' -# TODO max_reg: Missing tags %reg_count, %reg_names, %max_acc -max_reg: '&cAtingiu o numero máximo de registos permitidos' +max_reg: '&cAtingiu o numero máximo de %reg_count contas registas, maximo de contas %max_acc' no_perm: '&cSem Permissões' error: '&fOcorreu um erro; Por favor contacte um admin' login_msg: '&cIdentifique-se com "/login password"' @@ -36,7 +35,7 @@ name_len: '&cO seu nick é demasiado curto ou muito longo.' regex: '&cO seu nickname contém caracteres não permitidos. Permitido: REG_EX' add_email: '&cPor favor adicione o seu email com : /email add seuEmail confirmarSeuEmail' recovery_email: '&cPerdeu a sua password? Para a recuperar escreva /email recovery ' -usage_captcha: '&cVocê precisa digitar um captcha, escreva: /captcha ' +usage_captcha: '&cPrecisa digitar um captcha, escreva: /captcha ' wrong_captcha: '&cCaptcha errado, por favor escreva: /captcha THE_CAPTCHA' valid_captcha: '&cO seu captcha é válido!' kick_forvip: '&cUm jogador VIP entrou no servidor cheio!' @@ -55,20 +54,20 @@ email_send: 'Nova palavra-passe enviada para o seu email!' country_banned: 'O seu país está banido deste servidor' antibot_auto_enabled: '[AuthMe] AntiBotMod activado automaticamente devido a um aumento anormal de tentativas de ligação!' antibot_auto_disabled: '[AuthMe] AntiBotMod desactivado automaticamente após %m minutos, esperamos que a invasão tenha parado' -# TODO password_error_nick: '&cYou can''t use your name as password, please choose another one...' -# TODO email_already_used: '&4The email address is already being used' -# TODO password_error_unsafe: '&cThe chosen password isn''t safe, please choose another one...' -# TODO kick_antibot: 'AntiBot protection mode is enabled! You have to wait some minutes before joining the server.' -# TODO invalid_name_case: 'You should join using username %valid, not %invalid.' +password_error_nick: '&cNão pode o usar seu nome como senha, por favor, escolha outra ...' +not_owner_error: 'Não é o proprietário da conta. Por favor, escolha outro nome!' +two_factor_create: '&2O seu código secreto é o %code. Você pode verificá-lo a partir daqui %url' +email_already_used: '&4O endereço de e-mail já está sendo usado' +denied_command: '&cPara utilizar este comando é necessário estar logado!' +same_ip_online: 'Um jogador com o mesmo IP já está em jogo!' +password_error_chars: '&4Sua senha contém caracteres ilegais. caracteres permitidos: REG_EX' +denied_chat: '&cPara usar o chat deve estar logado!' +password_error_unsafe: '&cA senha escolhida não é segura, por favor, escolha outra ...' +kick_antibot: 'Modo de protecção anti-Bot está habilitado! Tem que espere alguns minutos antes de entrar no servidor.' +email_exists: '&cUm e-mail de recuperação já foi enviado! Pode descartá-lo e enviar um novo usando o comando abaixo:' +invalid_name_case: 'Deve se juntar usando nome de usuário %valid, não %invalid.' # TODO accounts_owned_other: 'The player %name has %count accounts:' # TODO kicked_admin_registered: 'An admin just registered you; please log in again' # TODO tempban_max_logins: '&cYou have been temporarily banned for failing to log in too many times.' -# TODO password_error_chars: '&4Your password contains illegal characters. Allowed chars: REG_EX' # TODO incomplete_email_settings: 'Error: not all required settings are set for sending emails. Please contact an admin.' -# TODO denied_chat: '&cIn order to chat you must be authenticated!' -# TODO denied_command: '&cIn order to use this command you must be authenticated!' -# TODO same_ip_online: 'A player with the same IP is already in game!' -# TODO email_exists: '&cA recovery email was already sent! You can discard it and send a new one using the command below:' # TODO accounts_owned_self: 'You own %count accounts:' -# TODO two_factor_create: '&2Your secret code is %code. You can scan it from here %url' -# TODO not_owner_error: 'You are not the owner of this account. Please choose another name!' \ No newline at end of file diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 769f9fffc..f6af6d4c7 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -8,7 +8,8 @@ softdepend: - Vault - PermissionsBukkit - PermissionsEX - - EssentialsGroupManager + - bPermissions + - zPermissions - Multiverse-Core - Essentials - EssentialsSpawn diff --git a/src/test/java/fr/xephi/authme/command/executable/authme/ConverterCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/authme/ConverterCommandTest.java index 2f4eaa944..a978833a4 100644 --- a/src/test/java/fr/xephi/authme/command/executable/authme/ConverterCommandTest.java +++ b/src/test/java/fr/xephi/authme/command/executable/authme/ConverterCommandTest.java @@ -3,25 +3,30 @@ package fr.xephi.authme.command.executable.authme; import ch.jalu.injector.Injector; import fr.xephi.authme.TestHelper; import fr.xephi.authme.command.CommandService; -import fr.xephi.authme.converter.RakamakConverter; +import fr.xephi.authme.converter.Converter; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.util.BukkitService; +import fr.xephi.authme.util.StringUtils; import org.bukkit.command.CommandSender; +import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; -import java.util.ArrayList; import java.util.Collections; -import java.util.List; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; -import static org.hamcrest.Matchers.hasItem; -import static org.hamcrest.Matchers.not; -import static org.hamcrest.Matchers.nullValue; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertThat; import static org.mockito.BDDMockito.given; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.argThat; +import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; @@ -45,6 +50,11 @@ public class ConverterCommandTest { @Mock private Injector injector; + @BeforeClass + public static void initLogger() { + TestHelper.setupLogger(); + } + @Test public void shouldHandleUnknownConversionType() { // given @@ -54,51 +64,71 @@ public class ConverterCommandTest { command.executeCommand(sender, Collections.singletonList("invalid")); // then - verify(commandService).send(sender, MessageKey.ERROR); + verify(sender).sendMessage(argThat(containsString("Converter does not exist"))); verifyNoMoreInteractions(commandService); verifyZeroInteractions(injector); verifyZeroInteractions(bukkitService); } @Test - public void shouldHaveUniqueNameAndClassForEachType() { + public void shouldHaveUniqueClassForEachConverter() { // given - ConverterCommand.ConvertType[] types = ConverterCommand.ConvertType.values(); - List names = new ArrayList<>(types.length); - List> classes = new ArrayList<>(types.length); + Set> classes = new HashSet<>(); // when / then - for (ConverterCommand.ConvertType type : types) { - assertThat("Name for '" + type + "' is not null", - type.getName(), not(nullValue())); - assertThat("Class for '" + type + "' is not null", - type.getConverterClass(), not(nullValue())); - assertThat("Name '" + type.getName() + "' is unique", - names, not(hasItem(type.getName()))); - assertThat("Class '" + type.getConverterClass() + "' is unique", - classes, not(hasItem(type.getConverterClass()))); - names.add(type.getName()); - classes.add(type.getConverterClass()); + for (Map.Entry> entry : ConverterCommand.CONVERTERS.entrySet()) { + assertThat("Name is not null or empty", + StringUtils.isEmpty(entry.getKey()), equalTo(false)); + + assertThat("Converter class is unique for each entry", + classes.add(entry.getValue()), equalTo(true)); } } @Test public void shouldLaunchConverterForAllTypes() { // given - ConverterCommand.ConvertType type = ConverterCommand.ConvertType.RAKAMAK; - RakamakConverter converter = mock(RakamakConverter.class); - given(injector.newInstance(RakamakConverter.class)).willReturn(converter); + String converterName = "rakamak"; + Class converterClass = ConverterCommand.CONVERTERS.get(converterName); + Converter converter = createMockReturnedByInjector(converterClass); CommandSender sender = mock(CommandSender.class); // when - command.executeCommand(sender, Collections.singletonList(type.getName())); + command.executeCommand(sender, Collections.singletonList(converterName)); TestHelper.runInnerRunnable(bukkitService); // then verify(converter).execute(sender); verifyNoMoreInteractions(converter); - verify(injector).newInstance(type.getConverterClass()); + verify(injector).newInstance(converterClass); verifyNoMoreInteractions(injector); } + @Test + public void shouldCatchExceptionInConverterAndInformSender() { + // given + String converterName = "vauth"; + Class converterClass = ConverterCommand.CONVERTERS.get(converterName); + Converter converter = createMockReturnedByInjector(converterClass); + doThrow(IllegalStateException.class).when(converter).execute(any(CommandSender.class)); + CommandSender sender = mock(CommandSender.class); + + // when + command.executeCommand(sender, Collections.singletonList(converterName.toUpperCase())); + TestHelper.runInnerRunnable(bukkitService); + + // then + verify(converter).execute(sender); + verifyNoMoreInteractions(converter); + verify(injector).newInstance(converterClass); + verifyNoMoreInteractions(injector); + verify(commandService).send(sender, MessageKey.ERROR); + } + + private T createMockReturnedByInjector(Class clazz) { + T converter = mock(clazz); + given(injector.newInstance(clazz)).willReturn(converter); + return converter; + } + } diff --git a/src/test/java/fr/xephi/authme/converter/AbstractDataSourceConverterTest.java b/src/test/java/fr/xephi/authme/converter/AbstractDataSourceConverterTest.java new file mode 100644 index 000000000..a14923f3a --- /dev/null +++ b/src/test/java/fr/xephi/authme/converter/AbstractDataSourceConverterTest.java @@ -0,0 +1,126 @@ +package fr.xephi.authme.converter; + +import fr.xephi.authme.TestHelper; +import fr.xephi.authme.cache.auth.PlayerAuth; +import fr.xephi.authme.datasource.DataSource; +import fr.xephi.authme.datasource.DataSourceType; +import org.bukkit.command.CommandSender; +import org.junit.BeforeClass; +import org.junit.Test; +import org.mockito.Mockito; + +import java.util.Arrays; +import java.util.List; + +import static org.hamcrest.Matchers.containsString; +import static org.mockito.BDDMockito.given; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.argThat; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.only; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.verifyZeroInteractions; + +/** + * Test for {@link AbstractDataSourceConverter}. + */ +public class AbstractDataSourceConverterTest { + + @BeforeClass + public static void initLogger() { + TestHelper.setupLogger(); + } + + @Test + public void shouldThrowForDestinationTypeMismatch() { + // given + DataSource destination = mock(DataSource.class); + given(destination.getType()).willReturn(DataSourceType.MYSQL); + DataSourceType destinationType = DataSourceType.SQLITE; + DataSource source = mock(DataSource.class); + Converter converter = new DataSourceConverterTestImpl<>(source, destination, destinationType); + CommandSender sender = mock(CommandSender.class); + + // when + converter.execute(sender); + + // then + verify(sender).sendMessage(argThat(containsString("Please configure your connection to SQLITE"))); + verify(destination, only()).getType(); + verifyZeroInteractions(source); + } + + @Test + public void shouldHandleSourceThrowingException() { + // given + DataSource source = mock(DataSource.class); + DataSource destination = mock(DataSource.class); + DataSourceType destinationType = DataSourceType.SQLITE; + given(destination.getType()).willReturn(destinationType); + DataSourceConverterTestImpl converter = + Mockito.spy(new DataSourceConverterTestImpl<>(source, destination, destinationType)); + doThrow(IllegalStateException.class).when(converter).getSource(); + CommandSender sender = mock(CommandSender.class); + + // when + converter.execute(sender); + + // then + verify(sender).sendMessage("The data source to convert from could not be initialized"); + verify(destination, only()).getType(); + verifyZeroInteractions(source); + } + + @Test + public void shouldConvertAndSkipExistingPlayers() { + // given + DataSource source = mock(DataSource.class); + DataSource destination = mock(DataSource.class); + DataSourceType destinationType = DataSourceType.MYSQL; + given(destination.getType()).willReturn(destinationType); + + List auths = + Arrays.asList(mockAuthWithName("Steven"), mockAuthWithName("bobby"), mockAuthWithName("Jack")); + given(source.getAllAuths()).willReturn(auths); + given(destination.isAuthAvailable(auths.get(0).getNickname())).willReturn(true); + + Converter converter = new DataSourceConverterTestImpl<>(source, destination, destinationType); + CommandSender sender = mock(CommandSender.class); + + // when + converter.execute(sender); + + // then + verify(destination).getType(); + verify(destination, times(3)).isAuthAvailable(anyString()); + verify(destination, times(2)).saveAuth(any(PlayerAuth.class)); + verify(destination, times(2)).updateQuitLoc(any(PlayerAuth.class)); + verifyNoMoreInteractions(destination); + verify(sender).sendMessage(argThat(containsString(auths.get(0).getNickname()))); + verify(sender).sendMessage(argThat(containsString("successfully converted"))); + } + + private static PlayerAuth mockAuthWithName(String name) { + PlayerAuth auth = mock(PlayerAuth.class); + given(auth.getNickname()).willReturn(name); + return auth; + } + + private static class DataSourceConverterTestImpl extends AbstractDataSourceConverter { + private final S source; + + DataSourceConverterTestImpl(S source, DataSource destination, DataSourceType destinationType) { + super(destination, destinationType); + this.source = source; + } + + @Override + protected S getSource() { + return source; + } + } +} diff --git a/src/test/java/fr/xephi/authme/converter/ForceFlatToSqliteTest.java b/src/test/java/fr/xephi/authme/converter/ForceFlatToSqliteTest.java index 903c58ff3..273d5530f 100644 --- a/src/test/java/fr/xephi/authme/converter/ForceFlatToSqliteTest.java +++ b/src/test/java/fr/xephi/authme/converter/ForceFlatToSqliteTest.java @@ -4,6 +4,7 @@ import com.google.common.io.Files; import fr.xephi.authme.TestHelper; import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.datasource.DataSource; +import fr.xephi.authme.datasource.DataSourceType; import fr.xephi.authme.datasource.FlatFile; import org.junit.Before; import org.junit.BeforeClass; @@ -20,6 +21,7 @@ import static fr.xephi.authme.AuthMeMatchers.hasAuthBasicData; import static fr.xephi.authme.AuthMeMatchers.hasAuthLocation; import static org.hamcrest.Matchers.hasItem; import static org.junit.Assert.assertThat; +import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -51,10 +53,11 @@ public class ForceFlatToSqliteTest { public void shouldConvertToSqlite() { // given DataSource dataSource = mock(DataSource.class); + given(dataSource.getType()).willReturn(DataSourceType.MYSQL); ForceFlatToSqlite converter = new ForceFlatToSqlite(flatFile, dataSource); // when - converter.run(); + converter.execute(null); // then ArgumentCaptor authCaptor = ArgumentCaptor.forClass(PlayerAuth.class);